Comparing version 0.16.0-beta.5 to 0.16.0-beta.6
@@ -14,3 +14,3 @@ import { Either } from './Either'; | ||
} | ||
/** You can use this to get a free type from an interface codec */ | ||
/** You can use this to get a free type from any codec */ | ||
export declare type GetInterface<T extends Codec<any>> = T extends Codec<infer U> ? U : never; | ||
@@ -43,3 +43,3 @@ export declare const Codec: { | ||
/** 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>>; | ||
export declare const oneOf: <T extends [Codec<any>, ...Codec<any>[]]>(codecs: T) => Codec<GetInterface<T extends (infer U)[] ? U : never>>; | ||
/** A codec for an array */ | ||
@@ -63,1 +63,25 @@ export declare const array: <T>(codec: Codec<T>) => Codec<T[]>; | ||
export declare const intersect: <T, U>(t: Codec<T>, u: Codec<U>) => Codec<T & U>; | ||
export declare type ExpectedType = 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null' | 'undefined' | 'enum'; | ||
export declare type ReceivedType = 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null' | 'undefined' | 'bigint' | 'symbol' | 'function'; | ||
export declare type DecodeError = { | ||
type: 'property'; | ||
property: string; | ||
error: DecodeError; | ||
} | { | ||
type: 'index'; | ||
index: number; | ||
error: DecodeError; | ||
} | { | ||
type: 'oneOf'; | ||
errors: DecodeError[]; | ||
} | { | ||
type: 'failure'; | ||
expectedType?: ExpectedType; | ||
receivedType: ReceivedType; | ||
receivedValue?: unknown; | ||
} | { | ||
type: 'custom'; | ||
message: string; | ||
}; | ||
/** Turns a string error message produced by a built-in purify codec into a meta object */ | ||
export declare const parseError: (error: string) => DecodeError; |
162
Codec.js
@@ -45,3 +45,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.intersect = exports.date = exports.tuple = exports.nonEmptyList = exports.maybe = exports.lazy = exports.exactly = exports.record = exports.array = exports.oneOf = exports.enumeration = exports.unknown = exports.boolean = exports.nullable = exports.optional = exports.nullType = exports.number = exports.string = exports.Codec = void 0; | ||
exports.parseError = exports.intersect = exports.date = exports.tuple = exports.nonEmptyList = exports.maybe = exports.lazy = exports.exactly = exports.record = exports.array = exports.oneOf = exports.enumeration = exports.unknown = exports.boolean = exports.nullable = exports.optional = exports.nullType = exports.number = exports.string = exports.Codec = void 0; | ||
var Either_1 = require("./Either"); | ||
@@ -57,3 +57,3 @@ var Function_1 = require("./Function"); | ||
}; | ||
var reportError = function (type, input) { | ||
var reportError = function (expectedType, input) { | ||
var receivedString = ''; | ||
@@ -75,6 +75,14 @@ switch (typeof input) { | ||
break; | ||
case 'symbol': | ||
receivedString = 'a symbol'; | ||
break; | ||
case 'function': | ||
receivedString = 'a function'; | ||
break; | ||
case 'bigint': | ||
receivedString = "a bigint with value " + input.toString(); | ||
} | ||
receivedString = | ||
receivedString || "a " + typeof input + " with value " + JSON.stringify(input); | ||
return "Expected " + type + ", but received " + receivedString; | ||
return "Expected " + expectedType + ", but received " + receivedString; | ||
}; | ||
@@ -117,3 +125,2 @@ var removeOneOfWithSingleElement = function (schema) { | ||
var e_1, _a; | ||
var _b, _c; | ||
if (!isObject(input)) { | ||
@@ -127,3 +134,3 @@ return Either_1.Left(reportError('an object', input)); | ||
if (!input.hasOwnProperty(key) && | ||
!((_c = (_b = properties[key])._isOptional) === null || _c === void 0 ? void 0 : _c.call(_b))) { | ||
!properties[key]._isOptional) { | ||
return Either_1.Left("Problem with property \"" + key + "\": it does not exist in received object " + JSON.stringify(input)); | ||
@@ -174,4 +181,3 @@ } | ||
return keys.reduce(function (acc, key) { | ||
var _a, _b; | ||
var isOptional = (_b = (_a = properties[key])._isOptional) === null || _b === void 0 ? void 0 : _b.call(_a); | ||
var isOptional = properties[key]._isOptional; | ||
if (!isOptional) { | ||
@@ -238,3 +244,3 @@ acc.required.push(key); | ||
exports.optional = function (codec) { | ||
return (__assign(__assign({}, exports.oneOf([codec, undefinedType])), { schema: codec.schema, _isOptional: function () { return true; } })); | ||
return (__assign(__assign({}, exports.oneOf([codec, undefinedType])), { schema: codec.schema, _isOptional: true })); | ||
}; | ||
@@ -266,9 +272,10 @@ /** A codec for a value T or null. Keep in mind if you use `nullable` inside `Codec.interface` the property will still be required */ | ||
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)); | ||
return exports.oneOf([exports.string, exports.number]) | ||
.decode(input) | ||
.chain(function (x) { | ||
var enumIndex = enumValues.indexOf(x); | ||
return enumIndex !== -1 | ||
? Either_1.Right(enumValues[enumIndex]) | ||
: Either_1.Left(reportError('an enum member', input)); | ||
}); | ||
}, | ||
@@ -353,3 +360,3 @@ encode: Function_1.identity, | ||
else { | ||
return Either_1.Left("Problem with value at index " + i + ": " + decoded.extract()); | ||
return Either_1.Left("Problem with the value at index " + i + ": " + decoded.extract()); | ||
} | ||
@@ -372,3 +379,3 @@ } | ||
.chain(function (x) { | ||
return isFinite(+x) ? Either_1.Right(x) : Either_1.Left(reportError('a number key', input)); | ||
return isFinite(+x) ? Either_1.Right(x) : Either_1.Left(reportError('a number', input)); | ||
}); | ||
@@ -402,3 +409,3 @@ }, | ||
else if (decodedValue.isLeft()) { | ||
return Either_1.Left("Problem with value of property \"" + key + "\": " + decodedValue.extract()); | ||
return Either_1.Left("Problem with the value of property \"" + key + "\": " + decodedValue.extract()); | ||
} | ||
@@ -472,3 +479,3 @@ } | ||
}); | ||
return __assign(__assign({}, baseCodec), { _isOptional: function () { return true; } }); | ||
return __assign(__assign({}, baseCodec), { _isOptional: true }); | ||
}; | ||
@@ -508,3 +515,3 @@ /** A codec for purify's NEL type */ | ||
else { | ||
return Either_1.Left("Problem with value at index " + i + ": " + decoded.extract()); | ||
return Either_1.Left("Problem with the value at index " + i + ": " + decoded.extract()); | ||
} | ||
@@ -568,1 +575,116 @@ } | ||
}; | ||
var oneofRegex = /^(One of the following problems occured:)\s/; | ||
var oneOfCounterRegex = /\(\d\)\s/; | ||
var oneOfSeparatorRegex = /\, (?=\()/g; | ||
var failureRegex = /^(Expected ).+(, but received )/; | ||
var failureReceivedSeparator = ' with value'; | ||
var missingPropertyMarker = 'Problem with property "'; | ||
var badPropertyMarker = 'Problem with the value of property "'; | ||
var badPropertyKeyMarker = 'Problem with key type of property "'; | ||
var dateFailureMarket = 'Problem with date string: '; | ||
var indexMarker = 'Problem with the value at index '; | ||
var expectedTypesMap = { | ||
'an object': 'object', | ||
'a number': 'number', | ||
'a string': 'string', | ||
'an undefined': 'undefined', | ||
'a boolean': 'boolean', | ||
'an array': 'array', | ||
'a null': 'null', | ||
'an enum member': 'enum' | ||
}; | ||
var receivedTypesMap = { | ||
'a string': 'string', | ||
'a number': 'number', | ||
null: 'null', | ||
undefined: 'undefined', | ||
'a boolean': 'boolean', | ||
'an array': 'array', | ||
'an object': 'object', | ||
'a symbol': 'symbol', | ||
'a function': 'function', | ||
'a bigint': 'bigint' | ||
}; | ||
var receivedTypesWithoutValue = [ | ||
'null', | ||
'undefined', | ||
'boolean', | ||
'symbol', | ||
'function', | ||
'bigint' | ||
]; | ||
/** Turns a string error message produced by a built-in purify codec into a meta object */ | ||
exports.parseError = function (error) { | ||
var oneOfCheck = error.match(oneofRegex); | ||
// One of the following problems occured: (0) *, (1) * | ||
if (oneOfCheck) { | ||
var remainer = error.replace(oneOfCheck[0], ''); | ||
return { | ||
type: 'oneOf', | ||
errors: remainer | ||
.split(oneOfSeparatorRegex) | ||
.map(function (x) { return exports.parseError(x.replace(x.match(oneOfCounterRegex)[0], '')); }) | ||
}; | ||
} | ||
var failureCheck = error.match(failureRegex); | ||
// Expected an object, but received an array with value [] | ||
if (failureCheck) { | ||
var receivedTypeRaw = error.split(failureCheck[2]).pop(); | ||
var receivedType = receivedTypesMap[receivedTypeRaw.split(failureReceivedSeparator)[0]]; | ||
if (receivedType) { | ||
var expectedTypeRaw = error | ||
.replace(failureCheck[1], '') | ||
.split(failureCheck[2])[0]; | ||
return { | ||
type: 'failure', | ||
expectedType: expectedTypesMap[expectedTypeRaw], | ||
receivedType: receivedType, | ||
receivedValue: receivedTypesWithoutValue.includes(receivedType) | ||
? undefined | ||
: JSON.parse(receivedTypeRaw.split(failureReceivedSeparator).pop()) | ||
}; | ||
} | ||
} | ||
// Problem with property "a": it does not exist in received object {} | ||
if (error.startsWith(missingPropertyMarker)) { | ||
var property = error.replace(missingPropertyMarker, '').split('": ')[0]; | ||
return { | ||
type: 'property', | ||
property: property, | ||
error: { | ||
type: 'failure', | ||
receivedType: 'undefined' | ||
} | ||
}; | ||
} | ||
// Problem with the value of property "a": * | ||
// Problem with key type of property "a": * | ||
if (error.startsWith(badPropertyMarker) || | ||
error.startsWith(badPropertyKeyMarker)) { | ||
var _a = __read(error | ||
.replace(badPropertyMarker, '') | ||
.replace(badPropertyKeyMarker, '') | ||
.split(/": (.+)/)), property = _a[0], restOfError = _a.slice(1); | ||
return { | ||
type: 'property', | ||
property: property, | ||
error: exports.parseError(restOfError.join('')) | ||
}; | ||
} | ||
// Problem with date string: * | ||
if (error.startsWith(dateFailureMarket)) { | ||
return exports.parseError(error.replace(dateFailureMarket, '')); | ||
} | ||
// Problem with the value at index 0: * | ||
if (error.startsWith(indexMarker)) { | ||
var _b = __read(error | ||
.replace(indexMarker, '') | ||
.split(/: (.+)/)), index = _b[0], restOfError = _b.slice(1); | ||
return { | ||
type: 'index', | ||
index: Number(index), | ||
error: exports.parseError(restOfError.join('')) | ||
}; | ||
} | ||
return { type: 'custom', message: error }; | ||
}; |
@@ -38,5 +38,5 @@ import { Maybe } from './Maybe'; | ||
reduce<T>(reducer: (accumulator: T, value: R) => T, initialValue: T): T; | ||
/** Returns `this` if it\'s a `Left`, otherwise it returns the result of applying the function argument to `this` and wrapping it in a `Right` */ | ||
/** Returns `this` if it's a `Left`, otherwise it returns the result of applying the function argument to `this` and wrapping it in a `Right` */ | ||
extend<R2>(f: (value: Either<L, R>) => R2): Either<L, R2>; | ||
/** Returns the value inside `this` or throws an error if `this` is a `Left` */ | ||
/** Returns the value inside `this` if it's a `Right` or either throws the value or a generic exception depending on whether the value is an Error */ | ||
unsafeCoerce(): R; | ||
@@ -81,5 +81,5 @@ /** Structural pattern matching for `Either` in the form of a function */ | ||
of<L, R>(value: R): Either<L, R>; | ||
/** Takes a list of eithers and returns a list of all `Left` values */ | ||
/** Takes a list of `Either`s and returns a list of all `Left` values */ | ||
lefts<L, R>(list: Either<L, R>[]): L[]; | ||
/** Takes a list of eithers and returns a list of all `Right` values */ | ||
/** Takes a list of `Either`s and returns a list of all `Right` values */ | ||
rights<L, R>(list: Either<L, R>[]): R[]; | ||
@@ -90,2 +90,3 @@ /** Calls a function and returns a `Right` with the return value or an exception wrapped in a `Left` in case of failure */ | ||
sequence<L, R>(eithers: Either<L, R>[]): Either<L, R[]>; | ||
isEither<L, R>(x: unknown): x is Either<L, R>; | ||
'fantasy-land/of'<L, R>(value: R): Either<L, R>; | ||
@@ -92,0 +93,0 @@ } |
@@ -89,2 +89,5 @@ "use strict"; | ||
}, | ||
isEither: function (x) { | ||
return x instanceof Left || x instanceof Right; | ||
}, | ||
'fantasy-land/of': function (value) { | ||
@@ -98,2 +101,10 @@ return exports.Either.of(value); | ||
this._ = 'R'; | ||
this['fantasy-land/bimap'] = this.bimap; | ||
this['fantasy-land/map'] = this.map; | ||
this['fantasy-land/ap'] = this.ap; | ||
this['fantasy-land/equals'] = this.equals; | ||
this['fantasy-land/chain'] = this.chain; | ||
this['fantasy-land/alt'] = this.alt; | ||
this['fantasy-land/reduce'] = this.reduce; | ||
this['fantasy-land/extend'] = this.extend; | ||
} | ||
@@ -187,26 +198,2 @@ Right.prototype.isLeft = function () { | ||
}; | ||
Right.prototype['fantasy-land/bimap'] = function (f, g) { | ||
return this.bimap(f, g); | ||
}; | ||
Right.prototype['fantasy-land/map'] = function (f) { | ||
return this.map(f); | ||
}; | ||
Right.prototype['fantasy-land/ap'] = function (other) { | ||
return this.ap(other); | ||
}; | ||
Right.prototype['fantasy-land/equals'] = function (other) { | ||
return this.equals(other); | ||
}; | ||
Right.prototype['fantasy-land/chain'] = function (f) { | ||
return this.chain(f); | ||
}; | ||
Right.prototype['fantasy-land/alt'] = function (other) { | ||
return this.alt(other); | ||
}; | ||
Right.prototype['fantasy-land/reduce'] = function (reducer, initialValue) { | ||
return this.reduce(reducer, initialValue); | ||
}; | ||
Right.prototype['fantasy-land/extend'] = function (f) { | ||
return this.extend(f); | ||
}; | ||
return Right; | ||
@@ -269,3 +256,6 @@ }()); | ||
Left.prototype.unsafeCoerce = function () { | ||
throw new Error('Either got coerced to a Left'); | ||
if (this.__value instanceof Error) { | ||
throw this.__value; | ||
} | ||
throw new Error('Either#unsafeCoerce was ran on a Left'); | ||
}; | ||
@@ -272,0 +262,0 @@ Left.prototype.caseOf = function (patterns) { |
import { Either } from './Either'; | ||
import { MaybeAsync } from './MaybeAsync'; | ||
export interface EitherAsyncTypeRef { | ||
/** Constructs an EitherAsync object from a function that takes an object full of helpers that let you lift things into the EitherAsync context and returns a Promise */ | ||
/** Constructs an `EitherAsync` object from a function that takes an object full of helpers that let you lift things into the `EitherAsync` context and returns a Promise */ | ||
<L, R>(runPromise: (helpers: EitherAsyncHelpers<L>) => PromiseLike<R>): EitherAsync<L, R>; | ||
/** Constructs an EitherAsync object from a function that returns an Either wrapped in a Promise */ | ||
/** Constructs an `EitherAsync` object from a function that returns an Either wrapped in a Promise */ | ||
fromPromise<L, R>(f: () => PromiseLike<Either<L, R>>): EitherAsync<L, R>; | ||
/** Constructs an EitherAsync object from a function that returns a Promise. The left type is defaulted to the built-in Error type */ | ||
/** Constructs an `EitherAsync` object from a function that returns a Promise. The left type is defaulted to the built-in Error type */ | ||
liftPromise<R, L = Error>(f: () => PromiseLike<R>): EitherAsync<L, R>; | ||
/** Constructs an EitherAsync object from an Either */ | ||
/** Constructs an `EitherAsync` object from an Either */ | ||
liftEither<L, R>(either: Either<L, R>): EitherAsync<L, R>; | ||
/** Takes a list of `EitherAsync`s and returns a Promise that will resolve with all `Left` values. Internally it uses `Promise.all` to wait for all results */ | ||
lefts<L, R>(list: EitherAsync<L, R>[]): Promise<L[]>; | ||
/** Takes a list of `EitherAsync`s and returns a Promise that will resolve with all `Right` values. Internally it uses `Promise.all` to wait for all results */ | ||
rights<L, R>(list: EitherAsync<L, R>[]): Promise<R[]>; | ||
/** Turns a list of `EitherAsync`s into an `EitherAsync` of list. The returned `Promise` will be rejected as soon as a single `EitherAsync` resolves to a `Left`, it will not wait for all Promises to resolve and since `EitherAsync` is lazy, unlike `Promise`, the remaining async operations will not be executed at all */ | ||
sequence<L, R>(eas: EitherAsync<L, R>[]): EitherAsync<L, R[]>; | ||
} | ||
@@ -28,3 +34,5 @@ export interface EitherAsync<L, R> extends PromiseLike<Either<L, R>> { | ||
run(): Promise<Either<L, R>>; | ||
/** Transforms the `Right` value of `this` with a given function. If the EitherAsync that is being mapped resolves to a Left then the mapping function won't be called and `run` will resolve the whole thing to that Left, just like the regular Either#map */ | ||
/** Given two functions, maps the value that the Promise inside `this` resolves to using the first if it is `Left` or using the second one if it is `Right` */ | ||
bimap<L2, R2>(f: (value: L) => L2, g: (value: R) => R2): EitherAsync<L2, R2>; | ||
/** Transforms the `Right` value of `this` with a given function. If the `EitherAsync` that is being mapped resolves to a Left then the mapping function won't be called and `run` will resolve the whole thing to that Left, just like the regular Either#map */ | ||
map<R2>(f: (value: R) => R2): EitherAsync<L, R2>; | ||
@@ -37,2 +45,4 @@ /** Maps the `Left` value of `this`, acts like an identity if `this` is `Right` */ | ||
chainLeft<L2>(f: (value: L) => PromiseLike<Either<L2, R>>): EitherAsync<L2, R>; | ||
/** Flattens nested `EitherAsync`s. `e.join()` is equivalent to `e.chain(x => x)` */ | ||
join<R2>(this: EitherAsync<L, EitherAsync<L, R2>>): EitherAsync<L, R2>; | ||
/** Converts `this` to a MaybeAsync, discarding any error values */ | ||
@@ -42,4 +52,22 @@ toMaybeAsync(): MaybeAsync<R>; | ||
swap(): EitherAsync<R, L>; | ||
/** Runs an effect if `this` is `Left`, returns `this` to make chaining other methods possible */ | ||
ifLeft(effect: (value: L) => any): EitherAsync<L, R>; | ||
/** Runs an effect if `this` is `Right`, returns `this` to make chaining other methods possible */ | ||
ifRight(effect: (value: R) => any): EitherAsync<L, R>; | ||
/** Applies a `Right` function wrapped in `EitherAsync` over a future `Right` value. Returns `Left` if either the `this` resolves to a `Left` or the function is `Left` */ | ||
ap<R2>(other: PromiseLike<Either<L, (value: R) => R2>>): EitherAsync<L, R2>; | ||
/** Returns the first `Right` between the future value of `this` and another future `EitherAsync` or the `Left` in the argument if both `this` and the argument resolve to `Left` */ | ||
alt(other: EitherAsync<L, R>): EitherAsync<L, R>; | ||
/** Returns `this` if it resolves to a `Left`, otherwise it returns the result of applying the function argument to `this` and wrapping it in a `Right` */ | ||
extend<R2>(f: (value: EitherAsync<L, R>) => R2): EitherAsync<L, R2>; | ||
/** Returns a Promise that resolves to the value inside `this` if it\'s `Left` or a default value if `this` is `Right` */ | ||
leftOrDefault(defaultValue: L): Promise<L>; | ||
/** Returns a Promise that resolves to the value inside `this` if it\'s `Right` or a default value if `this` is `Left` */ | ||
orDefault(defaultValue: R): Promise<R>; | ||
'fantasy-land/map'<R2>(f: (value: R) => R2): EitherAsync<L, R2>; | ||
'fantasy-land/bimap'<L2, R2>(f: (value: L) => L2, g: (value: R) => R2): EitherAsync<L2, R2>; | ||
'fantasy-land/chain'<R2>(f: (value: R) => PromiseLike<Either<L, R2>>): EitherAsync<L, R2>; | ||
'fantasy-land/ap'<R2>(other: EitherAsync<L, (value: R) => R2>): EitherAsync<L, R2>; | ||
'fantasy-land/alt'(other: EitherAsync<L, R>): EitherAsync<L, R>; | ||
'fantasy-land/extend'<R2>(f: (value: EitherAsync<L, R>) => R2): EitherAsync<L, R2>; | ||
/** WARNING: This is implemented only for Promise compatibility. Please use `chain` instead. */ | ||
@@ -51,5 +79,5 @@ then: PromiseLike<Either<L, R>>['then']; | ||
export interface EitherAsyncHelpers<L> { | ||
/** Allows you to take a regular Either value and lift it to the EitherAsync context. Awaiting a lifted Either will give you the `Right` value inside. If the Either is Left then the function will exit immediately and EitherAsync will resolve to that Left after running it */ | ||
/** Allows you to take a regular Either value and lift it to the `EitherAsync` context. Awaiting a lifted Either will give you the `Right` value inside. If the Either is Left then the function will exit immediately and EitherAsync will resolve to that Left after running it */ | ||
liftEither<R>(either: Either<L, R>): EitherAsyncValue<R>; | ||
/** Allows you to take an Either inside a Promise and lift it to the EitherAsync context. Awaiting a lifted Promise<Either> will give you the `Right` value inside the Either. If the Either is Left or the Promise is rejected then the function will exit immediately and MaybeAsync will resolve to that Left or the rejection value after running it */ | ||
/** Allows you to take an Either inside a Promise and lift it to the `EitherAsync` context. Awaiting a lifted Promise<Either> will give you the `Right` value inside the Either. If the Either is Left or the Promise is rejected then the function will exit immediately and MaybeAsync will resolve to that Left or the rejection value after running it */ | ||
fromPromise<R>(promise: PromiseLike<Either<L, R>>): EitherAsyncValue<R>; | ||
@@ -56,0 +84,0 @@ /** A type safe version of throwing an exception. Unlike the Error constructor, which will take anything, throwE only accepts values of the same type as the Left part of the Either */ |
@@ -38,2 +38,25 @@ "use strict"; | ||
}; | ||
var __asyncValues = (this && this.__asyncValues) || function (o) { | ||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); | ||
var m = o[Symbol.asyncIterator], i; | ||
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); | ||
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } | ||
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } | ||
}; | ||
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; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -59,5 +82,86 @@ exports.EitherAsync = void 0; | ||
function EitherAsyncImpl(runPromise) { | ||
var _this = this; | ||
this.runPromise = runPromise; | ||
this[Symbol.toStringTag] = 'EitherAsync'; | ||
this['fantasy-land/map'] = this.map; | ||
this['fantasy-land/bimap'] = this.bimap; | ||
this['fantasy-land/chain'] = this.chain; | ||
this['fantasy-land/ap'] = this.ap; | ||
this['fantasy-land/extend'] = this.extend; | ||
this['fantasy-land/alt'] = this.alt; | ||
this.then = function (onfulfilled, onrejected) { | ||
return _this.run().then(onfulfilled, onrejected); | ||
}; | ||
} | ||
EitherAsyncImpl.prototype.leftOrDefault = function (defaultValue) { | ||
return this.run().then(function (x) { return x.leftOrDefault(defaultValue); }); | ||
}; | ||
EitherAsyncImpl.prototype.orDefault = function (defaultValue) { | ||
return this.run().then(function (x) { return x.orDefault(defaultValue); }); | ||
}; | ||
EitherAsyncImpl.prototype.join = function () { | ||
var _this = this; | ||
return exports.EitherAsync(function (helpers) { return __awaiter(_this, void 0, void 0, function () { | ||
var either, nestedEither; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.run()]; | ||
case 1: | ||
either = _a.sent(); | ||
if (!either.isRight()) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, either.extract()]; | ||
case 2: | ||
nestedEither = _a.sent(); | ||
return [2 /*return*/, helpers.liftEither(nestedEither)]; | ||
case 3: return [2 /*return*/, helpers.liftEither(either)]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
EitherAsyncImpl.prototype.ap = function (other) { | ||
var _this = this; | ||
return exports.EitherAsync(function (helpers) { return __awaiter(_this, void 0, void 0, function () { | ||
var _a, either, o; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, Promise.all([this.run(), other])]; | ||
case 1: | ||
_a = __read.apply(void 0, [_b.sent(), 2]), either = _a[0], o = _a[1]; | ||
return [2 /*return*/, helpers.liftEither(either.ap(o))]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
EitherAsyncImpl.prototype.alt = function (other) { | ||
var _this = this; | ||
return exports.EitherAsync(function (helpers) { return __awaiter(_this, void 0, void 0, function () { | ||
var _a, either, o; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, Promise.all([this.run(), other])]; | ||
case 1: | ||
_a = __read.apply(void 0, [_b.sent(), 2]), either = _a[0], o = _a[1]; | ||
return [2 /*return*/, helpers.liftEither(either.alt(o))]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
EitherAsyncImpl.prototype.extend = function (f) { | ||
var _this = this; | ||
return exports.EitherAsync(function (helpers) { return __awaiter(_this, void 0, void 0, function () { | ||
var either, v; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.run()]; | ||
case 1: | ||
either = _a.sent(); | ||
if (either.isRight()) { | ||
v = exports.EitherAsync.liftEither(either); | ||
return [2 /*return*/, helpers.liftEither(Either_1.Right(f(v)))]; | ||
} | ||
return [2 /*return*/, helpers.liftEither(either)]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
EitherAsyncImpl.prototype.run = function () { | ||
@@ -81,2 +185,16 @@ return __awaiter(this, void 0, void 0, function () { | ||
}; | ||
EitherAsyncImpl.prototype.bimap = function (f, g) { | ||
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(); | ||
return [2 /*return*/, helpers.liftEither(either.bimap(f, g))]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
EitherAsyncImpl.prototype.map = function (f) { | ||
@@ -169,11 +287,32 @@ var _this = this; | ||
}; | ||
EitherAsyncImpl.prototype['fantasy-land/map'] = function (f) { | ||
return this.map(f); | ||
EitherAsyncImpl.prototype.ifLeft = function (effect) { | ||
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(); | ||
either.ifLeft(effect); | ||
return [2 /*return*/, helpers.liftEither(either)]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
EitherAsyncImpl.prototype['fantasy-land/chain'] = function (f) { | ||
return this.chain(f); | ||
EitherAsyncImpl.prototype.ifRight = function (effect) { | ||
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(); | ||
either.ifRight(effect); | ||
return [2 /*return*/, helpers.liftEither(either)]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
EitherAsyncImpl.prototype.then = function (onfulfilled, onrejected) { | ||
return this.run().then(onfulfilled, onrejected); | ||
}; | ||
return EitherAsyncImpl; | ||
@@ -194,3 +333,55 @@ }()); | ||
}); | ||
}, | ||
lefts: function (list) { | ||
return Promise.all(list.map(function (x) { return x.run(); })).then(Either_1.Either.lefts); | ||
}, | ||
rights: function (list) { | ||
return Promise.all(list.map(function (x) { return x.run(); })).then(Either_1.Either.rights); | ||
}, | ||
sequence: function (eas) { | ||
return exports.EitherAsync(function (helpers) { return __awaiter(void 0, void 0, void 0, function () { | ||
var res, eas_1, eas_1_1, e, e_4_1; | ||
var e_4, _a; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
res = []; | ||
_b.label = 1; | ||
case 1: | ||
_b.trys.push([1, 6, 7, 12]); | ||
eas_1 = __asyncValues(eas); | ||
_b.label = 2; | ||
case 2: return [4 /*yield*/, eas_1.next()]; | ||
case 3: | ||
if (!(eas_1_1 = _b.sent(), !eas_1_1.done)) return [3 /*break*/, 5]; | ||
e = eas_1_1.value; | ||
if (e.isLeft()) { | ||
return [2 /*return*/, helpers.liftEither(e)]; | ||
} | ||
res.push(e.extract()); | ||
_b.label = 4; | ||
case 4: return [3 /*break*/, 2]; | ||
case 5: return [3 /*break*/, 12]; | ||
case 6: | ||
e_4_1 = _b.sent(); | ||
e_4 = { error: e_4_1 }; | ||
return [3 /*break*/, 12]; | ||
case 7: | ||
_b.trys.push([7, , 10, 11]); | ||
if (!(eas_1_1 && !eas_1_1.done && (_a = eas_1.return))) return [3 /*break*/, 9]; | ||
return [4 /*yield*/, _a.call(eas_1)]; | ||
case 8: | ||
_b.sent(); | ||
_b.label = 9; | ||
case 9: return [3 /*break*/, 11]; | ||
case 10: | ||
if (e_4) throw e_4.error; | ||
return [7 /*endfinally*/]; | ||
case 11: return [7 /*endfinally*/]; | ||
case 12: return [2 /*return*/, helpers.liftEither(Either_1.Right(res))]; | ||
} | ||
}); | ||
}); }); | ||
} | ||
}); | ||
EitherAsyncImpl.prototype.constructor = exports.EitherAsync; |
@@ -14,3 +14,3 @@ import { Either } from './Either'; | ||
} | ||
/** You can use this to get a free type from an interface codec */ | ||
/** You can use this to get a free type from any codec */ | ||
export declare type GetInterface<T extends Codec<any>> = T extends Codec<infer U> ? U : never; | ||
@@ -43,3 +43,3 @@ export declare const Codec: { | ||
/** 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>>; | ||
export declare const oneOf: <T extends [Codec<any>, ...Codec<any>[]]>(codecs: T) => Codec<GetInterface<T extends (infer U)[] ? U : never>>; | ||
/** A codec for an array */ | ||
@@ -63,1 +63,25 @@ export declare const array: <T>(codec: Codec<T>) => Codec<T[]>; | ||
export declare const intersect: <T, U>(t: Codec<T>, u: Codec<U>) => Codec<T & U>; | ||
export declare type ExpectedType = 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null' | 'undefined' | 'enum'; | ||
export declare type ReceivedType = 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null' | 'undefined' | 'bigint' | 'symbol' | 'function'; | ||
export declare type DecodeError = { | ||
type: 'property'; | ||
property: string; | ||
error: DecodeError; | ||
} | { | ||
type: 'index'; | ||
index: number; | ||
error: DecodeError; | ||
} | { | ||
type: 'oneOf'; | ||
errors: DecodeError[]; | ||
} | { | ||
type: 'failure'; | ||
expectedType?: ExpectedType; | ||
receivedType: ReceivedType; | ||
receivedValue?: unknown; | ||
} | { | ||
type: 'custom'; | ||
message: string; | ||
}; | ||
/** Turns a string error message produced by a built-in purify codec into a meta object */ | ||
export declare const parseError: (error: string) => DecodeError; |
162
es/Codec.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.intersect = exports.date = exports.tuple = exports.nonEmptyList = exports.maybe = exports.lazy = exports.exactly = exports.record = exports.array = exports.oneOf = exports.enumeration = exports.unknown = exports.boolean = exports.nullable = exports.optional = exports.nullType = exports.number = exports.string = exports.Codec = void 0; | ||
exports.parseError = exports.intersect = exports.date = exports.tuple = exports.nonEmptyList = exports.maybe = exports.lazy = exports.exactly = exports.record = exports.array = exports.oneOf = exports.enumeration = exports.unknown = exports.boolean = exports.nullable = exports.optional = exports.nullType = exports.number = exports.string = exports.Codec = void 0; | ||
const Either_1 = require("./Either"); | ||
@@ -10,3 +10,3 @@ const Function_1 = require("./Function"); | ||
const isObject = (obj) => typeof obj === 'object' && obj !== null && !Array.isArray(obj); | ||
const reportError = (type, input) => { | ||
const reportError = (expectedType, input) => { | ||
let receivedString = ''; | ||
@@ -28,6 +28,14 @@ switch (typeof input) { | ||
break; | ||
case 'symbol': | ||
receivedString = 'a symbol'; | ||
break; | ||
case 'function': | ||
receivedString = 'a function'; | ||
break; | ||
case 'bigint': | ||
receivedString = `a bigint with value ${input.toString()}`; | ||
} | ||
receivedString = | ||
receivedString || `a ${typeof input} with value ${JSON.stringify(input)}`; | ||
return `Expected ${type}, but received ${receivedString}`; | ||
return `Expected ${expectedType}, but received ${receivedString}`; | ||
}; | ||
@@ -68,3 +76,2 @@ const removeOneOfWithSingleElement = (schema) => { | ||
const decode = (input) => { | ||
var _a, _b; | ||
if (!isObject(input)) { | ||
@@ -76,3 +83,3 @@ return Either_1.Left(reportError('an object', input)); | ||
if (!input.hasOwnProperty(key) && | ||
!((_b = (_a = properties[key])._isOptional) === null || _b === void 0 ? void 0 : _b.call(_a))) { | ||
!properties[key]._isOptional) { | ||
return Either_1.Left(`Problem with property "${key}": it does not exist in received object ${JSON.stringify(input)}`); | ||
@@ -103,4 +110,3 @@ } | ||
schema: () => keys.reduce((acc, key) => { | ||
var _a, _b; | ||
const isOptional = (_b = (_a = properties[key])._isOptional) === null || _b === void 0 ? void 0 : _b.call(_a); | ||
const isOptional = properties[key]._isOptional; | ||
if (!isOptional) { | ||
@@ -159,3 +165,3 @@ acc.required.push(key); | ||
schema: codec.schema, | ||
_isOptional: () => true | ||
_isOptional: true | ||
}); | ||
@@ -183,9 +189,10 @@ /** A codec for a value T or null. Keep in mind if you use `nullable` inside `Codec.interface` the property will still be required */ | ||
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)); | ||
return exports.oneOf([exports.string, exports.number]) | ||
.decode(input) | ||
.chain((x) => { | ||
const enumIndex = enumValues.indexOf(x); | ||
return enumIndex !== -1 | ||
? Either_1.Right(enumValues[enumIndex]) | ||
: Either_1.Left(reportError('an enum member', input)); | ||
}); | ||
}, | ||
@@ -240,3 +247,3 @@ encode: Function_1.identity, | ||
else { | ||
return Either_1.Left(`Problem with value at index ${i}: ${decoded.extract()}`); | ||
return Either_1.Left(`Problem with the value at index ${i}: ${decoded.extract()}`); | ||
} | ||
@@ -256,3 +263,3 @@ } | ||
.decode(input) | ||
.chain((x) => isFinite(+x) ? Either_1.Right(x) : Either_1.Left(reportError('a number key', input))), | ||
.chain((x) => isFinite(+x) ? Either_1.Right(x) : Either_1.Left(reportError('a number', input))), | ||
encode: Function_1.identity, | ||
@@ -280,3 +287,3 @@ schema: exports.number.schema | ||
else if (decodedValue.isLeft()) { | ||
return Either_1.Left(`Problem with value of property "${key}": ${decodedValue.extract()}`); | ||
return Either_1.Left(`Problem with the value of property "${key}": ${decodedValue.extract()}`); | ||
} | ||
@@ -335,3 +342,3 @@ } | ||
...baseCodec, | ||
_isOptional: () => true | ||
_isOptional: true | ||
}; | ||
@@ -367,3 +374,3 @@ }; | ||
else { | ||
return Either_1.Left(`Problem with value at index ${i}: ${decoded.extract()}`); | ||
return Either_1.Left(`Problem with the value at index ${i}: ${decoded.extract()}`); | ||
} | ||
@@ -420,1 +427,116 @@ } | ||
}); | ||
const oneofRegex = /^(One of the following problems occured:)\s/; | ||
const oneOfCounterRegex = /\(\d\)\s/; | ||
const oneOfSeparatorRegex = /\, (?=\()/g; | ||
const failureRegex = /^(Expected ).+(, but received )/; | ||
const failureReceivedSeparator = ' with value'; | ||
const missingPropertyMarker = 'Problem with property "'; | ||
const badPropertyMarker = 'Problem with the value of property "'; | ||
const badPropertyKeyMarker = 'Problem with key type of property "'; | ||
const dateFailureMarket = 'Problem with date string: '; | ||
const indexMarker = 'Problem with the value at index '; | ||
const expectedTypesMap = { | ||
'an object': 'object', | ||
'a number': 'number', | ||
'a string': 'string', | ||
'an undefined': 'undefined', | ||
'a boolean': 'boolean', | ||
'an array': 'array', | ||
'a null': 'null', | ||
'an enum member': 'enum' | ||
}; | ||
const receivedTypesMap = { | ||
'a string': 'string', | ||
'a number': 'number', | ||
null: 'null', | ||
undefined: 'undefined', | ||
'a boolean': 'boolean', | ||
'an array': 'array', | ||
'an object': 'object', | ||
'a symbol': 'symbol', | ||
'a function': 'function', | ||
'a bigint': 'bigint' | ||
}; | ||
const receivedTypesWithoutValue = [ | ||
'null', | ||
'undefined', | ||
'boolean', | ||
'symbol', | ||
'function', | ||
'bigint' | ||
]; | ||
/** Turns a string error message produced by a built-in purify codec into a meta object */ | ||
exports.parseError = (error) => { | ||
const oneOfCheck = error.match(oneofRegex); | ||
// One of the following problems occured: (0) *, (1) * | ||
if (oneOfCheck) { | ||
const remainer = error.replace(oneOfCheck[0], ''); | ||
return { | ||
type: 'oneOf', | ||
errors: remainer | ||
.split(oneOfSeparatorRegex) | ||
.map((x) => exports.parseError(x.replace(x.match(oneOfCounterRegex)[0], ''))) | ||
}; | ||
} | ||
const failureCheck = error.match(failureRegex); | ||
// Expected an object, but received an array with value [] | ||
if (failureCheck) { | ||
const receivedTypeRaw = error.split(failureCheck[2]).pop(); | ||
const receivedType = receivedTypesMap[receivedTypeRaw.split(failureReceivedSeparator)[0]]; | ||
if (receivedType) { | ||
const expectedTypeRaw = error | ||
.replace(failureCheck[1], '') | ||
.split(failureCheck[2])[0]; | ||
return { | ||
type: 'failure', | ||
expectedType: expectedTypesMap[expectedTypeRaw], | ||
receivedType, | ||
receivedValue: receivedTypesWithoutValue.includes(receivedType) | ||
? undefined | ||
: JSON.parse(receivedTypeRaw.split(failureReceivedSeparator).pop()) | ||
}; | ||
} | ||
} | ||
// Problem with property "a": it does not exist in received object {} | ||
if (error.startsWith(missingPropertyMarker)) { | ||
const property = error.replace(missingPropertyMarker, '').split('": ')[0]; | ||
return { | ||
type: 'property', | ||
property, | ||
error: { | ||
type: 'failure', | ||
receivedType: 'undefined' | ||
} | ||
}; | ||
} | ||
// Problem with the value of property "a": * | ||
// Problem with key type of property "a": * | ||
if (error.startsWith(badPropertyMarker) || | ||
error.startsWith(badPropertyKeyMarker)) { | ||
const [property, ...restOfError] = error | ||
.replace(badPropertyMarker, '') | ||
.replace(badPropertyKeyMarker, '') | ||
.split(/": (.+)/); | ||
return { | ||
type: 'property', | ||
property, | ||
error: exports.parseError(restOfError.join('')) | ||
}; | ||
} | ||
// Problem with date string: * | ||
if (error.startsWith(dateFailureMarket)) { | ||
return exports.parseError(error.replace(dateFailureMarket, '')); | ||
} | ||
// Problem with the value at index 0: * | ||
if (error.startsWith(indexMarker)) { | ||
const [index, ...restOfError] = error | ||
.replace(indexMarker, '') | ||
.split(/: (.+)/); | ||
return { | ||
type: 'index', | ||
index: Number(index), | ||
error: exports.parseError(restOfError.join('')) | ||
}; | ||
} | ||
return { type: 'custom', message: error }; | ||
}; |
@@ -38,5 +38,5 @@ import { Maybe } from './Maybe'; | ||
reduce<T>(reducer: (accumulator: T, value: R) => T, initialValue: T): T; | ||
/** Returns `this` if it\'s a `Left`, otherwise it returns the result of applying the function argument to `this` and wrapping it in a `Right` */ | ||
/** Returns `this` if it's a `Left`, otherwise it returns the result of applying the function argument to `this` and wrapping it in a `Right` */ | ||
extend<R2>(f: (value: Either<L, R>) => R2): Either<L, R2>; | ||
/** Returns the value inside `this` or throws an error if `this` is a `Left` */ | ||
/** Returns the value inside `this` if it's a `Right` or either throws the value or a generic exception depending on whether the value is an Error */ | ||
unsafeCoerce(): R; | ||
@@ -81,5 +81,5 @@ /** Structural pattern matching for `Either` in the form of a function */ | ||
of<L, R>(value: R): Either<L, R>; | ||
/** Takes a list of eithers and returns a list of all `Left` values */ | ||
/** Takes a list of `Either`s and returns a list of all `Left` values */ | ||
lefts<L, R>(list: Either<L, R>[]): L[]; | ||
/** Takes a list of eithers and returns a list of all `Right` values */ | ||
/** Takes a list of `Either`s and returns a list of all `Right` values */ | ||
rights<L, R>(list: Either<L, R>[]): R[]; | ||
@@ -90,2 +90,3 @@ /** Calls a function and returns a `Right` with the return value or an exception wrapped in a `Left` in case of failure */ | ||
sequence<L, R>(eithers: Either<L, R>[]): Either<L, R[]>; | ||
isEither<L, R>(x: unknown): x is Either<L, R>; | ||
'fantasy-land/of'<L, R>(value: R): Either<L, R>; | ||
@@ -92,0 +93,0 @@ } |
@@ -45,2 +45,5 @@ "use strict"; | ||
}, | ||
isEither(x) { | ||
return x instanceof Left || x instanceof Right; | ||
}, | ||
'fantasy-land/of'(value) { | ||
@@ -54,2 +57,10 @@ return exports.Either.of(value); | ||
this._ = 'R'; | ||
this['fantasy-land/bimap'] = this.bimap; | ||
this['fantasy-land/map'] = this.map; | ||
this['fantasy-land/ap'] = this.ap; | ||
this['fantasy-land/equals'] = this.equals; | ||
this['fantasy-land/chain'] = this.chain; | ||
this['fantasy-land/alt'] = this.alt; | ||
this['fantasy-land/reduce'] = this.reduce; | ||
this['fantasy-land/extend'] = this.extend; | ||
} | ||
@@ -143,26 +154,2 @@ isLeft() { | ||
} | ||
'fantasy-land/bimap'(f, g) { | ||
return this.bimap(f, g); | ||
} | ||
'fantasy-land/map'(f) { | ||
return this.map(f); | ||
} | ||
'fantasy-land/ap'(other) { | ||
return this.ap(other); | ||
} | ||
'fantasy-land/equals'(other) { | ||
return this.equals(other); | ||
} | ||
'fantasy-land/chain'(f) { | ||
return this.chain(f); | ||
} | ||
'fantasy-land/alt'(other) { | ||
return this.alt(other); | ||
} | ||
'fantasy-land/reduce'(reducer, initialValue) { | ||
return this.reduce(reducer, initialValue); | ||
} | ||
'fantasy-land/extend'(f) { | ||
return this.extend(f); | ||
} | ||
} | ||
@@ -224,3 +211,6 @@ Right.prototype.constructor = exports.Either; | ||
unsafeCoerce() { | ||
throw new Error('Either got coerced to a Left'); | ||
if (this.__value instanceof Error) { | ||
throw this.__value; | ||
} | ||
throw new Error('Either#unsafeCoerce was ran on a Left'); | ||
} | ||
@@ -227,0 +217,0 @@ caseOf(patterns) { |
import { Either } from './Either'; | ||
import { MaybeAsync } from './MaybeAsync'; | ||
export interface EitherAsyncTypeRef { | ||
/** Constructs an EitherAsync object from a function that takes an object full of helpers that let you lift things into the EitherAsync context and returns a Promise */ | ||
/** Constructs an `EitherAsync` object from a function that takes an object full of helpers that let you lift things into the `EitherAsync` context and returns a Promise */ | ||
<L, R>(runPromise: (helpers: EitherAsyncHelpers<L>) => PromiseLike<R>): EitherAsync<L, R>; | ||
/** Constructs an EitherAsync object from a function that returns an Either wrapped in a Promise */ | ||
/** Constructs an `EitherAsync` object from a function that returns an Either wrapped in a Promise */ | ||
fromPromise<L, R>(f: () => PromiseLike<Either<L, R>>): EitherAsync<L, R>; | ||
/** Constructs an EitherAsync object from a function that returns a Promise. The left type is defaulted to the built-in Error type */ | ||
/** Constructs an `EitherAsync` object from a function that returns a Promise. The left type is defaulted to the built-in Error type */ | ||
liftPromise<R, L = Error>(f: () => PromiseLike<R>): EitherAsync<L, R>; | ||
/** Constructs an EitherAsync object from an Either */ | ||
/** Constructs an `EitherAsync` object from an Either */ | ||
liftEither<L, R>(either: Either<L, R>): EitherAsync<L, R>; | ||
/** Takes a list of `EitherAsync`s and returns a Promise that will resolve with all `Left` values. Internally it uses `Promise.all` to wait for all results */ | ||
lefts<L, R>(list: EitherAsync<L, R>[]): Promise<L[]>; | ||
/** Takes a list of `EitherAsync`s and returns a Promise that will resolve with all `Right` values. Internally it uses `Promise.all` to wait for all results */ | ||
rights<L, R>(list: EitherAsync<L, R>[]): Promise<R[]>; | ||
/** Turns a list of `EitherAsync`s into an `EitherAsync` of list. The returned `Promise` will be rejected as soon as a single `EitherAsync` resolves to a `Left`, it will not wait for all Promises to resolve and since `EitherAsync` is lazy, unlike `Promise`, the remaining async operations will not be executed at all */ | ||
sequence<L, R>(eas: EitherAsync<L, R>[]): EitherAsync<L, R[]>; | ||
} | ||
@@ -28,3 +34,5 @@ export interface EitherAsync<L, R> extends PromiseLike<Either<L, R>> { | ||
run(): Promise<Either<L, R>>; | ||
/** Transforms the `Right` value of `this` with a given function. If the EitherAsync that is being mapped resolves to a Left then the mapping function won't be called and `run` will resolve the whole thing to that Left, just like the regular Either#map */ | ||
/** Given two functions, maps the value that the Promise inside `this` resolves to using the first if it is `Left` or using the second one if it is `Right` */ | ||
bimap<L2, R2>(f: (value: L) => L2, g: (value: R) => R2): EitherAsync<L2, R2>; | ||
/** Transforms the `Right` value of `this` with a given function. If the `EitherAsync` that is being mapped resolves to a Left then the mapping function won't be called and `run` will resolve the whole thing to that Left, just like the regular Either#map */ | ||
map<R2>(f: (value: R) => R2): EitherAsync<L, R2>; | ||
@@ -37,2 +45,4 @@ /** Maps the `Left` value of `this`, acts like an identity if `this` is `Right` */ | ||
chainLeft<L2>(f: (value: L) => PromiseLike<Either<L2, R>>): EitherAsync<L2, R>; | ||
/** Flattens nested `EitherAsync`s. `e.join()` is equivalent to `e.chain(x => x)` */ | ||
join<R2>(this: EitherAsync<L, EitherAsync<L, R2>>): EitherAsync<L, R2>; | ||
/** Converts `this` to a MaybeAsync, discarding any error values */ | ||
@@ -42,4 +52,22 @@ toMaybeAsync(): MaybeAsync<R>; | ||
swap(): EitherAsync<R, L>; | ||
/** Runs an effect if `this` is `Left`, returns `this` to make chaining other methods possible */ | ||
ifLeft(effect: (value: L) => any): EitherAsync<L, R>; | ||
/** Runs an effect if `this` is `Right`, returns `this` to make chaining other methods possible */ | ||
ifRight(effect: (value: R) => any): EitherAsync<L, R>; | ||
/** Applies a `Right` function wrapped in `EitherAsync` over a future `Right` value. Returns `Left` if either the `this` resolves to a `Left` or the function is `Left` */ | ||
ap<R2>(other: PromiseLike<Either<L, (value: R) => R2>>): EitherAsync<L, R2>; | ||
/** Returns the first `Right` between the future value of `this` and another future `EitherAsync` or the `Left` in the argument if both `this` and the argument resolve to `Left` */ | ||
alt(other: EitherAsync<L, R>): EitherAsync<L, R>; | ||
/** Returns `this` if it resolves to a `Left`, otherwise it returns the result of applying the function argument to `this` and wrapping it in a `Right` */ | ||
extend<R2>(f: (value: EitherAsync<L, R>) => R2): EitherAsync<L, R2>; | ||
/** Returns a Promise that resolves to the value inside `this` if it\'s `Left` or a default value if `this` is `Right` */ | ||
leftOrDefault(defaultValue: L): Promise<L>; | ||
/** Returns a Promise that resolves to the value inside `this` if it\'s `Right` or a default value if `this` is `Left` */ | ||
orDefault(defaultValue: R): Promise<R>; | ||
'fantasy-land/map'<R2>(f: (value: R) => R2): EitherAsync<L, R2>; | ||
'fantasy-land/bimap'<L2, R2>(f: (value: L) => L2, g: (value: R) => R2): EitherAsync<L2, R2>; | ||
'fantasy-land/chain'<R2>(f: (value: R) => PromiseLike<Either<L, R2>>): EitherAsync<L, R2>; | ||
'fantasy-land/ap'<R2>(other: EitherAsync<L, (value: R) => R2>): EitherAsync<L, R2>; | ||
'fantasy-land/alt'(other: EitherAsync<L, R>): EitherAsync<L, R>; | ||
'fantasy-land/extend'<R2>(f: (value: EitherAsync<L, R>) => R2): EitherAsync<L, R2>; | ||
/** WARNING: This is implemented only for Promise compatibility. Please use `chain` instead. */ | ||
@@ -51,5 +79,5 @@ then: PromiseLike<Either<L, R>>['then']; | ||
export interface EitherAsyncHelpers<L> { | ||
/** Allows you to take a regular Either value and lift it to the EitherAsync context. Awaiting a lifted Either will give you the `Right` value inside. If the Either is Left then the function will exit immediately and EitherAsync will resolve to that Left after running it */ | ||
/** Allows you to take a regular Either value and lift it to the `EitherAsync` context. Awaiting a lifted Either will give you the `Right` value inside. If the Either is Left then the function will exit immediately and EitherAsync will resolve to that Left after running it */ | ||
liftEither<R>(either: Either<L, R>): EitherAsyncValue<R>; | ||
/** Allows you to take an Either inside a Promise and lift it to the EitherAsync context. Awaiting a lifted Promise<Either> will give you the `Right` value inside the Either. If the Either is Left or the Promise is rejected then the function will exit immediately and MaybeAsync will resolve to that Left or the rejection value after running it */ | ||
/** Allows you to take an Either inside a Promise and lift it to the `EitherAsync` context. Awaiting a lifted Promise<Either> will give you the `Right` value inside the Either. If the Either is Left or the Promise is rejected then the function will exit immediately and MaybeAsync will resolve to that Left or the rejection value after running it */ | ||
fromPromise<R>(promise: PromiseLike<Either<L, R>>): EitherAsyncValue<R>; | ||
@@ -56,0 +84,0 @@ /** A type safe version of throwing an exception. Unlike the Error constructor, which will take anything, throwE only accepts values of the same type as the Left part of the Either */ |
@@ -24,3 +24,50 @@ "use strict"; | ||
this[Symbol.toStringTag] = 'EitherAsync'; | ||
this['fantasy-land/map'] = this.map; | ||
this['fantasy-land/bimap'] = this.bimap; | ||
this['fantasy-land/chain'] = this.chain; | ||
this['fantasy-land/ap'] = this.ap; | ||
this['fantasy-land/extend'] = this.extend; | ||
this['fantasy-land/alt'] = this.alt; | ||
this.then = (onfulfilled, onrejected) => { | ||
return this.run().then(onfulfilled, onrejected); | ||
}; | ||
} | ||
leftOrDefault(defaultValue) { | ||
return this.run().then((x) => x.leftOrDefault(defaultValue)); | ||
} | ||
orDefault(defaultValue) { | ||
return this.run().then((x) => x.orDefault(defaultValue)); | ||
} | ||
join() { | ||
return exports.EitherAsync(async (helpers) => { | ||
const either = await this.run(); | ||
if (either.isRight()) { | ||
const nestedEither = await either.extract(); | ||
return helpers.liftEither(nestedEither); | ||
} | ||
return helpers.liftEither(either); | ||
}); | ||
} | ||
ap(other) { | ||
return exports.EitherAsync(async (helpers) => { | ||
const [either, o] = await Promise.all([this.run(), other]); | ||
return helpers.liftEither(either.ap(o)); | ||
}); | ||
} | ||
alt(other) { | ||
return exports.EitherAsync(async (helpers) => { | ||
const [either, o] = await Promise.all([this.run(), other]); | ||
return helpers.liftEither(either.alt(o)); | ||
}); | ||
} | ||
extend(f) { | ||
return exports.EitherAsync(async (helpers) => { | ||
const either = await this.run(); | ||
if (either.isRight()) { | ||
const v = exports.EitherAsync.liftEither(either); | ||
return helpers.liftEither(Either_1.Right(f(v))); | ||
} | ||
return helpers.liftEither(either); | ||
}); | ||
} | ||
async run() { | ||
@@ -34,2 +81,8 @@ try { | ||
} | ||
bimap(f, g) { | ||
return exports.EitherAsync(async (helpers) => { | ||
const either = await this.run(); | ||
return helpers.liftEither(either.bimap(f, g)); | ||
}); | ||
} | ||
map(f) { | ||
@@ -78,11 +131,16 @@ return exports.EitherAsync((helpers) => this.runPromise(helpers).then(f)); | ||
} | ||
'fantasy-land/map'(f) { | ||
return this.map(f); | ||
ifLeft(effect) { | ||
return exports.EitherAsync(async (helpers) => { | ||
const either = await this.run(); | ||
either.ifLeft(effect); | ||
return helpers.liftEither(either); | ||
}); | ||
} | ||
'fantasy-land/chain'(f) { | ||
return this.chain(f); | ||
ifRight(effect) { | ||
return exports.EitherAsync(async (helpers) => { | ||
const either = await this.run(); | ||
either.ifRight(effect); | ||
return helpers.liftEither(either); | ||
}); | ||
} | ||
then(onfulfilled, onrejected) { | ||
return this.run().then(onfulfilled, onrejected); | ||
} | ||
} | ||
@@ -92,3 +150,16 @@ exports.EitherAsync = Object.assign((runPromise) => new EitherAsyncImpl(runPromise), { | ||
liftPromise: (f) => exports.EitherAsync(f), | ||
liftEither: (either) => exports.EitherAsync(({ liftEither }) => liftEither(either)) | ||
liftEither: (either) => exports.EitherAsync(({ liftEither }) => liftEither(either)), | ||
lefts: (list) => Promise.all(list.map((x) => x.run())).then(Either_1.Either.lefts), | ||
rights: (list) => Promise.all(list.map((x) => x.run())).then(Either_1.Either.rights), | ||
sequence: (eas) => exports.EitherAsync(async (helpers) => { | ||
let res = []; | ||
for await (const e of eas) { | ||
if (e.isLeft()) { | ||
return helpers.liftEither(e); | ||
} | ||
res.push(e.extract()); | ||
} | ||
return helpers.liftEither(Either_1.Right(res)); | ||
}) | ||
}); | ||
EitherAsyncImpl.prototype.constructor = exports.EitherAsync; |
@@ -10,5 +10,6 @@ "use strict"; | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.EitherAsync = exports.MaybeAsync = void 0; | ||
__exportStar(require("./Codec"), exports); | ||
@@ -15,0 +16,0 @@ __exportStar(require("./Either"), exports); |
@@ -36,3 +36,3 @@ import { Either } from './Either'; | ||
reduce<U>(reducer: (accumulator: U, value: T) => U, initialValue: U): U; | ||
/** Returns `this` if it\'s `Nothing`, otherwise it returns the result of applying the function argument to `this` and wrapping it in a `Just` */ | ||
/** Returns `this` if it's `Nothing`, otherwise it returns the result of applying the function argument to `this` and wrapping it in a `Just` */ | ||
extend<U>(f: (value: Maybe<T>) => U): Maybe<U>; | ||
@@ -93,2 +93,3 @@ /** Returns the value inside `this` or throws an error if `this` is `Nothing` */ | ||
encase<T>(thunk: () => T): Maybe<T>; | ||
isMaybe<T>(x: unknown): x is Maybe<T>; | ||
'fantasy-land/of'<T>(value: T): Maybe<T>; | ||
@@ -127,10 +128,10 @@ 'fantasy-land/empty'(): Nothing; | ||
filter(_: (value: never) => boolean): Maybe<never>; | ||
'fantasy-land/equals'(other: Maybe<never>): boolean; | ||
'fantasy-land/map'<U>(f: (value: never) => U): Maybe<U>; | ||
'fantasy-land/ap'<U>(maybeF: Maybe<(value: never) => U>): Maybe<U>; | ||
'fantasy-land/alt'(other: Maybe<never>): Maybe<never>; | ||
'fantasy-land/chain'<U>(f: (value: never) => Maybe<U>): Maybe<U>; | ||
'fantasy-land/reduce'<U>(reducer: (accumulator: U, value: never) => U, initialValue: U): U; | ||
'fantasy-land/extend'<U>(f: (value: Maybe<never>) => U): Maybe<U>; | ||
'fantasy-land/filter'(pred: (value: never) => boolean): Maybe<never>; | ||
'fantasy-land/equals': <T>(other: Maybe<T>) => boolean; | ||
'fantasy-land/map': <U>(_: (value: never) => U) => Maybe<U>; | ||
'fantasy-land/ap': <U>(_: Maybe<(value: never) => U>) => Maybe<U>; | ||
'fantasy-land/alt': <T>(other: Maybe<T>) => Maybe<T>; | ||
'fantasy-land/chain': <U>(_: (value: never) => Maybe<U>) => Maybe<U>; | ||
'fantasy-land/reduce': <U>(_: (accumulator: U, value: never) => U, initialValue: U) => U; | ||
'fantasy-land/extend': <U>(_: (value: Maybe<never>) => U) => Maybe<U>; | ||
'fantasy-land/filter': (_: (value: never) => boolean) => Maybe<never>; | ||
} | ||
@@ -137,0 +138,0 @@ /** Constructs a Just. Represents an optional value that exists */ |
@@ -54,2 +54,5 @@ "use strict"; | ||
}, | ||
isMaybe(x) { | ||
return x instanceof Just || x instanceof Nothing; | ||
}, | ||
'fantasy-land/of'(value) { | ||
@@ -174,2 +177,12 @@ return this.of(value); | ||
class Nothing { | ||
constructor() { | ||
this['fantasy-land/equals'] = this.equals; | ||
this['fantasy-land/map'] = this.map; | ||
this['fantasy-land/ap'] = this.ap; | ||
this['fantasy-land/alt'] = this.alt; | ||
this['fantasy-land/chain'] = this.chain; | ||
this['fantasy-land/reduce'] = this.reduce; | ||
this['fantasy-land/extend'] = this.extend; | ||
this['fantasy-land/filter'] = this.filter; | ||
} | ||
isJust() { | ||
@@ -218,3 +231,3 @@ return false; | ||
unsafeCoerce() { | ||
throw new Error('Maybe got coerced to a null'); | ||
throw new Error('Maybe#unsafeCoerce was ran on a Nothing'); | ||
} | ||
@@ -254,26 +267,2 @@ caseOf(patterns) { | ||
} | ||
'fantasy-land/equals'(other) { | ||
return this.equals(other); | ||
} | ||
'fantasy-land/map'(f) { | ||
return this.map(f); | ||
} | ||
'fantasy-land/ap'(maybeF) { | ||
return this.ap(maybeF); | ||
} | ||
'fantasy-land/alt'(other) { | ||
return this.alt(other); | ||
} | ||
'fantasy-land/chain'(f) { | ||
return this.chain(f); | ||
} | ||
'fantasy-land/reduce'(reducer, initialValue) { | ||
return this.reduce(reducer, initialValue); | ||
} | ||
'fantasy-land/extend'(f) { | ||
return this.extend(f); | ||
} | ||
'fantasy-land/filter'(pred) { | ||
return this.filter(pred); | ||
} | ||
} | ||
@@ -280,0 +269,0 @@ Nothing.prototype.constructor = exports.Maybe; |
@@ -12,2 +12,4 @@ import { Maybe } from './Maybe'; | ||
liftMaybe<T>(maybe: Maybe<T>): MaybeAsync<T>; | ||
/** Takes a list of `MaybeAsync`s and returns a Promise that will resolve with all `Just` values. Internally it uses `Promise.all` to wait for all results */ | ||
catMaybes<T>(list: MaybeAsync<T>[]): Promise<T[]>; | ||
} | ||
@@ -35,4 +37,24 @@ export interface MaybeAsync<T> extends PromiseLike<Maybe<T>> { | ||
toEitherAsync<L>(error: L): EitherAsync<L, T>; | ||
/** Runs an effect if `this` is `Just`, returns `this` to make chaining other methods possible */ | ||
ifJust(effect: (value: T) => any): MaybeAsync<T>; | ||
/** Runs an effect if `this` is `Nothing`, returns `this` to make chaining other methods possible */ | ||
ifNothing(effect: () => any): MaybeAsync<T>; | ||
/** Returns the default value if `this` is `Nothing`, otherwise it return the value inside `this` */ | ||
orDefault(defaultValue: T): Promise<T>; | ||
/** Maps the future value of `this` with another future `Maybe` function */ | ||
ap<U>(maybeF: MaybeAsync<(value: T) => U>): MaybeAsync<U>; | ||
/** Returns the first `Just` between the future value of `this` and another future `Maybe` or future `Nothing` if both `this` and the argument are `Nothing` */ | ||
alt(other: MaybeAsync<T>): MaybeAsync<T>; | ||
/** Returns `this` if this resolves to `Nothing`, otherwise it returns the future result of applying the function argument to future value `this` and wrapping it in a `Just` */ | ||
extend<U>(f: (value: MaybeAsync<T>) => U): MaybeAsync<U>; | ||
/** Takes a predicate function and returns `this` if the predicate resolved to true or Nothing if it resolves to false */ | ||
filter(pred: (value: T) => boolean): MaybeAsync<T>; | ||
/** Flattens nested Maybes. `m.join()` is equivalent to `m.chain(x => x)` */ | ||
join<U>(this: MaybeAsync<MaybeAsync<U>>): MaybeAsync<U>; | ||
'fantasy-land/map'<U>(f: (value: T) => U): MaybeAsync<U>; | ||
'fantasy-land/chain'<U>(f: (value: T) => PromiseLike<Maybe<U>>): MaybeAsync<U>; | ||
'fantasy-land/ap'<U>(maybeF: MaybeAsync<(value: T) => U>): MaybeAsync<U>; | ||
'fantasy-land/alt'(other: MaybeAsync<T>): MaybeAsync<T>; | ||
'fantasy-land/extend'<U>(f: (value: MaybeAsync<T>) => U): MaybeAsync<U>; | ||
'fantasy-land/filter'(pred: (value: T) => boolean): MaybeAsync<T>; | ||
/** WARNING: This is implemented only for Promise compatibility. Please use `chain` instead. */ | ||
@@ -39,0 +61,0 @@ then: PromiseLike<Maybe<T>>['then']; |
@@ -21,3 +21,52 @@ "use strict"; | ||
this[Symbol.toStringTag] = 'MaybeAsync'; | ||
this['fantasy-land/map'] = this.map; | ||
this['fantasy-land/chain'] = this.chain; | ||
this['fantasy-land/ap'] = this.ap; | ||
this['fantasy-land/filter'] = this.filter; | ||
this['fantasy-land/extend'] = this.extend; | ||
this['fantasy-land/alt'] = this.alt; | ||
} | ||
orDefault(defaultValue) { | ||
return this.run().then((x) => x.orDefault(defaultValue)); | ||
} | ||
join() { | ||
return exports.MaybeAsync(async (helpers) => { | ||
const maybe = await this.run(); | ||
if (maybe.isJust()) { | ||
const nestedMaybe = await maybe.extract(); | ||
return helpers.liftMaybe(nestedMaybe); | ||
} | ||
return helpers.liftMaybe(Maybe_1.Nothing); | ||
}); | ||
} | ||
ap(maybeF) { | ||
return exports.MaybeAsync(async (helpers) => { | ||
const value = await this.run(); | ||
const maybe = await maybeF; | ||
return helpers.liftMaybe(value.ap(maybe)); | ||
}); | ||
} | ||
alt(other) { | ||
return exports.MaybeAsync(async (helpers) => { | ||
const value = await this.run(); | ||
const maybe = await other; | ||
return helpers.liftMaybe(value.alt(maybe)); | ||
}); | ||
} | ||
extend(f) { | ||
return exports.MaybeAsync(async (helpers) => { | ||
const maybe = await this.run(); | ||
if (maybe.isJust()) { | ||
const v = exports.MaybeAsync.liftMaybe(maybe); | ||
return helpers.liftMaybe(Maybe_1.Just(f(v))); | ||
} | ||
return helpers.liftMaybe(Maybe_1.Nothing); | ||
}); | ||
} | ||
filter(pred) { | ||
return exports.MaybeAsync(async (helpers) => { | ||
const value = await this.run(); | ||
return helpers.liftMaybe(value.filter(pred)); | ||
}); | ||
} | ||
async run() { | ||
@@ -46,7 +95,15 @@ try { | ||
} | ||
'fantasy-land/map'(f) { | ||
return this.map(f); | ||
ifJust(effect) { | ||
return exports.MaybeAsync(async (helpers) => { | ||
const maybe = await this.run(); | ||
maybe.ifJust(effect); | ||
return helpers.liftMaybe(maybe); | ||
}); | ||
} | ||
'fantasy-land/chain'(f) { | ||
return this.chain(f); | ||
ifNothing(effect) { | ||
return exports.MaybeAsync(async (helpers) => { | ||
const maybe = await this.run(); | ||
maybe.ifNothing(effect); | ||
return helpers.liftMaybe(maybe); | ||
}); | ||
} | ||
@@ -58,2 +115,3 @@ then(onfulfilled, onrejected) { | ||
exports.MaybeAsync = Object.assign((runPromise) => new MaybeAsyncImpl(runPromise), { | ||
catMaybes: (list) => Promise.all(list).then(Maybe_1.Maybe.catMaybes), | ||
fromPromise: (f) => exports.MaybeAsync(({ fromPromise: fP }) => fP(f())), | ||
@@ -63,1 +121,2 @@ liftPromise: (f) => exports.MaybeAsync(f), | ||
}); | ||
MaybeAsyncImpl.prototype.constructor = exports.MaybeAsync; |
@@ -8,7 +8,8 @@ "use strict"; | ||
fromArray: (source) => exports.NonEmptyList.isNonEmpty(source) ? Maybe_1.Just(source) : Maybe_1.Nothing, | ||
unsafeCoerce: (source) => exports.NonEmptyList.isNonEmpty(source) | ||
? source | ||
: (() => { | ||
throw new Error('NonEmptyList#unsafeCoerce passed an empty array'); | ||
})(), | ||
unsafeCoerce: (source) => { | ||
if (exports.NonEmptyList.isNonEmpty(source)) { | ||
return source; | ||
} | ||
throw new Error('NonEmptyList#unsafeCoerce was ran on an empty array'); | ||
}, | ||
fromTuple: (source) => exports.NonEmptyList(source.toArray()), | ||
@@ -15,0 +16,0 @@ head: (list) => list[0], |
@@ -9,2 +9,7 @@ "use strict"; | ||
this.length = 2; | ||
this['fantasy-land/equals'] = this.equals; | ||
this['fantasy-land/bimap'] = this.bimap; | ||
this['fantasy-land/map'] = this.map; | ||
this['fantasy-land/reduce'] = this.reduce; | ||
this['fantasy-land/ap'] = this.ap; | ||
this[0] = first; | ||
@@ -62,17 +67,2 @@ this[1] = second; | ||
} | ||
'fantasy-land/equals'(other) { | ||
return this.equals(other); | ||
} | ||
'fantasy-land/bimap'(f, g) { | ||
return this.bimap(f, g); | ||
} | ||
'fantasy-land/map'(f) { | ||
return this.map(f); | ||
} | ||
'fantasy-land/reduce'(reducer, initialValue) { | ||
return this.reduce(reducer, initialValue); | ||
} | ||
'fantasy-land/ap'(f) { | ||
return this.ap(f); | ||
} | ||
} | ||
@@ -79,0 +69,0 @@ exports.Tuple = Object.assign((fst, snd) => new TupleImpl(fst, snd), { |
@@ -10,5 +10,6 @@ "use strict"; | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.EitherAsync = exports.MaybeAsync = void 0; | ||
__exportStar(require("./Codec"), exports); | ||
@@ -15,0 +16,0 @@ __exportStar(require("./Either"), exports); |
@@ -36,3 +36,3 @@ import { Either } from './Either'; | ||
reduce<U>(reducer: (accumulator: U, value: T) => U, initialValue: U): U; | ||
/** Returns `this` if it\'s `Nothing`, otherwise it returns the result of applying the function argument to `this` and wrapping it in a `Just` */ | ||
/** Returns `this` if it's `Nothing`, otherwise it returns the result of applying the function argument to `this` and wrapping it in a `Just` */ | ||
extend<U>(f: (value: Maybe<T>) => U): Maybe<U>; | ||
@@ -93,2 +93,3 @@ /** Returns the value inside `this` or throws an error if `this` is `Nothing` */ | ||
encase<T>(thunk: () => T): Maybe<T>; | ||
isMaybe<T>(x: unknown): x is Maybe<T>; | ||
'fantasy-land/of'<T>(value: T): Maybe<T>; | ||
@@ -127,10 +128,10 @@ 'fantasy-land/empty'(): Nothing; | ||
filter(_: (value: never) => boolean): Maybe<never>; | ||
'fantasy-land/equals'(other: Maybe<never>): boolean; | ||
'fantasy-land/map'<U>(f: (value: never) => U): Maybe<U>; | ||
'fantasy-land/ap'<U>(maybeF: Maybe<(value: never) => U>): Maybe<U>; | ||
'fantasy-land/alt'(other: Maybe<never>): Maybe<never>; | ||
'fantasy-land/chain'<U>(f: (value: never) => Maybe<U>): Maybe<U>; | ||
'fantasy-land/reduce'<U>(reducer: (accumulator: U, value: never) => U, initialValue: U): U; | ||
'fantasy-land/extend'<U>(f: (value: Maybe<never>) => U): Maybe<U>; | ||
'fantasy-land/filter'(pred: (value: never) => boolean): Maybe<never>; | ||
'fantasy-land/equals': <T>(other: Maybe<T>) => boolean; | ||
'fantasy-land/map': <U>(_: (value: never) => U) => Maybe<U>; | ||
'fantasy-land/ap': <U>(_: Maybe<(value: never) => U>) => Maybe<U>; | ||
'fantasy-land/alt': <T>(other: Maybe<T>) => Maybe<T>; | ||
'fantasy-land/chain': <U>(_: (value: never) => Maybe<U>) => Maybe<U>; | ||
'fantasy-land/reduce': <U>(_: (accumulator: U, value: never) => U, initialValue: U) => U; | ||
'fantasy-land/extend': <U>(_: (value: Maybe<never>) => U) => Maybe<U>; | ||
'fantasy-land/filter': (_: (value: never) => boolean) => Maybe<never>; | ||
} | ||
@@ -137,0 +138,0 @@ /** Constructs a Just. Represents an optional value that exists */ |
37
Maybe.js
@@ -76,2 +76,5 @@ "use strict"; | ||
}, | ||
isMaybe: function (x) { | ||
return x instanceof Just || x instanceof Nothing; | ||
}, | ||
'fantasy-land/of': function (value) { | ||
@@ -198,2 +201,10 @@ return this.of(value); | ||
function Nothing() { | ||
this['fantasy-land/equals'] = this.equals; | ||
this['fantasy-land/map'] = this.map; | ||
this['fantasy-land/ap'] = this.ap; | ||
this['fantasy-land/alt'] = this.alt; | ||
this['fantasy-land/chain'] = this.chain; | ||
this['fantasy-land/reduce'] = this.reduce; | ||
this['fantasy-land/extend'] = this.extend; | ||
this['fantasy-land/filter'] = this.filter; | ||
} | ||
@@ -243,3 +254,3 @@ Nothing.prototype.isJust = function () { | ||
Nothing.prototype.unsafeCoerce = function () { | ||
throw new Error('Maybe got coerced to a null'); | ||
throw new Error('Maybe#unsafeCoerce was ran on a Nothing'); | ||
}; | ||
@@ -279,26 +290,2 @@ Nothing.prototype.caseOf = function (patterns) { | ||
}; | ||
Nothing.prototype['fantasy-land/equals'] = function (other) { | ||
return this.equals(other); | ||
}; | ||
Nothing.prototype['fantasy-land/map'] = function (f) { | ||
return this.map(f); | ||
}; | ||
Nothing.prototype['fantasy-land/ap'] = function (maybeF) { | ||
return this.ap(maybeF); | ||
}; | ||
Nothing.prototype['fantasy-land/alt'] = function (other) { | ||
return this.alt(other); | ||
}; | ||
Nothing.prototype['fantasy-land/chain'] = function (f) { | ||
return this.chain(f); | ||
}; | ||
Nothing.prototype['fantasy-land/reduce'] = function (reducer, initialValue) { | ||
return this.reduce(reducer, initialValue); | ||
}; | ||
Nothing.prototype['fantasy-land/extend'] = function (f) { | ||
return this.extend(f); | ||
}; | ||
Nothing.prototype['fantasy-land/filter'] = function (pred) { | ||
return this.filter(pred); | ||
}; | ||
return Nothing; | ||
@@ -305,0 +292,0 @@ }()); |
@@ -12,2 +12,4 @@ import { Maybe } from './Maybe'; | ||
liftMaybe<T>(maybe: Maybe<T>): MaybeAsync<T>; | ||
/** Takes a list of `MaybeAsync`s and returns a Promise that will resolve with all `Just` values. Internally it uses `Promise.all` to wait for all results */ | ||
catMaybes<T>(list: MaybeAsync<T>[]): Promise<T[]>; | ||
} | ||
@@ -35,4 +37,24 @@ export interface MaybeAsync<T> extends PromiseLike<Maybe<T>> { | ||
toEitherAsync<L>(error: L): EitherAsync<L, T>; | ||
/** Runs an effect if `this` is `Just`, returns `this` to make chaining other methods possible */ | ||
ifJust(effect: (value: T) => any): MaybeAsync<T>; | ||
/** Runs an effect if `this` is `Nothing`, returns `this` to make chaining other methods possible */ | ||
ifNothing(effect: () => any): MaybeAsync<T>; | ||
/** Returns the default value if `this` is `Nothing`, otherwise it return the value inside `this` */ | ||
orDefault(defaultValue: T): Promise<T>; | ||
/** Maps the future value of `this` with another future `Maybe` function */ | ||
ap<U>(maybeF: MaybeAsync<(value: T) => U>): MaybeAsync<U>; | ||
/** Returns the first `Just` between the future value of `this` and another future `Maybe` or future `Nothing` if both `this` and the argument are `Nothing` */ | ||
alt(other: MaybeAsync<T>): MaybeAsync<T>; | ||
/** Returns `this` if this resolves to `Nothing`, otherwise it returns the future result of applying the function argument to future value `this` and wrapping it in a `Just` */ | ||
extend<U>(f: (value: MaybeAsync<T>) => U): MaybeAsync<U>; | ||
/** Takes a predicate function and returns `this` if the predicate resolved to true or Nothing if it resolves to false */ | ||
filter(pred: (value: T) => boolean): MaybeAsync<T>; | ||
/** Flattens nested Maybes. `m.join()` is equivalent to `m.chain(x => x)` */ | ||
join<U>(this: MaybeAsync<MaybeAsync<U>>): MaybeAsync<U>; | ||
'fantasy-land/map'<U>(f: (value: T) => U): MaybeAsync<U>; | ||
'fantasy-land/chain'<U>(f: (value: T) => PromiseLike<Maybe<U>>): MaybeAsync<U>; | ||
'fantasy-land/ap'<U>(maybeF: MaybeAsync<(value: T) => U>): MaybeAsync<U>; | ||
'fantasy-land/alt'(other: MaybeAsync<T>): MaybeAsync<T>; | ||
'fantasy-land/extend'<U>(f: (value: MaybeAsync<T>) => U): MaybeAsync<U>; | ||
'fantasy-land/filter'(pred: (value: T) => boolean): MaybeAsync<T>; | ||
/** WARNING: This is implemented only for Promise compatibility. Please use `chain` instead. */ | ||
@@ -39,0 +61,0 @@ then: PromiseLike<Maybe<T>>['then']; |
@@ -57,3 +57,97 @@ "use strict"; | ||
this[Symbol.toStringTag] = 'MaybeAsync'; | ||
this['fantasy-land/map'] = this.map; | ||
this['fantasy-land/chain'] = this.chain; | ||
this['fantasy-land/ap'] = this.ap; | ||
this['fantasy-land/filter'] = this.filter; | ||
this['fantasy-land/extend'] = this.extend; | ||
this['fantasy-land/alt'] = this.alt; | ||
} | ||
MaybeAsyncImpl.prototype.orDefault = function (defaultValue) { | ||
return this.run().then(function (x) { return x.orDefault(defaultValue); }); | ||
}; | ||
MaybeAsyncImpl.prototype.join = function () { | ||
var _this = this; | ||
return exports.MaybeAsync(function (helpers) { return __awaiter(_this, void 0, void 0, function () { | ||
var maybe, nestedMaybe; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.run()]; | ||
case 1: | ||
maybe = _a.sent(); | ||
if (!maybe.isJust()) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, maybe.extract()]; | ||
case 2: | ||
nestedMaybe = _a.sent(); | ||
return [2 /*return*/, helpers.liftMaybe(nestedMaybe)]; | ||
case 3: return [2 /*return*/, helpers.liftMaybe(Maybe_1.Nothing)]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
MaybeAsyncImpl.prototype.ap = function (maybeF) { | ||
var _this = this; | ||
return exports.MaybeAsync(function (helpers) { return __awaiter(_this, void 0, void 0, function () { | ||
var value, maybe; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.run()]; | ||
case 1: | ||
value = _a.sent(); | ||
return [4 /*yield*/, maybeF]; | ||
case 2: | ||
maybe = _a.sent(); | ||
return [2 /*return*/, helpers.liftMaybe(value.ap(maybe))]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
MaybeAsyncImpl.prototype.alt = function (other) { | ||
var _this = this; | ||
return exports.MaybeAsync(function (helpers) { return __awaiter(_this, void 0, void 0, function () { | ||
var value, maybe; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.run()]; | ||
case 1: | ||
value = _a.sent(); | ||
return [4 /*yield*/, other]; | ||
case 2: | ||
maybe = _a.sent(); | ||
return [2 /*return*/, helpers.liftMaybe(value.alt(maybe))]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
MaybeAsyncImpl.prototype.extend = function (f) { | ||
var _this = this; | ||
return exports.MaybeAsync(function (helpers) { return __awaiter(_this, void 0, void 0, function () { | ||
var maybe, v; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.run()]; | ||
case 1: | ||
maybe = _a.sent(); | ||
if (maybe.isJust()) { | ||
v = exports.MaybeAsync.liftMaybe(maybe); | ||
return [2 /*return*/, helpers.liftMaybe(Maybe_1.Just(f(v)))]; | ||
} | ||
return [2 /*return*/, helpers.liftMaybe(Maybe_1.Nothing)]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
MaybeAsyncImpl.prototype.filter = function (pred) { | ||
var _this = this; | ||
return exports.MaybeAsync(function (helpers) { return __awaiter(_this, void 0, void 0, function () { | ||
var value; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.run()]; | ||
case 1: | ||
value = _a.sent(); | ||
return [2 /*return*/, helpers.liftMaybe(value.filter(pred))]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
MaybeAsyncImpl.prototype.run = function () { | ||
@@ -112,7 +206,31 @@ return __awaiter(this, void 0, void 0, function () { | ||
}; | ||
MaybeAsyncImpl.prototype['fantasy-land/map'] = function (f) { | ||
return this.map(f); | ||
MaybeAsyncImpl.prototype.ifJust = function (effect) { | ||
var _this = this; | ||
return exports.MaybeAsync(function (helpers) { return __awaiter(_this, void 0, void 0, function () { | ||
var maybe; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.run()]; | ||
case 1: | ||
maybe = _a.sent(); | ||
maybe.ifJust(effect); | ||
return [2 /*return*/, helpers.liftMaybe(maybe)]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
MaybeAsyncImpl.prototype['fantasy-land/chain'] = function (f) { | ||
return this.chain(f); | ||
MaybeAsyncImpl.prototype.ifNothing = function (effect) { | ||
var _this = this; | ||
return exports.MaybeAsync(function (helpers) { return __awaiter(_this, void 0, void 0, function () { | ||
var maybe; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.run()]; | ||
case 1: | ||
maybe = _a.sent(); | ||
maybe.ifNothing(effect); | ||
return [2 /*return*/, helpers.liftMaybe(maybe)]; | ||
} | ||
}); | ||
}); }); | ||
}; | ||
@@ -125,2 +243,5 @@ MaybeAsyncImpl.prototype.then = function (onfulfilled, onrejected) { | ||
exports.MaybeAsync = Object.assign(function (runPromise) { return new MaybeAsyncImpl(runPromise); }, { | ||
catMaybes: function (list) { | ||
return Promise.all(list).then(Maybe_1.Maybe.catMaybes); | ||
}, | ||
fromPromise: function (f) { | ||
@@ -140,1 +261,2 @@ return exports.MaybeAsync(function (_a) { | ||
}); | ||
MaybeAsyncImpl.prototype.constructor = exports.MaybeAsync; |
@@ -11,7 +11,6 @@ "use strict"; | ||
unsafeCoerce: function (source) { | ||
return exports.NonEmptyList.isNonEmpty(source) | ||
? source | ||
: (function () { | ||
throw new Error('NonEmptyList#unsafeCoerce passed an empty array'); | ||
})(); | ||
if (exports.NonEmptyList.isNonEmpty(source)) { | ||
return source; | ||
} | ||
throw new Error('NonEmptyList#unsafeCoerce was ran on an empty array'); | ||
}, | ||
@@ -18,0 +17,0 @@ fromTuple: function (source) { |
{ | ||
"name": "purify-ts", | ||
"version": "0.16.0-beta.5", | ||
"version": "0.16.0-beta.6", | ||
"description": "Functional programming standard library for TypeScript ", | ||
@@ -31,6 +31,6 @@ "main": "index.js", | ||
"@types/jest": "^26.0.0", | ||
"jest": "26.1.0", | ||
"jest": "26.6.1", | ||
"prettier": "^2.0.1", | ||
"ts-jest": "26.1.3", | ||
"typescript": "3.9.7" | ||
"ts-jest": "26.4.3", | ||
"typescript": "4.0.5" | ||
}, | ||
@@ -37,0 +37,0 @@ "dependencies": { |
@@ -48,2 +48,3 @@ <h3 align="center"> | ||
- [chai-purify](https://github.com/dave-inc/chai-purify) - Chai assert helpers | ||
- [purifree](https://github.com/nythrox/purifree) - A fork that allows you to program in a point-free style, and adds a few new capabilities | ||
@@ -50,0 +51,0 @@ # Inspired by |
20
Tuple.js
@@ -52,2 +52,7 @@ "use strict"; | ||
this.length = 2; | ||
this['fantasy-land/equals'] = this.equals; | ||
this['fantasy-land/bimap'] = this.bimap; | ||
this['fantasy-land/map'] = this.map; | ||
this['fantasy-land/reduce'] = this.reduce; | ||
this['fantasy-land/ap'] = this.ap; | ||
this[0] = first; | ||
@@ -114,17 +119,2 @@ this[1] = second; | ||
}; | ||
TupleImpl.prototype['fantasy-land/equals'] = function (other) { | ||
return this.equals(other); | ||
}; | ||
TupleImpl.prototype['fantasy-land/bimap'] = function (f, g) { | ||
return this.bimap(f, g); | ||
}; | ||
TupleImpl.prototype['fantasy-land/map'] = function (f) { | ||
return this.map(f); | ||
}; | ||
TupleImpl.prototype['fantasy-land/reduce'] = function (reducer, initialValue) { | ||
return this.reduce(reducer, initialValue); | ||
}; | ||
TupleImpl.prototype['fantasy-land/ap'] = function (f) { | ||
return this.ap(f); | ||
}; | ||
return TupleImpl; | ||
@@ -131,0 +121,0 @@ }()); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
228268
5032
55
0