Comparing version 7.0.1 to 7.1.0
@@ -19,2 +19,4 @@ module.exports = { | ||
reify: require('./lib/reify'), | ||
intersection: require('./lib/intersection'), | ||
union: require('./lib/union'), | ||
}; | ||
@@ -21,0 +23,0 @@ |
@@ -18,3 +18,3 @@ /** | ||
var type = { | ||
var TYPES = { | ||
@@ -89,2 +89,5 @@ | ||
return ''; | ||
}, | ||
isExemplar: function (eg){ | ||
return TYPES.str.is(eg) && !TYPES.lamda.isExemplar(eg) && !TYPES.json.isExemplar(eg) && !TYPES.ref.isExemplar(eg); | ||
} | ||
@@ -126,5 +129,5 @@ }, | ||
if(type.number.is(v)) return v; | ||
if(type.boolean.is(v)) return v ? 1 : 0; | ||
if(type.string.is(v)) { | ||
if(TYPES.number.is(v)) return v; | ||
if(TYPES.boolean.is(v)) return v ? 1 : 0; | ||
if(TYPES.string.is(v)) { | ||
@@ -166,2 +169,5 @@ // Is this a string that appears to be a number? | ||
return 0; | ||
}, | ||
isExemplar: function (eg){ | ||
return TYPES.number.is(eg); | ||
} | ||
@@ -210,2 +216,5 @@ }, | ||
return false; | ||
}, | ||
isExemplar: function (eg){ | ||
return TYPES.boolean.is(eg); | ||
} | ||
@@ -239,3 +248,3 @@ }, | ||
if (!_.isObject(v)) return false; | ||
if (type.arr.is(v)) return false; | ||
if (TYPES.array.is(v)) return false; | ||
if (!_.isPlainObject(v)) return false; | ||
@@ -286,2 +295,5 @@ // Reject readable streams | ||
return {}; | ||
}, | ||
isExemplar: function (eg){ | ||
return TYPES.dictionary.is(eg); | ||
} | ||
@@ -320,2 +332,5 @@ }, | ||
return []; | ||
}, | ||
isExemplar: function (eg){ | ||
return TYPES.array.is(eg); | ||
} | ||
@@ -364,2 +379,5 @@ }, | ||
return undefined; | ||
}, | ||
isExemplar: function (eg){ | ||
return eg === '===' || eg === undefined; | ||
} | ||
@@ -437,2 +455,5 @@ }, | ||
return null; | ||
}, | ||
isExemplar: function (eg){ | ||
return eg === '*'; | ||
} | ||
@@ -480,2 +501,5 @@ }, | ||
return function () { throw new Error('Not implemented! (this function was automatically created by `rttc`'); }; | ||
}, | ||
isExemplar: function (eg){ | ||
return _.isString(eg) && eg.match(/(^-+>$)|(^=+>$)|(^<=+$)|(^<-+$)/); | ||
} | ||
@@ -493,13 +517,18 @@ }, | ||
// Aliases for backwards compat. | ||
type.str = type.email = type.url = type.string; | ||
type.bool = type.boolean; | ||
type.arr = type.array; | ||
type.integer = type.int; | ||
type.float = type.number; | ||
type.object = type.obj = type.dictionary; | ||
// Abbreviation aliases for backwards compat. | ||
TYPES.str = TYPES.string; | ||
TYPES.num = TYPES.number; | ||
TYPES.bool = TYPES.boolean; | ||
TYPES.arr = TYPES.array; | ||
TYPES.dict = TYPES.dictionary; | ||
module.exports = type; | ||
// (Mi)spelling aliases | ||
TYPES.lambda = TYPES.lambda; | ||
// Case-folding aliases | ||
TYPES.JSON = TYPES.json; | ||
module.exports = TYPES; | ||
@@ -11,5 +11,5 @@ /** | ||
/** | ||
* Given a primitive value, return its type. | ||
* Given a primitive exemplar, return its type. | ||
* ________________________________________________________________________________ | ||
* @param {*} val there's that "mystery meat" again | ||
* @param {*} eg there's that "mystery meat" again | ||
* ________________________________________________________________________________ | ||
@@ -19,6 +19,6 @@ * @returns {String} | ||
function getTypeOfPrimitive(val) { | ||
function getTypeOfPrimitive(eg) { | ||
// Check for `type: 'ref'` (===) | ||
if (val === '===' || val === undefined) { | ||
if (types.ref.isExemplar(eg)) { | ||
return 'ref'; | ||
@@ -28,3 +28,3 @@ } | ||
// Check for `type: 'lamda'` (->) | ||
if (_.isString(val) && val.match(/(^-+>$)|(^=+>$)|(^<=+$)|(^<-+$)/)) { | ||
if (types.lamda.isExemplar(eg)) { | ||
return 'lamda'; | ||
@@ -34,3 +34,3 @@ } | ||
// Check for `type: 'json'` (*) | ||
if (val === '*') { | ||
if (types.json.isExemplar(eg)){ | ||
return 'json'; | ||
@@ -40,3 +40,3 @@ } | ||
// Check for string | ||
if(types.str.is(val)) { | ||
if (types.string.isExemplar(eg)) { | ||
return 'string'; | ||
@@ -46,3 +46,3 @@ } | ||
// Check for number | ||
if(types.number.is(val)) { | ||
if (types.number.isExemplar(eg)) { | ||
return 'number'; | ||
@@ -52,3 +52,3 @@ } | ||
// Check for boolean | ||
if(types.bool.is(val)) { | ||
if (types.boolean.isExemplar(eg)) { | ||
return 'boolean'; | ||
@@ -63,3 +63,3 @@ } | ||
/** | ||
* Recursively create a new schema object from an example object. | ||
* Recursively create a new type schema dictionary from an exemplar. | ||
* ________________________________________________________________________________ | ||
@@ -73,3 +73,3 @@ * @param {Object} obj | ||
function getSchemaOfObject(obj) { | ||
if(!types.obj.is(obj)) return; | ||
if(!types.dictionary.is(obj)) return; | ||
@@ -81,6 +81,6 @@ var newObj = {}; | ||
var type; | ||
if(types.arr.is(val)) { | ||
type = getSchema(val); | ||
if(types.array.is(val)) { | ||
type = infer(val); | ||
} | ||
else if(types.obj.is(val)) { | ||
else if(types.dictionary.is(val)) { | ||
type = getSchemaOfObject(val); | ||
@@ -101,22 +101,22 @@ } | ||
/** | ||
* Given an example, parse it to infer its schema. | ||
* Given an exemplar, parse it to infer its type schema. | ||
* ________________________________________________________________________________ | ||
* @param {*} example | ||
* @param {*} eg | ||
* ________________________________________________________________________________ | ||
* @returns {*} a schema object | ||
* @returns {*} a type schema | ||
*/ | ||
function getSchema(example) { | ||
function infer(eg) { | ||
// If the example isn't an object or array, we will derive its primitive type. | ||
if(!types.obj.is(example) && !types.arr.is(example)) { | ||
return getTypeOfPrimitive(example); | ||
// If the exemplar isn't an object or array, we will derive its primitive type. | ||
if(!types.dictionary.is(eg) && !types.array.is(eg)) { | ||
return getTypeOfPrimitive(eg); | ||
} | ||
// If the example is an array, figure out what to do. | ||
// If the exemplar is an array, figure out what to do. | ||
// For now just check that it's an array. | ||
if(types.arr.is(example)) { | ||
if(types.array.is(eg)) { | ||
// Ensure empty arrays are not recursively parsed. | ||
if (example.length === 0) { | ||
if (eg.length === 0) { | ||
return []; | ||
@@ -126,20 +126,20 @@ } | ||
// Parse arrays of arrays | ||
if (_.isArray(example[0])) { | ||
return [getSchema(example[0])]; | ||
if (_.isArray(eg[0])) { | ||
return [infer(eg[0])]; | ||
} | ||
// Parse arrays of objects | ||
if (_.isObject(example[0])) { | ||
return [getSchemaOfObject(example[0])]; | ||
if (_.isObject(eg[0])) { | ||
return [getSchemaOfObject(eg[0])]; | ||
} | ||
// Parse arrays of primitives | ||
return [getTypeOfPrimitive(example[0])]; | ||
return [getTypeOfPrimitive(eg[0])]; | ||
} | ||
// Otherwise parse the object | ||
return getSchemaOfObject(example); | ||
return getSchemaOfObject(eg); | ||
} | ||
module.exports = getSchema; | ||
module.exports = infer; |
{ | ||
"name": "rttc", | ||
"version": "7.0.1", | ||
"version": "7.1.0", | ||
"description": "Runtime type-checking for JavaScript.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
387
README.md
@@ -80,182 +80,60 @@ # rttc | ||
> Note that all of the validation and coercion strategies used in this modules are recursive through the keys of plain old JavaScript objects and the indices of arrays. | ||
Finally, note that all of the validation and coercion strategies used in this modules are recursive through the keys of plain old JavaScript objects and the indices of arrays. | ||
## Types | ||
## Usage | ||
> Each type can be validated or coerced against. If coercion fails, the "base value" for the type will be used. | ||
### Validation | ||
> Also note that all types below may be expressed recursively within faceted dictionaries and patterned arrays. If those words don't make sense, keep reading, you'll see what I mean. | ||
##### .validateStrict(expectedTypeSchema, actualValue) | ||
Throws if the provided value is not the right type (recursive). | ||
There are 10 different types recognized by `rttc`: | ||
| type | rttc example notation | base value | | ||
|-------------------------|--------------------------|-------------------------------------| | ||
| string | `'any string like this'` | `''` | ||
| number | `1337` _(any number)_ | `0` | ||
| boolean | `false` _(or `true`)_ | `false` | ||
| lamda | `function anyFunction(){ /* any function */ }` | `function () { throw new Error('Not implemented! (this function was automatically created by `rttc`'); };` | ||
| generic dictionary | `{}` | `{}` _(empty dictionary)_ | ||
| generic array | `[]` | `[]` _(empty array)_ | ||
| json | `'*'` | `null` | ||
| ref | `'==='` | `undefined` | ||
| faceted dictionary (recursive) | `{...}` _(i.e. w/ keys)_ | `{...}` (w/ all expected keys and _their_ base values) | ||
| pattern array (recursive) | `[...]` _(i.e. w/ 1 item)_ | `[]` _(empty array)_ | ||
##### .validate(expectedTypeSchema, actualValue) | ||
Either returns a (potentially "lightly" coerced) version of the value that was accepted, or it throws. The "lightly" coerced value turns `"3"` into `3`, `"true"` into `true`, `-4.5` into `"-4.5"`, etc. | ||
### Strings | ||
`example: 'stuff'` | ||
### Munging | ||
The **string** type accepts any string. | ||
### Numbers | ||
##### .coerce(expectedTypeSchema, actualValue) | ||
`example: 323` | ||
ALWAYS returns an acceptable version of the value, even if it has to mangle it to get there (i.e. by using the "base value" for the expected type. More on that below.) | ||
The **number** type accepts numbers like `0`, `-4`, or `235.3`. Anathemas like `Infinity`, `-Infinity`, `NaN`, and `-0` are all coerced to zero. | ||
### Booleans | ||
##### .hydrate(value, [_typeSchema_=`undefined`]) | ||
`example: false` | ||
This function will use the provided `typeSchema` to figure out where "lamda" values (functions) are expected, then will use `eval()` to bring them back to life. Use with care. | ||
The **boolean** type accepts `true` or `false`. | ||
### Lamdas | ||
##### .dehydrate(value, [_allowNull_=`false`]) | ||
`example: ->` | ||
This takes care of a few serialization edge-cases, such as: | ||
The **lamda** type accepts any function. | ||
+ stringifies functions, regexps, and errors (grabs the `.stack` property) | ||
+ replacing circular references with a string (e.g. `[Circular]`) | ||
+ replaces `-Infinity`, `Infinity`, and `NaN` with 0 | ||
+ strips keys and array items with `undefined` or `null` values. If `allowNull` is set to true, `null` values will not be stripped from the encoded string. | ||
### Generic dictionaries | ||
##### .parse(stringifiedValue, [_typeSchema_=`undefined`], [_unsafeMode_=`false`]) | ||
Parse a stringified value back into a usable value. | ||
This is basically just a variation on JSON.parse that calls `rttc.hydrate()` first if `unsafeMode` is enabled. | ||
##### .stringify(value, [_allowNull_=`false`]) | ||
Encode a value into a string. | ||
This is basically just a variation on JSON.stringify that calls `rttc.dehydrate()` first. | ||
##### .parseHuman(stringFromHuman, [_typeSchema_=`undefined`], [_unsafeMode_=`false`]) | ||
Parse a string from a human into something usable. If provided, `typeSchema` will be used to make a better guess. If `unsafeMode` is enabled, lamda functions will be hydrated. | ||
##### .stringifyHuman(value, typeSchema) | ||
The inverse of `.parseHuman()`, this function encodes a string that, if run through `.parseHuman()` would result in the given value. | ||
##### .reify(typeSchema) | ||
Given a type schema, strip out generics ("ref", "json", {}, and []) to convert it into a strict type. In other words, this makes a type schema "strict", and the result of this function always passes `rttc.isStrictType()`. | ||
### Assertions | ||
##### .isEqual(firstValue, secondValue, [_expectedTypeSchema_=`undefined`]) | ||
Determine whether two values are equivalent using `_.isEqual()`, but also look for expected `lamda` values in the optional type schema and call `toString()` on functions before comparing them. | ||
> This is the method used by `rttc`'s own tests to validate that expected values and actual values match. | ||
##### .infer(exampleValue) | ||
Guess the type schema from an example value. | ||
##### .isStrictType(typeSchema, [recursive=false]) | ||
Determine whether the given type schema is "strict" (meaning it is a string, number, boolean, lamda, faceted dictionary, or patterned array). If second argument (`recursive`) is set to `true`, then also recursively check the subkeys of faceted dictionaries and patterns of arrays in the type schema. | ||
| type | is strict? | | ||
|-------------------------|---------------------| | ||
| string | yes _(always)_ | | ||
| number | yes _(always)_ | | ||
| boolean | yes _(always)_ | | ||
| lamda | yes _(always)_ | | ||
| `{}` (generic) | no | | ||
| `[]` (generic) | no | | ||
| `{...}` (faceted) | yes _(maybe recursively)_ | | ||
| `[...]` (patterned) | yes _(maybe recursively)_ | | ||
| json | no | | ||
| ref | no | | ||
### Utilities | ||
##### .sample(typeSchema, [n=2]) | ||
Given a type schema, return an array of up to `n` unique sample values that would validate against it (in random order). `n` defaults to 2 if left undefined. | ||
##### .getDisplayType(value) | ||
Given a value, return its type as a human-readable string (this is not limited to rttc types-- it can return strings like `"Error"` and `"Date"`) | ||
##### .compile(value) | ||
Given a value, return a human-readable string which represents it. This string is equivalent to a JavaScript code snippet which would accurately represent the value in code. | ||
This is a lot like `util.inspect(val, false, null)`, but it also has special handling for Errors, Dates, RegExps, and Functions (using `dehydrate()` with `allowNull` enabled.) The biggest difference is that everything you get from `rttc.compile()` is ready for use as values in `*`, `{}`, or `[]` type machines, Treeline, Angular's rendering engine, and JavaScript code in general (i.e. if you were to append it on the right-hand side of `var x = `, or if you ran `eval()` on it) | ||
Note that undefined values in arrays and undefined values of keys in dictionaries will be stripped out, and circular references will be handled as they are in `util.inspect(val, false, null)` | ||
Useful for: | ||
+ generating code samples | ||
+ in particular for bootstrapping data on server-rendered views for access by client-side JavaScript | ||
+ error messages, | ||
+ debugging | ||
+ user interfaces | ||
Here's a table listing notable differences between `util.inspect()` and `rttc.compile()` for reference: | ||
| value | util.inspect() | rttc.compile() | | ||
|--------------------------|-------------------------------------------|--------------------------------------| | ||
| a function | `[Function: foo]` | `'function foo (){}'` | | ||
| a Date | `Tue May 26 2015 20:05:37 GMT-0500 (CDT)` | `'2015-05-27T01:06:37.072Z'` | | ||
| a RegExp | `/foo/gi` | `'/foo/gi/'` | | ||
| an Error | `[Error]` | `'Error\n at repl:1:24\n...'` | | ||
| a deeply nested thing | `{ a: { b: { c: [Object] } } }` | `{ a: { b: { c: { d: {} } } } }` | | ||
| a circular thing | `{ y: { z: [Circular] } }` | `{ y: { z: '[Circular ~]' } }` | | ||
| undefined | `undefined` | `null` | | ||
| [undefined] | `[undefined]` | [] | | ||
| {foo: undefined} | `{foo: undefined}` | {} | | ||
| Infinity | `Infinity` | `0` | | ||
| -Infinity | `-Infinity` | `0` | | ||
| NaN | `NaN` | `0` | | ||
| Readable (Node stream) | `{ _readableState: { highWaterMar..}}` | `null` | | ||
| Buffer (Node bytestring) | `<Buffer 61 62 63>` | `null` | | ||
## Types | ||
Here are the various types recognized by `rttc`. They are recursive within faceted dictionaries and patterned arrays. If those words don't make sense, keep reading, you'll see what I mean. | ||
#### Strings | ||
`example: 'stuff'` | ||
#### Numbers | ||
`example: 323` | ||
#### Booleans | ||
`example: false` | ||
#### Generic dictionaries | ||
`example: {}` | ||
The **generic dictionary** type is a dictionary type schema with no keys. | ||
The **generic dictionary** type accepts any JSON-serializable dictionary. | ||
Dictionaries that have been validated/coerced against the generic dictionary type: | ||
@@ -272,3 +150,3 @@ + will have no prototypal properties, getters, or setters, as well as a complete deficit of any other sort of deceit, lies, or magic | ||
#### Faceted dictionaries | ||
### Faceted dictionaries | ||
@@ -299,3 +177,3 @@ `example: {...}` | ||
#### Generic arrays | ||
### Generic arrays | ||
@@ -318,3 +196,3 @@ `example: []` | ||
#### Patterned arrays | ||
### Patterned arrays | ||
@@ -354,3 +232,3 @@ `example: ['Margaret']` | ||
#### Generic JSON | ||
### Generic JSON | ||
@@ -365,3 +243,3 @@ `example: '*'` | ||
#### Mutable reference ("ref") | ||
### Mutable reference ("ref") | ||
@@ -375,18 +253,2 @@ `example: '==='` | ||
## Base values | ||
As mentioned above, every type has a base value. | ||
+ For the "string" type, base value is `""` | ||
+ For the "number" type, base value is `0` | ||
+ For the "boolean" type, base value is `false` | ||
+ For the "lamda" type (`'->'`), base value is a function that uses the standard machine fn signature and triggers its "error" callback w/ a message about being the rttc default (e.g. `function(inputs,exits,env) { return exits.error(new Error('not implemented')); }`) | ||
+ For the generic dictionary type (`{}`) or a faceted dictionary type (e.g. `{foo:'bar'}`), the base value is `{}`. | ||
+ For the generic array type (`[]`), or a faceted/homogenous array type (e.g. `[3]` or `[{age:48,name: 'Nico'}]`), the base value is `[]` | ||
+ For the "json" type (`'*'`), base value is `null`. | ||
+ For the "ref" type (`'==='`), base value is `undefined`. | ||
> Note that, for both arrays and dictionaries, any keys in the schema will get the base value for their type (and their keys for their type, etc. -- recursive) | ||
## Edge-cases | ||
@@ -423,2 +285,178 @@ | ||
##### Base values | ||
As mentioned above, every type has a base value. | ||
+ For the "string" type, base value is `""` | ||
+ For the "number" type, base value is `0` | ||
+ For the "boolean" type, base value is `false` | ||
+ For the "lamda" type (`'->'`), base value is a function that uses the standard machine fn signature and triggers its "error" callback w/ a message about being the rttc default (e.g. `function(inputs,exits,env) { return exits.error(new Error('not implemented')); }`) | ||
+ For the generic dictionary type (`{}`) or a faceted dictionary type (e.g. `{foo:'bar'}`), the base value is `{}`. | ||
+ For the generic array type (`[]`), or a faceted/homogenous array type (e.g. `[3]` or `[{age:48,name: 'Nico'}]`), the base value is `[]` | ||
+ For the "json" type (`'*'`), base value is `null`. | ||
+ For the "ref" type (`'==='`), base value is `undefined`. | ||
> Note that, for both arrays and dictionaries, any keys in the schema will get the base value for their type (and their keys for their type, etc. -- recursive) | ||
## Methods | ||
This package exposes a number of different utility methods. If you're interested in using any of these directly, we highly recommend you consider looking at [machinepack-rttc](http://node-machine.org/machinepack-rttc), which provides a higher-level abstraction with better documentation. | ||
> The low-level reference below assumes you are willing/able to dig into the source code of this module for more information. So continue at your own risk! | ||
### Validation | ||
##### .validateStrict(expectedTypeSchema, actualValue) | ||
Throws if the provided value is not the right type (recursive). | ||
##### .validate(expectedTypeSchema, actualValue) | ||
Either returns a (potentially "lightly" coerced) version of the value that was accepted, or it throws. The "lightly" coerced value turns `"3"` into `3`, `"true"` into `true`, `-4.5` into `"-4.5"`, etc. | ||
### Munging | ||
##### .coerce(expectedTypeSchema, actualValue) | ||
ALWAYS returns an acceptable version of the value, even if it has to mangle it to get there (i.e. by using the "base value" for the expected type. More on that below.) | ||
##### .hydrate(value, [_typeSchema_=`undefined`]) | ||
This function will use the provided `typeSchema` to figure out where "lamda" values (functions) are expected, then will use `eval()` to bring them back to life. Use with care. | ||
##### .dehydrate(value, [_allowNull_=`false`]) | ||
This takes care of a few serialization edge-cases, such as: | ||
+ stringifies functions, regexps, and errors (grabs the `.stack` property) | ||
+ replacing circular references with a string (e.g. `[Circular]`) | ||
+ replaces `-Infinity`, `Infinity`, and `NaN` with 0 | ||
+ strips keys and array items with `undefined` or `null` values. If `allowNull` is set to true, `null` values will not be stripped from the encoded string. | ||
##### .parse(stringifiedValue, [_typeSchema_=`undefined`], [_unsafeMode_=`false`]) | ||
Parse a stringified value back into a usable value. | ||
This is basically just a variation on JSON.parse that calls `rttc.hydrate()` first if `unsafeMode` is enabled. | ||
##### .stringify(value, [_allowNull_=`false`]) | ||
Encode a value into a string. | ||
This is basically just a variation on JSON.stringify that calls `rttc.dehydrate()` first. | ||
##### .parseHuman(stringFromHuman, [_typeSchema_=`undefined`], [_unsafeMode_=`false`]) | ||
Parse a string from a human into something usable. If provided, `typeSchema` will be used to make a better guess. If `unsafeMode` is enabled, lamda functions will be hydrated. | ||
##### .stringifyHuman(value, typeSchema) | ||
The inverse of `.parseHuman()`, this function encodes a string that, if run through `.parseHuman()` would result in the given value. | ||
##### .reify(typeSchema) | ||
Given a type schema, strip out generics ("ref", "json", {}, and []) to convert it into a strict type. In other words, this makes a type schema "strict", and the result of this function always passes `rttc.isStrictType()`. | ||
### Assertions | ||
##### .isEqual(firstValue, secondValue, [_expectedTypeSchema_=`undefined`]) | ||
Determine whether two values are equivalent using `_.isEqual()`, but also look for expected `lamda` values in the optional type schema and call `toString()` on functions before comparing them. | ||
> This is the method used by `rttc`'s own tests to validate that expected values and actual values match. | ||
##### .infer(exampleValue) | ||
Guess the type schema from an example value. | ||
##### .isStrictType(typeSchema, [recursive=false]) | ||
Determine whether the given type schema is "strict" (meaning it is a string, number, boolean, lamda, faceted dictionary, or patterned array). If second argument (`recursive`) is set to `true`, then also recursively check the subkeys of faceted dictionaries and patterns of arrays in the type schema. | ||
| type | is strict? | | ||
|-------------------------|---------------------| | ||
| string | yes _(always)_ | | ||
| number | yes _(always)_ | | ||
| boolean | yes _(always)_ | | ||
| lamda | yes _(always)_ | | ||
| `{}` (generic) | no | | ||
| `[]` (generic) | no | | ||
| `{...}` (faceted) | yes _(maybe recursively)_ | | ||
| `[...]` (patterned) | yes _(maybe recursively)_ | | ||
| json | no | | ||
| ref | no | | ||
### Utilities | ||
##### .sample(typeSchema, [n=2]) | ||
Given a type schema, return an array of up to `n` unique sample values that would validate against it (in random order). `n` defaults to 2 if left undefined. | ||
##### .getDisplayType(value) | ||
Given a value, return its type as a human-readable string (this is not limited to rttc types-- it can return strings like `"Error"` and `"Date"`) | ||
##### .compile(value) | ||
Given a value, return a human-readable string which represents it. This string is equivalent to a JavaScript code snippet which would accurately represent the value in code. | ||
This is a lot like `util.inspect(val, false, null)`, but it also has special handling for Errors, Dates, RegExps, and Functions (using `dehydrate()` with `allowNull` enabled.) The biggest difference is that everything you get from `rttc.compile()` is ready for use as values in `*`, `{}`, or `[]` type machines, Treeline, Angular's rendering engine, and JavaScript code in general (i.e. if you were to append it on the right-hand side of `var x = `, or if you ran `eval()` on it) | ||
Note that undefined values in arrays and undefined values of keys in dictionaries will be stripped out, and circular references will be handled as they are in `util.inspect(val, false, null)` | ||
Useful for: | ||
+ generating code samples | ||
+ in particular for bootstrapping data on server-rendered views for access by client-side JavaScript | ||
+ error messages, | ||
+ debugging | ||
+ user interfaces | ||
Here's a table listing notable differences between `util.inspect()` and `rttc.compile()` for reference: | ||
| value | util.inspect() | rttc.compile() | | ||
|--------------------------|-------------------------------------------|--------------------------------------| | ||
| a function | `[Function: foo]` | `'function foo (){}'` | | ||
| a Date | `Tue May 26 2015 20:05:37 GMT-0500 (CDT)` | `'2015-05-27T01:06:37.072Z'` | | ||
| a RegExp | `/foo/gi` | `'/foo/gi/'` | | ||
| an Error | `[Error]` | `'Error\n at repl:1:24\n...'` | | ||
| a deeply nested thing | `{ a: { b: { c: [Object] } } }` | `{ a: { b: { c: { d: {} } } } }` | | ||
| a circular thing | `{ y: { z: [Circular] } }` | `{ y: { z: '[Circular ~]' } }` | | ||
| undefined | `undefined` | `null` | | ||
| [undefined] | `[undefined]` | [] | | ||
| {foo: undefined} | `{foo: undefined}` | {} | | ||
| Infinity | `Infinity` | `0` | | ||
| -Infinity | `-Infinity` | `0` | | ||
| NaN | `NaN` | `0` | | ||
| Readable (Node stream) | `{ _readableState: { highWaterMar..}}` | `null` | | ||
| Buffer (Node bytestring) | `<Buffer 61 62 63>` | `null` | | ||
<!-- | ||
## More examples | ||
@@ -599,2 +637,3 @@ | ||
--> | ||
@@ -601,0 +640,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
193632
36
4039
637