parse-js
Version:
Utility library for object structure conversion.
558 lines (404 loc) • 15.5 kB
Markdown
# parse-js
[](https://circleci.com/gh/ambassify/parse-js)
Utility library for object structure conversion.
- [Installation](#installation)
- [Usage](#usage)
- [.parse()](#parse)
- [.reverse()](#reverse)
- [.transform()](#transform)
- [.chain()](#chain)
- [Configuration](#configuration)
- [.setOption() / .getOption()](#configuration)
- [Transformers](#transformers)
- [.select()](#select)
- [.default()](#default)
- [.match()](#match)
- [.rename()](#rename)
- [.map()](#map)
- [.group()](#group)
- [.oneOf()](#oneof)
- [.equals()](#equals)
- [.constant()](#constant)
- [.date()](#date)
- [.bool()](#bool)
- [.number()](#number)
- [.string()](#string)
- [.switch()](#switch)
- [.array()](#array)
- [.base64()](#base64)
- [.json()](#json)
- [.spec()](#spec)
- [.multilingual()](#multilingual)
- [.stripPrefix()](#stripprefix)
## Installation
```shell
npm install --save parse-js
```
## Usage
A parser always starts with a call to `parse()`, next you can chain any transformer of of that as is required.
```javascript
const parse = require('parse-js');
parse().bool().parse('true'); // true
parse().match('a').parse({
atest: 'test123',
btest: 'test456'
}); // { atest: 'test123' }
```
Parse also accepts one argument which can be the key to extract from the object to parse. Passing this argument will automatically chain the `select` transformer.
```javascript
const parse = require('parse-js');
parse('a-key').parse({
'a-key': 'a-value',
'some-key': 'some-value'
}); // 'a-value'
```
This is equivalent to:
```javascript
const parse = require('parse-js');
parse().select('a-key').parse({
'a-key': 'a-value',
'some-key': 'some-value'
}); // 'a-value'
```
#### .parse()
```javascript
.parse(data)
```
Whenever `.parse()` is called the configured chain will be executed on the first argument `data`.
If the option `direction` is set to `REVERSE` this method will simply return
the `data` argument as is without modifying it.
Example:
```javascript
parse('test-key').base64().parse({ 'test-key': 'SGVsbG8gV29ybGQ=' });
// Hello World
```
#### .reverse()
```javascript
.reverse(sourceData)
```
The `.reverse()` method will apply all the `reverse` methods of each transformer
and attempts to reassembly the original object based on the sourceData.
Example:
```javascript
parse('test-key').base64().reverse('Hello World');
// {
// 'test-key': 'SGVsbG8gV29ybGQ='
// }
```
#### .transform()
```javascript
.transform(parser, [reverser])
```
This method allows you to chain your own custom `parser` and `reverser`. Both
the `parser` and `reverser` take one argument as input which is the value to
be parsed or reversed.
Instead of supplying both methods as separator arguments you can also pass
the `parser` and `reverser` as an object with both the keys defined.
Example:
```javascript
// Increment / decrement transformer
function parser(v) { return v + 1; };
function reverser(v) { return v - 1; };
parse().transform(parser, reverser).parse(1); // 2
parse().transform(parser, reverser).reverse(3); // 2
// or alternatively
const transformer = {
parser: parser,
reverser: reverser
}
parse().transform(transformer).parse(1); // 2
```
#### .chain()
```javascript
.chain(configurator)
```
The `.chain()` method allows your to create pre-defined chains which can be
easily re-used for different parsers.
Example:
This example created a pre-defined one-way base64 parser.
```javascript
function base64_decode(p) {
return p.base64().setOption('direction', 'PARSE');
}
parse().select('some-key')
.chain(base64_decode)
.parse({ 'some-key': 'SGVsbG8gV29ybGQ=' }); // Hello World
```
### Configuration
Both `parse-js` instances and the `parse` method have methods to set global
options `setOption` and `getOption`, these can be used to configure
transformers that have global settings.
```javascript
Parse.setOption(key, value);
Parse.getOption(key);
parse().setOption(key, value);
parse().getOption(key);
```
Currently only the [multilingual transformer](#multilingual) has such options.
The behaviour of a `parse-js` chain can be altered using the `direction` option
which configures in which directions the transformers should be applied. When
set to `PARSE` the `.reverse()` calls will not touch the data supplied. Similarly
setting `direction` to `REVERSE` will leave the data untouched as `.parse()` is
called. By default both directions are enabled and the option is set to `ANY`.
### Transformers
#### .select()
```javascript
parse().select(key)
```
Selects a value from the object provided to the final `.parse()` call, the key supplied here can be any key supported by [lodash get](https://lodash.com/docs/4.16.0#get).
#### .default()
```javascript
parse().default(defaultValue, reverseDefaultValue)
```
Sets a default value when either the selected value or the reversed value is `undefined`.
- `defaultValue` the value to return whenever the selected value is `undefined`
- `reverseDefaultValue` the value to return whenever the value to reverse is `undefined`
#### .match()
```javascript
parse().match(valueToMatch)
```
Only selects those properties from an object that match `valueToMatch`.
- `valueToMatch` can either be a string or a regular expression.
#### .rename()
```javascript
parse().rename(nameParser, nameReverser);
```
Converts key names using a function for each transition.
- `nameParser(key, value)` will be called with the original key and value as arguments and should return the new key.
- `nameReverser(key, value)` will be called with the generated key and the value set on the object and should return the key to which this value should be written.
#### .map()
```javascript
parse().map(callback)
```
Map will walk each key of a select value and call the `callback` function with a new instance of `parse-js` specific to that key.
- `callback(parse)` will be called with a new instance of parse for each key, which you can then customize by adding new chained transformers.
Example
```javascript
parse().map(p => p.number()).parse({
a: '123',
b: 0,
c: '12.222,3'
}); // { a: 123, b: 0, c: 12222.3 }
```
#### .group()
```
parse().group(regex, key, index)
```
`group` will walk over each key of an object matching it against regular expression `regex`. If it matches the value will be stored at `result[match[key]][match[index]]`, where `match` is the set of matching groups from `regex`. If a key does not match the `regex` it will be re-attached to the object untouched.
- The `key` argument should be set to the index of the matching group that selects the new key to use.
- The `index` arguments should be set to the index of the matching group that selects the sub-key under which to store the value.
Example:
```javascript
parse().group(/(a|b|c)-(name|value)/, 1, 2).parse({
'a-name': 'a-name',
'b-name': 'b-name',
'c-value': 'c-value',
'b-value': 'b-value',
'c-name': 'c-name',
'a-value': 'a-value'
});
// {
// a: { value: 'a-value', name: 'a-name' },
// b: { value: 'b-value', name: 'b-name' },
// c: { value: 'c-value', name: 'c-name' }
// }
```
#### .oneOf()
```javascript
parse().oneOf(parsers, [options = {}])
```
`oneOf` lets you define multiple parsers of which the first in the list with a
result that is valid according to the `test` option will be used.
- `parsers` an array of `parse-js` parsers to go through.
- `options`
- `test` a method which returns true if the result of a parser is valid. (default: `!isEmpty(v)`)
- `reverseAll` controls whether all parsers are called to reverse the value or only the first one. (default: `true`)
Example:
```javascript
parse().oneOf([
parse().select('givenName').string(),
parse().select('firstName').string(),
parse().select('email')
]).parse({ 'firstName': 'John', email: 'john.doe@gmail.com' });
// 'John'
```
#### .equals()
```javascript
parse().equals(valueToMatch, [options = {}])
```
If the selected value matched `valueToMatch` it will return `true`, if it does not it will return `false`.
- `valueToMatch` can be either a regular expressions, function or simply any value.
- `options` can be used to change behaviour of the transformer
- `strict` will ensure `===` comparison is used when comparing. (default: `false`).
- `reverse` can be set to the value that should be set when reversing a `true` value. (default: `valueToMatch`)
Example:
```javascript
parse().equals('some-value').parse('some-other-value'); // false
parse().equals('some-value').parse('some-value'); // true
```
#### .constant()
```javascript
parse().constant(constantValue, [options = {}])
```
Always returns `constantValue` from `parse` and `reverse`.
The value returned from `reverse` can be different from `constantValue`
using the `reverseValue` option.
- `constantValue` the value that will be returned by this transformer.
- `options`
- `reverseValue` If `reverse` should return a different value it can be configured using this option.
Example:
```javascript
parse().constant('a-constant').parse('some-value'); // 'a-constant'
parse().constant('a-constant', {
reverseValue: 'b-constant'
}).reverse('some-value'); // 'b-constant'
```
#### .date()
```javascript
parse().date([nowOnInvalid = false])
```
Converts the selected value into a javascript date object.
- `nowOnInvalid` If set to true will return the current date-time whenever the value being parsed is not a valid date.
#### .bool()
```javascript
parse().bool([options = {}])
```
Converts the selected value to a boolean value.
- `options`
- `defaultValue` when the value being parsed is `undefined` what should be set as the default value.
- `reverseTo` configures the datatype to which the boolean values are reversed. Valid options are `BOOLEAN`, `STRING` or `NUMBER`.
#### .number()
```javascript
parse().number([options = {}])
```
Converts the selected value to a number.
- `options`
- `NaNValue` the value that will be set when the selected value can not be converted. (default: `0`)
- `normalizer` a function used to normalize strings to number-like strings. The default handles removing multiple comma or dots in the string.
- `base` the base in which the value is expressed. (default: `10`)
- `decimalSeparator` the sign to use as decimal separator (`.` or `,`), if not configured, the library does its best to auto-detect
#### .string()
```javascript
parse().string([options = {}])
```
Converts the selected value to a string.
The selected value will be concatenated with an empty string which will call the `toString()` method of most values.
- `options`
- `defaultValue` the value to return whenever the selected value is `undefined`.
#### .switch()
```javascript
parse().switch(cases, parseSelector, reverseSelector)
```
Selects a different parser from the `cases` object by looking up the value at
`parseSelector` / `reverseSelector` in the cases object and executing it.
If the `cases` object does not define a key for the value at returned by the selector,
the `_default_` key will be called if defined. If neither of these exist `undefined` will be returned.
Both `parseSelector ` and `reverseSelector` can be any key supported by [lodash get](https://lodash.com/docs/4.16.0#get)
or a method which is passed the object to transform and the root object of this transform. Passing `null` or `undefined` will
disable the selector and `.switch()` will always return `undefined`.
- `cases` an object containing the different possible values for the field at `selector`.
- `parseSelector` a key that specifies which key to look up in the `cases` object when performing a `.parse()` operation.
- `reverseSelector` a key that specifies which key to look up in the `cases` object when performing a `.reverse()` operation.
Example:
```javascript
parse('test-key')
.switch({
'string': parse('value').string(),
'number': parse('value').number(),
'_default_': parse('value').string()
}, 'type', (v) => typeof v)
.parse({
'test-key': {
type: 'number',
value: '123'
}
});
// 123
```
#### .array()
```javascript
parse().array([options = {}])
```
This transformer will ensure that the selected value will be converted to an array. Whenever this fails it will return an empty array.
- `options`
- `mode` the methods that are allowed to be used to convert values to arrays. (default: `ANY`). Valid options are `ANY`, `JSON` and `SEPARATOR`.
- `separator` the separator to be used when `mode` is set to `ANY` or `SEPARATOR`. (default: `,`)
#### .base64()
```javascript
parse().base64([options = {}])
```
Handles conversion from and to base64 strings.
- `options`
- `allowBinary` when this option is set to `true` the `isPrintable` check will be disabled. Because of this any valid base64 formatted string will be decoded.
#### .json()
```javascript
parse().json([options = {}])
```
Converts the selected value from and to a JSON string.
- `options`
- `defaultValue` will be returned whenever no valid JSON string is selected.
#### .spec()
```javascript
parse().spec(specification)
```
A specification is an object that has the desired properties of the target format, where the values are the parsers that generate the value to store with this property. This allows a source format to be converted to the desired format using `parse-js`.
- `specification` an object containing `key` - `parser` combinations.
Example:
```javascript
parse().spec({
one: parse('two'),
two: parse('one').number(),
three: parse('four').array(),
nested: {
one: parse('one'),
two: parse('four').json()
}
}).parse({ one: '15.333.23', two: 'two', four: '[1,2,3,4,5]' });
// {
// one: 'two',
// two: 15333.23,
// three: [1, 2, 3, 4, 5],
// nested: {
// one: '15.333.23',
// two: [1, 2, 3, 4, 5]
// }
// }
```
#### .multilingual()
```javascript
parse().multilingual(languages)
```
Will group keys with language suffixes as defined by `group()`
- `languages` configures the languages that are supported. This option can also be set using the `setOption()` method of the parse-js instance or `Parse.setOption()`. When using `setOption()` this option is configured using the key `multilingual.languages`.
Example:
```javascript
parse().multilingual(['en', 'nl', 'fr', 'de']).parse({
keyEn: 'english text',
keyNl: 'dutch text'
});
// {
// key: { en: 'english text', nl: 'dutch text' }
// }
```
#### .stripPrefix()
```javascript
parse().stripPrefix(prefix)
```
Selects keys that start with `prefix` and removes that `prefix` from the target object.
- `prefix` the prefix that keys should contain and that will be removed.
Example:
```javascript
parse().stripPrefix('test').parse({
atest: 'value-1',
test1: 'value-2',
test2: 'value-3'
});
// { 1: 'value-2', 2: 'value-3' }
```
## Contribute
We really appreciate any contribution you would like to make, so don't
hesitate to report issues or submit pull requests.
## License
This project is released under a MIT license.
## About us
If you would like to know more about us, be sure to have a look at [our website](https://www.ambassify.com), or our Twitter accounts [Ambassify](https://twitter.com/Ambassify), [Sitebase](https://twitter.com/Sitebase), [JorgenEvens](https://twitter.com/JorgenEvens)