Comparing version 0.16.0-beta.1 to 0.16.0-beta.2
import { Either } from './Either'; | ||
import { Maybe } from './Maybe'; | ||
import { NonEmptyList } from './NonEmptyList'; | ||
import { JSONSchema6 } from 'json-schema'; | ||
export interface Codec<T> { | ||
@@ -11,3 +12,3 @@ /** Takes a JSON value and runs the decode function the codec was constructed with. All of purify's built-in codecs return a descriptive error message in case the decode fails */ | ||
unsafeDecode: (input: unknown) => T; | ||
schema: () => object; | ||
schema: () => JSONSchema6; | ||
} | ||
@@ -30,5 +31,7 @@ /** You can use this to get a free type from an interface codec */ | ||
export declare const number: Codec<number>; | ||
/** A codec for null only. Most of the time you will use it with the oneOf codec combinator to create a codec for a type like "string | null" */ | ||
/** A codec for null only */ | ||
export declare const nullType: Codec<null>; | ||
export declare const optional: <T>(codec: Codec<T>) => Codec<T | undefined>; | ||
/** A codec for a value T or null. Keep in mind if you use `nullable` inside `Codec.interface` the property will still be required */ | ||
export declare const nullable: <T>(codec: Codec<T>) => Codec<T | null>; | ||
/** A codec for a boolean value */ | ||
@@ -38,3 +41,5 @@ export declare const boolean: Codec<boolean>; | ||
export declare const unknown: Codec<unknown>; | ||
/** A codec combinator that receives a list of codecs and runs them one after another during decode and resolves to whichever returns Right or to Left if all fail. This module does not expose a "nullable" or "optional" codec combinators because it\'s trivial to implement/replace them using oneOf */ | ||
/** A codec for a TypeScript enum */ | ||
export declare const enumeration: <T extends Record<string, string | number>>(e: T) => Codec<T[keyof T]>; | ||
/** A codec combinator that receives a list of codecs and runs them one after another during decode and resolves to whichever returns Right or to Left if all fail */ | ||
export declare const oneOf: <T extends Codec<any>[]>(codecs: T) => Codec<GetInterface<T extends (infer U)[] ? U : never>>; | ||
@@ -45,3 +50,3 @@ /** A codec for an array */ | ||
export declare const record: <K extends string | number | symbol, V>(keyCodec: Codec<K>, valueCodec: Codec<V>) => Codec<Record<K, V>>; | ||
/** A codec that only succeeds decoding when the value is exactly what you've constructed the codec with. It's useful when you're decoding an enum, for example */ | ||
/** A codec that only succeeds decoding when the value is exactly what you've constructed the codec with */ | ||
export declare const exactly: <T extends string | number | boolean>(expectedValue: T) => Codec<T>; | ||
@@ -58,1 +63,3 @@ /** A special codec used when dealing with recursive data structures, it allows a codec to be recursively defined by itself */ | ||
export declare const date: Codec<Date>; | ||
/** Creates an intersection between two codecs. If the provided codecs are not for an object, the second decode result will be returned */ | ||
export declare const intersect: <T, U>(t: Codec<T>, u: Codec<U>) => Codec<T & U>; |
144
Codec.js
@@ -13,2 +13,22 @@ "use strict"; | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
var __spread = (this && this.__spread) || function () { | ||
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); | ||
return ar; | ||
}; | ||
var __values = (this && this.__values) || function(o) { | ||
@@ -30,2 +50,5 @@ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
var NonEmptyList_1 = require("./NonEmptyList"); | ||
var isEmptySchema = function (schema) { | ||
return Object.keys(schema).length === 0; | ||
}; | ||
var isObject = function (obj) { | ||
@@ -56,2 +79,32 @@ return typeof obj === 'object' && obj !== null && !Array.isArray(obj); | ||
}; | ||
var removeOneOfWithSingleElement = function (schema) { | ||
var _a; | ||
var schemaKeys = Object.keys(schema); | ||
if (schemaKeys.length === 1 && | ||
((_a = schema.oneOf) === null || _a === void 0 ? void 0 : _a.length) === 1 && | ||
typeof schema.oneOf[0] === 'object') { | ||
Object.assign(schema, schema.oneOf[0]); | ||
delete schema.oneOf; | ||
} | ||
return schema; | ||
}; | ||
var flattenNestedOneOf = function (schema) { | ||
var _a; | ||
if (Array.isArray(schema.oneOf)) { | ||
for (var i = 0; i < schema.oneOf.length; i++) { | ||
var e = schema.oneOf[i]; | ||
if (typeof e === 'object' && e.oneOf) { | ||
schema.oneOf.splice(i, 1); | ||
(_a = schema.oneOf).push.apply(_a, __spread(e.oneOf)); | ||
return optimizeSchema(schema); | ||
} | ||
} | ||
} | ||
return schema; | ||
}; | ||
var optimizeSchema = function (schema) { | ||
flattenNestedOneOf(schema); | ||
removeOneOfWithSingleElement(schema); | ||
return schema; | ||
}; | ||
exports.Codec = { | ||
@@ -63,2 +116,3 @@ /** Creates a codec for any JSON object */ | ||
var e_1, _a; | ||
var _b, _c; | ||
if (!isObject(input)) { | ||
@@ -72,3 +126,3 @@ return Either_1.Left(reportError('an object', input)); | ||
if (!input.hasOwnProperty(key) && | ||
!properties[key]._isOptional) { | ||
!((_c = (_b = properties[key])._isOptional) === null || _c === void 0 ? void 0 : _c.call(_b))) { | ||
return Either_1.Left("Problem with property \"" + key + "\": it does not exist in received object " + JSON.stringify(input)); | ||
@@ -80,3 +134,6 @@ } | ||
} | ||
result[key] = decodedProperty.extract(); | ||
var value = decodedProperty.extract(); | ||
if (value !== undefined) { | ||
result[key] = value; | ||
} | ||
} | ||
@@ -117,6 +174,8 @@ } | ||
return keys.reduce(function (acc, key) { | ||
if (!properties[key]._isOptional) { | ||
var _a, _b; | ||
var isOptional = (_b = (_a = properties[key])._isOptional) === null || _b === void 0 ? void 0 : _b.call(_a); | ||
if (!isOptional) { | ||
acc.required.push(key); | ||
} | ||
acc.properties[key] = properties[key].schema(); | ||
acc.properties[key] = optimizeSchema(properties[key].schema()); | ||
return acc; | ||
@@ -162,3 +221,3 @@ }, { | ||
}); | ||
/** A codec for null only. Most of the time you will use it with the oneOf codec combinator to create a codec for a type like "string | null" */ | ||
/** A codec for null only */ | ||
exports.nullType = exports.Codec.custom({ | ||
@@ -177,8 +236,11 @@ decode: function (input) { | ||
}, | ||
encode: Function_1.identity, | ||
schema: function () { return ({}); } | ||
encode: Function_1.identity | ||
}); | ||
exports.optional = function (codec) { | ||
return (__assign(__assign({}, exports.oneOf([codec, undefinedType])), { _isOptional: true })); | ||
return (__assign(__assign({}, exports.oneOf([codec, undefinedType])), { schema: codec.schema, _isOptional: function () { return true; } })); | ||
}; | ||
/** A codec for a value T or null. Keep in mind if you use `nullable` inside `Codec.interface` the property will still be required */ | ||
exports.nullable = function (codec) { | ||
return exports.oneOf([codec, exports.nullType]); | ||
}; | ||
/** A codec for a boolean value */ | ||
@@ -200,3 +262,20 @@ exports.boolean = exports.Codec.custom({ | ||
}); | ||
/** A codec combinator that receives a list of codecs and runs them one after another during decode and resolves to whichever returns Right or to Left if all fail. This module does not expose a "nullable" or "optional" codec combinators because it\'s trivial to implement/replace them using oneOf */ | ||
/** A codec for a TypeScript enum */ | ||
exports.enumeration = function (e) { | ||
var enumValues = Object.values(e); | ||
return exports.Codec.custom({ | ||
decode: function (input) { | ||
if (typeof input !== 'string' && typeof input !== 'number') { | ||
return Either_1.Left(reportError('a string or number', input)); | ||
} | ||
var enumIndex = enumValues.indexOf(input); | ||
return enumIndex !== -1 | ||
? Either_1.Right(enumValues[enumIndex]) | ||
: Either_1.Left(reportError('an enum member', input)); | ||
}, | ||
encode: Function_1.identity, | ||
schema: function () { return ({ enum: enumValues }); } | ||
}); | ||
}; | ||
/** A codec combinator that receives a list of codecs and runs them one after another during decode and resolves to whichever returns Right or to Left if all fail */ | ||
exports.oneOf = function (codecs) { | ||
@@ -277,3 +356,3 @@ return exports.Codec.custom({ | ||
type: 'array', | ||
items: codec.schema() ? [codec.schema()] : [] | ||
items: [codec.schema()] | ||
}); } | ||
@@ -345,3 +424,3 @@ }); | ||
}; | ||
/** A codec that only succeeds decoding when the value is exactly what you've constructed the codec with. It's useful when you're decoding an enum, for example */ | ||
/** A codec that only succeeds decoding when the value is exactly what you've constructed the codec with */ | ||
exports.exactly = function (expectedValue) { | ||
@@ -364,3 +443,6 @@ return exports.Codec.custom({ | ||
decode: function (input) { return getCodec().decode(input); }, | ||
encode: function (input) { return getCodec().encode(input); } | ||
encode: function (input) { return getCodec().encode(input); }, | ||
schema: function () { return ({ | ||
$comment: 'Lazy codecs are not supported when generating a JSON schema' | ||
}); } | ||
}); | ||
@@ -370,3 +452,3 @@ }; | ||
exports.maybe = function (codec) { | ||
return exports.Codec.custom({ | ||
var baseCodec = exports.Codec.custom({ | ||
decode: function (input) { | ||
@@ -380,6 +462,8 @@ return Maybe_1.Maybe.fromNullable(input).caseOf({ | ||
schema: function () { return ({ | ||
oneOf: codec.schema() ? [codec.schema(), { type: 'null' }] : [] | ||
}); }, | ||
_isOptional: true | ||
oneOf: isEmptySchema(codec.schema()) | ||
? [] | ||
: [codec.schema(), { type: 'null' }] | ||
}); } | ||
}); | ||
return __assign(__assign({}, baseCodec), { _isOptional: function () { return true; } }); | ||
}; | ||
@@ -450,1 +534,29 @@ /** A codec for purify's NEL type */ | ||
}); | ||
/** Creates an intersection between two codecs. If the provided codecs are not for an object, the second decode result will be returned */ | ||
exports.intersect = function (t, u) { | ||
return exports.Codec.custom({ | ||
decode: function (input) { | ||
var et = t.decode(input); | ||
if (et.isLeft()) { | ||
return et; | ||
} | ||
var eu = u.decode(input); | ||
if (eu.isLeft()) { | ||
return eu; | ||
} | ||
var valuet = et.extract(); | ||
var valueu = eu.extract(); | ||
return isObject(valuet) && isObject(valueu) | ||
? Either_1.Right(Object.assign(valuet, valueu)) | ||
: Either_1.Right(valueu); | ||
}, | ||
encode: function (x) { | ||
var valuet = t.encode(x); | ||
var valueu = u.encode(x); | ||
return isObject(valuet) && isObject(valueu) | ||
? Object.assign(valuet, valueu) | ||
: valueu; | ||
}, | ||
schema: function () { return ({ allOf: [t, u].map(function (x) { return x.schema(); }).filter(Boolean) }); } | ||
}); | ||
}; |
@@ -73,2 +73,3 @@ "use strict"; | ||
function Right(value) { | ||
this._ = 'R'; | ||
this.__value = value; | ||
@@ -192,2 +193,3 @@ } | ||
function Left(value) { | ||
this._ = 'L'; | ||
this.__value = value; | ||
@@ -194,0 +196,0 @@ } |
@@ -28,2 +28,4 @@ import { Either } from './Either'; | ||
toMaybeAsync(): MaybeAsync<R>; | ||
/** Returns `Right` if `this` is `Left` and vice versa */ | ||
swap(): EitherAsync<R, L>; | ||
'fantasy-land/map'<R2>(f: (value: R) => R2): EitherAsync<L, R2>; | ||
@@ -30,0 +32,0 @@ 'fantasy-land/chain'<R2>(f: (value: R) => EitherAsync<L, R2>): EitherAsync<L, R2>; |
@@ -148,2 +148,18 @@ "use strict"; | ||
}; | ||
EitherAsyncImpl.prototype.swap = function () { | ||
var _this = this; | ||
return exports.EitherAsync(function (helpers) { return __awaiter(_this, void 0, void 0, function () { | ||
var either; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.run()]; | ||
case 1: | ||
either = _a.sent(); | ||
if (either.isRight()) | ||
helpers.throwE(either.extract()); | ||
return [2 /*return*/, helpers.liftEither(Either_1.Right(either.extract()))]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
EitherAsyncImpl.prototype['fantasy-land/map'] = function (f) { | ||
@@ -150,0 +166,0 @@ return this.map(f); |
import { Either } from './Either'; | ||
import { Maybe } from './Maybe'; | ||
import { NonEmptyList } from './NonEmptyList'; | ||
import { JSONSchema6 } from 'json-schema'; | ||
export interface Codec<T> { | ||
@@ -11,3 +12,3 @@ /** Takes a JSON value and runs the decode function the codec was constructed with. All of purify's built-in codecs return a descriptive error message in case the decode fails */ | ||
unsafeDecode: (input: unknown) => T; | ||
schema: () => object; | ||
schema: () => JSONSchema6; | ||
} | ||
@@ -30,5 +31,7 @@ /** You can use this to get a free type from an interface codec */ | ||
export declare const number: Codec<number>; | ||
/** A codec for null only. Most of the time you will use it with the oneOf codec combinator to create a codec for a type like "string | null" */ | ||
/** A codec for null only */ | ||
export declare const nullType: Codec<null>; | ||
export declare const optional: <T>(codec: Codec<T>) => Codec<T | undefined>; | ||
/** A codec for a value T or null. Keep in mind if you use `nullable` inside `Codec.interface` the property will still be required */ | ||
export declare const nullable: <T>(codec: Codec<T>) => Codec<T | null>; | ||
/** A codec for a boolean value */ | ||
@@ -38,3 +41,5 @@ export declare const boolean: Codec<boolean>; | ||
export declare const unknown: Codec<unknown>; | ||
/** A codec combinator that receives a list of codecs and runs them one after another during decode and resolves to whichever returns Right or to Left if all fail. This module does not expose a "nullable" or "optional" codec combinators because it\'s trivial to implement/replace them using oneOf */ | ||
/** A codec for a TypeScript enum */ | ||
export declare const enumeration: <T extends Record<string, string | number>>(e: T) => Codec<T[keyof T]>; | ||
/** A codec combinator that receives a list of codecs and runs them one after another during decode and resolves to whichever returns Right or to Left if all fail */ | ||
export declare const oneOf: <T extends Codec<any>[]>(codecs: T) => Codec<GetInterface<T extends (infer U)[] ? U : never>>; | ||
@@ -45,3 +50,3 @@ /** A codec for an array */ | ||
export declare const record: <K extends string | number | symbol, V>(keyCodec: Codec<K>, valueCodec: Codec<V>) => Codec<Record<K, V>>; | ||
/** A codec that only succeeds decoding when the value is exactly what you've constructed the codec with. It's useful when you're decoding an enum, for example */ | ||
/** A codec that only succeeds decoding when the value is exactly what you've constructed the codec with */ | ||
export declare const exactly: <T extends string | number | boolean>(expectedValue: T) => Codec<T>; | ||
@@ -58,1 +63,3 @@ /** A special codec used when dealing with recursive data structures, it allows a codec to be recursively defined by itself */ | ||
export declare const date: Codec<Date>; | ||
/** Creates an intersection between two codecs. If the provided codecs are not for an object, the second decode result will be returned */ | ||
export declare const intersect: <T, U>(t: Codec<T>, u: Codec<U>) => Codec<T & U>; |
137
es/Codec.js
@@ -7,2 +7,3 @@ "use strict"; | ||
const NonEmptyList_1 = require("./NonEmptyList"); | ||
const isEmptySchema = (schema) => Object.keys(schema).length === 0; | ||
const isObject = (obj) => typeof obj === 'object' && obj !== null && !Array.isArray(obj); | ||
@@ -31,2 +32,31 @@ const reportError = (type, input) => { | ||
}; | ||
const removeOneOfWithSingleElement = (schema) => { | ||
var _a; | ||
const schemaKeys = Object.keys(schema); | ||
if (schemaKeys.length === 1 && | ||
((_a = schema.oneOf) === null || _a === void 0 ? void 0 : _a.length) === 1 && | ||
typeof schema.oneOf[0] === 'object') { | ||
Object.assign(schema, schema.oneOf[0]); | ||
delete schema.oneOf; | ||
} | ||
return schema; | ||
}; | ||
const flattenNestedOneOf = (schema) => { | ||
if (Array.isArray(schema.oneOf)) { | ||
for (let i = 0; i < schema.oneOf.length; i++) { | ||
const e = schema.oneOf[i]; | ||
if (typeof e === 'object' && e.oneOf) { | ||
schema.oneOf.splice(i, 1); | ||
schema.oneOf.push(...e.oneOf); | ||
return optimizeSchema(schema); | ||
} | ||
} | ||
} | ||
return schema; | ||
}; | ||
const optimizeSchema = (schema) => { | ||
flattenNestedOneOf(schema); | ||
removeOneOfWithSingleElement(schema); | ||
return schema; | ||
}; | ||
exports.Codec = { | ||
@@ -37,2 +67,3 @@ /** Creates a codec for any JSON object */ | ||
const decode = (input) => { | ||
var _a, _b; | ||
if (!isObject(input)) { | ||
@@ -44,3 +75,3 @@ return Either_1.Left(reportError('an object', input)); | ||
if (!input.hasOwnProperty(key) && | ||
!properties[key]._isOptional) { | ||
!((_b = (_a = properties[key])._isOptional) === null || _b === void 0 ? void 0 : _b.call(_a))) { | ||
return Either_1.Left(`Problem with property "${key}": it does not exist in received object ${JSON.stringify(input)}`); | ||
@@ -52,3 +83,6 @@ } | ||
} | ||
result[key] = decodedProperty.extract(); | ||
const value = decodedProperty.extract(); | ||
if (value !== undefined) { | ||
result[key] = value; | ||
} | ||
} | ||
@@ -69,6 +103,8 @@ return Either_1.Right(result); | ||
schema: () => keys.reduce((acc, key) => { | ||
if (!properties[key]._isOptional) { | ||
var _a, _b; | ||
const isOptional = (_b = (_a = properties[key])._isOptional) === null || _b === void 0 ? void 0 : _b.call(_a); | ||
if (!isOptional) { | ||
acc.required.push(key); | ||
} | ||
acc.properties[key] = properties[key].schema(); | ||
acc.properties[key] = optimizeSchema(properties[key].schema()); | ||
return acc; | ||
@@ -108,3 +144,3 @@ }, { | ||
}); | ||
/** A codec for null only. Most of the time you will use it with the oneOf codec combinator to create a codec for a type like "string | null" */ | ||
/** A codec for null only */ | ||
exports.nullType = exports.Codec.custom({ | ||
@@ -119,9 +155,11 @@ decode: (input) => input === null ? Either_1.Right(input) : Either_1.Left(reportError('a null', input)), | ||
: Either_1.Left(reportError('an undefined', input)), | ||
encode: Function_1.identity, | ||
schema: () => ({}) | ||
encode: Function_1.identity | ||
}); | ||
exports.optional = (codec) => ({ | ||
...exports.oneOf([codec, undefinedType]), | ||
_isOptional: true | ||
schema: codec.schema, | ||
_isOptional: () => true | ||
}); | ||
/** A codec for a value T or null. Keep in mind if you use `nullable` inside `Codec.interface` the property will still be required */ | ||
exports.nullable = (codec) => exports.oneOf([codec, exports.nullType]); | ||
/** A codec for a boolean value */ | ||
@@ -141,3 +179,20 @@ exports.boolean = exports.Codec.custom({ | ||
}); | ||
/** A codec combinator that receives a list of codecs and runs them one after another during decode and resolves to whichever returns Right or to Left if all fail. This module does not expose a "nullable" or "optional" codec combinators because it\'s trivial to implement/replace them using oneOf */ | ||
/** A codec for a TypeScript enum */ | ||
exports.enumeration = (e) => { | ||
const enumValues = Object.values(e); | ||
return exports.Codec.custom({ | ||
decode: (input) => { | ||
if (typeof input !== 'string' && typeof input !== 'number') { | ||
return Either_1.Left(reportError('a string or number', input)); | ||
} | ||
const enumIndex = enumValues.indexOf(input); | ||
return enumIndex !== -1 | ||
? Either_1.Right(enumValues[enumIndex]) | ||
: Either_1.Left(reportError('an enum member', input)); | ||
}, | ||
encode: Function_1.identity, | ||
schema: () => ({ enum: enumValues }) | ||
}); | ||
}; | ||
/** A codec combinator that receives a list of codecs and runs them one after another during decode and resolves to whichever returns Right or to Left if all fail */ | ||
exports.oneOf = (codecs) => exports.Codec.custom({ | ||
@@ -193,3 +248,3 @@ decode: (input) => { | ||
type: 'array', | ||
items: codec.schema() ? [codec.schema()] : [] | ||
items: [codec.schema()] | ||
}) | ||
@@ -243,3 +298,3 @@ }); | ||
}); | ||
/** A codec that only succeeds decoding when the value is exactly what you've constructed the codec with. It's useful when you're decoding an enum, for example */ | ||
/** A codec that only succeeds decoding when the value is exactly what you've constructed the codec with */ | ||
exports.exactly = (expectedValue) => exports.Codec.custom({ | ||
@@ -257,16 +312,26 @@ decode: (input) => input === expectedValue | ||
decode: (input) => getCodec().decode(input), | ||
encode: (input) => getCodec().encode(input) | ||
encode: (input) => getCodec().encode(input), | ||
schema: () => ({ | ||
$comment: 'Lazy codecs are not supported when generating a JSON schema' | ||
}) | ||
}); | ||
/** A codec for purify's Maybe type. Encode runs Maybe#toJSON, which effectively returns the value inside if it's a Just or undefined if it's Nothing */ | ||
exports.maybe = (codec) => exports.Codec.custom({ | ||
decode: (input) => Maybe_1.Maybe.fromNullable(input).caseOf({ | ||
Just: (x) => codec.decode(x).map(Maybe_1.Just), | ||
Nothing: () => Either_1.Right(Maybe_1.Nothing) | ||
}), | ||
encode: (input) => input.toJSON(), | ||
schema: () => ({ | ||
oneOf: codec.schema() ? [codec.schema(), { type: 'null' }] : [] | ||
}), | ||
_isOptional: true | ||
}); | ||
exports.maybe = (codec) => { | ||
const baseCodec = exports.Codec.custom({ | ||
decode: (input) => Maybe_1.Maybe.fromNullable(input).caseOf({ | ||
Just: (x) => codec.decode(x).map(Maybe_1.Just), | ||
Nothing: () => Either_1.Right(Maybe_1.Nothing) | ||
}), | ||
encode: (input) => input.toJSON(), | ||
schema: () => ({ | ||
oneOf: isEmptySchema(codec.schema()) | ||
? [] | ||
: [codec.schema(), { type: 'null' }] | ||
}) | ||
}); | ||
return { | ||
...baseCodec, | ||
_isOptional: () => true | ||
}; | ||
}; | ||
/** A codec for purify's NEL type */ | ||
@@ -326,1 +391,27 @@ exports.nonEmptyList = (codec) => { | ||
}); | ||
/** Creates an intersection between two codecs. If the provided codecs are not for an object, the second decode result will be returned */ | ||
exports.intersect = (t, u) => exports.Codec.custom({ | ||
decode: (input) => { | ||
const et = t.decode(input); | ||
if (et.isLeft()) { | ||
return et; | ||
} | ||
const eu = u.decode(input); | ||
if (eu.isLeft()) { | ||
return eu; | ||
} | ||
const valuet = et.extract(); | ||
const valueu = eu.extract(); | ||
return isObject(valuet) && isObject(valueu) | ||
? Either_1.Right(Object.assign(valuet, valueu)) | ||
: Either_1.Right(valueu); | ||
}, | ||
encode: (x) => { | ||
const valuet = t.encode(x); | ||
const valueu = u.encode(x); | ||
return isObject(valuet) && isObject(valueu) | ||
? Object.assign(valuet, valueu) | ||
: valueu; | ||
}, | ||
schema: () => ({ allOf: [t, u].map((x) => x.schema()).filter(Boolean) }) | ||
}); |
@@ -40,2 +40,3 @@ "use strict"; | ||
constructor(value) { | ||
this._ = 'R'; | ||
this.__value = value; | ||
@@ -158,2 +159,3 @@ } | ||
constructor(value) { | ||
this._ = 'L'; | ||
this.__value = value; | ||
@@ -160,0 +162,0 @@ } |
@@ -28,2 +28,4 @@ import { Either } from './Either'; | ||
toMaybeAsync(): MaybeAsync<R>; | ||
/** Returns `Right` if `this` is `Left` and vice versa */ | ||
swap(): EitherAsync<R, L>; | ||
'fantasy-land/map'<R2>(f: (value: R) => R2): EitherAsync<L, R2>; | ||
@@ -30,0 +32,0 @@ 'fantasy-land/chain'<R2>(f: (value: R) => EitherAsync<L, R2>): EitherAsync<L, R2>; |
@@ -66,2 +66,10 @@ "use strict"; | ||
} | ||
swap() { | ||
return exports.EitherAsync(async (helpers) => { | ||
const either = await this.run(); | ||
if (either.isRight()) | ||
helpers.throwE(either.extract()); | ||
return helpers.liftEither(Either_1.Right(either.extract())); | ||
}); | ||
} | ||
'fantasy-land/map'(f) { | ||
@@ -68,0 +76,0 @@ return this.map(f); |
@@ -11,11 +11,19 @@ import { Maybe } from './Maybe'; | ||
export interface NonEmptyListTypeRef { | ||
/** Typecasts an array with at least one element into a `NonEmptyList`. Works only if the compiler can confirm that the array has one or more elements */ | ||
<T extends NonEmptyListCompliant<T[number]>>(list: T): NonEmptyList<T[number]>; | ||
/** Returns a `Just NonEmptyList` if the parameter has one or more elements, otherwise it returns `Nothing` */ | ||
fromArray<T>(source: T[]): Maybe<NonEmptyList<T>>; | ||
/** Converts a `Tuple` to a `NonEmptyList` */ | ||
fromTuple<T, U>(source: Tuple<T, U>): NonEmptyList<T | U>; | ||
/** Typecasts any array into a `NonEmptyList`, but throws an exception if the array is empty. Use `fromArray` as a safe alternative */ | ||
unsafeCoerce<T>(source: T[]): NonEmptyList<T>; | ||
/** Returns true and narrows the type if the passed array has one or more elements */ | ||
isNonEmpty<T>(list: T[]): list is NonEmptyList<T>; | ||
/** The same function as \`List#head\`, but it doesn't return a Maybe as a NonEmptyList will always have a head */ | ||
head<T>(list: NonEmptyList<T>): T; | ||
/** The same function as \`List#last\`, but it doesn't return a Maybe as a NonEmptyList will always have a last element */ | ||
last<T>(list: NonEmptyList<T>): T; | ||
/** The same function as \`List#tail\`, but it doesn't return a Maybe as a NonEmptyList will always have a tail (although it may be of length 0) */ | ||
tail<T>(list: NonEmptyList<T>): T[]; | ||
} | ||
export declare const NonEmptyList: NonEmptyListTypeRef; |
@@ -38,2 +38,6 @@ export interface TupleTypeRef { | ||
ap<T, S2>(f: Tuple<T, (value: S) => S2>): Tuple<F, S2>; | ||
/** Tests whether both elements in the tuple pass the test implemented by the provided function */ | ||
every(pred: (value: F | S) => boolean): boolean; | ||
/** Tests whether at least one element in the tuple passes the test implemented by the provided function */ | ||
some(pred: (value: F | S) => boolean): boolean; | ||
'fantasy-land/equals'(other: Tuple<F, S>): boolean; | ||
@@ -40,0 +44,0 @@ 'fantasy-land/bimap'<F2, S2>(f: (fst: F) => F2, g: (snd: S) => S2): Tuple<F2, S2>; |
@@ -54,2 +54,8 @@ "use strict"; | ||
} | ||
every(pred) { | ||
return pred(this.first) && pred(this.second); | ||
} | ||
some(pred) { | ||
return pred(this.first) || pred(this.second); | ||
} | ||
'fantasy-land/equals'(other) { | ||
@@ -56,0 +62,0 @@ return this.equals(other); |
@@ -11,11 +11,19 @@ import { Maybe } from './Maybe'; | ||
export interface NonEmptyListTypeRef { | ||
/** Typecasts an array with at least one element into a `NonEmptyList`. Works only if the compiler can confirm that the array has one or more elements */ | ||
<T extends NonEmptyListCompliant<T[number]>>(list: T): NonEmptyList<T[number]>; | ||
/** Returns a `Just NonEmptyList` if the parameter has one or more elements, otherwise it returns `Nothing` */ | ||
fromArray<T>(source: T[]): Maybe<NonEmptyList<T>>; | ||
/** Converts a `Tuple` to a `NonEmptyList` */ | ||
fromTuple<T, U>(source: Tuple<T, U>): NonEmptyList<T | U>; | ||
/** Typecasts any array into a `NonEmptyList`, but throws an exception if the array is empty. Use `fromArray` as a safe alternative */ | ||
unsafeCoerce<T>(source: T[]): NonEmptyList<T>; | ||
/** Returns true and narrows the type if the passed array has one or more elements */ | ||
isNonEmpty<T>(list: T[]): list is NonEmptyList<T>; | ||
/** The same function as \`List#head\`, but it doesn't return a Maybe as a NonEmptyList will always have a head */ | ||
head<T>(list: NonEmptyList<T>): T; | ||
/** The same function as \`List#last\`, but it doesn't return a Maybe as a NonEmptyList will always have a last element */ | ||
last<T>(list: NonEmptyList<T>): T; | ||
/** The same function as \`List#tail\`, but it doesn't return a Maybe as a NonEmptyList will always have a tail (although it may be of length 0) */ | ||
tail<T>(list: NonEmptyList<T>): T[]; | ||
} | ||
export declare const NonEmptyList: NonEmptyListTypeRef; |
{ | ||
"name": "purify-ts", | ||
"version": "0.16.0-beta.1", | ||
"version": "0.16.0-beta.2", | ||
"description": "Functional programming standard library for TypeScript ", | ||
@@ -34,5 +34,7 @@ "main": "lib/index.js", | ||
"ts-jest": "^25.0.0", | ||
"typescript": "3.8.3" | ||
"typescript": "3.9.3" | ||
}, | ||
"dependencies": {} | ||
"dependencies": { | ||
"@types/json-schema": "^7.0.4" | ||
} | ||
} |
@@ -46,4 +46,4 @@ <h3 align="center"> | ||
- [Haskell](https://haskell-lang.org/) | ||
- [Elm](https://elm-lang.org/) | ||
- [Arrow - Functional companion to Kotlin's Standard Library](http://arrow-kt.io/) | ||
- [fp-ts - Functional programming in TypeScript](https://github.com/gcanti/fp-ts) |
@@ -38,2 +38,6 @@ export interface TupleTypeRef { | ||
ap<T, S2>(f: Tuple<T, (value: S) => S2>): Tuple<F, S2>; | ||
/** Tests whether both elements in the tuple pass the test implemented by the provided function */ | ||
every(pred: (value: F | S) => boolean): boolean; | ||
/** Tests whether at least one element in the tuple passes the test implemented by the provided function */ | ||
some(pred: (value: F | S) => boolean): boolean; | ||
'fantasy-land/equals'(other: Tuple<F, S>): boolean; | ||
@@ -40,0 +44,0 @@ 'fantasy-land/bimap'<F2, S2>(f: (fst: F) => F2, g: (snd: S) => S2): Tuple<F2, S2>; |
@@ -106,2 +106,8 @@ "use strict"; | ||
}; | ||
TupleImpl.prototype.every = function (pred) { | ||
return pred(this.first) && pred(this.second); | ||
}; | ||
TupleImpl.prototype.some = function (pred) { | ||
return pred(this.first) || pred(this.second); | ||
}; | ||
TupleImpl.prototype['fantasy-land/equals'] = function (other) { | ||
@@ -108,0 +114,0 @@ return this.equals(other); |
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
184351
4126
1
+ Added@types/json-schema@^7.0.4
+ Added@types/json-schema@7.0.15(transitive)