UNPKG

parse-js

Version:

Utility library for object structure conversion.

558 lines (404 loc) 15.5 kB
# parse-js [![CircleCI](https://circleci.com/gh/ambassify/parse-js.svg?style=svg)](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)