decoders 2.0.0-beta12 → 2.0.0-beta13
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 +53 -35
- package/Decoder.d.ts +71 -5
- package/Decoder.js +41 -42
- package/Decoder.js.flow +102 -66
- package/Decoder.mjs +41 -42
- package/README.md +81 -62
- package/format.d.ts +4 -2
- package/format.js.flow +2 -0
- package/index.d.ts +1 -1
- package/index.js +1 -2
- package/index.js.flow +1 -1
- package/index.mjs +1 -1
- package/lib/arrays.d.ts +22 -0
- package/lib/arrays.js +5 -4
- package/lib/arrays.js.flow +6 -6
- package/lib/arrays.mjs +5 -4
- package/lib/basics.d.ts +64 -9
- package/lib/basics.js +22 -12
- package/lib/basics.js.flow +23 -12
- package/lib/basics.mjs +22 -12
- package/lib/booleans.d.ts +11 -0
- package/lib/booleans.js +1 -1
- package/lib/booleans.js.flow +1 -1
- package/lib/booleans.mjs +1 -1
- package/lib/dates.d.ts +11 -0
- package/lib/dates.js +1 -1
- package/lib/dates.js.flow +1 -1
- package/lib/dates.mjs +1 -1
- package/lib/json.d.ts +24 -0
- package/lib/numbers.d.ts +26 -2
- package/lib/numbers.js +4 -5
- package/lib/numbers.js.flow +4 -5
- package/lib/numbers.mjs +4 -5
- package/lib/objects.d.ts +38 -1
- package/lib/strings.d.ts +43 -0
- package/lib/unions.d.ts +40 -63
- package/lib/unions.js +10 -11
- package/lib/unions.js.flow +10 -13
- package/lib/unions.mjs +9 -8
- package/lib/utilities.d.ts +24 -0
- package/lib/utilities.js +0 -19
- package/lib/utilities.js.flow +0 -19
- package/lib/utilities.mjs +0 -19
- package/package.json +1 -1
package/lib/basics.js.flow
CHANGED
|
@@ -28,23 +28,28 @@ const undefined_or_null: Decoder<null | void> = define((blob, ok, err) =>
|
|
|
28
28
|
|
|
29
29
|
interface Maybeish<E> {
|
|
30
30
|
<T>(decoder: Decoder<T>): Decoder<E | T>;
|
|
31
|
-
<T, V>(
|
|
31
|
+
<T, V>(
|
|
32
|
+
decoder: Decoder<T>,
|
|
33
|
+
defaultValue: (() => V) | V,
|
|
34
|
+
): Decoder<$NonMaybeType<T> | V>;
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
/**
|
|
35
|
-
* Accepts whatever the given decoder accepts, or `null`, or `undefined`.
|
|
36
|
-
*/
|
|
37
37
|
function _maybeish<E>(emptyCase: Decoder<E>): Maybeish<E> {
|
|
38
38
|
function _inner(decoder /* defaultValue */) {
|
|
39
39
|
const rv = either(emptyCase, decoder);
|
|
40
|
-
|
|
40
|
+
if (
|
|
41
41
|
// If a default value is provided...
|
|
42
42
|
arguments.length >= 2
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
) {
|
|
44
|
+
// ...then return the default value
|
|
45
|
+
const _defaultValue = arguments[1];
|
|
46
|
+
const defaultValue =
|
|
47
|
+
typeof _defaultValue === 'function' ? _defaultValue() : _defaultValue;
|
|
48
|
+
return rv.transform((value) => value ?? defaultValue);
|
|
49
|
+
} else {
|
|
50
|
+
// Otherwise the "normal" empty case
|
|
51
|
+
return rv;
|
|
52
|
+
}
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
return (_inner: _Any);
|
|
@@ -89,8 +94,14 @@ export function constant<T: Scalar>(value: T): Decoder<T> {
|
|
|
89
94
|
*
|
|
90
95
|
* This is useful to manually add extra fields to object decoders.
|
|
91
96
|
*/
|
|
92
|
-
export function always<T>(value: T): Decoder<T> {
|
|
93
|
-
return define(
|
|
97
|
+
export function always<T>(value: (() => T) | T): Decoder<T> {
|
|
98
|
+
return define(
|
|
99
|
+
typeof value === 'function'
|
|
100
|
+
? (blob /* ignored */, ok, _) =>
|
|
101
|
+
// $FlowFixMe[incompatible-use]
|
|
102
|
+
ok(value())
|
|
103
|
+
: (blob /* ignored */, ok, _) => ok(value),
|
|
104
|
+
);
|
|
94
105
|
}
|
|
95
106
|
|
|
96
107
|
/**
|
package/lib/basics.mjs
CHANGED
|
@@ -19,22 +19,26 @@ var undefined_or_null = define(function (blob, ok, err) {
|
|
|
19
19
|
err('Must be undefined or null');
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
/**
|
|
23
|
-
* Accepts whatever the given decoder accepts, or `null`, or `undefined`.
|
|
24
|
-
*/
|
|
25
22
|
function _maybeish(emptyCase) {
|
|
26
23
|
function _inner(decoder
|
|
27
24
|
/* defaultValue */
|
|
28
25
|
) {
|
|
29
|
-
var _arguments = arguments;
|
|
30
26
|
var rv = either(emptyCase, decoder);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
|
|
28
|
+
if ( // If a default value is provided...
|
|
29
|
+
arguments.length >= 2) {
|
|
30
|
+
// ...then return the default value
|
|
31
|
+
var _defaultValue = arguments[1];
|
|
32
|
+
|
|
33
|
+
var _defaultValue2 = typeof _defaultValue === 'function' ? _defaultValue() : _defaultValue;
|
|
34
|
+
|
|
35
|
+
return rv.transform(function (value) {
|
|
36
|
+
return value != null ? value : _defaultValue2;
|
|
37
|
+
});
|
|
38
|
+
} else {
|
|
39
|
+
// Otherwise the "normal" empty case
|
|
40
|
+
return rv;
|
|
41
|
+
}
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
return _inner;
|
|
@@ -81,7 +85,13 @@ export function constant(value) {
|
|
|
81
85
|
*/
|
|
82
86
|
|
|
83
87
|
export function always(value) {
|
|
84
|
-
return define(function (blob
|
|
88
|
+
return define(typeof value === 'function' ? function (blob
|
|
89
|
+
/* ignored */
|
|
90
|
+
, ok, _) {
|
|
91
|
+
return (// $FlowFixMe[incompatible-use]
|
|
92
|
+
ok(value())
|
|
93
|
+
);
|
|
94
|
+
} : function (blob
|
|
85
95
|
/* ignored */
|
|
86
96
|
, ok, _) {
|
|
87
97
|
return ok(value);
|
package/lib/booleans.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { Decoder } from '../Decoder';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Accepts and returns booleans.
|
|
5
|
+
*/
|
|
3
6
|
export const boolean: Decoder<boolean>;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Accepts anything and will return its "truth" value. Will never reject.
|
|
10
|
+
*/
|
|
4
11
|
export const truthy: Decoder<boolean>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Accepts numbers, but return their boolean representation.
|
|
15
|
+
*/
|
|
5
16
|
export const numericBoolean: Decoder<boolean>;
|
package/lib/booleans.js
CHANGED
|
@@ -14,7 +14,7 @@ var _boolean = (0, _Decoder.define)(function (blob, ok, err) {
|
|
|
14
14
|
return typeof blob === 'boolean' ? ok(blob) : err('Must be boolean');
|
|
15
15
|
});
|
|
16
16
|
/**
|
|
17
|
-
* Accepts anything and will return its
|
|
17
|
+
* Accepts anything and will return its "truth" value. Will never reject.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
|
package/lib/booleans.js.flow
CHANGED
|
@@ -12,7 +12,7 @@ export const boolean: Decoder<boolean> = define((blob, ok, err) => {
|
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Accepts anything and will return its
|
|
15
|
+
* Accepts anything and will return its "truth" value. Will never reject.
|
|
16
16
|
*/
|
|
17
17
|
export const truthy: Decoder<boolean> = define((blob, ok, _) => ok(!!blob));
|
|
18
18
|
|
package/lib/booleans.mjs
CHANGED
|
@@ -8,7 +8,7 @@ var _boolean = define(function (blob, ok, err) {
|
|
|
8
8
|
return typeof blob === 'boolean' ? ok(blob) : err('Must be boolean');
|
|
9
9
|
});
|
|
10
10
|
/**
|
|
11
|
-
* Accepts anything and will return its
|
|
11
|
+
* Accepts anything and will return its "truth" value. Will never reject.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
|
package/lib/dates.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import { Decoder } from '../Decoder';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Accepts and returns `Date` instances.
|
|
5
|
+
*/
|
|
3
6
|
export const date: Decoder<Date>;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Accepts [ISO8601](https://en.wikipedia.org/wiki/ISO_8601)-formatted strings,
|
|
10
|
+
* returns them as `Date` instances.
|
|
11
|
+
*
|
|
12
|
+
* This is very useful for working with dates in APIs: serialize them as
|
|
13
|
+
* `.toISOString()` when sending, decode them with `iso8601` when receiving.
|
|
14
|
+
*/
|
|
4
15
|
export const iso8601: Decoder<Date>;
|
package/lib/dates.js
CHANGED
|
@@ -23,7 +23,7 @@ var date = (0, _Decoder.define)(function (blob, ok, err) {
|
|
|
23
23
|
});
|
|
24
24
|
/**
|
|
25
25
|
* Accepts [ISO8601](https://en.wikipedia.org/wiki/ISO_8601)-formatted strings,
|
|
26
|
-
* returns
|
|
26
|
+
* returns them as `Date` instances.
|
|
27
27
|
*
|
|
28
28
|
* This is very useful for working with dates in APIs: serialize them as
|
|
29
29
|
* `.toISOString()` when sending, decode them with `iso8601` when receiving.
|
package/lib/dates.js.flow
CHANGED
|
@@ -21,7 +21,7 @@ export const date: Decoder<Date> = define((blob, ok, err) => {
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Accepts [ISO8601](https://en.wikipedia.org/wiki/ISO_8601)-formatted strings,
|
|
24
|
-
* returns
|
|
24
|
+
* returns them as `Date` instances.
|
|
25
25
|
*
|
|
26
26
|
* This is very useful for working with dates in APIs: serialize them as
|
|
27
27
|
* `.toISOString()` when sending, decode them with `iso8601` when receiving.
|
package/lib/dates.mjs
CHANGED
|
@@ -15,7 +15,7 @@ export var date = define(function (blob, ok, err) {
|
|
|
15
15
|
});
|
|
16
16
|
/**
|
|
17
17
|
* Accepts [ISO8601](https://en.wikipedia.org/wiki/ISO_8601)-formatted strings,
|
|
18
|
-
* returns
|
|
18
|
+
* returns them as `Date` instances.
|
|
19
19
|
*
|
|
20
20
|
* This is very useful for working with dates in APIs: serialize them as
|
|
21
21
|
* `.toISOString()` when sending, decode them with `iso8601` when receiving.
|
package/lib/json.d.ts
CHANGED
|
@@ -6,6 +6,30 @@ export interface JSONObject {
|
|
|
6
6
|
}
|
|
7
7
|
export type JSONArray = JSONValue[];
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Accepts any value that's a valid JSON value.
|
|
11
|
+
*
|
|
12
|
+
* In other words: any value returned by `JSON.parse()` should decode without
|
|
13
|
+
* failure.
|
|
14
|
+
*
|
|
15
|
+
* ```typescript
|
|
16
|
+
* type JSONValue =
|
|
17
|
+
* | null
|
|
18
|
+
* | string
|
|
19
|
+
* | number
|
|
20
|
+
* | boolean
|
|
21
|
+
* | { [string]: JSONValue }
|
|
22
|
+
* | JSONValue[]
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
9
25
|
export const json: Decoder<JSONValue>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Like `json`, but will only decode when the JSON value is an array.
|
|
29
|
+
*/
|
|
10
30
|
export const jsonArray: Decoder<JSONArray>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Like `json`, but will only decode when the JSON value is an object.
|
|
34
|
+
*/
|
|
11
35
|
export const jsonObject: Decoder<JSONObject>;
|
package/lib/numbers.d.ts
CHANGED
|
@@ -1,7 +1,31 @@
|
|
|
1
1
|
import { Decoder } from '../Decoder';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Accepts any valid ``number`` value.
|
|
5
|
+
*
|
|
6
|
+
* This also accepts special values like `NaN` and `Infinity`. Unless you
|
|
7
|
+
* want to deliberately accept those, you'll likely want to use the
|
|
8
|
+
* `number` decoder instead.
|
|
9
|
+
*/
|
|
3
10
|
export const anyNumber: Decoder<number>;
|
|
4
|
-
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Accepts finite numbers (can be integer or float values). Values `NaN`,
|
|
14
|
+
* or positive and negative `Infinity` will get rejected.
|
|
15
|
+
*/
|
|
5
16
|
export const number: Decoder<number>;
|
|
6
|
-
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Accepts only finite whole numbers.
|
|
20
|
+
*/
|
|
21
|
+
export const integer: Decoder<number>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Accepts only positive finite numbers.
|
|
25
|
+
*/
|
|
7
26
|
export const positiveNumber: Decoder<number>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Accepts only positive finite whole numbers.
|
|
30
|
+
*/
|
|
31
|
+
export const positiveInteger: Decoder<number>;
|
package/lib/numbers.js
CHANGED
|
@@ -8,16 +8,15 @@ var _Decoder = require("../Decoder");
|
|
|
8
8
|
/**
|
|
9
9
|
* Accepts any valid ``number`` value.
|
|
10
10
|
*
|
|
11
|
-
* This also accepts special values like `NaN` and `Infinity`. Unless you
|
|
12
|
-
* to deliberately accept those, you'll likely want to use the
|
|
13
|
-
* instead.
|
|
11
|
+
* This also accepts special values like `NaN` and `Infinity`. Unless you
|
|
12
|
+
* want to deliberately accept those, you'll likely want to use the
|
|
13
|
+
* `number` decoder instead.
|
|
14
14
|
*/
|
|
15
15
|
var anyNumber = (0, _Decoder.define)(function (blob, ok, err) {
|
|
16
16
|
return typeof blob === 'number' ? ok(blob) : err('Must be number');
|
|
17
17
|
});
|
|
18
18
|
/**
|
|
19
|
-
* Accepts finite numbers (can be integer or float values). Values
|
|
20
|
-
* `NaN`,
|
|
19
|
+
* Accepts finite numbers (can be integer or float values). Values `NaN`,
|
|
21
20
|
* or positive and negative `Infinity` will get rejected.
|
|
22
21
|
*/
|
|
23
22
|
|
package/lib/numbers.js.flow
CHANGED
|
@@ -6,17 +6,16 @@ import type { Decoder } from '../Decoder';
|
|
|
6
6
|
/**
|
|
7
7
|
* Accepts any valid ``number`` value.
|
|
8
8
|
*
|
|
9
|
-
* This also accepts special values like `NaN` and `Infinity`. Unless you
|
|
10
|
-
* to deliberately accept those, you'll likely want to use the
|
|
11
|
-
* instead.
|
|
9
|
+
* This also accepts special values like `NaN` and `Infinity`. Unless you
|
|
10
|
+
* want to deliberately accept those, you'll likely want to use the
|
|
11
|
+
* `number` decoder instead.
|
|
12
12
|
*/
|
|
13
13
|
export const anyNumber: Decoder<number> = define((blob, ok, err) =>
|
|
14
14
|
typeof blob === 'number' ? ok(blob) : err('Must be number'),
|
|
15
15
|
);
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Accepts finite numbers (can be integer or float values). Values
|
|
19
|
-
* `NaN`,
|
|
18
|
+
* Accepts finite numbers (can be integer or float values). Values `NaN`,
|
|
20
19
|
* or positive and negative `Infinity` will get rejected.
|
|
21
20
|
*/
|
|
22
21
|
export const number: Decoder<number> = anyNumber.refine(
|
package/lib/numbers.mjs
CHANGED
|
@@ -3,16 +3,15 @@ import { define } from '../Decoder.mjs';
|
|
|
3
3
|
/**
|
|
4
4
|
* Accepts any valid ``number`` value.
|
|
5
5
|
*
|
|
6
|
-
* This also accepts special values like `NaN` and `Infinity`. Unless you
|
|
7
|
-
* to deliberately accept those, you'll likely want to use the
|
|
8
|
-
* instead.
|
|
6
|
+
* This also accepts special values like `NaN` and `Infinity`. Unless you
|
|
7
|
+
* want to deliberately accept those, you'll likely want to use the
|
|
8
|
+
* `number` decoder instead.
|
|
9
9
|
*/
|
|
10
10
|
export var anyNumber = define(function (blob, ok, err) {
|
|
11
11
|
return typeof blob === 'number' ? ok(blob) : err('Must be number');
|
|
12
12
|
});
|
|
13
13
|
/**
|
|
14
|
-
* Accepts finite numbers (can be integer or float values). Values
|
|
15
|
-
* `NaN`,
|
|
14
|
+
* Accepts finite numbers (can be integer or float values). Values `NaN`,
|
|
16
15
|
* or positive and negative `Infinity` will get rejected.
|
|
17
16
|
*/
|
|
18
17
|
|
package/lib/objects.d.ts
CHANGED
|
@@ -7,8 +7,17 @@ export type ObjectDecoderType<T> = AllowImplicit<{
|
|
|
7
7
|
[key in keyof T]: DecoderType<T[key]>;
|
|
8
8
|
}>;
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Accepts any "plain old JavaScript object", but doesn't validate its keys or
|
|
12
|
+
* values further.
|
|
13
|
+
*/
|
|
10
14
|
export const pojo: Decoder<{ [key: string]: unknown }>;
|
|
11
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Accepts objects with fields matching the given decoders. Extra fields that
|
|
18
|
+
* exist on the input object are ignored and will not be returned.
|
|
19
|
+
*/
|
|
20
|
+
export function object(decodersByKey: Record<any, never>): Decoder<Record<string, never>>;
|
|
12
21
|
export function object<O extends { [key: string]: Decoder<any> }>(
|
|
13
22
|
decodersByKey: O,
|
|
14
23
|
): Decoder<{ [K in keyof ObjectDecoderType<O>]: ObjectDecoderType<O>[K] }>;
|
|
@@ -20,12 +29,24 @@ export function object<O extends { [key: string]: Decoder<any> }>(
|
|
|
20
29
|
// type names from the inferred type here, making this much easier to
|
|
21
30
|
// work with while developing.
|
|
22
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Like `object()`, but will reject inputs that contain extra fields that are
|
|
34
|
+
* not specified explicitly.
|
|
35
|
+
*/
|
|
36
|
+
export function exact(decodersByKey: Record<any, never>): Decoder<Record<string, never>>;
|
|
23
37
|
export function exact<O extends { [key: string]: Decoder<any> }>(
|
|
24
38
|
decodersByKey: O,
|
|
25
39
|
): Decoder<{ [K in keyof ObjectDecoderType<O>]: ObjectDecoderType<O>[K] }>;
|
|
26
40
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
27
41
|
// Ditto (see above)
|
|
28
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Like `object()`, but will pass through any extra fields on the input object
|
|
45
|
+
* unvalidated that will thus be of `unknown` type statically.
|
|
46
|
+
*/
|
|
47
|
+
export function inexact(
|
|
48
|
+
decodersByKey: Record<any, never>,
|
|
49
|
+
): Decoder<{ [extra: string]: unknown }>;
|
|
29
50
|
export function inexact<O extends { [key: string]: Decoder<any> }>(
|
|
30
51
|
decodersByKey: O,
|
|
31
52
|
): Decoder<
|
|
@@ -34,5 +55,21 @@ export function inexact<O extends { [key: string]: Decoder<any> }>(
|
|
|
34
55
|
}
|
|
35
56
|
>;
|
|
36
57
|
|
|
37
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Accepts objects where all values match the given decoder, and returns the
|
|
60
|
+
* result as a `{ [string]: T }`.
|
|
61
|
+
*
|
|
62
|
+
* The main difference between `object()` and `dict()` is that you'd typically
|
|
63
|
+
* use `object()` if this is a record-like object, where all field names are
|
|
64
|
+
* known and the values are heterogeneous. Whereas with `dict()` the keys are
|
|
65
|
+
* typically dynamic and the values homogeneous, like in a dictionary,
|
|
66
|
+
* a lookup table, or a cache.
|
|
67
|
+
*/
|
|
38
68
|
export function dict<T>(decoder: Decoder<T>): Decoder<{ [key: string]: T }>;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Similar to `dict()`, but returns the result as a `Map<string, T>` (an [ES6
|
|
72
|
+
* Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map))
|
|
73
|
+
* instead.
|
|
74
|
+
*/
|
|
75
|
+
export function mapping<T>(decoder: Decoder<T>): Decoder<Map<string, T>>;
|
package/lib/strings.d.ts
CHANGED
|
@@ -2,12 +2,55 @@
|
|
|
2
2
|
|
|
3
3
|
import { Decoder } from '../Decoder';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Accepts and returns strings.
|
|
7
|
+
*/
|
|
5
8
|
export const string: Decoder<string>;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Like `string`, but will reject the empty string or strings containing only whitespace.
|
|
12
|
+
*/
|
|
6
13
|
export const nonEmptyString: Decoder<string>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Accepts and returns strings that match the given regular expression.
|
|
17
|
+
*/
|
|
7
18
|
export function regex(regex: RegExp, msg: string): Decoder<string>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Accepts and returns strings that are syntactically valid email addresses.
|
|
22
|
+
* (This will not mean that the email address actually exist.)
|
|
23
|
+
*/
|
|
8
24
|
export const email: Decoder<string>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Accepts strings that are valid URLs, returns the value as a URL instance.
|
|
28
|
+
*/
|
|
9
29
|
export const url: Decoder<URL>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Accepts strings that are valid URLs, but only HTTPS ones. Returns the value
|
|
33
|
+
* as a URL instance.
|
|
34
|
+
*/
|
|
10
35
|
export const httpsUrl: Decoder<URL>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Accepts strings that are valid
|
|
39
|
+
* [UUIDs](https://en.wikipedia.org/wiki/universally_unique_identifier)
|
|
40
|
+
* (universally unique identifier).
|
|
41
|
+
*/
|
|
11
42
|
export const uuid: Decoder<string>;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Like `uuid`, but only accepts
|
|
46
|
+
* [UUIDv1](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_%28date-time_and_MAC_address%29)
|
|
47
|
+
* strings.
|
|
48
|
+
*/
|
|
12
49
|
export const uuidv1: Decoder<string>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Like `uuid`, but only accepts
|
|
53
|
+
* [UUIDv4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_%28random%29)
|
|
54
|
+
* strings.
|
|
55
|
+
*/
|
|
13
56
|
export const uuidv4: Decoder<string>;
|
package/lib/unions.d.ts
CHANGED
|
@@ -4,75 +4,52 @@ export type Values<T extends object> = T[keyof T];
|
|
|
4
4
|
|
|
5
5
|
export type DecoderTypes<T> = T extends ReadonlyArray<Decoder<infer U>> ? U : never;
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Accepts values accepted by any of the given decoders.
|
|
9
|
+
*
|
|
10
|
+
* The decoders are tried on the input one by one, in the given order. The
|
|
11
|
+
* first one that accepts the input "wins". If all decoders reject the input,
|
|
12
|
+
* the input gets rejected.
|
|
13
|
+
*/
|
|
7
14
|
export function either<T extends ReadonlyArray<Decoder<any>>>(
|
|
8
15
|
...args: T
|
|
9
16
|
): Decoder<DecoderTypes<T>>;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
// d3: Decoder<T3>,
|
|
16
|
-
// ): Decoder<T1 | T2 | T3>;
|
|
17
|
-
// export function either4<T1, T2, T3, T4>(
|
|
18
|
-
// d1: Decoder<T1>,
|
|
19
|
-
// d2: Decoder<T2>,
|
|
20
|
-
// d3: Decoder<T3>,
|
|
21
|
-
// d4: Decoder<T4>,
|
|
22
|
-
// ): Decoder<T1 | T2 | T3 | T4>;
|
|
23
|
-
// export function either5<T1, T2, T3, T4, T5>(
|
|
24
|
-
// d1: Decoder<T1>,
|
|
25
|
-
// d2: Decoder<T2>,
|
|
26
|
-
// d3: Decoder<T3>,
|
|
27
|
-
// d4: Decoder<T4>,
|
|
28
|
-
// d5: Decoder<T5>,
|
|
29
|
-
// ): Decoder<T1 | T2 | T3 | T4 | T5>;
|
|
30
|
-
// export function either6<T1, T2, T3, T4, T5, T6>(
|
|
31
|
-
// d1: Decoder<T1>,
|
|
32
|
-
// d2: Decoder<T2>,
|
|
33
|
-
// d3: Decoder<T3>,
|
|
34
|
-
// d4: Decoder<T4>,
|
|
35
|
-
// d5: Decoder<T5>,
|
|
36
|
-
// d6: Decoder<T6>,
|
|
37
|
-
// ): Decoder<T1 | T2 | T3 | T4 | T5 | T6>;
|
|
38
|
-
// export function either7<T1, T2, T3, T4, T5, T6, T7>(
|
|
39
|
-
// d1: Decoder<T1>,
|
|
40
|
-
// d2: Decoder<T2>,
|
|
41
|
-
// d3: Decoder<T3>,
|
|
42
|
-
// d4: Decoder<T4>,
|
|
43
|
-
// d5: Decoder<T5>,
|
|
44
|
-
// d6: Decoder<T6>,
|
|
45
|
-
// d7: Decoder<T7>,
|
|
46
|
-
// ): Decoder<T1 | T2 | T3 | T4 | T5 | T6 | T7>;
|
|
47
|
-
// export function either8<T1, T2, T3, T4, T5, T6, T7, T8>(
|
|
48
|
-
// d1: Decoder<T1>,
|
|
49
|
-
// d2: Decoder<T2>,
|
|
50
|
-
// d3: Decoder<T3>,
|
|
51
|
-
// d4: Decoder<T4>,
|
|
52
|
-
// d5: Decoder<T5>,
|
|
53
|
-
// d6: Decoder<T6>,
|
|
54
|
-
// d7: Decoder<T7>,
|
|
55
|
-
// d8: Decoder<T8>,
|
|
56
|
-
// ): Decoder<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8>;
|
|
57
|
-
// export function either9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
|
|
58
|
-
// d1: Decoder<T1>,
|
|
59
|
-
// d2: Decoder<T2>,
|
|
60
|
-
// d3: Decoder<T3>,
|
|
61
|
-
// d4: Decoder<T4>,
|
|
62
|
-
// d5: Decoder<T5>,
|
|
63
|
-
// d6: Decoder<T6>,
|
|
64
|
-
// d7: Decoder<T7>,
|
|
65
|
-
// d8: Decoder<T8>,
|
|
66
|
-
// d9: Decoder<T9>,
|
|
67
|
-
// ): Decoder<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Accepts any value that is strictly-equal (using `===`) to one of the
|
|
20
|
+
* specified values.
|
|
21
|
+
*/
|
|
68
22
|
export function oneOf<T extends Scalar>(constants: readonly T[]): Decoder<T>;
|
|
69
23
|
|
|
24
|
+
/**
|
|
25
|
+
* If you are decoding tagged unions you may want to use the `taggedUnion()`
|
|
26
|
+
* decoder instead of the general purpose `either()` decoder to get better
|
|
27
|
+
* error messages and better performance.
|
|
28
|
+
*
|
|
29
|
+
* This decoder is optimized for [tagged
|
|
30
|
+
* unions](https://en.wikipedia.org/wiki/Tagged_union), i.e. a union of
|
|
31
|
+
* objects where one field is used as the discriminator.
|
|
32
|
+
*
|
|
33
|
+
* ```ts
|
|
34
|
+
* const A = object({ tag: constant('A'), foo: string });
|
|
35
|
+
* const B = object({ tag: constant('B'), bar: number });
|
|
36
|
+
*
|
|
37
|
+
* const AorB = taggedUnion('tag', { A, B });
|
|
38
|
+
* // ^^^
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* Decoding now works in two steps:
|
|
42
|
+
*
|
|
43
|
+
* 1. Look at the `'tag'` field in the incoming object (this is the field
|
|
44
|
+
* that decides which decoder will be used)
|
|
45
|
+
* 2. If the value is `'A'`, then decoder `A` will be used. If it's `'B'`, then
|
|
46
|
+
* decoder `B` will be used. Otherwise, this will fail.
|
|
47
|
+
*
|
|
48
|
+
* This is effectively equivalent to `either(A, B)`, but will provide better
|
|
49
|
+
* error messages and is more performant at runtime because it doesn't have to
|
|
50
|
+
* try all decoders one by one.
|
|
51
|
+
*/
|
|
70
52
|
export function taggedUnion<O extends { [key: string]: Decoder<any> }>(
|
|
71
53
|
field: string,
|
|
72
54
|
mapping: O,
|
|
73
55
|
): Decoder<Values<{ [key in keyof O]: DecoderType<O[key]> }>>;
|
|
74
|
-
|
|
75
|
-
export function dispatch<O extends { [key: string]: Decoder<any> }>(
|
|
76
|
-
field: string,
|
|
77
|
-
mapping: O,
|
|
78
|
-
): Decoder<Values<{ [key in keyof O]: DecoderType<O[key]> }>>;
|
package/lib/unions.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.either =
|
|
4
|
+
exports.either = void 0;
|
|
5
5
|
exports.oneOf = oneOf;
|
|
6
6
|
exports.taggedUnion = taggedUnion;
|
|
7
7
|
|
|
@@ -94,8 +94,8 @@ function _either() {
|
|
|
94
94
|
|
|
95
95
|
var either = _either;
|
|
96
96
|
/**
|
|
97
|
-
* Accepts any value that is strictly-equal (using
|
|
98
|
-
* values.
|
|
97
|
+
* Accepts any value that is strictly-equal (using `===`) to one of the
|
|
98
|
+
* specified values.
|
|
99
99
|
*/
|
|
100
100
|
|
|
101
101
|
exports.either = either;
|
|
@@ -124,11 +124,13 @@ function oneOf(constants) {
|
|
|
124
124
|
* unions](https://en.wikipedia.org/wiki/Tagged_union), i.e. a union of
|
|
125
125
|
* objects where one field is used as the discriminator.
|
|
126
126
|
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
127
|
+
* ```ts
|
|
128
|
+
* const A = object({ tag: constant('A'), foo: string });
|
|
129
|
+
* const B = object({ tag: constant('B'), bar: number });
|
|
129
130
|
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
131
|
+
* const AorB = taggedUnion('tag', { A, B });
|
|
132
|
+
* // ^^^
|
|
133
|
+
* ```
|
|
132
134
|
*
|
|
133
135
|
* Decoding now works in two steps:
|
|
134
136
|
*
|
|
@@ -155,7 +157,4 @@ function taggedUnion(field, mapping) {
|
|
|
155
157
|
var decoder = mapping[key];
|
|
156
158
|
return decoder.decode(blob);
|
|
157
159
|
});
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
var dispatch = taggedUnion;
|
|
161
|
-
exports.dispatch = dispatch;
|
|
160
|
+
}
|
package/lib/unions.js.flow
CHANGED
|
@@ -48,7 +48,7 @@ function nest(errText: string): string {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// prettier-ignore
|
|
51
|
-
interface
|
|
51
|
+
interface EitherT {
|
|
52
52
|
<A>(a: Decoder<A>): Decoder<A>;
|
|
53
53
|
<A, B>(a: Decoder<A>, b: Decoder<B>): Decoder<A | B>;
|
|
54
54
|
<A, B, C>(a: Decoder<A>, b: Decoder<B>, c: Decoder<C>): Decoder<A | B | C>;
|
|
@@ -93,11 +93,11 @@ function _either(...decoders: $ReadOnlyArray<Decoder<mixed>>): Decoder<mixed> {
|
|
|
93
93
|
* first one that accepts the input "wins". If all decoders reject the input,
|
|
94
94
|
* the input gets rejected.
|
|
95
95
|
*/
|
|
96
|
-
export const either:
|
|
96
|
+
export const either: EitherT = (_either: _Any);
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
|
-
* Accepts any value that is strictly-equal (using
|
|
100
|
-
* values.
|
|
99
|
+
* Accepts any value that is strictly-equal (using `===`) to one of the
|
|
100
|
+
* specified values.
|
|
101
101
|
*/
|
|
102
102
|
export function oneOf<T: Scalar>(constants: $ReadOnlyArray<T>): Decoder<T> {
|
|
103
103
|
return define((blob, ok, err) => {
|
|
@@ -122,11 +122,13 @@ export function oneOf<T: Scalar>(constants: $ReadOnlyArray<T>): Decoder<T> {
|
|
|
122
122
|
* unions](https://en.wikipedia.org/wiki/Tagged_union), i.e. a union of
|
|
123
123
|
* objects where one field is used as the discriminator.
|
|
124
124
|
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
125
|
+
* ```ts
|
|
126
|
+
* const A = object({ tag: constant('A'), foo: string });
|
|
127
|
+
* const B = object({ tag: constant('B'), bar: number });
|
|
127
128
|
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
129
|
+
* const AorB = taggedUnion('tag', { A, B });
|
|
130
|
+
* // ^^^
|
|
131
|
+
* ```
|
|
130
132
|
*
|
|
131
133
|
* Decoding now works in two steps:
|
|
132
134
|
*
|
|
@@ -151,8 +153,3 @@ export function taggedUnion<O: { +[field: string]: Decoder<_Any>, ... }>(
|
|
|
151
153
|
return decoder.decode(blob);
|
|
152
154
|
});
|
|
153
155
|
}
|
|
154
|
-
|
|
155
|
-
export const dispatch: <O: { +[field: string]: Decoder<_Any>, ... }>(
|
|
156
|
-
field: string,
|
|
157
|
-
mapping: O,
|
|
158
|
-
) => Decoder<$Values<$ObjMap<O, <T>(Decoder<T>) => T>>> = taggedUnion;
|