transformed
v1.1.4
Published
A lightweight, low-level, performant, customizable object transformer utility.
Downloads
65
Readme
A lightweight, low-level, performant, customizable object transformer utility.
- Custom parsers per prop.
- Custom output transformer.
- Built-in value map support.
- Multi-key support.
- Post-instantiation configuration.
Install
npm i transformed
Usage
import transformed from 'transformed'
const myTransformer = transformed()
myTransformer({ foo: 'bar' })
By default transformed
won't do anything with your data, you need to define your rules:
props
: definitions of how to process which propoutputTransformer
: how to process your output
Options
autoCamelCase
(default: false): automatically adds support for camelCase versions of the passed prop names.hasOwnPropertyCheck
(default: false): for a slight performance improvement we're not doinghasOwnProperty
checks by default, but you can enable for cases when not using simple objects as input.toValueCache
(default: true): Enables/disable toValue call caching. This can greatly improve performance in when doing expensive repeated tasks usingtoValue
calls.
API
(InputObject): Whatever registry: Map<string, Definition> outputTransformer: OutputTransformer options: Partial setOptions(options: Partial): TransformedFn setOutputTransformer(outputTransformer: OutputTransformer): TransformedFn setProps(props: Props | ObjectProps): TransformedFn toValue(prop: string, value: unknown)
transformed()
(default export)
A constructor method to create your transformer instance.
setOptions()
Set options for your instance.
const myTransformer = transformed()
myTransformer.setOptions({
autoCamelCase: true,
foo: 'bar'
})
You may add custom config keys/values. You can access these options inside your property parsers and output transformer.
setOutputTransformer()
Set outputTransformer
for your instance.
const myOutputTransformer = ...
const myTransformer = transformed()
myTransformer.setOutputTransformer(myOutputTransformer)
Output transformers always should be set before calling any
setProps
because they have the capability to alter prop names when registering them.
setProps()
Set supported properties for your instance.
Properties defined in "Babel config fashion". Arrays of property descriptors.
// All props
const props = [
// Property
[
// Property names
['p', 'pad', 'padding'],
// Optional value map for this property. Use `null` or leave emoty if not needed.
{ large: '30px' },
// Optional value parsers
[input => output],
// Optional descriptor options for any extra options you want to add for yourself.
{ foo: 'bar' }
]
]
const props = [
[['p', 'pad', 'padding'], { large: '30px' }],
[['bg', 'background'], { cars: 'cars.png' }, [(input, prop) => ({ [prop]: `http://mysite.com/images/${input}` })]]
]
const transform = transformed().setProps(props)
transform({
padding: 'large',
background: 'cars'
})
// Output: { padding: '30px', background: 'http://mysite.com/images/cars.png' }
In case you're setting an existing prop it will:
- reuse the existing
property names
found in the registry, you don't need to redefine all; - merge the passed
valueMap
with the existing one; - merge the list of
parsers
with the existing one.
Based on the circumstances you need to control the execution order of parser. Extending the parser
list can be done
using Webpack style extend operator (...
):
ObjectProp shorthand
You may also pass a key: valueMap
object. This is useful if you want re-configure some existing prop's value map, or
you simply want to set a single new prop with a value map.
It cannot set handlers and multiple keys.
const transform = transformed().setProps({ myProp: { foo: 'bar' } })
transform({ myProp: 'foo' })
// Output: { myProp: 'bar' }
const props = [
// In this case transformed will simply prepend your own parser before the existing ones
[['p', 'pad', 'padding'], null, [myOwnParser, '...']]
]
toValue()
Sometimes you just want to get a value for a prop/value pair.
myTransformer.toValue('padding', 'large')
use()
A simple helper method used to achieve a streaming interface for customization. It awaits a function where you can do your customization inside. It's just an API sugar.
// Instead of
useMyCustomProp1(myTransformer)
useMyCustomProp2(myTransformer)
useMyCustomProp3(myTransformer)
// You can do
myTransformer.use(myCustomProp1).use(myCustomProp2).use(myCustomProp3)
myTransformer.toValue('padding', 'large')
Creating Object Transformers
Object transformer is just a single function with static properties that loops through each property and values using the following API:
myOutputTransformer()
: returns your transformed output, receives the following arguments:output
: currently generated output in current iteration (on first iteration it's defaultOutput)value
: the generated value in the current iterationprop
: the prop name for the current iterationinputObject
: the original object passed to transformedtransformedFn
: current transformed instance used for this iteration
defaultOutput()
: mandatory function returning the default outputunsupportedHandler()
: optional you may specify a handler for unsupported (not registered) properties; receives same arguments as your outputTransformer functioncamelCaseReducer
: optional reducer function to alter how generated camelCase keys stored; parameters are the same as for a normalarray.reduce
callback (accumulator, currentValue, index)transformed
will simply push it into the existing key list
See Complete Example for details on usage.
Creating parsers
Parsers are telling how to process values for a certain property. You can apply as many parser functions as you want, during generation the next function will get the previous function's output value (pipe).
The parser function receives the following arguments:
- value: initial value, or the previous parser's output
- prop: property name,
- transformedFn: transformed instance
- inputObject: original input object
- definition: definition object stored in the property registry for this prop
const alwaysBar = (input, prop) => ({ [prop]: 'bar' })
const myTransformer = transformed().setProps([[['foo'], null, [alwaysBar]]])
myTransformer({ foo: 'baz' })
// Output: { foo: 'bar' }
See Complete Example for more advanced details on usage.
Handling unsupported
(un-registered) values
Keys that don't have registered handler ignored by default. However, you can tell which key's you want to proceed with.
This can be useful for example when dealing with CSS, and you need to pass some ancient or browser specific style property.
You have tu use the prop key: unsupported
which can be:
true
: all props allowedstring[]
: list of props to allowstring
: a single prop to allow
// `-moz-*` will be ignored
{
padding: '10px',
'-moz-border-radius': '10px',
'-moz-foo-bar': 12
}
// only `-moz-foo-bar` will be ignored
{
padding: '10px',
'-moz-border-radius': '10px',
'-moz-foo-bar': 12
unsupported: '-moz-foo-bar'
}
// allow all
{
padding: '10px',
'-moz-border-radius': '10px',
'-moz-foo-bar': 12
unsupported: true
}
// specify what's allowed
{
padding: '10px',
'-moz-border-radius': '10px',
'-moz-foo-bar': 12
unsupported: ['-moz-foo-bar', '-moz-border-radius']
}
Complete example
Let's see a simple example to build string based CSS output for a Style Object:
const toCSSParser = (value, prop, transformedFn, inputObject, definition) => {
// Let's always use the last key as CSS key
const cssProperty = definition.keys[definition.keys.length - 1]
return `${cssProperty}: ${value};\n`
}
// It'll just simply concat
const cssTransformer = (output, value) => `${output}${value}`
// Default output is just a string we will concat into
cssTransformer.defaultOutput = () => ''
const props = [
[['p', 'pad', 'padding'], { large: '30px' }, [toCSSParser]],
[['bg', 'background'], null, [toCSSParser]]
]
const myTransformer = transformed().setOutputTransformer(cssTransformer).setProps(props)
myTransformer({ p: 'large', bg: './cars.png' })
/**
* Output:
*
* padding: 30px;
* background: './cars.png'
*/
Show your support
Give a ⭐️ if this project helped you!
This README was generated with ❤️ by readme-md-generator