decoders 2.0.0-beta5 → 2.0.0-beta9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/NotSupportedTSVersion.d.ts +1 -0
- package/README.md +934 -387
- package/_guard.d.ts +7 -0
- package/_guard.js +2 -6
- package/_guard.js.flow +3 -3
- package/{_esm/_guard.js → _guard.mjs} +3 -3
- package/_types.d.ts +13 -0
- package/{_esm/_types.js → _types.mjs} +0 -0
- package/_utils.d.ts +10 -0
- package/_utils.js +1 -1
- package/_utils.js.flow +3 -3
- package/{_esm/_utils.js → _utils.mjs} +1 -1
- package/annotate.d.ts +62 -0
- package/{_esm/annotate.js → annotate.mjs} +0 -0
- package/core/_helpers.d.ts +79 -0
- package/core/array.d.ts +8 -0
- package/core/array.js +19 -12
- package/core/array.js.flow +15 -11
- package/{_esm/core/array.js → core/array.mjs} +19 -10
- package/core/boolean.d.ts +5 -0
- package/core/boolean.js +5 -9
- package/core/boolean.js.flow +5 -7
- package/{_esm/core/boolean.js → core/boolean.mjs} +7 -7
- package/core/composition.d.ts +18 -0
- package/core/composition.js +41 -15
- package/core/composition.js.flow +41 -10
- package/core/composition.mjs +70 -0
- package/core/constants.d.ts +11 -0
- package/core/constants.js +6 -10
- package/core/constants.js.flow +7 -9
- package/{_esm/core/constants.js → core/constants.mjs} +7 -7
- package/core/date.d.ts +4 -0
- package/core/date.js +5 -9
- package/core/date.js.flow +4 -6
- package/{_esm/core/date.js → core/date.mjs} +7 -7
- package/core/describe.d.ts +3 -0
- package/core/describe.js +2 -6
- package/core/describe.js.flow +2 -2
- package/{_esm/core/describe.js → core/describe.mjs} +3 -3
- package/core/dispatch.d.ts +8 -0
- package/core/dispatch.js +11 -13
- package/core/dispatch.js.flow +13 -12
- package/{_esm/core/dispatch.js → core/dispatch.mjs} +12 -11
- package/core/either.d.ts +66 -0
- package/core/either.js +34 -50
- package/core/either.js.flow +40 -86
- package/core/either.mjs +90 -0
- package/core/fail.d.ts +3 -0
- package/core/fail.js +2 -6
- package/core/fail.js.flow +2 -2
- package/{_esm/core/fail.js → core/fail.mjs} +3 -3
- package/core/instanceOf.d.ts +3 -0
- package/core/instanceOf.js +2 -6
- package/core/instanceOf.js.flow +3 -3
- package/core/instanceOf.mjs +8 -0
- package/core/json.d.ts +11 -0
- package/core/json.js +3 -3
- package/core/json.js.flow +3 -3
- package/core/json.mjs +15 -0
- package/core/lazy.d.ts +3 -0
- package/{_esm/core/lazy.js → core/lazy.mjs} +0 -0
- package/core/number.d.ts +6 -0
- package/core/number.js +9 -13
- package/core/number.js.flow +18 -12
- package/core/number.mjs +25 -0
- package/core/object.d.ts +38 -0
- package/core/object.js +66 -13
- package/core/object.js.flow +84 -28
- package/{_esm/core/object.js → core/object.mjs} +64 -11
- package/core/optional.d.ts +5 -0
- package/core/optional.js +4 -8
- package/core/optional.js.flow +3 -3
- package/{_esm/core/optional.js → core/optional.mjs} +6 -6
- package/core/string.d.ts +13 -0
- package/core/string.js +31 -49
- package/core/string.js.flow +29 -39
- package/core/string.mjs +58 -0
- package/core/tuple.d.ts +30 -0
- package/core/tuple.js +30 -149
- package/core/tuple.js.flow +33 -197
- package/core/tuple.mjs +45 -0
- package/format.d.ts +4 -0
- package/{format/inline.js → format.js} +6 -1
- package/{_esm/format/inline.js.flow → format.js.flow} +6 -2
- package/{_esm/format/inline.js → format.mjs} +4 -1
- package/index.d.ts +42 -0
- package/index.js +33 -42
- package/index.js.flow +17 -18
- package/{_esm/index.js → index.mjs} +18 -19
- package/package.json +15 -3
- package/result.d.ts +39 -0
- package/result.js +9 -90
- package/result.js.flow +11 -87
- package/result.mjs +81 -0
- package/_esm/_guard.js.flow +0 -20
- package/_esm/_types.js.flow +0 -20
- package/_esm/_utils.js.flow +0 -97
- package/_esm/annotate.js.flow +0 -218
- package/_esm/core/array.js.flow +0 -103
- package/_esm/core/boolean.js.flow +0 -29
- package/_esm/core/composition.js +0 -42
- package/_esm/core/composition.js.flow +0 -43
- package/_esm/core/constants.js.flow +0 -46
- package/_esm/core/date.js.flow +0 -40
- package/_esm/core/describe.js.flow +0 -17
- package/_esm/core/dispatch.js.flow +0 -58
- package/_esm/core/either.js +0 -90
- package/_esm/core/either.js.flow +0 -151
- package/_esm/core/fail.js.flow +0 -12
- package/_esm/core/instanceOf.js +0 -8
- package/_esm/core/instanceOf.js.flow +0 -20
- package/_esm/core/json.js +0 -15
- package/_esm/core/json.js.flow +0 -28
- package/_esm/core/lazy.js.flow +0 -15
- package/_esm/core/mapping.js +0 -54
- package/_esm/core/mapping.js.flow +0 -54
- package/_esm/core/number.js +0 -25
- package/_esm/core/number.js.flow +0 -34
- package/_esm/core/object.js.flow +0 -203
- package/_esm/core/optional.js.flow +0 -41
- package/_esm/core/string.js +0 -76
- package/_esm/core/string.js.flow +0 -82
- package/_esm/core/tuple.js +0 -155
- package/_esm/core/tuple.js.flow +0 -215
- package/_esm/format/index.js +0 -2
- package/_esm/format/index.js.flow +0 -4
- package/_esm/format/short.js +0 -4
- package/_esm/format/short.js.flow +0 -8
- package/_esm/index.js.flow +0 -63
- package/_esm/result.js +0 -148
- package/_esm/result.js.flow +0 -174
- package/core/mapping.js +0 -67
- package/core/mapping.js.flow +0 -54
- package/format/index.js +0 -12
- package/format/index.js.flow +0 -4
- package/format/inline.js.flow +0 -122
- package/format/short.js +0 -10
- package/format/short.js.flow +0 -8
package/_guard.d.ts
ADDED
package/_guard.js
CHANGED
|
@@ -3,13 +3,9 @@
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.guard = guard;
|
|
5
5
|
|
|
6
|
-
var Result = _interopRequireWildcard(require("./result"));
|
|
7
|
-
|
|
8
6
|
var _format = require("./format");
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
8
|
+
var _result = require("./result");
|
|
13
9
|
|
|
14
10
|
function guard(decoder, formatter) {
|
|
15
11
|
if (formatter === void 0) {
|
|
@@ -17,7 +13,7 @@ function guard(decoder, formatter) {
|
|
|
17
13
|
}
|
|
18
14
|
|
|
19
15
|
return function (blob) {
|
|
20
|
-
return
|
|
16
|
+
return (0, _result.unwrap)((0, _result.mapError)(decoder(blob), function (annotation) {
|
|
21
17
|
var err = new Error('\n' + formatter(annotation));
|
|
22
18
|
err.name = 'Decoding error';
|
|
23
19
|
return err;
|
package/_guard.js.flow
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
|
|
3
|
-
import * as Result from './result';
|
|
4
3
|
import { formatInline } from './format';
|
|
4
|
+
import { mapError, unwrap } from './result';
|
|
5
5
|
import type { Annotation } from './annotate';
|
|
6
6
|
import type { Decoder, Guard } from './_types';
|
|
7
7
|
|
|
@@ -10,8 +10,8 @@ export function guard<T>(
|
|
|
10
10
|
formatter: (Annotation) => string = formatInline,
|
|
11
11
|
): Guard<T> {
|
|
12
12
|
return (blob: mixed) =>
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
unwrap(
|
|
14
|
+
mapError(decoder(blob), (annotation) => {
|
|
15
15
|
const err = new Error('\n' + formatter(annotation));
|
|
16
16
|
err.name = 'Decoding error';
|
|
17
17
|
return err;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { formatInline } from './format.mjs';
|
|
2
|
+
import { mapError, unwrap } from './result.mjs';
|
|
3
3
|
export function guard(decoder, formatter) {
|
|
4
4
|
if (formatter === void 0) {
|
|
5
5
|
formatter = formatInline;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
return function (blob) {
|
|
9
|
-
return
|
|
9
|
+
return unwrap(mapError(decoder(blob), function (annotation) {
|
|
10
10
|
var err = new Error('\n' + formatter(annotation));
|
|
11
11
|
err.name = 'Decoding error';
|
|
12
12
|
return err;
|
package/_types.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Annotation } from './annotate';
|
|
2
|
+
import { Result } from './result';
|
|
3
|
+
|
|
4
|
+
export type Scalar = string | number | boolean | symbol | undefined | null;
|
|
5
|
+
|
|
6
|
+
export type Predicate<T> = (value: T) => boolean;
|
|
7
|
+
export type DecodeResult<T> = Result<T, Annotation>;
|
|
8
|
+
|
|
9
|
+
export type Decoder<T, F = unknown> = (blob: F) => DecodeResult<T>;
|
|
10
|
+
export type Guard<T> = (blob: unknown) => T;
|
|
11
|
+
|
|
12
|
+
export type DecoderType<T> = T extends Decoder<infer V> ? V : never;
|
|
13
|
+
export type GuardType<T> = T extends Guard<infer V> ? V : never;
|
|
File without changes
|
package/_utils.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Annotation } from './annotate';
|
|
2
|
+
|
|
3
|
+
export function isDate(value: unknown): boolean;
|
|
4
|
+
export function asDate(value: unknown): Date | null;
|
|
5
|
+
export function isMultiline(s: string): boolean;
|
|
6
|
+
export function indent(s: string, prefix?: string): string;
|
|
7
|
+
export function summarize(
|
|
8
|
+
ann: Annotation,
|
|
9
|
+
keypath?: ReadonlyArray<number | string>,
|
|
10
|
+
): string[];
|
package/_utils.js
CHANGED
|
@@ -7,7 +7,7 @@ exports.indent = indent;
|
|
|
7
7
|
exports.isDate = isDate;
|
|
8
8
|
exports.isMultiline = isMultiline;
|
|
9
9
|
exports.summarize = summarize;
|
|
10
|
-
// $FlowFixMe[unclear-type] - deliberate
|
|
10
|
+
// $FlowFixMe[unclear-type] - deliberate use of `any`
|
|
11
11
|
// Two spaces of indentation
|
|
12
12
|
var INDENT = ' ';
|
|
13
13
|
/**
|
package/_utils.js.flow
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import type { Annotation } from './annotate';
|
|
4
4
|
|
|
5
|
-
// $FlowFixMe[unclear-type] - deliberate
|
|
6
|
-
type
|
|
5
|
+
// $FlowFixMe[unclear-type] - deliberate use of `any`
|
|
6
|
+
export type _Any = any;
|
|
7
7
|
|
|
8
8
|
// Two spaces of indentation
|
|
9
9
|
export const INDENT = ' ';
|
|
@@ -29,7 +29,7 @@ export function isDate(value: mixed): boolean {
|
|
|
29
29
|
* null.
|
|
30
30
|
*/
|
|
31
31
|
export function asDate(value: mixed): Date | null {
|
|
32
|
-
return isDate(value) ? ((value:
|
|
32
|
+
return isDate(value) ? ((value: _Any): Date) : null;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export function isMultiline(s: string): boolean {
|
package/annotate.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export interface ObjectAnnotation {
|
|
2
|
+
readonly type: 'object';
|
|
3
|
+
readonly fields: { readonly [key: string]: Annotation };
|
|
4
|
+
readonly text?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface ArrayAnnotation {
|
|
8
|
+
readonly type: 'array';
|
|
9
|
+
readonly items: readonly Annotation[];
|
|
10
|
+
readonly text?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ScalarAnnotation {
|
|
14
|
+
readonly type: 'scalar';
|
|
15
|
+
readonly value: unknown;
|
|
16
|
+
readonly text?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface FunctionAnnotation {
|
|
20
|
+
readonly type: 'function';
|
|
21
|
+
readonly text?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface CircularRefAnnotation {
|
|
25
|
+
readonly type: 'circular-ref';
|
|
26
|
+
readonly text?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface UnknownAnnotation {
|
|
30
|
+
readonly type: 'unknown';
|
|
31
|
+
readonly value: unknown;
|
|
32
|
+
readonly text?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type Annotation =
|
|
36
|
+
| ObjectAnnotation
|
|
37
|
+
| ArrayAnnotation
|
|
38
|
+
| ScalarAnnotation
|
|
39
|
+
| FunctionAnnotation
|
|
40
|
+
| CircularRefAnnotation
|
|
41
|
+
| UnknownAnnotation;
|
|
42
|
+
|
|
43
|
+
export function object(
|
|
44
|
+
fields: { readonly [key: string]: Annotation },
|
|
45
|
+
text?: string,
|
|
46
|
+
): ObjectAnnotation;
|
|
47
|
+
export function array(items: readonly Annotation[], text?: string): ArrayAnnotation;
|
|
48
|
+
export function func(text?: string): FunctionAnnotation;
|
|
49
|
+
export function unknown(value: unknown, text?: string): UnknownAnnotation;
|
|
50
|
+
export function scalar(value: unknown, text?: string): ScalarAnnotation;
|
|
51
|
+
export function circularRef(text?: string): CircularRefAnnotation;
|
|
52
|
+
export function updateText<A extends Annotation>(annotation: A, text?: string): A;
|
|
53
|
+
export function merge(
|
|
54
|
+
objAnnotation: ObjectAnnotation,
|
|
55
|
+
fields: { readonly [key: string]: Annotation },
|
|
56
|
+
): ObjectAnnotation;
|
|
57
|
+
export function asAnnotation(thing: unknown): Annotation | void;
|
|
58
|
+
export function annotate(value: unknown, text?: string): Annotation;
|
|
59
|
+
export function annotateObject(
|
|
60
|
+
obj: { readonly [field: string]: unknown },
|
|
61
|
+
text?: string,
|
|
62
|
+
): ObjectAnnotation;
|
|
File without changes
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Given a type like:
|
|
3
|
+
*
|
|
4
|
+
* {
|
|
5
|
+
* a: string;
|
|
6
|
+
* b: number | undefined;
|
|
7
|
+
* c: null | undefined;
|
|
8
|
+
* d: null;
|
|
9
|
+
* e: undefined;
|
|
10
|
+
* }
|
|
11
|
+
*
|
|
12
|
+
* Will drop all the "undefined" types. In this case, only "e":
|
|
13
|
+
*
|
|
14
|
+
* {
|
|
15
|
+
* a: string;
|
|
16
|
+
* b: number | undefined;
|
|
17
|
+
* c: null | undefined;
|
|
18
|
+
* d: null;
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
type Compact<T> = { [K in IsDefined<T, keyof T>]: T[K] };
|
|
23
|
+
|
|
24
|
+
type IsDefined<T, K extends keyof T> = K extends any
|
|
25
|
+
? T[K] extends undefined
|
|
26
|
+
? never
|
|
27
|
+
: K
|
|
28
|
+
: never;
|
|
29
|
+
|
|
30
|
+
//
|
|
31
|
+
// HACK:
|
|
32
|
+
// These weird conditionals test whether TypeScript is configured with the
|
|
33
|
+
// `strictNullChecks` compiler option. We use these definitions to influence
|
|
34
|
+
// what's considered a "required" vs an "optional" key for the AllowImplicit
|
|
35
|
+
// type.
|
|
36
|
+
//
|
|
37
|
+
// If strictNullChecks is false, then we should not be emitting any `?` fields
|
|
38
|
+
// and consider all fields "required" because everything is optional by default
|
|
39
|
+
// in that mode anyway.
|
|
40
|
+
//
|
|
41
|
+
type NoStrictNullChecks = undefined extends string ? 1 : undefined;
|
|
42
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
43
|
+
type StrictNullChecks = undefined extends string ? undefined : 1;
|
|
44
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
45
|
+
|
|
46
|
+
export type RequiredKeys<T> = keyof Compact<{
|
|
47
|
+
[K in keyof T]: undefined extends T[K] ? NoStrictNullChecks : 1;
|
|
48
|
+
}>;
|
|
49
|
+
|
|
50
|
+
export type OptionalKeys<T> = keyof Compact<{
|
|
51
|
+
[K in keyof T]: undefined extends T[K] ? 1 : StrictNullChecks;
|
|
52
|
+
}>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Transforms an object type, by marking all fields that contain "undefined"
|
|
56
|
+
* with a question mark, i.e. allowing implicit-undefineds when
|
|
57
|
+
* explicit-undefined are also allowed.
|
|
58
|
+
*
|
|
59
|
+
* For example, if:
|
|
60
|
+
*
|
|
61
|
+
* type User = {
|
|
62
|
+
* name: string;
|
|
63
|
+
* age: number | null | undefined;
|
|
64
|
+
* }
|
|
65
|
+
*
|
|
66
|
+
* Then AllowImplicit<User> will become equivalent to:
|
|
67
|
+
*
|
|
68
|
+
* {
|
|
69
|
+
* name: string;
|
|
70
|
+
* age?: number | null;
|
|
71
|
+
* ^
|
|
72
|
+
* Note the question mark
|
|
73
|
+
* }
|
|
74
|
+
*/
|
|
75
|
+
type AllowImplicit<T> = { [K in RequiredKeys<T>]-?: T[K] } & {
|
|
76
|
+
[K in OptionalKeys<T>]+?: Exclude<T[K], undefined>;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export { AllowImplicit };
|
package/core/array.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference lib="es6" />
|
|
2
|
+
|
|
3
|
+
import { Decoder } from '../_types';
|
|
4
|
+
|
|
5
|
+
export const poja: Decoder<unknown[]>;
|
|
6
|
+
export function array<T>(decoder: Decoder<T>): Decoder<T[]>;
|
|
7
|
+
export function nonEmptyArray<T>(decoder: Decoder<T>): Decoder<[T, ...T[]]>;
|
|
8
|
+
export function set<T>(decoder: Decoder<T>): Decoder<Set<T>>;
|
package/core/array.js
CHANGED
|
@@ -4,16 +4,13 @@ exports.__esModule = true;
|
|
|
4
4
|
exports.array = array;
|
|
5
5
|
exports.nonEmptyArray = nonEmptyArray;
|
|
6
6
|
exports.poja = void 0;
|
|
7
|
-
|
|
8
|
-
var Result = _interopRequireWildcard(require("../result"));
|
|
7
|
+
exports.set = set;
|
|
9
8
|
|
|
10
9
|
var _annotate = require("../annotate");
|
|
11
10
|
|
|
12
11
|
var _composition = require("./composition");
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
13
|
+
var _result = require("../result");
|
|
17
14
|
|
|
18
15
|
/**
|
|
19
16
|
* Like a "Plain Old JavaScript Object", but for arrays: "Plain Old JavaScript
|
|
@@ -21,10 +18,10 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
21
18
|
*/
|
|
22
19
|
var poja = function poja(blob) {
|
|
23
20
|
if (!Array.isArray(blob)) {
|
|
24
|
-
return
|
|
21
|
+
return (0, _result.err)((0, _annotate.annotate)(blob, 'Must be an array'));
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
return
|
|
24
|
+
return (0, _result.ok)( // NOTE: Since Flow 0.98, Array.isArray() returns $ReadOnlyArray<mixed>
|
|
28
25
|
// instead of Array<mixed>. For rationale, see
|
|
29
26
|
// https://github.com/facebook/flow/issues/7684. In this case, we
|
|
30
27
|
// don't want to output read-only types because it's up to the user of
|
|
@@ -51,7 +48,7 @@ function all(items, blobs) {
|
|
|
51
48
|
for (var index = 0; index < items.length; ++index) {
|
|
52
49
|
var result = items[index];
|
|
53
50
|
|
|
54
|
-
if (result.
|
|
51
|
+
if (result.ok) {
|
|
55
52
|
results.push(result.value);
|
|
56
53
|
} else {
|
|
57
54
|
var ann = result.error; // Rewrite the annotation to include the index information, and inject it into the original blob
|
|
@@ -67,11 +64,11 @@ function all(items, blobs) {
|
|
|
67
64
|
// errValue.push('...'); // TODO: make special mark, not string!
|
|
68
65
|
// }
|
|
69
66
|
|
|
70
|
-
return
|
|
67
|
+
return (0, _result.err)((0, _annotate.annotate)(clone));
|
|
71
68
|
}
|
|
72
69
|
}
|
|
73
70
|
|
|
74
|
-
return
|
|
71
|
+
return (0, _result.ok)(results);
|
|
75
72
|
}
|
|
76
73
|
/**
|
|
77
74
|
* Given a T, builds a decoder that assumes an array input and returns an
|
|
@@ -102,7 +99,17 @@ function array(decoder) {
|
|
|
102
99
|
|
|
103
100
|
|
|
104
101
|
function nonEmptyArray(decoder) {
|
|
105
|
-
return (0, _composition.
|
|
102
|
+
return (0, _composition.predicate)(array(decoder), function (arr) {
|
|
106
103
|
return arr.length > 0;
|
|
107
|
-
}, 'Must be non-empty array')
|
|
104
|
+
}, 'Must be non-empty array');
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Similar to `array()`, but returns the result as an ES6 Set.
|
|
108
|
+
*/
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
function set(decoder) {
|
|
112
|
+
return (0, _composition.transform)(array(decoder), function (items) {
|
|
113
|
+
return new Set(items);
|
|
114
|
+
});
|
|
108
115
|
}
|
package/core/array.js.flow
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
|
|
3
|
-
import * as Result from '../result';
|
|
4
3
|
import { annotate } from '../annotate';
|
|
5
|
-
import { compose, predicate } from './composition';
|
|
4
|
+
import { compose, predicate, transform } from './composition';
|
|
5
|
+
import { err, ok } from '../result';
|
|
6
6
|
import type { Decoder, DecodeResult } from '../_types';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -11,9 +11,9 @@ import type { Decoder, DecodeResult } from '../_types';
|
|
|
11
11
|
*/
|
|
12
12
|
export const poja: Decoder<Array<mixed>> = (blob: mixed) => {
|
|
13
13
|
if (!Array.isArray(blob)) {
|
|
14
|
-
return
|
|
14
|
+
return err(annotate(blob, 'Must be an array'));
|
|
15
15
|
}
|
|
16
|
-
return
|
|
16
|
+
return ok(
|
|
17
17
|
// NOTE: Since Flow 0.98, Array.isArray() returns $ReadOnlyArray<mixed>
|
|
18
18
|
// instead of Array<mixed>. For rationale, see
|
|
19
19
|
// https://github.com/facebook/flow/issues/7684. In this case, we
|
|
@@ -40,7 +40,7 @@ function all<T>(
|
|
|
40
40
|
const results: Array<T> = [];
|
|
41
41
|
for (let index = 0; index < items.length; ++index) {
|
|
42
42
|
const result = items[index];
|
|
43
|
-
if (result.
|
|
43
|
+
if (result.ok) {
|
|
44
44
|
results.push(result.value);
|
|
45
45
|
} else {
|
|
46
46
|
const ann = result.error;
|
|
@@ -65,10 +65,10 @@ function all<T>(
|
|
|
65
65
|
// if (index < iterable.length - 1) {
|
|
66
66
|
// errValue.push('...'); // TODO: make special mark, not string!
|
|
67
67
|
// }
|
|
68
|
-
return
|
|
68
|
+
return err(annotate(clone));
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
return
|
|
71
|
+
return ok(results);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
/**
|
|
@@ -96,8 +96,12 @@ export function array<T>(decoder: Decoder<T>): Decoder<Array<T>> {
|
|
|
96
96
|
* empty arrays.
|
|
97
97
|
*/
|
|
98
98
|
export function nonEmptyArray<T>(decoder: Decoder<T>): Decoder<Array<T>> {
|
|
99
|
-
return
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
return predicate(array(decoder), (arr) => arr.length > 0, 'Must be non-empty array');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Similar to `array()`, but returns the result as an ES6 Set.
|
|
104
|
+
*/
|
|
105
|
+
export function set<T>(decoder: Decoder<T>): Decoder<Set<T>> {
|
|
106
|
+
return transform(array(decoder), (items) => new Set(items));
|
|
103
107
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { annotate } from '../annotate.mjs';
|
|
2
|
+
import { compose, predicate, transform } from './composition.mjs';
|
|
3
|
+
import { err, ok } from '../result.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Like a "Plain Old JavaScript Object", but for arrays: "Plain Old JavaScript
|
|
@@ -8,10 +8,10 @@ import { compose, predicate } from './composition';
|
|
|
8
8
|
*/
|
|
9
9
|
export var poja = function poja(blob) {
|
|
10
10
|
if (!Array.isArray(blob)) {
|
|
11
|
-
return
|
|
11
|
+
return err(annotate(blob, 'Must be an array'));
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
return
|
|
14
|
+
return ok( // NOTE: Since Flow 0.98, Array.isArray() returns $ReadOnlyArray<mixed>
|
|
15
15
|
// instead of Array<mixed>. For rationale, see
|
|
16
16
|
// https://github.com/facebook/flow/issues/7684. In this case, we
|
|
17
17
|
// don't want to output read-only types because it's up to the user of
|
|
@@ -35,7 +35,7 @@ function all(items, blobs) {
|
|
|
35
35
|
for (var index = 0; index < items.length; ++index) {
|
|
36
36
|
var result = items[index];
|
|
37
37
|
|
|
38
|
-
if (result.
|
|
38
|
+
if (result.ok) {
|
|
39
39
|
results.push(result.value);
|
|
40
40
|
} else {
|
|
41
41
|
var ann = result.error; // Rewrite the annotation to include the index information, and inject it into the original blob
|
|
@@ -51,11 +51,11 @@ function all(items, blobs) {
|
|
|
51
51
|
// errValue.push('...'); // TODO: make special mark, not string!
|
|
52
52
|
// }
|
|
53
53
|
|
|
54
|
-
return
|
|
54
|
+
return err(annotate(clone));
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
return
|
|
58
|
+
return ok(results);
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
61
|
* Given a T, builds a decoder that assumes an array input and returns an
|
|
@@ -85,7 +85,16 @@ export function array(decoder) {
|
|
|
85
85
|
*/
|
|
86
86
|
|
|
87
87
|
export function nonEmptyArray(decoder) {
|
|
88
|
-
return
|
|
88
|
+
return predicate(array(decoder), function (arr) {
|
|
89
89
|
return arr.length > 0;
|
|
90
|
-
}, 'Must be non-empty array')
|
|
90
|
+
}, 'Must be non-empty array');
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Similar to `array()`, but returns the result as an ES6 Set.
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
export function set(decoder) {
|
|
97
|
+
return transform(array(decoder), function (items) {
|
|
98
|
+
return new Set(items);
|
|
99
|
+
});
|
|
91
100
|
}
|
package/core/boolean.js
CHANGED
|
@@ -3,23 +3,19 @@
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.truthy = exports.numericBoolean = exports["boolean"] = void 0;
|
|
5
5
|
|
|
6
|
-
var Result = _interopRequireWildcard(require("../result"));
|
|
7
|
-
|
|
8
6
|
var _annotate = require("../annotate");
|
|
9
7
|
|
|
10
|
-
var
|
|
8
|
+
var _result = require("../result");
|
|
11
9
|
|
|
12
10
|
var _number = require("./number");
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
12
|
+
var _composition = require("./composition");
|
|
17
13
|
|
|
18
14
|
/**
|
|
19
15
|
* Decoder that only returns Ok for boolean inputs. Err otherwise.
|
|
20
16
|
*/
|
|
21
17
|
var _boolean = function _boolean(blob) {
|
|
22
|
-
return typeof blob === 'boolean' ?
|
|
18
|
+
return typeof blob === 'boolean' ? (0, _result.ok)(blob) : (0, _result.err)((0, _annotate.annotate)(blob, 'Must be boolean'));
|
|
23
19
|
};
|
|
24
20
|
/**
|
|
25
21
|
* Decoder that returns true for all truthy values, and false otherwise. Never fails.
|
|
@@ -29,7 +25,7 @@ var _boolean = function _boolean(blob) {
|
|
|
29
25
|
exports["boolean"] = _boolean;
|
|
30
26
|
|
|
31
27
|
var truthy = function truthy(blob) {
|
|
32
|
-
return
|
|
28
|
+
return (0, _result.ok)(!!blob);
|
|
33
29
|
};
|
|
34
30
|
/**
|
|
35
31
|
* Decoder that only returns Ok for numeric input values representing booleans.
|
|
@@ -38,7 +34,7 @@ var truthy = function truthy(blob) {
|
|
|
38
34
|
|
|
39
35
|
|
|
40
36
|
exports.truthy = truthy;
|
|
41
|
-
var numericBoolean = (0, _composition.
|
|
37
|
+
var numericBoolean = (0, _composition.transform)(_number.number, function (n) {
|
|
42
38
|
return !!n;
|
|
43
39
|
});
|
|
44
40
|
exports.numericBoolean = numericBoolean;
|
package/core/boolean.js.flow
CHANGED
|
@@ -1,29 +1,27 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
|
|
3
|
-
import * as Result from '../result';
|
|
4
3
|
import { annotate } from '../annotate';
|
|
5
|
-
import {
|
|
4
|
+
import { err, ok } from '../result';
|
|
6
5
|
import { number } from './number';
|
|
6
|
+
import { transform } from './composition';
|
|
7
7
|
import type { Decoder } from '../_types';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Decoder that only returns Ok for boolean inputs. Err otherwise.
|
|
11
11
|
*/
|
|
12
12
|
export const boolean: Decoder<boolean> = (blob: mixed) => {
|
|
13
|
-
return typeof blob === 'boolean'
|
|
14
|
-
? Result.ok(blob)
|
|
15
|
-
: Result.err(annotate(blob, 'Must be boolean'));
|
|
13
|
+
return typeof blob === 'boolean' ? ok(blob) : err(annotate(blob, 'Must be boolean'));
|
|
16
14
|
};
|
|
17
15
|
|
|
18
16
|
/**
|
|
19
17
|
* Decoder that returns true for all truthy values, and false otherwise. Never fails.
|
|
20
18
|
*/
|
|
21
19
|
export const truthy: Decoder<boolean> = (blob: mixed) => {
|
|
22
|
-
return
|
|
20
|
+
return ok(!!blob);
|
|
23
21
|
};
|
|
24
22
|
|
|
25
23
|
/**
|
|
26
24
|
* Decoder that only returns Ok for numeric input values representing booleans.
|
|
27
25
|
* Returns their boolean representation. Err otherwise.
|
|
28
26
|
*/
|
|
29
|
-
export const numericBoolean: Decoder<boolean> =
|
|
27
|
+
export const numericBoolean: Decoder<boolean> = transform(number, (n) => !!n);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { annotate } from '../annotate.mjs';
|
|
2
|
+
import { err, ok } from '../result.mjs';
|
|
3
|
+
import { number } from './number.mjs';
|
|
4
|
+
import { transform } from './composition.mjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Decoder that only returns Ok for boolean inputs. Err otherwise.
|
|
8
8
|
*/
|
|
9
9
|
var _boolean = function _boolean(blob) {
|
|
10
|
-
return typeof blob === 'boolean' ?
|
|
10
|
+
return typeof blob === 'boolean' ? ok(blob) : err(annotate(blob, 'Must be boolean'));
|
|
11
11
|
};
|
|
12
12
|
/**
|
|
13
13
|
* Decoder that returns true for all truthy values, and false otherwise. Never fails.
|
|
@@ -16,13 +16,13 @@ var _boolean = function _boolean(blob) {
|
|
|
16
16
|
|
|
17
17
|
export { _boolean as boolean };
|
|
18
18
|
export var truthy = function truthy(blob) {
|
|
19
|
-
return
|
|
19
|
+
return ok(!!blob);
|
|
20
20
|
};
|
|
21
21
|
/**
|
|
22
22
|
* Decoder that only returns Ok for numeric input values representing booleans.
|
|
23
23
|
* Returns their boolean representation. Err otherwise.
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
export var numericBoolean =
|
|
26
|
+
export var numericBoolean = transform(number, function (n) {
|
|
27
27
|
return !!n;
|
|
28
28
|
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Decoder } from '../_types';
|
|
2
|
+
|
|
3
|
+
export function transform<T, V>(decoder: Decoder<T>, mapper: (value: T) => V): Decoder<V>;
|
|
4
|
+
export function compose<T, V>(decoder: Decoder<T>, next: Decoder<V, T>): Decoder<V>;
|
|
5
|
+
export function predicate<T, N extends T>(
|
|
6
|
+
decoder: Decoder<T>,
|
|
7
|
+
predicate: (value: T) => value is N,
|
|
8
|
+
msg: string,
|
|
9
|
+
): Decoder<N>;
|
|
10
|
+
export function predicate<T>(
|
|
11
|
+
decoder: Decoder<T>,
|
|
12
|
+
predicate: (value: T) => boolean,
|
|
13
|
+
msg: string,
|
|
14
|
+
): Decoder<T>;
|
|
15
|
+
export function prep<T, I>(
|
|
16
|
+
mapperFn: (blob: unknown) => I,
|
|
17
|
+
decoder: Decoder<T, I>,
|
|
18
|
+
): Decoder<T>;
|