@cloudflare/util-en-garde
Advanced tools
Comparing version 7.1.2 to 7.2.0
@@ -6,2 +6,13 @@ # Change Log | ||
# [7.2.0](http://stash.cfops.it:7999/fe/stratus/compare/@cloudflare/util-en-garde@7.1.2...@cloudflare/util-en-garde@7.2.0) (2020-07-17) | ||
### Features | ||
* **util-en-garde:** UI-3626: Add exact codec ([82050f2](http://stash.cfops.it:7999/fe/stratus/commits/82050f2)) | ||
## [7.1.2](http://stash.cfops.it:7999/fe/stratus/compare/@cloudflare/util-en-garde@7.1.0...@cloudflare/util-en-garde@7.1.2) (2020-04-27) | ||
@@ -8,0 +19,0 @@ |
/// <reference types="react" /> | ||
import * as t from 'io-ts'; | ||
import { Compute } from './type-helpers'; | ||
import { Compute, ValueOf } from './type-helpers'; | ||
/** | ||
@@ -145,6 +145,7 @@ * Why does this wrapper exist? | ||
instanceof: <Constructor extends new (...args: any[]) => any>(c: Constructor) => Codec<t.Type<InstanceType<Constructor>, InstanceType<Constructor>, unknown>>; | ||
exactStrict: <P_1 extends t.Props, IT extends t.InterfaceType<P_1, any, any, unknown>>(wrappedInterfaceType: IT) => ObjectCodec<IT["props"]>; | ||
array: <C_3 extends t.Mixed>(codec: C_3, name?: string | undefined) => Codec<t.ArrayC<C_3>>; | ||
union: <CS extends [t.Mixed, t.Mixed, ...t.Mixed[]]>(codecs: CS, name?: string | undefined) => Codec<t.UnionC<CS>>; | ||
record: <D extends t.Mixed, C_4 extends t.Mixed>(domain: D, codomain: C_4, name?: string | undefined) => Codec<t.RecordC<D, C_4>>; | ||
partial: <P_1 extends t.Props>(props: P_1, name?: string | undefined) => Codec<t.PartialC<P_1>>; | ||
partial: <P_2 extends t.Props>(props: P_2, name?: string | undefined) => Codec<t.PartialC<P_2>>; | ||
literal: <V extends string | number | boolean>(value: V, name?: string | undefined) => Codec<t.LiteralC<V>>; | ||
@@ -151,0 +152,0 @@ exact: <C_5 extends t.HasProps>(codec: C_5, name?: string | undefined) => Codec<t.ExactC<C_5>>; |
@@ -5,2 +5,10 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } | ||
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } | ||
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } | ||
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } | ||
@@ -235,3 +243,3 @@ | ||
return new Codec(t.never); | ||
return new Codec(t.undefined); | ||
}, | ||
@@ -247,2 +255,45 @@ instanceof: function _instanceof(c) { | ||
}, | ||
// decorates an InterfaceType like eg.exact, | ||
// but fails validation if keySet of target is not equivalent to codec's | ||
exactStrict: function exactStrict(wrappedInterfaceType) { | ||
var wrappedKeySet = new Set(Object.keys(wrappedInterfaceType.props)); // ensure every key in u exists in the codec | ||
var guard = function guard(u) { | ||
return wrappedInterfaceType.is(u) && Object.keys(u).every(function (key) { | ||
return wrappedKeySet.has(key); | ||
}); | ||
}; | ||
var extraKeys = function extraKeys(obj) { | ||
return Object.keys(obj).filter(function (key) { | ||
return !wrappedKeySet.has(key); | ||
}); | ||
}; | ||
var extraKeyContextEntries = function extraKeyContextEntries(keys, obj) { | ||
return keys.map(function (key) { | ||
return { | ||
key: key, | ||
actual: obj[key], | ||
type: t.undefined | ||
}; | ||
}); | ||
}; | ||
return new ObjectCodec(new t.InterfaceType("exactStrict(".concat(wrappedInterfaceType.name, ")"), guard, function (unknownValue, context) { | ||
var decoded = wrappedInterfaceType.validate(unknownValue, context); | ||
if (decoded._tag === 'Right') { | ||
var ks = extraKeys(decoded.right); | ||
return ks.length === 0 ? t.success(decoded.right) : t.failure(unknownValue, _toConsumableArray(context).concat(_toConsumableArray(extraKeyContextEntries(ks, decoded.right))), 'found extra keys not present in codec'); | ||
} else { | ||
// wrapped codec's validation failed | ||
// include wrapped codec failures, as well as any extra keys | ||
return t.failure(unknownValue, _toConsumableArray(context).concat(_toConsumableArray(decoded.left.reduce( // poor man's flat map | ||
function (acc, err) { | ||
return _toConsumableArray(acc).concat(_toConsumableArray(err.context)); | ||
}, [])), _toConsumableArray(eg.record(eg.string, eg.any).is(unknownValue) ? extraKeyContextEntries(extraKeys(unknownValue), unknownValue) : []))); | ||
} | ||
}, wrappedInterfaceType.encode, wrappedInterfaceType.props)); | ||
}, | ||
// The types for these higher order codecs work with simple hoc wrapper | ||
@@ -313,6 +364,6 @@ array: wrapHigherOrderCodec(t.array), | ||
return new Codec(t.never); | ||
return new Codec(t.undefined); | ||
}, | ||
// io-ts doesn't support creating an empty tuple or an array of type never | ||
// so we're creating a custom codec to reprepsent this. | ||
// so we're creating a custom codec to represent this. | ||
emptyArray: new Codec(new t.Type('[]', isEmptyArray, function (value, context) { | ||
@@ -319,0 +370,0 @@ return isEmptyArray(value) ? t.success(value) : t.failure(value, context); |
@@ -20,2 +20,10 @@ "use strict"; | ||
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } | ||
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } | ||
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } | ||
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } | ||
@@ -181,3 +189,3 @@ | ||
return new Codec(t.never); | ||
return new Codec(t.undefined); | ||
}, | ||
@@ -193,2 +201,45 @@ instanceof: function _instanceof(c) { | ||
}, | ||
// decorates an InterfaceType like eg.exact, | ||
// but fails validation if keySet of target is not equivalent to codec's | ||
exactStrict: function exactStrict(wrappedInterfaceType) { | ||
var wrappedKeySet = new Set(Object.keys(wrappedInterfaceType.props)); // ensure every key in u exists in the codec | ||
var guard = function guard(u) { | ||
return wrappedInterfaceType.is(u) && Object.keys(u).every(function (key) { | ||
return wrappedKeySet.has(key); | ||
}); | ||
}; | ||
var extraKeys = function extraKeys(obj) { | ||
return Object.keys(obj).filter(function (key) { | ||
return !wrappedKeySet.has(key); | ||
}); | ||
}; | ||
var extraKeyContextEntries = function extraKeyContextEntries(keys, obj) { | ||
return keys.map(function (key) { | ||
return { | ||
key: key, | ||
actual: obj[key], | ||
type: t.undefined | ||
}; | ||
}); | ||
}; | ||
return new ObjectCodec(new t.InterfaceType("exactStrict(".concat(wrappedInterfaceType.name, ")"), guard, function (unknownValue, context) { | ||
var decoded = wrappedInterfaceType.validate(unknownValue, context); | ||
if (decoded._tag === 'Right') { | ||
var ks = extraKeys(decoded.right); | ||
return ks.length === 0 ? t.success(decoded.right) : t.failure(unknownValue, _toConsumableArray(context).concat(_toConsumableArray(extraKeyContextEntries(ks, decoded.right))), 'found extra keys not present in codec'); | ||
} else { | ||
// wrapped codec's validation failed | ||
// include wrapped codec failures, as well as any extra keys | ||
return t.failure(unknownValue, _toConsumableArray(context).concat(_toConsumableArray(decoded.left.reduce( // poor man's flat map | ||
function (acc, err) { | ||
return _toConsumableArray(acc).concat(_toConsumableArray(err.context)); | ||
}, [])), _toConsumableArray(eg.record(eg.string, eg.any).is(unknownValue) ? extraKeyContextEntries(extraKeys(unknownValue), unknownValue) : []))); | ||
} | ||
}, wrappedInterfaceType.encode, wrappedInterfaceType.props)); | ||
}, | ||
// The types for these higher order codecs work with simple hoc wrapper | ||
@@ -259,6 +310,6 @@ array: wrapHigherOrderCodec(t.array), | ||
return new Codec(t.never); | ||
return new Codec(t.undefined); | ||
}, | ||
// io-ts doesn't support creating an empty tuple or an array of type never | ||
// so we're creating a custom codec to reprepsent this. | ||
// so we're creating a custom codec to represent this. | ||
emptyArray: new Codec(new t.Type('[]', isEmptyArray, function (value, context) { | ||
@@ -265,0 +316,0 @@ return isEmptyArray(value) ? t.success(value) : t.failure(value, context); |
{ | ||
"name": "@cloudflare/util-en-garde", | ||
"description": "", | ||
"version": "7.1.2", | ||
"version": "7.2.0", | ||
"types": "./dist/index.d.ts", | ||
@@ -29,3 +29,3 @@ "main": "lib/index.js", | ||
}, | ||
"gitHead": "3a5a556f3392b3c8b6e35a7857a39f05ac1bb7eb" | ||
"gitHead": "d8e7e783275d80f783cc84e2c4db2b49714c4896" | ||
} |
@@ -214,3 +214,3 @@ import * as t from 'io-ts'; | ||
return new Codec(t.never as any) as any; | ||
return new Codec(t.undefined as any) as any; | ||
}, | ||
@@ -231,2 +231,68 @@ instanceof: <Constructor extends new (...args: any[]) => any>( | ||
}, | ||
// decorates an InterfaceType like eg.exact, | ||
// but fails validation if keySet of target is not equivalent to codec's | ||
exactStrict: <P extends t.Props, IT extends t.InterfaceType<P>>( | ||
wrappedInterfaceType: IT | ||
) => { | ||
const wrappedKeySet = new Set(Object.keys(wrappedInterfaceType.props)); | ||
// ensure every key in u exists in the codec | ||
const guard = (u: unknown): u is TypeFromCodec<IT> => | ||
wrappedInterfaceType.is(u) && | ||
Object.keys(u).every(key => wrappedKeySet.has(key)); | ||
const extraKeys = (obj: t.TypeOf<IT>) => | ||
Object.keys(obj).filter(key => !wrappedKeySet.has(key)); | ||
const extraKeyContextEntries = ( | ||
keys: string[], | ||
obj: t.TypeOf<IT> | ||
): t.ContextEntry[] => | ||
keys.map(key => ({ | ||
key, | ||
actual: obj[key], | ||
type: t.undefined | ||
})); | ||
return new ObjectCodec( | ||
new t.InterfaceType< | ||
IT['props'], | ||
t.TypeOf<IT>, | ||
t.OutputOf<IT>, | ||
t.InputOf<IT> | ||
>( | ||
`exactStrict(${wrappedInterfaceType.name})`, | ||
guard, | ||
(unknownValue, context) => { | ||
const decoded = wrappedInterfaceType.validate(unknownValue, context); | ||
if (decoded._tag === 'Right') { | ||
const ks = extraKeys(decoded.right); | ||
return ks.length === 0 | ||
? t.success(decoded.right) | ||
: t.failure( | ||
unknownValue, | ||
[...context, ...extraKeyContextEntries(ks, decoded.right)], | ||
'found extra keys not present in codec' | ||
); | ||
} else { | ||
// wrapped codec's validation failed | ||
// include wrapped codec failures, as well as any extra keys | ||
return t.failure(unknownValue, [ | ||
...context, | ||
...decoded.left.reduce<t.ContextEntry[]>( // poor man's flat map | ||
(acc, err) => [...acc, ...err.context], | ||
[] | ||
), | ||
...(eg.record(eg.string, eg.any).is(unknownValue) | ||
? extraKeyContextEntries(extraKeys(unknownValue), unknownValue) | ||
: []) | ||
]); | ||
} | ||
}, | ||
wrappedInterfaceType.encode, | ||
wrappedInterfaceType.props | ||
) | ||
); | ||
}, | ||
// The types for these higher order codecs work with simple hoc wrapper | ||
@@ -308,7 +374,7 @@ array: wrapHigherOrderCodec(t.array), | ||
return new Codec(t.never as any) as any; | ||
return new Codec(t.undefined as any) as any; | ||
}, | ||
// io-ts doesn't support creating an empty tuple or an array of type never | ||
// so we're creating a custom codec to reprepsent this. | ||
// so we're creating a custom codec to represent this. | ||
emptyArray: new Codec( | ||
@@ -315,0 +381,0 @@ new t.Type<[], []>( |
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
79690
1234