decoders 2.0.0-beta8 → 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 +11 -2
- package/README.md +234 -72
- package/_utils.js +1 -1
- package/_utils.js.flow +3 -3
- package/_utils.mjs +1 -1
- package/core/array.d.ts +3 -0
- package/core/array.js +12 -1
- package/core/array.js.flow +9 -2
- package/core/array.mjs +11 -2
- package/core/boolean.js +3 -3
- package/core/boolean.js.flow +2 -2
- package/core/boolean.mjs +2 -2
- package/core/composition.d.ts +5 -1
- package/core/composition.js +33 -5
- package/core/composition.js.flow +31 -5
- package/core/composition.mjs +31 -5
- package/core/date.js +3 -3
- package/core/date.js.flow +2 -2
- package/core/date.mjs +2 -2
- package/core/dispatch.d.ts +1 -1
- package/core/dispatch.js +8 -6
- package/core/dispatch.js.flow +9 -8
- package/core/dispatch.mjs +6 -5
- package/core/either.d.ts +63 -58
- package/core/either.js +30 -42
- package/core/either.js.flow +38 -84
- package/core/either.mjs +34 -34
- package/core/instanceOf.d.ts +1 -1
- package/core/json.js +3 -3
- package/core/json.js.flow +3 -3
- package/core/json.mjs +3 -3
- package/core/object.d.ts +5 -0
- package/core/object.js +59 -2
- package/core/object.js.flow +77 -21
- package/core/object.mjs +56 -3
- package/core/string.d.ts +3 -0
- package/core/string.js +15 -3
- package/core/string.js.flow +15 -2
- package/core/string.mjs +12 -3
- package/core/tuple.d.ts +28 -28
- package/core/tuple.js +28 -151
- package/core/tuple.js.flow +31 -191
- package/core/tuple.mjs +27 -141
- package/index.d.ts +17 -18
- package/index.js +33 -43
- package/index.js.flow +17 -18
- package/index.mjs +8 -9
- package/package.json +1 -1
- package/result.d.ts +2 -2
- package/result.js +9 -9
- package/result.js.flow +11 -11
- package/result.mjs +9 -9
- package/core/mapping.d.ts +0 -6
- package/core/mapping.js +0 -67
- package/core/mapping.js.flow +0 -62
- package/core/mapping.mjs +0 -58
package/core/either.js
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.either =
|
|
5
|
-
exports.either3 = either3;
|
|
6
|
-
exports.either4 = either4;
|
|
7
|
-
exports.either5 = either5;
|
|
8
|
-
exports.either6 = either6;
|
|
9
|
-
exports.either7 = either7;
|
|
10
|
-
exports.either8 = either8;
|
|
11
|
-
exports.either9 = either9;
|
|
4
|
+
exports.either = void 0;
|
|
12
5
|
exports.oneOf = oneOf;
|
|
13
6
|
|
|
14
7
|
var _annotate = require("../annotate");
|
|
@@ -17,9 +10,11 @@ var _result = require("../result");
|
|
|
17
10
|
|
|
18
11
|
var _utils = require("../_utils");
|
|
19
12
|
|
|
13
|
+
var EITHER_PREFIX = 'Either:\n';
|
|
20
14
|
/**
|
|
21
15
|
* Indents and adds a dash in front of this (potentially multiline) string.
|
|
22
16
|
*/
|
|
17
|
+
|
|
23
18
|
function itemize(s) {
|
|
24
19
|
return '-' + (0, _utils.indent)(s).substring(1);
|
|
25
20
|
}
|
|
@@ -51,51 +46,44 @@ function itemize(s) {
|
|
|
51
46
|
|
|
52
47
|
|
|
53
48
|
function nest(errText) {
|
|
54
|
-
var EITHER_PREFIX = 'Either:\n';
|
|
55
49
|
return errText.startsWith(EITHER_PREFIX) ? errText.substr(EITHER_PREFIX.length) : itemize(errText);
|
|
56
|
-
}
|
|
50
|
+
} // prettier-ignore
|
|
57
51
|
|
|
58
|
-
function either(d1, d2) {
|
|
59
|
-
return function (blob) {
|
|
60
|
-
return (0, _result.orElse)(d1(blob), function (err1) {
|
|
61
|
-
return (0, _result.orElse)(d2(blob), function (err2) {
|
|
62
|
-
var serr1 = (0, _utils.summarize)(err1).join('\n');
|
|
63
|
-
var serr2 = (0, _utils.summarize)(err2).join('\n');
|
|
64
|
-
var text = ['Either:', nest(serr1), nest(serr2)].join('\n');
|
|
65
|
-
return (0, _result.err)((0, _annotate.annotate)(blob, text));
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
52
|
|
|
71
|
-
function
|
|
72
|
-
|
|
73
|
-
|
|
53
|
+
function _either() {
|
|
54
|
+
for (var _len = arguments.length, decoders = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
55
|
+
decoders[_key] = arguments[_key];
|
|
56
|
+
}
|
|
74
57
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
58
|
+
if (decoders.length === 0) {
|
|
59
|
+
throw new Error('Pass at least one decoder to either()');
|
|
60
|
+
}
|
|
78
61
|
|
|
79
|
-
function
|
|
80
|
-
|
|
81
|
-
|
|
62
|
+
return function (blob) {
|
|
63
|
+
// Collect errors here along the way
|
|
64
|
+
var errors = [];
|
|
82
65
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
66
|
+
for (var _i = 0; _i < decoders.length; _i++) {
|
|
67
|
+
var result = decoders[_i](blob);
|
|
86
68
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
69
|
+
if (result.ok) {
|
|
70
|
+
return result;
|
|
71
|
+
} else {
|
|
72
|
+
errors.push(result.error);
|
|
73
|
+
}
|
|
74
|
+
} // Decoding all alternatives failed, return the combined error message
|
|
90
75
|
|
|
91
|
-
function either8(d1, d2, d3, d4, d5, d6, d7, d8) {
|
|
92
|
-
return either(d1, either7(d2, d3, d4, d5, d6, d7, d8));
|
|
93
|
-
}
|
|
94
76
|
|
|
95
|
-
|
|
96
|
-
|
|
77
|
+
var text = EITHER_PREFIX + errors.map(function (err) {
|
|
78
|
+
return nest((0, _utils.summarize)(err).join('\n'));
|
|
79
|
+
}).join('\n');
|
|
80
|
+
return (0, _result.err)((0, _annotate.annotate)(blob, text));
|
|
81
|
+
};
|
|
97
82
|
}
|
|
98
83
|
|
|
84
|
+
var either = _either;
|
|
85
|
+
exports.either = either;
|
|
86
|
+
|
|
99
87
|
function oneOf(constants) {
|
|
100
88
|
return function (blob) {
|
|
101
89
|
var winner = constants.find(function (c) {
|
package/core/either.js.flow
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
|
|
3
3
|
import { annotate } from '../annotate';
|
|
4
|
-
import { err, ok
|
|
4
|
+
import { err, ok } from '../result';
|
|
5
5
|
import { indent, summarize } from '../_utils';
|
|
6
|
-
import type {
|
|
6
|
+
import type { _Any } from '../_utils';
|
|
7
|
+
import type { Decoder, DecodeResult, Scalar } from '../_types';
|
|
8
|
+
|
|
9
|
+
const EITHER_PREFIX = 'Either:\n';
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Indents and adds a dash in front of this (potentially multiline) string.
|
|
@@ -38,100 +41,51 @@ function itemize(s: string): string {
|
|
|
38
41
|
*
|
|
39
42
|
*/
|
|
40
43
|
function nest(errText: string): string {
|
|
41
|
-
const EITHER_PREFIX = 'Either:\n';
|
|
42
44
|
return errText.startsWith(EITHER_PREFIX)
|
|
43
45
|
? errText.substr(EITHER_PREFIX.length)
|
|
44
46
|
: itemize(errText);
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
export function either3<T1, T2, T3>(
|
|
60
|
-
d1: Decoder<T1>,
|
|
61
|
-
d2: Decoder<T2>,
|
|
62
|
-
d3: Decoder<T3>,
|
|
63
|
-
): Decoder<T1 | T2 | T3> {
|
|
64
|
-
return either(d1, either(d2, d3));
|
|
49
|
+
// prettier-ignore
|
|
50
|
+
interface EitherDecoderSignatures {
|
|
51
|
+
<A>(a: Decoder<A>): Decoder<A>;
|
|
52
|
+
<A, B>(a: Decoder<A>, b: Decoder<B>): Decoder<A | B>;
|
|
53
|
+
<A, B, C>(a: Decoder<A>, b: Decoder<B>, c: Decoder<C>): Decoder<A | B | C>;
|
|
54
|
+
<A, B, C, D>(a: Decoder<A>, b: Decoder<B>, c: Decoder<C>, d: Decoder<D>): Decoder<A | B | C | D>;
|
|
55
|
+
<A, B, C, D, E>(a: Decoder<A>, b: Decoder<B>, c: Decoder<C>, d: Decoder<D>, e: Decoder<E>): Decoder<A | B | C | D | E>;
|
|
56
|
+
<A, B, C, D, E, F>(a: Decoder<A>, b: Decoder<B>, c: Decoder<C>, d: Decoder<D>, e: Decoder<E>, f: Decoder<F>): Decoder<A | B | C | D | E | F>;
|
|
57
|
+
<A, B, C, D, E, F, G>(a: Decoder<A>, b: Decoder<B>, c: Decoder<C>, d: Decoder<D>, e: Decoder<E>, f: Decoder<F>, g: Decoder<G>): Decoder<A | B | C | D | E | F | G>;
|
|
58
|
+
<A, B, C, D, E, F, G, H>(a: Decoder<A>, b: Decoder<B>, c: Decoder<C>, d: Decoder<D>, e: Decoder<E>, f: Decoder<F>, g: Decoder<G>, h: Decoder<H>): Decoder<A | B | C | D | E | F | G | H>;
|
|
59
|
+
<A, B, C, D, E, F, G, H, I>(a: Decoder<A>, b: Decoder<B>, c: Decoder<C>, d: Decoder<D>, e: Decoder<E>, f: Decoder<F>, g: Decoder<G>, h: Decoder<H>, i: Decoder<I>): Decoder<A | B | C | D | E | F | G | H | I>;
|
|
65
60
|
}
|
|
66
61
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
d4: Decoder<T4>,
|
|
72
|
-
): Decoder<T1 | T2 | T3 | T4> {
|
|
73
|
-
return either(d1, either3(d2, d3, d4));
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function either5<T1, T2, T3, T4, T5>(
|
|
77
|
-
d1: Decoder<T1>,
|
|
78
|
-
d2: Decoder<T2>,
|
|
79
|
-
d3: Decoder<T3>,
|
|
80
|
-
d4: Decoder<T4>,
|
|
81
|
-
d5: Decoder<T5>,
|
|
82
|
-
): Decoder<T1 | T2 | T3 | T4 | T5> {
|
|
83
|
-
return either(d1, either4(d2, d3, d4, d5));
|
|
84
|
-
}
|
|
62
|
+
function _either(...decoders: $ReadOnlyArray<Decoder<mixed>>): Decoder<mixed> {
|
|
63
|
+
if (decoders.length === 0) {
|
|
64
|
+
throw new Error('Pass at least one decoder to either()');
|
|
65
|
+
}
|
|
85
66
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
d3: Decoder<T3>,
|
|
90
|
-
d4: Decoder<T4>,
|
|
91
|
-
d5: Decoder<T5>,
|
|
92
|
-
d6: Decoder<T6>,
|
|
93
|
-
): Decoder<T1 | T2 | T3 | T4 | T5 | T6> {
|
|
94
|
-
return either(d1, either5(d2, d3, d4, d5, d6));
|
|
95
|
-
}
|
|
67
|
+
return (blob: mixed) => {
|
|
68
|
+
// Collect errors here along the way
|
|
69
|
+
const errors = [];
|
|
96
70
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
): Decoder<T1 | T2 | T3 | T4 | T5 | T6 | T7> {
|
|
106
|
-
return either(d1, either6(d2, d3, d4, d5, d6, d7));
|
|
107
|
-
}
|
|
71
|
+
for (let i = 0; i < decoders.length; i++) {
|
|
72
|
+
const result: DecodeResult<mixed> = decoders[i](blob);
|
|
73
|
+
if (result.ok) {
|
|
74
|
+
return result;
|
|
75
|
+
} else {
|
|
76
|
+
errors.push(result.error);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
108
79
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
d6: Decoder<T6>,
|
|
116
|
-
d7: Decoder<T7>,
|
|
117
|
-
d8: Decoder<T8>,
|
|
118
|
-
): Decoder<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8> {
|
|
119
|
-
return either(d1, either7(d2, d3, d4, d5, d6, d7, d8));
|
|
80
|
+
// Decoding all alternatives failed, return the combined error message
|
|
81
|
+
const text =
|
|
82
|
+
EITHER_PREFIX +
|
|
83
|
+
errors.map((err) => nest(summarize(err).join('\n'))).join('\n');
|
|
84
|
+
return err(annotate(blob, text));
|
|
85
|
+
};
|
|
120
86
|
}
|
|
121
87
|
|
|
122
|
-
export
|
|
123
|
-
d1: Decoder<T1>,
|
|
124
|
-
d2: Decoder<T2>,
|
|
125
|
-
d3: Decoder<T3>,
|
|
126
|
-
d4: Decoder<T4>,
|
|
127
|
-
d5: Decoder<T5>,
|
|
128
|
-
d6: Decoder<T6>,
|
|
129
|
-
d7: Decoder<T7>,
|
|
130
|
-
d8: Decoder<T8>,
|
|
131
|
-
d9: Decoder<T9>,
|
|
132
|
-
): Decoder<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9> {
|
|
133
|
-
return either(d1, either8(d2, d3, d4, d5, d6, d7, d8, d9));
|
|
134
|
-
}
|
|
88
|
+
export const either: EitherDecoderSignatures = (_either: _Any);
|
|
135
89
|
|
|
136
90
|
export function oneOf<T: Scalar>(constants: $ReadOnlyArray<T>): Decoder<T> {
|
|
137
91
|
return (blob: mixed) => {
|
package/core/either.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { annotate } from '../annotate.mjs';
|
|
2
|
-
import { err, ok
|
|
2
|
+
import { err, ok } from '../result.mjs';
|
|
3
3
|
import { indent, summarize } from '../_utils.mjs';
|
|
4
|
-
|
|
4
|
+
var EITHER_PREFIX = 'Either:\n';
|
|
5
5
|
/**
|
|
6
6
|
* Indents and adds a dash in front of this (potentially multiline) string.
|
|
7
7
|
*/
|
|
8
|
+
|
|
8
9
|
function itemize(s) {
|
|
9
10
|
return '-' + indent(s).substring(1);
|
|
10
11
|
}
|
|
@@ -36,43 +37,42 @@ function itemize(s) {
|
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
function nest(errText) {
|
|
39
|
-
var EITHER_PREFIX = 'Either:\n';
|
|
40
40
|
return errText.startsWith(EITHER_PREFIX) ? errText.substr(EITHER_PREFIX.length) : itemize(errText);
|
|
41
|
-
}
|
|
41
|
+
} // prettier-ignore
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
function _either() {
|
|
45
|
+
for (var _len = arguments.length, decoders = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
46
|
+
decoders[_key] = arguments[_key];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (decoders.length === 0) {
|
|
50
|
+
throw new Error('Pass at least one decoder to either()');
|
|
51
|
+
}
|
|
42
52
|
|
|
43
|
-
export function either(d1, d2) {
|
|
44
53
|
return function (blob) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
// Collect errors here along the way
|
|
55
|
+
var errors = [];
|
|
56
|
+
|
|
57
|
+
for (var _i = 0; _i < decoders.length; _i++) {
|
|
58
|
+
var result = decoders[_i](blob);
|
|
59
|
+
|
|
60
|
+
if (result.ok) {
|
|
61
|
+
return result;
|
|
62
|
+
} else {
|
|
63
|
+
errors.push(result.error);
|
|
64
|
+
}
|
|
65
|
+
} // Decoding all alternatives failed, return the combined error message
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
var text = EITHER_PREFIX + errors.map(function (err) {
|
|
69
|
+
return nest(summarize(err).join('\n'));
|
|
70
|
+
}).join('\n');
|
|
71
|
+
return err(annotate(blob, text));
|
|
53
72
|
};
|
|
54
73
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
export function either4(d1, d2, d3, d4) {
|
|
59
|
-
return either(d1, either3(d2, d3, d4));
|
|
60
|
-
}
|
|
61
|
-
export function either5(d1, d2, d3, d4, d5) {
|
|
62
|
-
return either(d1, either4(d2, d3, d4, d5));
|
|
63
|
-
}
|
|
64
|
-
export function either6(d1, d2, d3, d4, d5, d6) {
|
|
65
|
-
return either(d1, either5(d2, d3, d4, d5, d6));
|
|
66
|
-
}
|
|
67
|
-
export function either7(d1, d2, d3, d4, d5, d6, d7) {
|
|
68
|
-
return either(d1, either6(d2, d3, d4, d5, d6, d7));
|
|
69
|
-
}
|
|
70
|
-
export function either8(d1, d2, d3, d4, d5, d6, d7, d8) {
|
|
71
|
-
return either(d1, either7(d2, d3, d4, d5, d6, d7, d8));
|
|
72
|
-
}
|
|
73
|
-
export function either9(d1, d2, d3, d4, d5, d6, d7, d8, d9) {
|
|
74
|
-
return either(d1, either8(d2, d3, d4, d5, d6, d7, d8, d9));
|
|
75
|
-
}
|
|
74
|
+
|
|
75
|
+
export var either = _either;
|
|
76
76
|
export function oneOf(constants) {
|
|
77
77
|
return function (blob) {
|
|
78
78
|
var winner = constants.find(function (c) {
|
package/core/instanceOf.d.ts
CHANGED
package/core/json.js
CHANGED
|
@@ -7,7 +7,7 @@ var _array = require("./array");
|
|
|
7
7
|
|
|
8
8
|
var _boolean2 = require("./boolean");
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _object = require("./object");
|
|
11
11
|
|
|
12
12
|
var _either = require("./either");
|
|
13
13
|
|
|
@@ -20,12 +20,12 @@ var _number = require("./number");
|
|
|
20
20
|
var _string = require("./string");
|
|
21
21
|
|
|
22
22
|
var jsonObject = (0, _lazy.lazy)(function () {
|
|
23
|
-
return (0,
|
|
23
|
+
return (0, _object.dict)(json);
|
|
24
24
|
});
|
|
25
25
|
exports.jsonObject = jsonObject;
|
|
26
26
|
var jsonArray = (0, _lazy.lazy)(function () {
|
|
27
27
|
return (0, _array.array)(json);
|
|
28
28
|
});
|
|
29
29
|
exports.jsonArray = jsonArray;
|
|
30
|
-
var json = (0, _either.
|
|
30
|
+
var json = (0, _either.either)(_constants.null_, _string.string, _number.number, _boolean2["boolean"], jsonObject, jsonArray);
|
|
31
31
|
exports.json = json;
|
package/core/json.js.flow
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { array } from './array';
|
|
4
4
|
import { boolean } from './boolean';
|
|
5
|
-
import { dict } from './
|
|
6
|
-
import {
|
|
5
|
+
import { dict } from './object';
|
|
6
|
+
import { either } from './either';
|
|
7
7
|
import { lazy } from './lazy';
|
|
8
8
|
import { null_ } from './constants';
|
|
9
9
|
import { number } from './number';
|
|
@@ -18,7 +18,7 @@ export const jsonObject: Decoder<JSONObject> = lazy(() => dict(json));
|
|
|
18
18
|
|
|
19
19
|
export const jsonArray: Decoder<JSONArray> = lazy(() => array(json));
|
|
20
20
|
|
|
21
|
-
export const json: Decoder<JSONValue> =
|
|
21
|
+
export const json: Decoder<JSONValue> = either(
|
|
22
22
|
null_,
|
|
23
23
|
string,
|
|
24
24
|
number,
|
package/core/json.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { array } from './array.mjs';
|
|
2
2
|
import { boolean as _boolean } from './boolean.mjs';
|
|
3
|
-
import { dict } from './
|
|
4
|
-
import {
|
|
3
|
+
import { dict } from './object.mjs';
|
|
4
|
+
import { either } from './either.mjs';
|
|
5
5
|
import { lazy } from './lazy.mjs';
|
|
6
6
|
import { null_ } from './constants.mjs';
|
|
7
7
|
import { number } from './number.mjs';
|
|
@@ -12,4 +12,4 @@ export var jsonObject = lazy(function () {
|
|
|
12
12
|
export var jsonArray = lazy(function () {
|
|
13
13
|
return array(json);
|
|
14
14
|
});
|
|
15
|
-
export var json =
|
|
15
|
+
export var json = either(null_, string, number, _boolean, jsonObject, jsonArray);
|
package/core/object.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/// <reference lib="es6" />
|
|
2
|
+
|
|
1
3
|
import { Decoder, DecoderType } from '../_types';
|
|
2
4
|
import { AllowImplicit } from './_helpers';
|
|
3
5
|
|
|
@@ -31,3 +33,6 @@ export function inexact<O extends { [key: string]: Decoder<any> }>(
|
|
|
31
33
|
[extra: string]: unknown;
|
|
32
34
|
}
|
|
33
35
|
>;
|
|
36
|
+
|
|
37
|
+
export function mapping<T>(decoder: Decoder<T>): Decoder<Map<string, T>>;
|
|
38
|
+
export function dict<T>(decoder: Decoder<T>): Decoder<{ [key: string]: T }>;
|
package/core/object.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
+
exports.dict = dict;
|
|
4
5
|
exports.exact = exact;
|
|
5
6
|
exports.inexact = inexact;
|
|
7
|
+
exports.mapping = mapping;
|
|
6
8
|
exports.object = object;
|
|
7
9
|
exports.pojo = void 0;
|
|
8
10
|
|
|
@@ -87,7 +89,7 @@ function object(mapping) {
|
|
|
87
89
|
var rawValue = blob[key];
|
|
88
90
|
var result = decoder(rawValue);
|
|
89
91
|
|
|
90
|
-
if (result.
|
|
92
|
+
if (result.ok) {
|
|
91
93
|
var value = result.value;
|
|
92
94
|
|
|
93
95
|
if (value !== undefined) {
|
|
@@ -165,7 +167,7 @@ function exact(mapping) {
|
|
|
165
167
|
function inexact(mapping) {
|
|
166
168
|
return (0, _composition.compose)(pojo, function (blob) {
|
|
167
169
|
var allkeys = new Set(Object.keys(blob));
|
|
168
|
-
var decoder = (0, _composition.
|
|
170
|
+
var decoder = (0, _composition.transform)(object(mapping), function (safepart) {
|
|
169
171
|
var safekeys = new Set(Object.keys(mapping)); // To account for hard-coded keys that aren't part of the input
|
|
170
172
|
|
|
171
173
|
safekeys.forEach(function (k) {
|
|
@@ -187,4 +189,59 @@ function inexact(mapping) {
|
|
|
187
189
|
});
|
|
188
190
|
return decoder(blob);
|
|
189
191
|
});
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Like mapping(), but returns an object rather than a Map instance.
|
|
195
|
+
*/
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
function dict(decoder) {
|
|
199
|
+
return (0, _composition.compose)(pojo, function (blob) {
|
|
200
|
+
var rv = {};
|
|
201
|
+
var errors = null;
|
|
202
|
+
Object.keys(blob).forEach(function (key) {
|
|
203
|
+
var value = blob[key];
|
|
204
|
+
var result = decoder(value);
|
|
205
|
+
|
|
206
|
+
if (result.ok) {
|
|
207
|
+
if (errors === null) {
|
|
208
|
+
rv[key] = result.value;
|
|
209
|
+
}
|
|
210
|
+
} else {
|
|
211
|
+
rv = {}; // Clear the success value so it can get garbage collected early
|
|
212
|
+
|
|
213
|
+
if (errors === null) {
|
|
214
|
+
errors = {};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
errors[key] = result.error;
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
if (errors !== null) {
|
|
222
|
+
return (0, _result.err)((0, _annotate.merge)((0, _annotate.annotateObject)(blob), errors));
|
|
223
|
+
} else {
|
|
224
|
+
return (0, _result.ok)(rv);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Given an object, will decode a Map of string keys to whatever values.
|
|
230
|
+
*
|
|
231
|
+
* For example, given a decoder for a Person, we can verify a Person lookup
|
|
232
|
+
* table structure (of type Map<string, Person>) like so:
|
|
233
|
+
*
|
|
234
|
+
* mapping(person)
|
|
235
|
+
*
|
|
236
|
+
*/
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
function mapping(decoder) {
|
|
240
|
+
return (0, _composition.transform)(dict(decoder), function (obj) {
|
|
241
|
+
return new Map( // This is effectively Object.entries(obj), but in a way that Flow
|
|
242
|
+
// will know the types are okay
|
|
243
|
+
Object.keys(obj).map(function (key) {
|
|
244
|
+
return [key, obj[key]];
|
|
245
|
+
}));
|
|
246
|
+
});
|
|
190
247
|
}
|
package/core/object.js.flow
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
|
|
3
3
|
import { annotate, annotateObject, merge, updateText } from '../annotate';
|
|
4
|
-
import { compose,
|
|
4
|
+
import { compose, transform } from './composition';
|
|
5
5
|
import { err, ok } from '../result';
|
|
6
6
|
import type { Annotation } from '../annotate';
|
|
7
|
-
import type { Decoder, DecoderType } from '../_types';
|
|
7
|
+
import type { Decoder, DecodeResult, DecoderType } from '../_types';
|
|
8
8
|
|
|
9
9
|
// $FlowFixMe[unclear-type] (not really an issue) - deliberate use of `any` - not sure how we should get rid of this
|
|
10
10
|
type AnyDecoder = any;
|
|
@@ -94,9 +94,9 @@ export function object<O: { +[field: string]: AnyDecoder, ... }>(
|
|
|
94
94
|
Object.keys(mapping).forEach((key) => {
|
|
95
95
|
const decoder = mapping[key];
|
|
96
96
|
const rawValue = blob[key];
|
|
97
|
-
const result = decoder(rawValue);
|
|
97
|
+
const result: DecodeResult<mixed> = decoder(rawValue);
|
|
98
98
|
|
|
99
|
-
if (result.
|
|
99
|
+
if (result.ok) {
|
|
100
100
|
const value = result.value;
|
|
101
101
|
if (value !== undefined) {
|
|
102
102
|
record[key] = value;
|
|
@@ -179,25 +179,81 @@ export function inexact<O: { +[field: string]: AnyDecoder }>(
|
|
|
179
179
|
): Decoder<$ObjMap<O, DecoderType> & { +[string]: mixed }> {
|
|
180
180
|
return compose(pojo, (blob: {| [string]: mixed |}) => {
|
|
181
181
|
const allkeys = new Set(Object.keys(blob));
|
|
182
|
-
const decoder =
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if (
|
|
193
|
-
|
|
182
|
+
const decoder = transform(
|
|
183
|
+
object(mapping),
|
|
184
|
+
(safepart: $ObjMap<O, DecoderType>) => {
|
|
185
|
+
const safekeys = new Set(Object.keys(mapping));
|
|
186
|
+
|
|
187
|
+
// To account for hard-coded keys that aren't part of the input
|
|
188
|
+
safekeys.forEach((k) => allkeys.add(k));
|
|
189
|
+
|
|
190
|
+
const rv = {};
|
|
191
|
+
allkeys.forEach((k) => {
|
|
192
|
+
if (safekeys.has(k)) {
|
|
193
|
+
const value = safepart[k];
|
|
194
|
+
if (value !== undefined) {
|
|
195
|
+
rv[k] = value;
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
rv[k] = blob[k];
|
|
194
199
|
}
|
|
195
|
-
}
|
|
196
|
-
|
|
200
|
+
});
|
|
201
|
+
return rv;
|
|
202
|
+
},
|
|
203
|
+
);
|
|
204
|
+
return decoder(blob);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Like mapping(), but returns an object rather than a Map instance.
|
|
210
|
+
*/
|
|
211
|
+
export function dict<T>(decoder: Decoder<T>): Decoder<{ [string]: T }> {
|
|
212
|
+
return compose(pojo, (blob: { +[key: string]: mixed }) => {
|
|
213
|
+
let rv: { [key: string]: T } = {};
|
|
214
|
+
let errors: { [key: string]: Annotation } | null = null;
|
|
215
|
+
|
|
216
|
+
Object.keys(blob).forEach((key: string) => {
|
|
217
|
+
const value = blob[key];
|
|
218
|
+
const result = decoder(value);
|
|
219
|
+
if (result.ok) {
|
|
220
|
+
if (errors === null) {
|
|
221
|
+
rv[key] = result.value;
|
|
222
|
+
}
|
|
223
|
+
} else {
|
|
224
|
+
rv = {}; // Clear the success value so it can get garbage collected early
|
|
225
|
+
if (errors === null) {
|
|
226
|
+
errors = {};
|
|
197
227
|
}
|
|
198
|
-
|
|
199
|
-
|
|
228
|
+
errors[key] = result.error;
|
|
229
|
+
}
|
|
200
230
|
});
|
|
201
|
-
|
|
231
|
+
|
|
232
|
+
if (errors !== null) {
|
|
233
|
+
return err(merge(annotateObject(blob), errors));
|
|
234
|
+
} else {
|
|
235
|
+
return ok(rv);
|
|
236
|
+
}
|
|
202
237
|
});
|
|
203
238
|
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Given an object, will decode a Map of string keys to whatever values.
|
|
242
|
+
*
|
|
243
|
+
* For example, given a decoder for a Person, we can verify a Person lookup
|
|
244
|
+
* table structure (of type Map<string, Person>) like so:
|
|
245
|
+
*
|
|
246
|
+
* mapping(person)
|
|
247
|
+
*
|
|
248
|
+
*/
|
|
249
|
+
export function mapping<T>(decoder: Decoder<T>): Decoder<Map<string, T>> {
|
|
250
|
+
return transform(
|
|
251
|
+
dict(decoder),
|
|
252
|
+
(obj) =>
|
|
253
|
+
new Map(
|
|
254
|
+
// This is effectively Object.entries(obj), but in a way that Flow
|
|
255
|
+
// will know the types are okay
|
|
256
|
+
Object.keys(obj).map((key) => [key, obj[key]]),
|
|
257
|
+
),
|
|
258
|
+
);
|
|
259
|
+
}
|