Comparing version 9.4.0 to 9.5.0
@@ -25,2 +25,3 @@ module.exports = { | ||
coerceExemplar: require('./lib/coerce-exemplar'), | ||
getPatternFromExemplar: require('./lib/get-pattern-from-exemplar'), | ||
cast: require('./lib/cast'), | ||
@@ -27,0 +28,0 @@ rebuild: require('./lib/rebuild'), |
@@ -12,16 +12,56 @@ /** | ||
/** | ||
* Convert a normal value into an exemplar representative of the _most specific_ type schema which would accept it. | ||
* coerceExemplar() | ||
* | ||
* If `allowSpecialSyntax` is set, '->', '*', and '===' take on their traditional special meaning. | ||
* Otherwise, they will be "exemplified"-- that is, replaced with strings ('an arrow symbol', 'a star symbol', '3 equal signs') | ||
* Convert a normal JavaScript value into the _most specific_ RTTC exemplar | ||
* which would accept it.... more or less. | ||
* | ||
* @param {*} value | ||
* > -------------------------------------------------------------------------------- | ||
* > WARNING: While this logic is OK at understanding functions, it's not really | ||
* > smart enough to figure out cases where it would need refs. It dehydrates | ||
* > everything first, meaning it ensures everything is JSON compatible by ripping | ||
* > out circular references and replacing replacing streams, buffers, and | ||
* > RttcRefPlaceholder instances with `null`. It also rips out `undefined` array | ||
* > items, and dictionary keys with `undefined` values (meaning that there are | ||
* > never any _nested_ `undefined`s by the time it gets around to building the | ||
* > exemplar.) And finally, it converts all Dates, RegExps, and Error instances | ||
* > to strings. | ||
* > -------------------------------------------------------------------------------- | ||
* | ||
* @param {Anything} value | ||
* A normal JavaScript value. | ||
* | ||
* @param {Boolean} allowSpecialSyntax | ||
* @return {*} | ||
* If set, string literals which look like special RTTC exemplar syntax (->, *, and ===) | ||
* take on their traditional symbolism; meaning they will NOT be "exemplified"-- that is, | ||
* replaced with other strings: ('an arrow symbol', 'a star symbol', and '3 equal signs'). | ||
* > WARNING: Use with care! Remember other things need to be exemplified too! | ||
* > (e.g. consider the `null` literal) | ||
* @default false | ||
* | ||
* @param {Boolean} treatTopLvlUndefinedAsRef | ||
* If set, if the provided value is `undefined`, it will be treated as a ref. | ||
* Note that this purely for backwards compatibility, since as of rttc@9.3.0, | ||
* the `===` exemplar no longer accepts `undefined`; and its base value is now `null`. | ||
* > The default value for this flag will be changed to `false` in a future release. | ||
* @default true | ||
* | ||
* @returns {JSON} | ||
* An RTTC exemplar. | ||
*/ | ||
module.exports = function coerceExemplar (value, allowSpecialSyntax) { | ||
module.exports = function coerceExemplar (value, allowSpecialSyntax, treatTopLvlUndefinedAsRef) { | ||
// Top-level `undefined` becomes `===` | ||
// Default `treatTopLvlUndefinedAsRef` to `true`. | ||
// (will be changed to false in a future release) | ||
if (_.isUndefined(treatTopLvlUndefinedAsRef)) { treatTopLvlUndefinedAsRef = true; } | ||
// If the provided value is `undefined` at the top level... | ||
if (_.isUndefined(value)) { | ||
return '==='; | ||
// If `treatTopLvlUndefinedAsRef` is enabled, | ||
if (treatTopLvlUndefinedAsRef) { | ||
// then use `===` (note that this approach isn't quite 1-to-1 with reality, | ||
// since `===` doesn't accept `undefined` values as of rttc@9.3.0.) | ||
return '==='; | ||
} | ||
// Otherwise: treat it as if it were `null`, and use `*`. | ||
else { return '*'; } | ||
} | ||
@@ -59,25 +99,29 @@ | ||
else if (_.isArray(valuePart)) { | ||
// empty arrays just become generic arrays | ||
// empty arrays (`[]`) just become generic JSON array exemplars (`[]` aka `['*']`): | ||
if (valuePart.length === 0) { | ||
// Note: | ||
// In a future version of RTTC, this will be modified to | ||
// return `['*']` instead of `[]`. | ||
return valuePart; | ||
} | ||
// NON-empty arrays become pattern arrays | ||
// (any extra items beyond the first are folded together, in order to deduce the best pattern exemplar) | ||
// NON-empty arrays (e.g. `[1,2,3]`) become pattern array exemplars (e.g. `[1]`): | ||
else { | ||
// To do this, we union together all of the items in the array, | ||
// then use the result as our deduced pattern. | ||
// To do this, we recursively call `rttc.coerceExemplar()` on each of the normal | ||
// items in the array, then `rttc.union()` them all together and use the resulting | ||
// exemplar as our deduced pattern. | ||
var pattern = _.reduce(valuePart.slice(1), function (patternSoFar, item) { | ||
patternSoFar = union(patternSoFar, _recursivelyCoerceExemplar(item), true, true); // <= recursive step | ||
// meaning of `union` flags, in order: | ||
patternSoFar = union(patternSoFar, _recursivelyCoerceExemplar(item), true, true); | ||
// meaning of `rttc.union()` flags, in order: | ||
// • `true` (yes these are exemplars) | ||
// • `true` (yes, use strict validation rules to prevent confusion) | ||
return patternSoFar; | ||
}, _recursivelyCoerceExemplar(valuePart[0]) /* <= recursive step */); | ||
}, _recursivelyCoerceExemplar(valuePart[0])); | ||
//-------------------------------------------------------------------------------- | ||
// Note: | ||
// If the narrowest common schema for the pattern is "===" (ref), that means | ||
// the schema for the entire pattern array is `['===']`. If that's the case, | ||
// we can simply think of it as `[]` (generic/heterogeneous array), since there's | ||
// no material guarantee of homogeneity anyways (and since that way you're less | ||
// likely to inadverently deduce any weird conclusions about mutability). | ||
// So for our purposes here: `['===']` is the same as `[]` | ||
// that, as a whole, the exemplar is `['===']`. That makes it effectively | ||
// heterogeneous, as well as indicating that its items are not necessarily | ||
// JSON-compatible, and that they may even be mutable references. | ||
//-------------------------------------------------------------------------------- | ||
return [ | ||
@@ -90,3 +134,5 @@ pattern | ||
else if (_.isObject(valuePart)) { | ||
// Note that empty dictionaries just become generic dictionaries. | ||
// Empty dictionaries (`{}`) just become generic dictionaries (`{}`), | ||
// and NON-EMPTY dictionaries (e.g. `{foo: ['bar','baz'] }`) become | ||
// faceted dictionary exemplars (`{foo:'bar'}`) | ||
return _.reduce(_.keys(valuePart), function (dictSoFar, key) { | ||
@@ -93,0 +139,0 @@ var subValue = valuePart[key]; |
{ | ||
"name": "rttc", | ||
"version": "9.4.0", | ||
"version": "9.5.0", | ||
"description": "Runtime type-checking for JavaScript.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
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
238350
48
5105