Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@cloudflare/util-en-garde

Package Overview
Dependencies
Maintainers
29
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cloudflare/util-en-garde - npm Package Compare versions

Comparing version 4.0.2 to 6.0.0

30

CHANGELOG.md

@@ -6,10 +6,36 @@ # Change Log

## [4.0.2](http://stash.cfops.it:7999/fe/stratus/compare/@cloudflare/util-en-garde@4.0.1...@cloudflare/util-en-garde@4.0.2) (2019-11-14)
# [6.0.0](http://stash.cfops.it:7999/fe/stratus/compare/@cloudflare/util-en-garde@4.0.1...@cloudflare/util-en-garde@6.0.0) (2019-11-20)
**Note:** Version bump only for package @cloudflare/util-en-garde
### Features
* **util-en-garde:** TSX-153 Make en-garde wrap io-ts ([95bb19e](http://stash.cfops.it:7999/fe/stratus/commits/95bb19e))
### BREAKING CHANGES
* **util-en-garde:** Rather than en-garde simply being composable type guards, we are wrapping io-ts to
provide similar functionality with a nicer API.
# [5.0.0](http://stash.cfops.it:7999/fe/stratus/compare/@cloudflare/util-en-garde@4.0.1...@cloudflare/util-en-garde@5.0.0) (2019-11-19)
### Features
* **util-en-garde:** TSX-153 Make en-garde wrap io-ts ([95bb19e](http://stash.cfops.it:7999/fe/stratus/commits/95bb19e))
### BREAKING CHANGES
* **util-en-garde:** Rather than en-garde simply being composable type guards, we are wrapping io-ts to
provide similar functionality with a nicer API.
## [4.0.1](http://stash.cfops.it:7999/fe/stratus/compare/@cloudflare/util-en-garde@4.0.0...@cloudflare/util-en-garde@4.0.1) (2019-11-13)

@@ -16,0 +42,0 @@

216

dist/index.d.ts

@@ -1,112 +0,108 @@

import { primitiveGuards, higherOrderGuards } from './core';
import { TypeGuard, TypeFromGuard, TypeGuardWithOptional } from './type-helpers';
import { addOptionalToGuard, addOptionalToHigherOrderGuard } from './optional';
declare class TypeGuardError extends Error {
valueThatFailed: unknown;
constructor(message: string, valueThatFailed: unknown);
import * as t from 'io-ts';
/**
* Why does this wrapper exist?
*
* `io-ts` is awesome and super powerful, but the API leaves some things to be
* desired. It was designed to be used with `fp-ts` which is a library for
* functional programming patterns in TypeScipt. The resulting type on the
* "decode" method is an Either which is great to work with when using `fp-ts`,
* but is otherwise cumbersome.
*
* By introducing an `assert` method, we can guarantee the function will always
* return the decoded type by throwing an error if it fails to decode. With
* promises we can easily chain an assertion and the promise will reject if
* the data fails to decode.
*
* Additionally, this wrapper provides an `optional` property which unions
* the codec with the `undefined` codec. This provides an API that is both
* easier to use and more readable for a very common scenario.
*
* Next is the new `object` type which seeks to replace `t.type` in io-ts and
* which is less immediately obvious. When deriving type information from
* `t.type` with `t.TypeOf`, keys whose values are unioned with undefined
* are still required. The suggested strategy in `io-ts` is to define optional
* keys separately and intersect them with required keys. The `object` type
* addresses this by returning a type that automatically enables optional
* keys where values are unioned with undefined. This combined with the
* `optional` property makes for a much nicer API when defining object shapes.
*/
declare type KeysWithValueType<O, T> = {
[Key in keyof O]: Key;
}[Exclude<keyof O, KeysWithoutValueType<O, T>>];
declare type KeysWithoutValueType<O, T> = {
[Key in keyof O]: T extends O[Key] ? never : Key;
}[keyof O];
declare type RepackKeys<T> = {
[Key in keyof T]: T[Key];
} & {};
declare type EnableOptionalKeys<T> = RepackKeys<{
[MandatoryKey in KeysWithoutValueType<T, undefined>]: T[MandatoryKey];
} & {
[OptionalKey in KeysWithValueType<T, undefined>]?: T[OptionalKey];
}>;
export declare class EnGardeAssertionError extends Error {
errors: t.Errors;
constructor(errors: t.Errors);
}
declare const assertShape: <Guard extends TypeGuard<any>>(guard: Guard) => (obj: unknown) => TypeFromGuard<Guard>;
declare const eg: {
string: TypeGuardWithOptional<string>;
number: TypeGuardWithOptional<number>;
boolean: TypeGuardWithOptional<boolean>;
null: TypeGuardWithOptional<null>;
/**
* Accepts a guard and returns a guard that checks that the value is an
* array and that each element in the array matches the given guard.
*/
arrayOf: <T>(typeGuard: TypeGuard<T>) => TypeGuardWithOptional<T[]>;
/**
* Accepts any number of guards and returns a type guard that will only
* match if the given value is a tuple where each value matches the guard
* in that same position.
*
* @example
* const isStringStringNumber = eg.tuple(
* eg.string,
* eg.string,
* eg.number,
* )
*
* if (isStringStringNumber(["hi", "there", 4])) {
* // ...
* }
*/
tuple: <TypeGuards extends TypeGuard<any>[]>(...params: TypeGuards) => TypeGuardWithOptional<{
return: [];
recurse: {
return: [TypeFromGuard<import("@cloudflare/types/src").Head<TypeGuards>>];
recurse: {
return: [TypeFromGuard<import("@cloudflare/types/src").Head<import("@cloudflare/types/src").Tail<TypeGuards>>>];
recurse: {
return: [TypeFromGuard<import("@cloudflare/types/src").Head<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>];
recurse: {
return: [TypeFromGuard<import("@cloudflare/types/src").Head<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>];
recurse: {
return: [TypeFromGuard<import("@cloudflare/types/src").Head<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>>];
recurse: {
return: [TypeFromGuard<import("@cloudflare/types/src").Head<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>>>];
recurse: {
return: [TypeFromGuard<import("@cloudflare/types/src").Head<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>>>>];
recurse: {
return: [TypeFromGuard<import("@cloudflare/types/src").Head<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>>>>>];
recurse: {
return: [TypeFromGuard<import("@cloudflare/types/src").Head<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>>>>>>];
recurse: {
return: [TypeFromGuard<import("@cloudflare/types/src").Head<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>>>>>>>];
recurse: any[import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>>>>>>> extends [] ? "return" : "recurse"];
}[import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>>>>>> extends [] ? "return" : "recurse"];
}[import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>>>>> extends [] ? "return" : "recurse"];
}[import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>>>> extends [] ? "return" : "recurse"];
}[import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>>> extends [] ? "return" : "recurse"];
}[import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>>> extends [] ? "return" : "recurse"];
}[import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>>> extends [] ? "return" : "recurse"];
}[import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>>> extends [] ? "return" : "recurse"];
}[import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>>> extends [] ? "return" : "recurse"];
}[import("@cloudflare/types/src").Tail<import("@cloudflare/types/src").Tail<TypeGuards>> extends [] ? "return" : "recurse"];
}[import("@cloudflare/types/src").Tail<TypeGuards> extends [] ? "return" : "recurse"];
}[TypeGuards extends [] ? "return" : "recurse"]>;
/**
* Accepts an object definition where each key must be a guard. Returns
* a guard that checks that a given value is an object and that each key's
* value passes the definition's guard. Fails if any keys exist on the given
* value that do not exist on the object definition.
*/
exact: <Definition extends import("./type-helpers").ObjectGuardDefinition>(definition: Definition) => TypeGuardWithOptional<{ [Key_3 in keyof ({ [MandatoryKey in { [Key_1 in keyof { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }]: undefined extends { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }[Key_1] ? never : Key_1; }[keyof Definition]]: { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }[MandatoryKey]; } & { [OptionalKey in { [Key_2 in keyof { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }]: Key_2; }[Exclude<keyof Definition, { [Key_1 in keyof { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }]: undefined extends { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }[Key_1] ? never : Key_1; }[keyof Definition]>]]?: { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }[OptionalKey] | undefined; })]: ({ [MandatoryKey in { [Key_1 in keyof { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }]: undefined extends { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }[Key_1] ? never : Key_1; }[keyof Definition]]: { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }[MandatoryKey]; } & { [OptionalKey in { [Key_2 in keyof { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }]: Key_2; }[Exclude<keyof Definition, { [Key_1 in keyof { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }]: undefined extends { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }[Key_1] ? never : Key_1; }[keyof Definition]>]]?: { [Key in keyof Definition]: TypeFromGuard<Definition[Key]>; }[OptionalKey] | undefined; })[Key_3]; }>;
/**
* Accepts a constructor and returns a guard that checks whether a value is
* an instance of that constructor using `instanceof`
*/
instanceOf: <Constructor extends new (...args: any[]) => any>(ctor: Constructor) => TypeGuardWithOptional<InstanceType<Constructor>>;
/**
* Accepts an object definition where each key must be a guard. Returns
* a guard that checks that a given value is an object and that each key's
* value passes the definition's guard
*/
object: <Definition_1 extends import("./type-helpers").ObjectGuardDefinition>(definition: Definition_1) => TypeGuardWithOptional<{ [Key_7 in keyof ({ [MandatoryKey_1 in { [Key_5 in keyof { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }]: undefined extends { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }[Key_5] ? never : Key_5; }[keyof Definition_1]]: { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }[MandatoryKey_1]; } & { [OptionalKey_1 in { [Key_6 in keyof { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }]: Key_6; }[Exclude<keyof Definition_1, { [Key_5 in keyof { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }]: undefined extends { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }[Key_5] ? never : Key_5; }[keyof Definition_1]>]]?: { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }[OptionalKey_1] | undefined; })]: ({ [MandatoryKey_1 in { [Key_5 in keyof { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }]: undefined extends { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }[Key_5] ? never : Key_5; }[keyof Definition_1]]: { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }[MandatoryKey_1]; } & { [OptionalKey_1 in { [Key_6 in keyof { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }]: Key_6; }[Exclude<keyof Definition_1, { [Key_5 in keyof { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }]: undefined extends { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }[Key_5] ? never : Key_5; }[keyof Definition_1]>]]?: { [Key_4 in keyof Definition_1]: TypeFromGuard<Definition_1[Key_4]>; }[OptionalKey_1] | undefined; })[Key_7]; }>;
/**
* Accepts a type guard and returns an index signature where values must
* pass the type guard.
*/
objectWithValuesOf: <T_1, Keys extends string | number | symbol>(typeGuard: TypeGuard<T_1>) => TypeGuardWithOptional<Record<Keys, T_1>>;
/**
* Accepts any number of guards as arguments. Returns a guard that checks if
* a given value passes any of the input guards.
*/
oneOf: <TypeGuards_1 extends TypeGuard<any>[]>(...params: TypeGuards_1) => TypeGuardWithOptional<TypeFromGuard<import("./type-helpers").TypeOfArray<TypeGuards_1>>>;
/**
* Accepts any number of guards as arguments. Returns a guard that checks if
* a given value passes all of the input guards.
*/
all: <TypeGuards_2 extends TypeGuard<any>[]>(...params: TypeGuards_2) => TypeGuardWithOptional<import("@cloudflare/types/src").UnionToIntersection<TypeFromGuard<import("./type-helpers").TypeOfArray<TypeGuards_2>>>>;
/**
* Accepts primitives and infers their types. Returns a guard that checks
* whether a value matches any of the literal values.
*/
oneOfLiterals: <Args extends (string | number | boolean | null | undefined)[]>(...params: Args) => TypeGuardWithOptional<import("./type-helpers").TypeOfArray<Args>>;
any: (_: unknown) => _ is any;
unknown: (_: unknown) => _ is unknown;
undefined: (obj: unknown) => obj is undefined;
declare type IoTsCodec = t.Any;
export declare class Codec<Codec extends IoTsCodec> {
ioTsCodec: Codec;
constructor(ioTsCodec: Codec);
name: string;
is: Codec['is'];
encode: Codec['encode'];
decode: Codec['decode'];
validate: Codec['validate'];
pipe: Codec['pipe'];
_A: Codec['_A'];
_O: Codec['_O'];
_I: Codec['_I'];
asDecoder: Codec['asDecoder'];
asEncoder: Codec['asEncoder'];
assertDecode: (value: unknown) => Codec["_A"];
get optional(): import(".").Codec<t.UnionC<[Codec, t.UndefinedC]>>;
}
declare type InterfaceTypeWithOptionalKeys<P extends t.Props> = t.InterfaceType<P, EnableOptionalKeys<{
[K in keyof P]: t.TypeOf<P[K]>;
}>, EnableOptionalKeys<{
[K in keyof P]: t.OutputOf<P[K]>;
}>, unknown>;
export declare class ObjectCodec<P extends t.Props, CodecWithOptionalKeys extends t.InterfaceType<any, any, any, any> = InterfaceTypeWithOptionalKeys<P>> {
ioTsCodec: t.TypeC<P>;
constructor(ioTsCodec: t.TypeC<P>);
name: string;
is: CodecWithOptionalKeys['is'];
encode: CodecWithOptionalKeys['encode'];
decode: CodecWithOptionalKeys['decode'];
validate: CodecWithOptionalKeys['validate'];
pipe: CodecWithOptionalKeys['pipe'];
_A: CodecWithOptionalKeys['_A'];
_O: CodecWithOptionalKeys['_O'];
_I: CodecWithOptionalKeys['_I'];
asDecoder: CodecWithOptionalKeys['asDecoder'];
asEncoder: CodecWithOptionalKeys['asEncoder'];
assertDecode: (value: unknown) => CodecWithOptionalKeys["_A"];
get optional(): Codec<t.UnionC<[t.TypeC<P>, t.UndefinedC]>>;
readonly _tag: 'InterfaceType';
props: CodecWithOptionalKeys['props'];
}
export declare type TypeFromCodec<T extends IoTsCodec> = t.TypeOf<T>;
export declare const eg: {
object: <P extends t.Props>(p: P, name?: string | undefined) => ObjectCodec<P, InterfaceTypeWithOptionalKeys<P>>;
tuple: <Codecs extends never[] | [t.Any, ...t.Any[]]>(codecs: Codecs, name?: string | undefined) => Codec<t.TupleC<Exclude<Codecs, never[]>>>;
intersection: <Codecs_1 extends [t.Any, t.Any, ...t.Any[]]>(codecs: Codecs_1, name?: string | undefined) => Codec<t.IntersectionC<Codecs_1>>;
array: <C extends t.Mixed>(codec: C, name?: string | undefined) => Codec<t.ArrayC<C>>;
union: <CS extends [t.Mixed, t.Mixed, ...t.Mixed[]]>(codecs: CS, name?: string | undefined) => Codec<t.UnionC<CS>>;
record: <D extends t.Mixed, C_1 extends t.Mixed>(domain: D, codomain: C_1, name?: string | undefined) => Codec<t.RecordC<D, C_1>>;
partial: <P_1 extends t.Props>(props: P_1, name?: string | undefined) => Codec<t.PartialC<P_1>>;
literal: <V extends string | number | boolean>(value: V, name?: string | undefined) => Codec<t.LiteralC<V>>;
exact: <C_2 extends t.HasProps>(codec: C_2, name?: string | undefined) => Codec<t.ExactC<C_2>>;
string: Codec<t.StringC>;
number: Codec<t.NumberC>;
boolean: Codec<t.BooleanC>;
null: Codec<t.NullC>;
undefined: Codec<t.UndefinedC>;
any: Codec<t.AnyC>;
unknown: Codec<t.UnknownC>;
};
export default eg;
export { TypeGuard, TypeFromGuard, TypeGuardWithOptional, primitiveGuards, higherOrderGuards, TypeGuardError, assertShape, addOptionalToGuard, addOptionalToHigherOrderGuard };
export { t };
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 _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
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); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -7,6 +15,6 @@

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }

@@ -24,107 +32,182 @@

import { primitiveGuards, higherOrderGuards } from './core';
import { TypeGuard, TypeFromGuard, TypeGuardWithOptional } from './type-helpers';
import { addOptionalToGuard, addOptionalToHigherOrderGuard } from './optional';
import * as t from 'io-ts';
/**
* Why does this wrapper exist?
*
* `io-ts` is awesome and super powerful, but the API leaves some things to be
* desired. It was designed to be used with `fp-ts` which is a library for
* functional programming patterns in TypeScipt. The resulting type on the
* "decode" method is an Either which is great to work with when using `fp-ts`,
* but is otherwise cumbersome.
*
* By introducing an `assert` method, we can guarantee the function will always
* return the decoded type by throwing an error if it fails to decode. With
* promises we can easily chain an assertion and the promise will reject if
* the data fails to decode.
*
* Additionally, this wrapper provides an `optional` property which unions
* the codec with the `undefined` codec. This provides an API that is both
* easier to use and more readable for a very common scenario.
*
* Next is the new `object` type which seeks to replace `t.type` in io-ts and
* which is less immediately obvious. When deriving type information from
* `t.type` with `t.TypeOf`, keys whose values are unioned with undefined
* are still required. The suggested strategy in `io-ts` is to define optional
* keys separately and intersect them with required keys. The `object` type
* addresses this by returning a type that automatically enables optional
* keys where values are unioned with undefined. This combined with the
* `optional` property makes for a much nicer API when defining object shapes.
*/
var TypeGuardError =
export var EnGardeAssertionError =
/*#__PURE__*/
function (_Error) {
_inherits(TypeGuardError, _Error);
_inherits(EnGardeAssertionError, _Error);
function TypeGuardError(message, valueThatFailed) {
_classCallCheck(this, TypeGuardError);
function EnGardeAssertionError(errors) {
var _this;
return _possibleConstructorReturn(this, _getPrototypeOf(TypeGuardError).call(this, message));
_classCallCheck(this, EnGardeAssertionError);
_this = _possibleConstructorReturn(this, _getPrototypeOf(EnGardeAssertionError).call(this));
Object.setPrototypeOf(_assertThisInitialized(_assertThisInitialized(_this)), EnGardeAssertionError.prototype);
return _this;
}
return TypeGuardError;
return EnGardeAssertionError;
}(_wrapNativeSuper(Error));
export var Codec =
/*#__PURE__*/
function () {
function Codec(ioTsCodec) {
var _this2 = this;
var assertShape = function assertShape(guard) {
return function (obj) {
if (guard(obj)) return obj;
throw new TypeGuardError('Failed type guard', obj);
};
};
_classCallCheck(this, Codec);
var eg = {
string: addOptionalToGuard(primitiveGuards.string),
number: addOptionalToGuard(primitiveGuards.number),
boolean: addOptionalToGuard(primitiveGuards.boolean),
null: addOptionalToGuard(primitiveGuards.null),
_defineProperty(this, "name", this.ioTsCodec.name);
/**
* Accepts a guard and returns a guard that checks that the value is an
* array and that each element in the array matches the given guard.
*/
arrayOf: addOptionalToHigherOrderGuard(higherOrderGuards.arrayOf),
_defineProperty(this, "is", this.ioTsCodec.is);
/**
* Accepts any number of guards and returns a type guard that will only
* match if the given value is a tuple where each value matches the guard
* in that same position.
*
* @example
* const isStringStringNumber = eg.tuple(
* eg.string,
* eg.string,
* eg.number,
* )
*
* if (isStringStringNumber(["hi", "there", 4])) {
* // ...
* }
*/
tuple: addOptionalToHigherOrderGuard(higherOrderGuards.tuple),
_defineProperty(this, "encode", this.ioTsCodec.encode);
/**
* Accepts an object definition where each key must be a guard. Returns
* a guard that checks that a given value is an object and that each key's
* value passes the definition's guard. Fails if any keys exist on the given
* value that do not exist on the object definition.
*/
exact: addOptionalToHigherOrderGuard(higherOrderGuards.exact),
_defineProperty(this, "decode", this.ioTsCodec.decode);
/**
* Accepts a constructor and returns a guard that checks whether a value is
* an instance of that constructor using `instanceof`
*/
instanceOf: addOptionalToHigherOrderGuard(higherOrderGuards.instanceOf),
_defineProperty(this, "validate", this.ioTsCodec.validate);
/**
* Accepts an object definition where each key must be a guard. Returns
* a guard that checks that a given value is an object and that each key's
* value passes the definition's guard
*/
object: addOptionalToHigherOrderGuard(higherOrderGuards.object),
_defineProperty(this, "pipe", this.ioTsCodec.pipe);
/**
* Accepts a type guard and returns an index signature where values must
* pass the type guard.
*/
objectWithValuesOf: addOptionalToHigherOrderGuard(higherOrderGuards.objectWithValuesOf),
_defineProperty(this, "_A", this.ioTsCodec._A);
/**
* Accepts any number of guards as arguments. Returns a guard that checks if
* a given value passes any of the input guards.
*/
oneOf: addOptionalToHigherOrderGuard(higherOrderGuards.oneOf),
_defineProperty(this, "_O", this.ioTsCodec._O);
/**
* Accepts any number of guards as arguments. Returns a guard that checks if
* a given value passes all of the input guards.
*/
all: addOptionalToHigherOrderGuard(higherOrderGuards.all),
_defineProperty(this, "_I", this.ioTsCodec._I);
/**
* Accepts primitives and infers their types. Returns a guard that checks
* whether a value matches any of the literal values.
*/
oneOfLiterals: addOptionalToHigherOrderGuard(higherOrderGuards.oneOfLiterals),
// These guards do not require optional decoration
any: primitiveGuards.any,
unknown: primitiveGuards.unknown,
undefined: primitiveGuards.undefined
_defineProperty(this, "asDecoder", this.ioTsCodec.asDecoder);
_defineProperty(this, "asEncoder", this.ioTsCodec.asEncoder);
_defineProperty(this, "assertDecode", function (value) {
var result = _this2.ioTsCodec.decode(value);
if (result._tag === 'Left') throw new EnGardeAssertionError(result.left);
return result.right;
});
}
_createClass(Codec, [{
key: "optional",
get: function get() {
return new Codec(t.union([this.ioTsCodec, t.undefined]));
}
}]);
return Codec;
}();
export var ObjectCodec =
/*#__PURE__*/
function () {
function ObjectCodec(ioTsCodec) {
var _this3 = this;
_classCallCheck(this, ObjectCodec);
_defineProperty(this, "name", this.ioTsCodec.name);
_defineProperty(this, "is", this.ioTsCodec.is);
_defineProperty(this, "encode", this.ioTsCodec.encode);
_defineProperty(this, "decode", this.ioTsCodec.decode);
_defineProperty(this, "validate", this.ioTsCodec.validate);
_defineProperty(this, "pipe", this.ioTsCodec.pipe);
_defineProperty(this, "_A", this.ioTsCodec._A);
_defineProperty(this, "_O", this.ioTsCodec._O);
_defineProperty(this, "_I", this.ioTsCodec._I);
_defineProperty(this, "asDecoder", this.ioTsCodec.asDecoder);
_defineProperty(this, "asEncoder", this.ioTsCodec.asEncoder);
_defineProperty(this, "assertDecode", function (value) {
var result = _this3.ioTsCodec.decode(value);
if (result._tag === 'Left') throw new EnGardeAssertionError(result.left);
return result.right;
});
_defineProperty(this, "_tag", 'InterfaceType');
_defineProperty(this, "props", this.ioTsCodec.props);
}
_createClass(ObjectCodec, [{
key: "optional",
get: function get() {
return new Codec(t.union([this.ioTsCodec, t.undefined]));
}
}]);
return ObjectCodec;
}();
var primitiveCodecs = {
string: new Codec(t.string),
number: new Codec(t.number),
boolean: new Codec(t.boolean),
null: new Codec(t.null),
undefined: new Codec(t.undefined),
any: new Codec(t.any),
unknown: new Codec(t.unknown)
};
export default eg;
export { TypeGuard, TypeFromGuard, TypeGuardWithOptional, primitiveGuards, higherOrderGuards, TypeGuardError, assertShape, addOptionalToGuard, addOptionalToHigherOrderGuard };
var wrapHigherOrderCodec = function wrapHigherOrderCodec(higherOrderCodec) {
return function () {
return new Codec(higherOrderCodec.apply(void 0, arguments));
};
};
var higherOrderCodecs = {
// Using a special type for object which enables optional keys
object: function object(p, name) {
return new ObjectCodec(t.type(p, name));
},
tuple: function tuple(codecs, name) {
return new Codec(t.tuple(codecs, name));
},
intersection: function intersection(codecs, name) {
return new Codec(t.intersection(codecs, name));
},
// The types for these higher order codecs work with simple hoc wrapper
array: wrapHigherOrderCodec(t.array),
union: wrapHigherOrderCodec(t.union),
record: wrapHigherOrderCodec(t.record),
partial: wrapHigherOrderCodec(t.partial),
literal: wrapHigherOrderCodec(t.literal),
exact: wrapHigherOrderCodec(t.exact)
};
export var eg = _objectSpread({}, primitiveCodecs, higherOrderCodecs);
export { t };

@@ -6,54 +6,20 @@ "use strict";

});
Object.defineProperty(exports, "primitiveGuards", {
enumerable: true,
get: function get() {
return _core.primitiveGuards;
}
});
Object.defineProperty(exports, "higherOrderGuards", {
enumerable: true,
get: function get() {
return _core.higherOrderGuards;
}
});
Object.defineProperty(exports, "TypeGuard", {
enumerable: true,
get: function get() {
return _typeHelpers.TypeGuard;
}
});
Object.defineProperty(exports, "TypeFromGuard", {
enumerable: true,
get: function get() {
return _typeHelpers.TypeFromGuard;
}
});
Object.defineProperty(exports, "TypeGuardWithOptional", {
enumerable: true,
get: function get() {
return _typeHelpers.TypeGuardWithOptional;
}
});
Object.defineProperty(exports, "addOptionalToGuard", {
enumerable: true,
get: function get() {
return _optional.addOptionalToGuard;
}
});
Object.defineProperty(exports, "addOptionalToHigherOrderGuard", {
enumerable: true,
get: function get() {
return _optional.addOptionalToHigherOrderGuard;
}
});
exports.assertShape = exports.TypeGuardError = exports.default = void 0;
exports.t = exports.eg = exports.ObjectCodec = exports.Codec = exports.EnGardeAssertionError = void 0;
var _core = require("./core");
var t = _interopRequireWildcard(require("io-ts"));
var _typeHelpers = require("./type-helpers");
exports.t = t;
var _optional = require("./optional");
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
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 _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
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); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -63,6 +29,6 @@

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }

@@ -80,106 +46,163 @@

var TypeGuardError =
var EnGardeAssertionError =
/*#__PURE__*/
function (_Error) {
_inherits(TypeGuardError, _Error);
_inherits(EnGardeAssertionError, _Error);
function TypeGuardError(message, valueThatFailed) {
_classCallCheck(this, TypeGuardError);
function EnGardeAssertionError(errors) {
var _this;
return _possibleConstructorReturn(this, _getPrototypeOf(TypeGuardError).call(this, message));
_classCallCheck(this, EnGardeAssertionError);
_this = _possibleConstructorReturn(this, _getPrototypeOf(EnGardeAssertionError).call(this));
Object.setPrototypeOf(_assertThisInitialized(_assertThisInitialized(_this)), EnGardeAssertionError.prototype);
return _this;
}
return TypeGuardError;
return EnGardeAssertionError;
}(_wrapNativeSuper(Error));
exports.TypeGuardError = TypeGuardError;
exports.EnGardeAssertionError = EnGardeAssertionError;
var assertShape = function assertShape(guard) {
return function (obj) {
if (guard(obj)) return obj;
throw new TypeGuardError('Failed type guard', obj);
};
};
var Codec =
/*#__PURE__*/
function () {
function Codec(ioTsCodec) {
var _this2 = this;
exports.assertShape = assertShape;
var eg = {
string: (0, _optional.addOptionalToGuard)(_core.primitiveGuards.string),
number: (0, _optional.addOptionalToGuard)(_core.primitiveGuards.number),
boolean: (0, _optional.addOptionalToGuard)(_core.primitiveGuards.boolean),
null: (0, _optional.addOptionalToGuard)(_core.primitiveGuards.null),
_classCallCheck(this, Codec);
/**
* Accepts a guard and returns a guard that checks that the value is an
* array and that each element in the array matches the given guard.
*/
arrayOf: (0, _optional.addOptionalToHigherOrderGuard)(_core.higherOrderGuards.arrayOf),
_defineProperty(this, "name", this.ioTsCodec.name);
/**
* Accepts any number of guards and returns a type guard that will only
* match if the given value is a tuple where each value matches the guard
* in that same position.
*
* @example
* const isStringStringNumber = eg.tuple(
* eg.string,
* eg.string,
* eg.number,
* )
*
* if (isStringStringNumber(["hi", "there", 4])) {
* // ...
* }
*/
tuple: (0, _optional.addOptionalToHigherOrderGuard)(_core.higherOrderGuards.tuple),
_defineProperty(this, "is", this.ioTsCodec.is);
/**
* Accepts an object definition where each key must be a guard. Returns
* a guard that checks that a given value is an object and that each key's
* value passes the definition's guard. Fails if any keys exist on the given
* value that do not exist on the object definition.
*/
exact: (0, _optional.addOptionalToHigherOrderGuard)(_core.higherOrderGuards.exact),
_defineProperty(this, "encode", this.ioTsCodec.encode);
/**
* Accepts a constructor and returns a guard that checks whether a value is
* an instance of that constructor using `instanceof`
*/
instanceOf: (0, _optional.addOptionalToHigherOrderGuard)(_core.higherOrderGuards.instanceOf),
_defineProperty(this, "decode", this.ioTsCodec.decode);
/**
* Accepts an object definition where each key must be a guard. Returns
* a guard that checks that a given value is an object and that each key's
* value passes the definition's guard
*/
object: (0, _optional.addOptionalToHigherOrderGuard)(_core.higherOrderGuards.object),
_defineProperty(this, "validate", this.ioTsCodec.validate);
/**
* Accepts a type guard and returns an index signature where values must
* pass the type guard.
*/
objectWithValuesOf: (0, _optional.addOptionalToHigherOrderGuard)(_core.higherOrderGuards.objectWithValuesOf),
_defineProperty(this, "pipe", this.ioTsCodec.pipe);
/**
* Accepts any number of guards as arguments. Returns a guard that checks if
* a given value passes any of the input guards.
*/
oneOf: (0, _optional.addOptionalToHigherOrderGuard)(_core.higherOrderGuards.oneOf),
_defineProperty(this, "_A", this.ioTsCodec._A);
/**
* Accepts any number of guards as arguments. Returns a guard that checks if
* a given value passes all of the input guards.
*/
all: (0, _optional.addOptionalToHigherOrderGuard)(_core.higherOrderGuards.all),
_defineProperty(this, "_O", this.ioTsCodec._O);
/**
* Accepts primitives and infers their types. Returns a guard that checks
* whether a value matches any of the literal values.
*/
oneOfLiterals: (0, _optional.addOptionalToHigherOrderGuard)(_core.higherOrderGuards.oneOfLiterals),
// These guards do not require optional decoration
any: _core.primitiveGuards.any,
unknown: _core.primitiveGuards.unknown,
undefined: _core.primitiveGuards.undefined
_defineProperty(this, "_I", this.ioTsCodec._I);
_defineProperty(this, "asDecoder", this.ioTsCodec.asDecoder);
_defineProperty(this, "asEncoder", this.ioTsCodec.asEncoder);
_defineProperty(this, "assertDecode", function (value) {
var result = _this2.ioTsCodec.decode(value);
if (result._tag === 'Left') throw new EnGardeAssertionError(result.left);
return result.right;
});
}
_createClass(Codec, [{
key: "optional",
get: function get() {
return new Codec(t.union([this.ioTsCodec, t.undefined]));
}
}]);
return Codec;
}();
exports.Codec = Codec;
var ObjectCodec =
/*#__PURE__*/
function () {
function ObjectCodec(ioTsCodec) {
var _this3 = this;
_classCallCheck(this, ObjectCodec);
_defineProperty(this, "name", this.ioTsCodec.name);
_defineProperty(this, "is", this.ioTsCodec.is);
_defineProperty(this, "encode", this.ioTsCodec.encode);
_defineProperty(this, "decode", this.ioTsCodec.decode);
_defineProperty(this, "validate", this.ioTsCodec.validate);
_defineProperty(this, "pipe", this.ioTsCodec.pipe);
_defineProperty(this, "_A", this.ioTsCodec._A);
_defineProperty(this, "_O", this.ioTsCodec._O);
_defineProperty(this, "_I", this.ioTsCodec._I);
_defineProperty(this, "asDecoder", this.ioTsCodec.asDecoder);
_defineProperty(this, "asEncoder", this.ioTsCodec.asEncoder);
_defineProperty(this, "assertDecode", function (value) {
var result = _this3.ioTsCodec.decode(value);
if (result._tag === 'Left') throw new EnGardeAssertionError(result.left);
return result.right;
});
_defineProperty(this, "_tag", 'InterfaceType');
_defineProperty(this, "props", this.ioTsCodec.props);
}
_createClass(ObjectCodec, [{
key: "optional",
get: function get() {
return new Codec(t.union([this.ioTsCodec, t.undefined]));
}
}]);
return ObjectCodec;
}();
exports.ObjectCodec = ObjectCodec;
var primitiveCodecs = {
string: new Codec(t.string),
number: new Codec(t.number),
boolean: new Codec(t.boolean),
null: new Codec(t.null),
undefined: new Codec(t.undefined),
any: new Codec(t.any),
unknown: new Codec(t.unknown)
};
var _default = eg;
exports.default = _default;
var wrapHigherOrderCodec = function wrapHigherOrderCodec(higherOrderCodec) {
return function () {
return new Codec(higherOrderCodec.apply(void 0, arguments));
};
};
var higherOrderCodecs = {
// Using a special type for object which enables optional keys
object: function object(p, name) {
return new ObjectCodec(t.type(p, name));
},
tuple: function tuple(codecs, name) {
return new Codec(t.tuple(codecs, name));
},
intersection: function intersection(codecs, name) {
return new Codec(t.intersection(codecs, name));
},
// The types for these higher order codecs work with simple hoc wrapper
array: wrapHigherOrderCodec(t.array),
union: wrapHigherOrderCodec(t.union),
record: wrapHigherOrderCodec(t.record),
partial: wrapHigherOrderCodec(t.partial),
literal: wrapHigherOrderCodec(t.literal),
exact: wrapHigherOrderCodec(t.exact)
};
var eg = _objectSpread({}, primitiveCodecs, higherOrderCodecs);
exports.eg = eg;
{
"name": "@cloudflare/util-en-garde",
"description": "",
"version": "4.0.2",
"version": "6.0.0",
"types": "./dist/index.d.ts",

@@ -25,6 +25,7 @@ "main": "lib/index.js",

},
"devDependencies": {
"@cloudflare/types": "^3.0.2"
"dependencies": {
"fp-ts": "^2.1.1",
"io-ts": "^2.0.1"
},
"gitHead": "500ff258e12d77a670469794f3d4e9e10c137bd7"
"gitHead": "2c7116804e9d7e6f2e005ee4d7aa37829d2624a3"
}

@@ -1,107 +0,176 @@

import { primitiveGuards, higherOrderGuards } from './core';
import {
TypeGuard,
TypeFromGuard,
TypeGuardWithOptional
} from './type-helpers';
import { addOptionalToGuard, addOptionalToHigherOrderGuard } from './optional';
import * as t from 'io-ts';
class TypeGuardError extends Error {
constructor(message: string, public valueThatFailed: unknown) {
super(message);
/**
* Why does this wrapper exist?
*
* `io-ts` is awesome and super powerful, but the API leaves some things to be
* desired. It was designed to be used with `fp-ts` which is a library for
* functional programming patterns in TypeScipt. The resulting type on the
* "decode" method is an Either which is great to work with when using `fp-ts`,
* but is otherwise cumbersome.
*
* By introducing an `assert` method, we can guarantee the function will always
* return the decoded type by throwing an error if it fails to decode. With
* promises we can easily chain an assertion and the promise will reject if
* the data fails to decode.
*
* Additionally, this wrapper provides an `optional` property which unions
* the codec with the `undefined` codec. This provides an API that is both
* easier to use and more readable for a very common scenario.
*
* Next is the new `object` type which seeks to replace `t.type` in io-ts and
* which is less immediately obvious. When deriving type information from
* `t.type` with `t.TypeOf`, keys whose values are unioned with undefined
* are still required. The suggested strategy in `io-ts` is to define optional
* keys separately and intersect them with required keys. The `object` type
* addresses this by returning a type that automatically enables optional
* keys where values are unioned with undefined. This combined with the
* `optional` property makes for a much nicer API when defining object shapes.
*/
type KeysWithValueType<O, T> = { [Key in keyof O]: Key }[Exclude<
keyof O,
KeysWithoutValueType<O, T>
>];
type KeysWithoutValueType<O, T> = {
[Key in keyof O]: T extends O[Key] ? never : Key;
}[keyof O];
type RepackKeys<T> = { [Key in keyof T]: T[Key] } & {};
type EnableOptionalKeys<T> = RepackKeys<
{ [MandatoryKey in KeysWithoutValueType<T, undefined>]: T[MandatoryKey] } &
{ [OptionalKey in KeysWithValueType<T, undefined>]?: T[OptionalKey] }
>;
export class EnGardeAssertionError extends Error {
constructor(public errors: t.Errors) {
super();
Object.setPrototypeOf(this, EnGardeAssertionError.prototype);
}
}
const assertShape = <Guard extends TypeGuard<any>>(guard: Guard) => (
obj: unknown
): TypeFromGuard<Guard> => {
if (guard(obj)) return obj;
throw new TypeGuardError('Failed type guard', obj);
type IoTsCodec = t.Any;
export class Codec<Codec extends IoTsCodec> {
constructor(public ioTsCodec: Codec) {}
public name = this.ioTsCodec.name;
public is: Codec['is'] = this.ioTsCodec.is;
public encode: Codec['encode'] = this.ioTsCodec.encode;
public decode: Codec['decode'] = this.ioTsCodec.decode;
public validate: Codec['validate'] = this.ioTsCodec.validate;
public pipe: Codec['pipe'] = this.ioTsCodec.pipe;
public _A: Codec['_A'] = this.ioTsCodec._A;
public _O: Codec['_O'] = this.ioTsCodec._O;
public _I: Codec['_I'] = this.ioTsCodec._I;
public asDecoder: Codec['asDecoder'] = this.ioTsCodec.asDecoder;
public asEncoder: Codec['asEncoder'] = this.ioTsCodec.asEncoder;
public assertDecode = (value: unknown): Codec['_A'] => {
const result = this.ioTsCodec.decode(value);
if (result._tag === 'Left') throw new EnGardeAssertionError(result.left);
return result.right;
};
public get optional() {
return new Codec(t.union([this.ioTsCodec, t.undefined]));
}
}
type InterfaceTypeWithOptionalKeys<P extends t.Props> = t.InterfaceType<
P,
EnableOptionalKeys<{ [K in keyof P]: t.TypeOf<P[K]> }>,
EnableOptionalKeys<{ [K in keyof P]: t.OutputOf<P[K]> }>,
unknown
>;
export class ObjectCodec<
P extends t.Props,
CodecWithOptionalKeys extends t.InterfaceType<
any,
any,
any,
any
> = InterfaceTypeWithOptionalKeys<P>
> {
constructor(public ioTsCodec: t.TypeC<P>) {}
public name = this.ioTsCodec.name;
public is: CodecWithOptionalKeys['is'] = this.ioTsCodec.is;
public encode: CodecWithOptionalKeys['encode'] = this.ioTsCodec.encode;
public decode: CodecWithOptionalKeys['decode'] = this.ioTsCodec.decode;
public validate: CodecWithOptionalKeys['validate'] = this.ioTsCodec.validate;
public pipe: CodecWithOptionalKeys['pipe'] = this.ioTsCodec.pipe;
public _A: CodecWithOptionalKeys['_A'] = this.ioTsCodec._A;
public _O: CodecWithOptionalKeys['_O'] = this.ioTsCodec._O;
public _I: CodecWithOptionalKeys['_I'] = this.ioTsCodec._I;
public asDecoder: CodecWithOptionalKeys['asDecoder'] = this.ioTsCodec
.asDecoder;
public asEncoder: CodecWithOptionalKeys['asEncoder'] = this.ioTsCodec
.asEncoder;
public assertDecode = (value: unknown): CodecWithOptionalKeys['_A'] => {
const result = this.ioTsCodec.decode(value);
if (result._tag === 'Left') throw new EnGardeAssertionError(result.left);
return result.right;
};
public get optional() {
return new Codec(t.union([this.ioTsCodec, t.undefined]));
}
readonly _tag: 'InterfaceType' = 'InterfaceType';
public props: CodecWithOptionalKeys['props'] = this.ioTsCodec.props;
}
const primitiveCodecs = {
string: new Codec(t.string),
number: new Codec(t.number),
boolean: new Codec(t.boolean),
null: new Codec(t.null),
undefined: new Codec(t.undefined),
any: new Codec(t.any),
unknown: new Codec(t.unknown)
};
const eg = {
string: addOptionalToGuard(primitiveGuards.string),
number: addOptionalToGuard(primitiveGuards.number),
boolean: addOptionalToGuard(primitiveGuards.boolean),
null: addOptionalToGuard(primitiveGuards.null),
/**
* Accepts a guard and returns a guard that checks that the value is an
* array and that each element in the array matches the given guard.
*/
arrayOf: addOptionalToHigherOrderGuard(higherOrderGuards.arrayOf),
/**
* Accepts any number of guards and returns a type guard that will only
* match if the given value is a tuple where each value matches the guard
* in that same position.
*
* @example
* const isStringStringNumber = eg.tuple(
* eg.string,
* eg.string,
* eg.number,
* )
*
* if (isStringStringNumber(["hi", "there", 4])) {
* // ...
* }
*/
tuple: addOptionalToHigherOrderGuard(higherOrderGuards.tuple),
/**
* Accepts an object definition where each key must be a guard. Returns
* a guard that checks that a given value is an object and that each key's
* value passes the definition's guard. Fails if any keys exist on the given
* value that do not exist on the object definition.
*/
exact: addOptionalToHigherOrderGuard(higherOrderGuards.exact),
/**
* Accepts a constructor and returns a guard that checks whether a value is
* an instance of that constructor using `instanceof`
*/
instanceOf: addOptionalToHigherOrderGuard(higherOrderGuards.instanceOf),
/**
* Accepts an object definition where each key must be a guard. Returns
* a guard that checks that a given value is an object and that each key's
* value passes the definition's guard
*/
object: addOptionalToHigherOrderGuard(higherOrderGuards.object),
/**
* Accepts a type guard and returns an index signature where values must
* pass the type guard.
*/
objectWithValuesOf: addOptionalToHigherOrderGuard(
higherOrderGuards.objectWithValuesOf
),
/**
* Accepts any number of guards as arguments. Returns a guard that checks if
* a given value passes any of the input guards.
*/
oneOf: addOptionalToHigherOrderGuard(higherOrderGuards.oneOf),
/**
* Accepts any number of guards as arguments. Returns a guard that checks if
* a given value passes all of the input guards.
*/
all: addOptionalToHigherOrderGuard(higherOrderGuards.all),
/**
* Accepts primitives and infers their types. Returns a guard that checks
* whether a value matches any of the literal values.
*/
oneOfLiterals: addOptionalToHigherOrderGuard(higherOrderGuards.oneOfLiterals),
const wrapHigherOrderCodec = <Params extends any[], Codec extends IoTsCodec>(
higherOrderCodec: (...hocParams: Params) => Codec
) => (...hocParams: Params) => new Codec(higherOrderCodec(...hocParams));
// These guards do not require optional decoration
any: primitiveGuards.any,
unknown: primitiveGuards.unknown,
undefined: primitiveGuards.undefined
type NonEmpty<T extends any[]> = Exclude<T, never[]>;
const higherOrderCodecs = {
// Using a special type for object which enables optional keys
object: <P extends t.Props>(p: P, name?: string) =>
new ObjectCodec(t.type(p, name)),
tuple: <Codecs extends never[] | [IoTsCodec, ...IoTsCodec[]]>(
codecs: Codecs,
name?: string
): Codec<t.TupleC<NonEmpty<Codecs>>> =>
new Codec(t.tuple(codecs as any, name) as any),
intersection: <Codecs extends [IoTsCodec, IoTsCodec, ...IoTsCodec[]]>(
codecs: Codecs,
name?: string
): Codec<t.IntersectionC<Codecs>> =>
new Codec(t.intersection(codecs as any, name) as any),
// The types for these higher order codecs work with simple hoc wrapper
array: wrapHigherOrderCodec(t.array),
union: wrapHigherOrderCodec(t.union),
record: wrapHigherOrderCodec(t.record),
partial: wrapHigherOrderCodec(t.partial),
literal: wrapHigherOrderCodec(t.literal),
exact: wrapHigherOrderCodec(t.exact)
};
export default eg;
export {
TypeGuard,
TypeFromGuard,
TypeGuardWithOptional,
primitiveGuards,
higherOrderGuards,
TypeGuardError,
assertShape,
addOptionalToGuard,
addOptionalToHigherOrderGuard
export type TypeFromCodec<T extends IoTsCodec> = t.TypeOf<T>;
export const eg = {
...primitiveCodecs,
...higherOrderCodecs
};
export { t };
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc