securityos/node_modules/true-myth/dist/cjs/result.js

642 lines
21 KiB
JavaScript

"use strict";
/** [[include:doc/result.md]] */
Object.defineProperty(exports, "__esModule", { value: true });
/** (keep typedoc from getting confused by the import) */
const Maybe = require("./maybe");
const unit_1 = require("./unit");
const utils_1 = require("./utils");
// So that it doesn't appear unused but can be exported.
utils_1._Brand; // tslint:disable-line:no-unused-expression
/**
Discriminant for `Ok` and `Err` variants of `Result` type.
You can use the discriminant via the `variant` property of `Result` instances
if you need to match explicitly on it.
*/
var Variant;
(function (Variant) {
Variant["Ok"] = "Ok";
Variant["Err"] = "Err";
})(Variant = exports.Variant || (exports.Variant = {}));
/**
An `Ok` instance is the *successful* variant instance of the
[`Result`](../modules/_result_.html#result) type, representing a successful
outcome from an operation which may fail. For a full discussion, see [the
module docs](../modules/_result_.html).
@typeparam T The type wrapped in this `Ok` variant of `Result`.
@typeparam E The type which would be wrapped in an `Err` variant of `Result`.
*/
class Ok {
/**
Create an instance of `Result.Ok` with `new`.
Note: While you *may* create the `Result` type via normal
JavaScript class construction, it is not recommended for the functional
style for which the library is intended. Instead, use [`Result.ok`].
[`Result.ok`]: ../modules/_result_.html#ok
```ts
// Avoid:
const aString = new Result.Ok('characters');
// Prefer:
const aString = Result.ok('characters);
```
Note that you may explicitly pass `Unit` to the `Ok` constructor to create
a `Result<Unit, E>`. However, you may *not* call the `Ok` constructor with
`null` or `undefined` to get that result (the type system won't allow you to
construct it that way). Instead, for convenience, you can simply call
`Result.ok()`, which will construct the type correctly.
@param value
The value to wrap in a `Result.Ok`.
Note: `null` and `undefined` are allowed by the type signature so that the
constructor may `throw` on those rather than constructing a type like
`Result<undefined>`.
@throws If you pass `null`.
*/
constructor(value) {
/** `Ok` is always [`Variant.Ok`](../enums/_result_.variant#ok). */
this.variant = Variant.Ok;
if (utils_1.isVoid(value)) {
throw new Error('Tried to construct `Ok` with `null` or `undefined`. Maybe you want `Maybe.Nothing`?');
}
this.value = value;
}
/**
Unwrap the contained value. A convenience method for functional idioms.
A common scenario where you might want to use this is in a pipeline of
functions:
```ts
import Result, { Ok } from 'true-myth/result';
function getLengths(results: Array<Result<string, string>>): Array<number> {
return results
.filter(Result.isOk)
.map(Ok.unwrap)
.map(s => s.length);
}
```
*/
static unwrap(theOk) {
return theOk.value;
}
/** Method variant for [`Result.isOk`](../modules/_result_.html#isok) */
isOk() {
return true;
}
/** Method variant for [`Result.isErr`](../modules/_result_.html#iserr) */
isErr() {
return false;
}
/** Method variant for [`Result.map`](../modules/_result_.html#map) */
map(mapFn) {
return map(mapFn, this);
}
/** Method variant for [`Result.mapOr`](../modules/_result_.html#mapor) */
mapOr(orU, mapFn) {
return mapOr(orU, mapFn, this);
}
/** Method variant for [`Result.mapOrElse`](../modules/_result_.html#maporelse) */
mapOrElse(orElseFn, mapFn) {
return mapOrElse(orElseFn, mapFn, this);
}
/** Method variant for [`Result.match`](../modules/_result_.html#match) */
match(matcher) {
return match(matcher, this);
}
/** Method variant for [`Result.mapErr`](../modules/_result_.html#maperr) */
mapErr(mapErrFn) {
return mapErr(mapErrFn, this);
}
/** Method variant for [`Result.or`](../modules/_result_.html#or) */
or(orResult) {
return or(orResult, this);
}
/** Method variant for [`Result.orElse`](../modules/_result_.html#orelse) */
orElse(orElseFn) {
return orElse(orElseFn, this);
}
/** Method variant for [`Result.and`](../modules/_result_.html#and) */
and(mAnd) {
return and(mAnd, this);
}
/** Method variant for [`Result.andThen`](../modules/_result_.html#andthen) */
andThen(andThenFn) {
return andThen(andThenFn, this);
}
/** Method variant for [`Result.chain`](../modules/_result_.html#chain) */
chain(chainFn) {
return exports.chain(chainFn, this);
}
/** Method variant for [`Result.flatMap`](../modules/_result_.html#flatmap) */
flatMap(flatMapFn) {
return exports.flatMap(flatMapFn, this);
}
/** Method variant for [`Result.unwrap`](../modules/_result_.html#unwrap) */
unsafelyUnwrap() {
return this.value;
}
/** Method variant for [`Result.unwrapErr`](../modules/_result_.html#unwraperr) */
unsafelyUnwrapErr() {
throw new Error('Tried to `unsafelyUnwrapErr` an `Ok`');
}
/** Method variant for [`Result.unwrapOr`](../modules/_result_.html#unwrapor) */
unwrapOr(defaultValue) {
return unwrapOr(defaultValue, this);
}
/** Method variant for [`Result.unwrapOrElse`](../modules/_result_.html#unwrapOrElse) */
unwrapOrElse(elseFn) {
return unwrapOrElse(elseFn, this);
}
/** Method variant for [`Result.toMaybe`](../modules/_result_.html#tomaybe) */
toMaybe() {
return toMaybe(this);
}
/** Method variant for [`Result.toString`](../modules/_result_.html#tostring) */
toString() {
return exports.toString(this);
}
/** Method variant for [`Result.toJSON`](../modules/_result_.html#toJSON) */
toJSON() {
return exports.toJSON(this);
}
/** Method variant for [`Result.equals`](../modules/_result_.html#equals) */
equals(comparison) {
return equals(comparison, this);
}
/** Method variant for [`Result.ap`](../modules/_result_.html#ap) */
ap(r) {
return ap(this, r);
}
}
exports.Ok = Ok;
/**
An `Err` instance is the *failure* variant instance of the
[`Result`](../modules/_result_.html#result) type, representing a failure
outcome from an operation which may fail. For a full discussion, see [the
module docs](../modules/_result_.html).
@typeparam T The type which would be wrapped in an `Ok` variant of `Result`.
@typeparam E The type wrapped in this `Err` variant of `Result`.
*/
class Err {
/**
Create an instance of `Result.Err` with `new`.
Note: While you *may* create the `Result` type via normal
JavaScript class construction, it is not recommended for the functional
style for which the library is intended. Instead, use [`Result.err`].
[`Result.err`]: ../modules/_result_.html#err
```ts
// Avoid:
const anErr = new Result.Err('alas, failure');
// Prefer:
const anErr = Result.err('alas, failure');
```
Note that you may explicitly pass `Unit` to the `Err` constructor to create
a `Result<T, Unit>`. However, you may *not* call the `Err` constructor with
`null` or `undefined` to get that result (the type system won't allow you to
construct it that way). Instead, for convenience, you can simply call
`Result.err()`, which will construct the type correctly.
@param error
The value to wrap in a `Result.Err`.
`Note: null` and `undefined` are allowed by the type signature so that the
constructor may `throw` on those rather than constructing a type like
`Result<number, undefined>`.
@throws If you pass `null` or `undefined`.
*/
constructor(error) {
/** `Err` is always [`Variant.Err`](../enums/_result_.variant#err). */
this.variant = Variant.Err;
if (utils_1.isVoid(error)) {
throw new Error('Tried to construct `Err` with `null` or `undefined`. Maybe you want `Maybe.Nothing`?');
}
this.error = error;
}
/**
Unwrap the contained error . A convenience method for functional idioms.
A common scenario where you might want to use this is in a pipeline of
functions:
```ts
import Result, { Ok } from 'true-myth/result';
function getMessages(results: Array<Result<string, Error>>): Array<number> {
return maybeStrings
.filter(Result.isErr)
.map(Err.unwrapErr)
.map(e => e.message);
}
```
*/
static unwrapErr(theErr) {
return theErr.error;
}
/** Method variant for [`Result.isOk`](../modules/_result_.html#isok) */
isOk() {
return false;
}
/** Method variant for [`Result.isErr`](../modules/_result_.html#iserr) */
isErr() {
return true;
}
/** Method variant for [`Result.map`](../modules/_result_.html#map) */
map(mapFn) {
return map(mapFn, this);
}
/** Method variant for [`Result.mapOr`](../modules/_result_.html#mapor) */
mapOr(orU, mapFn) {
return mapOr(orU, mapFn, this);
}
/** Method variant for [`Result.mapOrElse`](../modules/_result_.html#maporelse) */
mapOrElse(orElseFn, mapFn) {
return mapOrElse(orElseFn, mapFn, this);
}
/** Method variant for [`Result.match`](../modules/_result_.html#match) */
match(matchObj) {
return match(matchObj, this);
}
/** Method variant for [`Result.mapErr`](../modules/_result_.html#maperr) */
mapErr(mapErrFn) {
return mapErr(mapErrFn, this);
}
/** Method variant for [`Result.or`](../modules/_result_.html#or) */
or(orResult) {
return or(orResult, this);
}
/** Method variant for [`Result.orElse`](../modules/_result_.html#orelse) */
orElse(orElseFn) {
return orElse(orElseFn, this);
}
/** Method variant for [`Result.and`](../modules/_result_.html#and) */
and(mAnd) {
return and(mAnd, this);
}
/** Method variant for [`Result.andThen`](../modules/_result_.html#andthen) */
andThen(andThenFn) {
return andThen(andThenFn, this);
}
/** Method variant for [`Result.chain`](../modules/_result_.html#chain) */
chain(chainFn) {
return this.andThen(chainFn);
}
/** Method variant for [`Result.flatMap`](../modules/_result_.html#flatmap) */
flatMap(flatMapFn) {
return this.andThen(flatMapFn);
}
/** Method variant for [`Result.unsafelyUnwrap`](../modules/_result_.html#unsafelyunwrap) */
unsafelyUnwrap() {
throw new Error('Tried to `unsafelyUnwrap an Err`');
}
/** Method variant for [`Result.unsafelyUnwrapErr`](../modules/_result_.html#unsafelyunwraperr) */
unsafelyUnwrapErr() {
return this.error;
}
/** Method variant for [`Result.unwrapOr`](../modules/_result_.html#unwrapor) */
unwrapOr(defaultValue) {
return unwrapOr(defaultValue, this);
}
/** Method variant for [`Result.unwrapOrElse`](../modules/_result_.html#unwraporelse) */
unwrapOrElse(elseFn) {
return unwrapOrElse(elseFn, this);
}
/** Method variant for [`Result.toMaybe`](../modules/_result_.html#tomaybe) */
toMaybe() {
return toMaybe(this);
}
/** Method variant for [`Result.toString`](../modules/_result_.html#tostring) */
toString() {
return exports.toString(this);
}
/** Method variant for [`Result.toJSON`](../modules/_result_.html#toJSON) */
toJSON() {
return exports.toJSON(this);
}
/** Method variant for [`Result.equals`](../modules/_result_.html#equals) */
equals(comparison) {
return equals(comparison, this);
}
/** Method variant for [`Result.ap`](../modules/_result_.html#ap) */
ap(r) {
return ap(this, r);
}
}
exports.Err = Err;
/**
Is this `Result` an `Ok` instance?
In TypeScript, narrows the type from `Result<T, E>` to `Ok<T, E>`.
*/
function isOk(result) {
return result.variant === Variant.Ok;
}
exports.isOk = isOk;
/**
Is this `Result` an `Err` instance?
In TypeScript, narrows the type from `Result<T, E>` to `Err<T, E>`.
*/
function isErr(result) {
return result.variant === Variant.Err;
}
exports.isErr = isErr;
function ok(value) {
return value === undefined ? new Ok(unit_1.default) : new Ok(value);
}
exports.ok = ok;
/** `Result.of` is an alias for `Result.ok`. */
exports.of = ok;
function err(error) {
return utils_1.isVoid(error) ? new Err(unit_1.default) : new Err(error);
}
exports.err = err;
function tryOr(error, callback) {
const op = (cb) => {
try {
return exports.Result.ok(cb());
}
catch (_a) {
return exports.Result.err(error);
}
};
return utils_1.curry1(op, callback);
}
exports.tryOr = tryOr;
function tryOrElse(onError, callback) {
const op = (cb) => {
try {
return exports.Result.ok(cb());
}
catch (e) {
return exports.Result.err(onError(e));
}
};
return utils_1.curry1(op, callback);
}
exports.tryOrElse = tryOrElse;
function map(mapFn, result) {
const op = (r) => (isOk(r) ? ok(mapFn(r.value)) : r);
return utils_1.curry1(op, result);
}
exports.map = map;
function mapOr(orU, mapFn, result) {
function fullOp(fn, r) {
return isOk(r) ? fn(r.value) : orU;
}
function partialOp(fn, curriedResult) {
return curriedResult !== undefined
? fullOp(fn, curriedResult)
: (extraCurriedResult) => fullOp(fn, extraCurriedResult);
}
return mapFn === undefined
? partialOp
: result === undefined
? partialOp(mapFn)
: partialOp(mapFn, result);
}
exports.mapOr = mapOr;
function mapOrElse(orElseFn, mapFn, result) {
function fullOp(fn, r) {
return isOk(r) ? fn(r.value) : orElseFn(r.error);
}
function partialOp(fn, curriedResult) {
return curriedResult !== undefined
? fullOp(fn, curriedResult)
: (extraCurriedResult) => fullOp(fn, extraCurriedResult);
}
return mapFn === undefined
? partialOp
: result === undefined
? partialOp(mapFn)
: partialOp(mapFn, result);
}
exports.mapOrElse = mapOrElse;
function mapErr(mapErrFn, result) {
const op = (r) => (isOk(r) ? r : err(mapErrFn(r.error)));
return utils_1.curry1(op, result);
}
exports.mapErr = mapErr;
function and(andResult, result) {
const op = (r) => (isOk(r) ? andResult : r);
return utils_1.curry1(op, result);
}
exports.and = and;
function andThen(thenFn, result) {
const op = (r) => (isOk(r) ? thenFn(r.value) : r);
return utils_1.curry1(op, result);
}
exports.andThen = andThen;
/** Alias for [`andThen`](#andthen). */
exports.chain = andThen;
/** Alias for [`andThen`](#andthen). */
exports.flatMap = andThen;
function or(defaultResult, result) {
const op = (r) => (isOk(r) ? r : defaultResult);
return utils_1.curry1(op, result);
}
exports.or = or;
function orElse(elseFn, result) {
const op = (r) => (isOk(r) ? r : elseFn(r.unsafelyUnwrapErr()));
return utils_1.curry1(op, result);
}
exports.orElse = orElse;
/**
Get the value out of the `Result`.
Returns the content of an `Ok`, but **throws if the `Result` is `Err`.**
Prefer to use [`unwrapOr`](#unwrapor) or [`unwrapOrElse`](#unwraporelse).
@throws If the `Result` instance is `Nothing`.
*/
function unsafelyUnwrap(result) {
return result.unsafelyUnwrap();
}
exports.unsafelyUnwrap = unsafelyUnwrap;
/** Alias for [`unsafelyUnwrap`](#unsafelyunwrap) */
exports.unsafelyGet = unsafelyUnwrap;
/** Alias for [`unsafelyUnwrap`](#unsafelyunwrap) */
exports.unsafeGet = unsafelyUnwrap;
/**
Get the error value out of the [`Result`](#result).
Returns the content of an `Err`, but **throws if the `Result` is `Ok`**.
Prefer to use [`unwrapOrElse`](#unwraporelse).
@param result
@throws Error If the `Result` instance is `Nothing`.
*/
function unsafelyUnwrapErr(result) {
return result.unsafelyUnwrapErr();
}
exports.unsafelyUnwrapErr = unsafelyUnwrapErr;
/** Alias for [`unsafelyUnwrapErr`](#unsafelyunwraperr) */
exports.unsafelyGetErr = unsafelyUnwrapErr;
function unwrapOr(defaultValue, result) {
const op = (r) => (isOk(r) ? r.value : defaultValue);
return utils_1.curry1(op, result);
}
exports.unwrapOr = unwrapOr;
/** Alias for [`unwrapOr`](#unwrapor) */
exports.getOr = unwrapOr;
function unwrapOrElse(orElseFn, result) {
const op = (r) => (isOk(r) ? r.value : orElseFn(r.error));
return utils_1.curry1(op, result);
}
exports.unwrapOrElse = unwrapOrElse;
/** Alias for [`unwrapOrElse`](#unwraporelse) */
exports.getOrElse = unwrapOrElse;
/**
Convert a [`Result`](#result) to a [`Maybe`](../modules/_maybe_.html#maybe).
The converted type will be [`Just`] if the `Result` is [`Ok`] or [`Nothing`]
if the `Result` is [`Err`]; the wrapped error value will be discarded.
[`Just`]: ../classes/_maybe_.just.html
[`Nothing`]: ../classes/_maybe_.nothing.html
[`Ok`]: ../classes/_result_.ok.html
[`Err`]: ../classes/_result_.err.html
@param result The `Result` to convert to a `Maybe`
@returns `Just` the value in `result` if it is `Ok`; otherwise `Nothing`
*/
function toMaybe(result) {
return isOk(result) ? Maybe.just(result.value) : Maybe.nothing();
}
exports.toMaybe = toMaybe;
function fromMaybe(errValue, maybe) {
const op = (m) => Maybe.isJust(m) ? ok(Maybe.unsafelyUnwrap(m)) : err(errValue);
return utils_1.curry1(op, maybe);
}
exports.fromMaybe = fromMaybe;
/**
Create a `String` representation of a `result` instance.
An `Ok` instance will be printed as `Ok(<representation of the value>)`, and
an `Err` instance will be printed as `Err(<representation of the error>)`,
where the representation of the value or error is simply the value or error's
own `toString` representation. For example:
call | output
--------------------------------- | ----------------------
`toString(ok(42))` | `Ok(42)`
`toString(ok([1, 2, 3]))` | `Ok(1,2,3)`
`toString(ok({ an: 'object' }))` | `Ok([object Object])`n
`toString(err(42))` | `Err(42)`
`toString(err([1, 2, 3]))` | `Err(1,2,3)`
`toString(err({ an: 'object' }))` | `Err([object Object])`
@typeparam T The type of the wrapped value; its own `.toString` will be used
to print the interior contents of the `Just` variant.
@param maybe The value to convert to a string.
@returns The string representation of the `Maybe`.
*/
exports.toString = (result) => {
const body = (isOk(result) ? result.value : result.error).toString();
return `${result.variant.toString()}(${body})`;
};
/**
* Create an `Object` representation of a `Result` instance.
*
* Useful for serialization. `JSON.stringify()` uses it.
*
* @param result The value to convert to JSON
* @returns The JSON representation of the `Result`
*/
exports.toJSON = (result) => {
return result.isOk()
? { variant: result.variant, value: result.value }
: { variant: result.variant, error: result.error };
};
function match(matcher, result) {
const op = (r) => mapOrElse(matcher.Err, matcher.Ok, r);
return utils_1.curry1(op, result);
}
exports.match = match;
/** Alias for [`match`](#match) */
exports.cata = match;
function equals(resultB, resultA) {
return resultA !== undefined
? resultA.match({
Err: () => isErr(resultB),
Ok: a => isOk(resultB) && resultB.unsafelyUnwrap() === a,
})
: (curriedResultA) => curriedResultA.match({
Err: () => isErr(resultB),
Ok: a => isOk(resultB) && resultB.unsafelyUnwrap() === a,
});
}
exports.equals = equals;
function ap(resultFn, result) {
const op = (r) => r.match({
Ok: val => resultFn.map(fn => fn(val)),
Err: e => exports.Result.err(e),
});
return utils_1.curry1(op, result);
}
exports.ap = ap;
/**
Determine whether an item is an instance of `Just` or `Nothing`.
@param item The item to check.
*/
function isInstance(item) {
return item instanceof Ok || item instanceof Err;
}
exports.isInstance = isInstance;
exports.Result = {
Variant,
Ok,
Err,
isOk,
isErr,
ok,
err,
tryOr,
tryOrElse,
map,
mapOr,
mapOrElse,
mapErr,
and,
andThen,
chain: exports.chain,
flatMap: exports.flatMap,
or,
orElse,
unsafelyUnwrap,
unsafelyGet: exports.unsafelyGet,
unsafeGet: exports.unsafeGet,
unsafelyUnwrapErr,
unsafelyGetErr: exports.unsafelyGetErr,
unwrapOr,
getOr: exports.getOr,
unwrapOrElse,
getOrElse: exports.getOrElse,
toMaybe,
fromMaybe,
toString: exports.toString,
toJSON: exports.toJSON,
match,
cata: exports.cata,
equals,
ap,
isInstance,
};
exports.default = exports.Result;
//# sourceMappingURL=result.js.map