decoders 2.0.0-beta4 → 2.0.0-beta8
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 +10 -0
- package/NotSupportedTSVersion.d.ts +1 -0
- package/README.md +728 -343
- 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/{_esm/_utils.js → _utils.mjs} +0 -0
- 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 +5 -0
- package/core/array.js +7 -11
- package/core/array.js.flow +6 -9
- package/{_esm/core/array.js → core/array.mjs} +9 -9
- package/core/boolean.d.ts +5 -0
- package/core/boolean.js +4 -8
- package/core/boolean.js.flow +3 -5
- package/{_esm/core/boolean.js → core/boolean.mjs} +6 -6
- package/core/composition.d.ts +14 -0
- package/core/composition.js +9 -11
- package/core/composition.js.flow +13 -8
- package/{_esm/core/composition.js → core/composition.mjs} +10 -8
- 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 +3 -7
- package/core/date.js.flow +2 -4
- package/{_esm/core/date.js → core/date.mjs} +6 -6
- 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 +9 -13
- package/core/dispatch.js.flow +8 -8
- package/{_esm/core/dispatch.js → core/dispatch.mjs} +10 -10
- package/core/either.d.ts +61 -0
- package/core/either.js +7 -11
- package/core/either.js.flow +6 -6
- package/{_esm/core/either.js → core/either.mjs} +8 -8
- 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.mjs +15 -0
- package/core/lazy.d.ts +3 -0
- package/{_esm/core/lazy.js → core/lazy.mjs} +0 -0
- package/core/mapping.d.ts +6 -0
- package/core/mapping.js +23 -23
- package/core/mapping.js.flow +25 -17
- package/{_esm/core/mapping.js → core/mapping.mjs} +26 -22
- 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 +33 -0
- package/core/object.js +7 -11
- package/core/object.js.flow +7 -7
- package/{_esm/core/object.js → core/object.mjs} +9 -9
- 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 +10 -0
- package/core/string.js +18 -48
- package/core/string.js.flow +16 -39
- package/core/string.mjs +49 -0
- package/core/tuple.d.ts +30 -0
- package/core/tuple.js +12 -8
- package/core/tuple.js.flow +25 -29
- package/{_esm/core/tuple.js → core/tuple.mjs} +16 -12
- 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 +43 -0
- package/index.js +3 -2
- package/index.js.flow +2 -2
- package/{_esm/index.js → index.mjs} +19 -19
- package/package.json +15 -3
- package/result.d.ts +39 -0
- package/result.js +3 -78
- package/result.js.flow +4 -76
- package/{_esm/result.js → result.mjs} +3 -64
- 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.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.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.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.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.flow +0 -170
- 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
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { indent, summarize } from '../_utils';
|
|
1
|
+
import { annotate } from '../annotate.mjs';
|
|
2
|
+
import { err, ok, orElse } from '../result.mjs';
|
|
3
|
+
import { indent, summarize } from '../_utils.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Indents and adds a dash in front of this (potentially multiline) string.
|
|
@@ -42,12 +42,12 @@ function nest(errText) {
|
|
|
42
42
|
|
|
43
43
|
export function either(d1, d2) {
|
|
44
44
|
return function (blob) {
|
|
45
|
-
return
|
|
46
|
-
return
|
|
45
|
+
return orElse(d1(blob), function (err1) {
|
|
46
|
+
return orElse(d2(blob), function (err2) {
|
|
47
47
|
var serr1 = summarize(err1).join('\n');
|
|
48
48
|
var serr2 = summarize(err2).join('\n');
|
|
49
49
|
var text = ['Either:', nest(serr1), nest(serr2)].join('\n');
|
|
50
|
-
return
|
|
50
|
+
return err(annotate(blob, text));
|
|
51
51
|
});
|
|
52
52
|
});
|
|
53
53
|
};
|
|
@@ -80,10 +80,10 @@ export function oneOf(constants) {
|
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
if (winner !== undefined) {
|
|
83
|
-
return
|
|
83
|
+
return ok(winner);
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
return
|
|
86
|
+
return err(annotate(blob, "Must be one of " + constants.map(function (value) {
|
|
87
87
|
return JSON.stringify(value);
|
|
88
88
|
}).join(', ')));
|
|
89
89
|
};
|
package/core/fail.d.ts
ADDED
package/core/fail.js
CHANGED
|
@@ -3,19 +3,15 @@
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.fail = fail;
|
|
5
5
|
|
|
6
|
-
var Result = _interopRequireWildcard(require("../result"));
|
|
7
|
-
|
|
8
6
|
var _annotate = require("../annotate");
|
|
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
|
/**
|
|
15
11
|
* Decoder that always fails with the given error message, no matter what the input.
|
|
16
12
|
*/
|
|
17
13
|
function fail(msg) {
|
|
18
14
|
return function (blob) {
|
|
19
|
-
return
|
|
15
|
+
return (0, _result.err)((0, _annotate.annotate)(blob, msg));
|
|
20
16
|
};
|
|
21
17
|
}
|
package/core/fail.js.flow
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
|
|
3
|
-
import * as Result from '../result';
|
|
4
3
|
import { annotate } from '../annotate';
|
|
4
|
+
import { err } from '../result';
|
|
5
5
|
import type { Decoder } from '../_types';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Decoder that always fails with the given error message, no matter what the input.
|
|
9
9
|
*/
|
|
10
10
|
export function fail(msg: string): Decoder<empty> {
|
|
11
|
-
return (blob: mixed) =>
|
|
11
|
+
return (blob: mixed) => err(annotate(blob, msg));
|
|
12
12
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { annotate } from '../annotate.mjs';
|
|
2
|
+
import { err } from '../result.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Decoder that always fails with the given error message, no matter what the input.
|
|
6
6
|
*/
|
|
7
7
|
export function fail(msg) {
|
|
8
8
|
return function (blob) {
|
|
9
|
-
return
|
|
9
|
+
return err(annotate(blob, msg));
|
|
10
10
|
};
|
|
11
11
|
}
|
package/core/instanceOf.js
CHANGED
|
@@ -3,17 +3,13 @@
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.instanceOf = instanceOf;
|
|
5
5
|
|
|
6
|
-
var Result = _interopRequireWildcard(require("../result"));
|
|
7
|
-
|
|
8
6
|
var _annotate = require("../annotate");
|
|
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 instanceOf(klass) {
|
|
15
11
|
return function (blob) {
|
|
16
|
-
return blob instanceof klass ?
|
|
12
|
+
return blob instanceof klass ? (0, _result.ok)(blob) : (0, _result.err)((0, _annotate.annotate)(blob, "Must be " + // $FlowFixMe[incompatible-use] - klass.name is fine?
|
|
17
13
|
klass.name + " instance"));
|
|
18
14
|
};
|
|
19
15
|
}
|
package/core/instanceOf.js.flow
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
|
|
3
|
-
import * as Result from '../result';
|
|
4
3
|
import { annotate } from '../annotate';
|
|
4
|
+
import { err, ok } from '../result';
|
|
5
5
|
import type { Decoder } from '../_types';
|
|
6
6
|
|
|
7
7
|
export function instanceOf<T>(klass: Class<T>): Decoder<T> {
|
|
8
8
|
return (blob: mixed) =>
|
|
9
9
|
blob instanceof klass
|
|
10
|
-
?
|
|
11
|
-
:
|
|
10
|
+
? ok(blob)
|
|
11
|
+
: err(
|
|
12
12
|
annotate(
|
|
13
13
|
blob,
|
|
14
14
|
`Must be ${
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { annotate } from '../annotate.mjs';
|
|
2
|
+
import { err, ok } from '../result.mjs';
|
|
3
|
+
export function instanceOf(klass) {
|
|
4
|
+
return function (blob) {
|
|
5
|
+
return blob instanceof klass ? ok(blob) : err(annotate(blob, "Must be " + // $FlowFixMe[incompatible-use] - klass.name is fine?
|
|
6
|
+
klass.name + " instance"));
|
|
7
|
+
};
|
|
8
|
+
}
|
package/core/json.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Decoder } from '../_types';
|
|
2
|
+
|
|
3
|
+
export type JSONValue = null | string | number | boolean | JSONObject | JSONArray;
|
|
4
|
+
export interface JSONObject {
|
|
5
|
+
[key: string]: JSONValue;
|
|
6
|
+
}
|
|
7
|
+
export type JSONArray = JSONValue[];
|
|
8
|
+
|
|
9
|
+
export const json: Decoder<JSONValue>;
|
|
10
|
+
export const jsonArray: Decoder<JSONArray>;
|
|
11
|
+
export const jsonObject: Decoder<JSONObject>;
|
package/core/json.mjs
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { array } from './array.mjs';
|
|
2
|
+
import { boolean as _boolean } from './boolean.mjs';
|
|
3
|
+
import { dict } from './mapping.mjs';
|
|
4
|
+
import { either6 } from './either.mjs';
|
|
5
|
+
import { lazy } from './lazy.mjs';
|
|
6
|
+
import { null_ } from './constants.mjs';
|
|
7
|
+
import { number } from './number.mjs';
|
|
8
|
+
import { string } from './string.mjs';
|
|
9
|
+
export var jsonObject = lazy(function () {
|
|
10
|
+
return dict(json);
|
|
11
|
+
});
|
|
12
|
+
export var jsonArray = lazy(function () {
|
|
13
|
+
return array(json);
|
|
14
|
+
});
|
|
15
|
+
export var json = either6(null_, string, number, _boolean, jsonObject, jsonArray);
|
package/core/lazy.d.ts
ADDED
|
File without changes
|
package/core/mapping.js
CHANGED
|
@@ -4,30 +4,20 @@ exports.__esModule = true;
|
|
|
4
4
|
exports.dict = dict;
|
|
5
5
|
exports.mapping = mapping;
|
|
6
6
|
|
|
7
|
-
var Result = _interopRequireWildcard(require("../result"));
|
|
8
|
-
|
|
9
7
|
var _annotate = require("../annotate");
|
|
10
8
|
|
|
11
9
|
var _composition = require("./composition");
|
|
12
10
|
|
|
13
|
-
var
|
|
14
|
-
|
|
15
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
11
|
+
var _result = require("../result");
|
|
16
12
|
|
|
17
|
-
|
|
13
|
+
var _object = require("./object");
|
|
18
14
|
|
|
19
15
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* For example, given a decoder for a Person, we can verify a Person lookup
|
|
23
|
-
* table structure (of type Map<string, Person>) like so:
|
|
24
|
-
*
|
|
25
|
-
* mapping(person)
|
|
26
|
-
*
|
|
16
|
+
* Like mapping(), but returns an object rather than a Map instance.
|
|
27
17
|
*/
|
|
28
|
-
function
|
|
18
|
+
function dict(decoder) {
|
|
29
19
|
return (0, _composition.compose)(_object.pojo, function (blob) {
|
|
30
|
-
var
|
|
20
|
+
var rv = {};
|
|
31
21
|
var errors = null;
|
|
32
22
|
Object.keys(blob).forEach(function (key) {
|
|
33
23
|
var value = blob[key];
|
|
@@ -35,10 +25,10 @@ function mapping(decoder) {
|
|
|
35
25
|
|
|
36
26
|
if (result.type === 'ok') {
|
|
37
27
|
if (errors === null) {
|
|
38
|
-
|
|
28
|
+
rv[key] = result.value;
|
|
39
29
|
}
|
|
40
30
|
} else {
|
|
41
|
-
|
|
31
|
+
rv = {}; // Clear the success value so it can get garbage collected early
|
|
42
32
|
|
|
43
33
|
if (errors === null) {
|
|
44
34
|
errors = {};
|
|
@@ -49,19 +39,29 @@ function mapping(decoder) {
|
|
|
49
39
|
});
|
|
50
40
|
|
|
51
41
|
if (errors !== null) {
|
|
52
|
-
return
|
|
42
|
+
return (0, _result.err)((0, _annotate.merge)((0, _annotate.annotateObject)(blob), errors));
|
|
53
43
|
} else {
|
|
54
|
-
return
|
|
44
|
+
return (0, _result.ok)(rv);
|
|
55
45
|
}
|
|
56
46
|
});
|
|
57
47
|
}
|
|
58
48
|
/**
|
|
59
|
-
*
|
|
49
|
+
* Given an object, will decode a Map of string keys to whatever values.
|
|
50
|
+
*
|
|
51
|
+
* For example, given a decoder for a Person, we can verify a Person lookup
|
|
52
|
+
* table structure (of type Map<string, Person>) like so:
|
|
53
|
+
*
|
|
54
|
+
* mapping(person)
|
|
55
|
+
*
|
|
60
56
|
*/
|
|
61
57
|
|
|
62
58
|
|
|
63
|
-
function
|
|
64
|
-
return (0, _composition.map)(
|
|
65
|
-
return Object.
|
|
59
|
+
function mapping(decoder) {
|
|
60
|
+
return (0, _composition.map)(dict(decoder), function (obj) {
|
|
61
|
+
return new Map( // This is effectively Object.entries(obj), but in a way that Flow
|
|
62
|
+
// will know the types are okay
|
|
63
|
+
Object.keys(obj).map(function (key) {
|
|
64
|
+
return [key, obj[key]];
|
|
65
|
+
}));
|
|
66
66
|
});
|
|
67
67
|
}
|
package/core/mapping.js.flow
CHANGED
|
@@ -1,25 +1,19 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
|
|
3
|
-
import * as Result from '../result';
|
|
4
3
|
import { annotateObject } from '../annotate';
|
|
5
4
|
import { compose, map } from './composition';
|
|
5
|
+
import { err, ok } from '../result';
|
|
6
6
|
import { merge } from '../annotate';
|
|
7
7
|
import { pojo } from './object';
|
|
8
8
|
import type { Annotation } from '../annotate';
|
|
9
9
|
import type { Decoder } from '../_types';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* For example, given a decoder for a Person, we can verify a Person lookup
|
|
15
|
-
* table structure (of type Map<string, Person>) like so:
|
|
16
|
-
*
|
|
17
|
-
* mapping(person)
|
|
18
|
-
*
|
|
12
|
+
* Like mapping(), but returns an object rather than a Map instance.
|
|
19
13
|
*/
|
|
20
|
-
export function
|
|
14
|
+
export function dict<T>(decoder: Decoder<T>): Decoder<{ [string]: T }> {
|
|
21
15
|
return compose(pojo, (blob: { +[key: string]: mixed }) => {
|
|
22
|
-
let
|
|
16
|
+
let rv: { [key: string]: T } = {};
|
|
23
17
|
let errors: { [key: string]: Annotation } | null = null;
|
|
24
18
|
|
|
25
19
|
Object.keys(blob).forEach((key: string) => {
|
|
@@ -27,10 +21,10 @@ export function mapping<T>(decoder: Decoder<T>): Decoder<Map<string, T>> {
|
|
|
27
21
|
const result = decoder(value);
|
|
28
22
|
if (result.type === 'ok') {
|
|
29
23
|
if (errors === null) {
|
|
30
|
-
|
|
24
|
+
rv[key] = result.value;
|
|
31
25
|
}
|
|
32
26
|
} else {
|
|
33
|
-
|
|
27
|
+
rv = {}; // Clear the success value so it can get garbage collected early
|
|
34
28
|
if (errors === null) {
|
|
35
29
|
errors = {};
|
|
36
30
|
}
|
|
@@ -39,16 +33,30 @@ export function mapping<T>(decoder: Decoder<T>): Decoder<Map<string, T>> {
|
|
|
39
33
|
});
|
|
40
34
|
|
|
41
35
|
if (errors !== null) {
|
|
42
|
-
return
|
|
36
|
+
return err(merge(annotateObject(blob), errors));
|
|
43
37
|
} else {
|
|
44
|
-
return
|
|
38
|
+
return ok(rv);
|
|
45
39
|
}
|
|
46
40
|
});
|
|
47
41
|
}
|
|
48
42
|
|
|
49
43
|
/**
|
|
50
|
-
*
|
|
44
|
+
* Given an object, will decode a Map of string keys to whatever values.
|
|
45
|
+
*
|
|
46
|
+
* For example, given a decoder for a Person, we can verify a Person lookup
|
|
47
|
+
* table structure (of type Map<string, Person>) like so:
|
|
48
|
+
*
|
|
49
|
+
* mapping(person)
|
|
50
|
+
*
|
|
51
51
|
*/
|
|
52
|
-
export function
|
|
53
|
-
return map(
|
|
52
|
+
export function mapping<T>(decoder: Decoder<T>): Decoder<Map<string, T>> {
|
|
53
|
+
return map(
|
|
54
|
+
dict(decoder),
|
|
55
|
+
(obj) =>
|
|
56
|
+
new Map(
|
|
57
|
+
// This is effectively Object.entries(obj), but in a way that Flow
|
|
58
|
+
// will know the types are okay
|
|
59
|
+
Object.keys(obj).map((key) => [key, obj[key]]),
|
|
60
|
+
),
|
|
61
|
+
);
|
|
54
62
|
}
|
|
@@ -1,21 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { merge } from '../annotate';
|
|
5
|
-
import { pojo } from './object';
|
|
1
|
+
import { annotateObject } from '../annotate.mjs';
|
|
2
|
+
import { compose, map } from './composition.mjs';
|
|
3
|
+
import { err, ok } from '../result.mjs';
|
|
4
|
+
import { merge } from '../annotate.mjs';
|
|
5
|
+
import { pojo } from './object.mjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* For example, given a decoder for a Person, we can verify a Person lookup
|
|
11
|
-
* table structure (of type Map<string, Person>) like so:
|
|
12
|
-
*
|
|
13
|
-
* mapping(person)
|
|
14
|
-
*
|
|
8
|
+
* Like mapping(), but returns an object rather than a Map instance.
|
|
15
9
|
*/
|
|
16
|
-
export function
|
|
10
|
+
export function dict(decoder) {
|
|
17
11
|
return compose(pojo, function (blob) {
|
|
18
|
-
var
|
|
12
|
+
var rv = {};
|
|
19
13
|
var errors = null;
|
|
20
14
|
Object.keys(blob).forEach(function (key) {
|
|
21
15
|
var value = blob[key];
|
|
@@ -23,10 +17,10 @@ export function mapping(decoder) {
|
|
|
23
17
|
|
|
24
18
|
if (result.type === 'ok') {
|
|
25
19
|
if (errors === null) {
|
|
26
|
-
|
|
20
|
+
rv[key] = result.value;
|
|
27
21
|
}
|
|
28
22
|
} else {
|
|
29
|
-
|
|
23
|
+
rv = {}; // Clear the success value so it can get garbage collected early
|
|
30
24
|
|
|
31
25
|
if (errors === null) {
|
|
32
26
|
errors = {};
|
|
@@ -37,18 +31,28 @@ export function mapping(decoder) {
|
|
|
37
31
|
});
|
|
38
32
|
|
|
39
33
|
if (errors !== null) {
|
|
40
|
-
return
|
|
34
|
+
return err(merge(annotateObject(blob), errors));
|
|
41
35
|
} else {
|
|
42
|
-
return
|
|
36
|
+
return ok(rv);
|
|
43
37
|
}
|
|
44
38
|
});
|
|
45
39
|
}
|
|
46
40
|
/**
|
|
47
|
-
*
|
|
41
|
+
* Given an object, will decode a Map of string keys to whatever values.
|
|
42
|
+
*
|
|
43
|
+
* For example, given a decoder for a Person, we can verify a Person lookup
|
|
44
|
+
* table structure (of type Map<string, Person>) like so:
|
|
45
|
+
*
|
|
46
|
+
* mapping(person)
|
|
47
|
+
*
|
|
48
48
|
*/
|
|
49
49
|
|
|
50
|
-
export function
|
|
51
|
-
return map(
|
|
52
|
-
return Object.
|
|
50
|
+
export function mapping(decoder) {
|
|
51
|
+
return map(dict(decoder), function (obj) {
|
|
52
|
+
return new Map( // This is effectively Object.entries(obj), but in a way that Flow
|
|
53
|
+
// will know the types are okay
|
|
54
|
+
Object.keys(obj).map(function (key) {
|
|
55
|
+
return [key, obj[key]];
|
|
56
|
+
}));
|
|
53
57
|
});
|
|
54
58
|
}
|
package/core/number.d.ts
ADDED
package/core/number.js
CHANGED
|
@@ -3,18 +3,14 @@
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.positiveNumber = exports.positiveInteger = exports.number = exports.integer = void 0;
|
|
5
5
|
|
|
6
|
-
var Result = _interopRequireWildcard(require("../result"));
|
|
7
|
-
|
|
8
6
|
var _annotate = require("../annotate");
|
|
9
7
|
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
8
|
+
var _result = require("../result");
|
|
13
9
|
|
|
14
|
-
|
|
10
|
+
var _composition = require("./composition");
|
|
15
11
|
|
|
16
12
|
var anyNumber = function anyNumber(blob) {
|
|
17
|
-
return typeof blob === 'number' && !Number.isNaN(blob) ?
|
|
13
|
+
return typeof blob === 'number' && !Number.isNaN(blob) ? (0, _result.ok)(blob) : (0, _result.err)((0, _annotate.annotate)(blob, 'Must be number'));
|
|
18
14
|
};
|
|
19
15
|
|
|
20
16
|
var isInteger = function isInteger(n) {
|
|
@@ -25,16 +21,16 @@ var isFinite = function isFinite(n) {
|
|
|
25
21
|
return Number.isFinite(n);
|
|
26
22
|
};
|
|
27
23
|
|
|
28
|
-
var number = (0, _composition.
|
|
24
|
+
var number = (0, _composition.predicate)(anyNumber, isFinite, 'Number must be finite');
|
|
29
25
|
exports.number = number;
|
|
30
|
-
var positiveNumber = (0, _composition.
|
|
26
|
+
var positiveNumber = (0, _composition.predicate)(number, function (n) {
|
|
31
27
|
return n >= 0;
|
|
32
|
-
}, 'Number must be positive')
|
|
28
|
+
}, 'Number must be positive'); // Integers
|
|
33
29
|
|
|
34
30
|
exports.positiveNumber = positiveNumber;
|
|
35
|
-
var integer = (0, _composition.
|
|
31
|
+
var integer = (0, _composition.predicate)(number, isInteger, 'Number must be an integer');
|
|
36
32
|
exports.integer = integer;
|
|
37
|
-
var positiveInteger = (0, _composition.
|
|
33
|
+
var positiveInteger = (0, _composition.predicate)(integer, function (n) {
|
|
38
34
|
return n >= 0;
|
|
39
|
-
}, 'Number must be positive')
|
|
35
|
+
}, 'Number must be positive');
|
|
40
36
|
exports.positiveInteger = positiveInteger;
|
package/core/number.js.flow
CHANGED
|
@@ -1,34 +1,40 @@
|
|
|
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';
|
|
5
|
+
import { predicate } from './composition';
|
|
6
6
|
import type { Decoder } from '../_types';
|
|
7
7
|
|
|
8
8
|
const anyNumber: Decoder<number> = (blob: mixed) => {
|
|
9
9
|
return typeof blob === 'number' && !Number.isNaN(blob)
|
|
10
|
-
?
|
|
11
|
-
:
|
|
10
|
+
? ok(blob)
|
|
11
|
+
: err(annotate(blob, 'Must be number'));
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
const isInteger = (n: number) => Number.isInteger(n);
|
|
15
15
|
const isFinite = (n: number) => Number.isFinite(n);
|
|
16
16
|
|
|
17
|
-
export const number: Decoder<number> =
|
|
17
|
+
export const number: Decoder<number> = predicate(
|
|
18
18
|
anyNumber,
|
|
19
|
-
|
|
19
|
+
isFinite,
|
|
20
|
+
'Number must be finite',
|
|
20
21
|
);
|
|
21
|
-
|
|
22
|
+
|
|
23
|
+
export const positiveNumber: Decoder<number> = predicate(
|
|
22
24
|
number,
|
|
23
|
-
|
|
25
|
+
(n) => n >= 0,
|
|
26
|
+
'Number must be positive',
|
|
24
27
|
);
|
|
25
28
|
|
|
26
29
|
// Integers
|
|
27
|
-
export const integer: Decoder<number> =
|
|
30
|
+
export const integer: Decoder<number> = predicate(
|
|
28
31
|
number,
|
|
29
|
-
|
|
32
|
+
isInteger,
|
|
33
|
+
'Number must be an integer',
|
|
30
34
|
);
|
|
31
|
-
|
|
35
|
+
|
|
36
|
+
export const positiveInteger: Decoder<number> = predicate(
|
|
32
37
|
integer,
|
|
33
|
-
|
|
38
|
+
(n) => n >= 0,
|
|
39
|
+
'Number must be positive',
|
|
34
40
|
);
|
package/core/number.mjs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { annotate } from '../annotate.mjs';
|
|
2
|
+
import { err, ok } from '../result.mjs';
|
|
3
|
+
import { predicate } from './composition.mjs';
|
|
4
|
+
|
|
5
|
+
var anyNumber = function anyNumber(blob) {
|
|
6
|
+
return typeof blob === 'number' && !Number.isNaN(blob) ? ok(blob) : err(annotate(blob, 'Must be number'));
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
var isInteger = function isInteger(n) {
|
|
10
|
+
return Number.isInteger(n);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
var isFinite = function isFinite(n) {
|
|
14
|
+
return Number.isFinite(n);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export var number = predicate(anyNumber, isFinite, 'Number must be finite');
|
|
18
|
+
export var positiveNumber = predicate(number, function (n) {
|
|
19
|
+
return n >= 0;
|
|
20
|
+
}, 'Number must be positive'); // Integers
|
|
21
|
+
|
|
22
|
+
export var integer = predicate(number, isInteger, 'Number must be an integer');
|
|
23
|
+
export var positiveInteger = predicate(integer, function (n) {
|
|
24
|
+
return n >= 0;
|
|
25
|
+
}, 'Number must be positive');
|
package/core/object.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Decoder, DecoderType } from '../_types';
|
|
2
|
+
import { AllowImplicit } from './_helpers';
|
|
3
|
+
|
|
4
|
+
export type ObjectDecoderType<T> = AllowImplicit<{
|
|
5
|
+
[key in keyof T]: DecoderType<T[key]>;
|
|
6
|
+
}>;
|
|
7
|
+
|
|
8
|
+
export const pojo: Decoder<{ [key: string]: unknown }>;
|
|
9
|
+
|
|
10
|
+
export function object<O extends { [key: string]: Decoder<any> }>(
|
|
11
|
+
mapping: O,
|
|
12
|
+
): Decoder<{ [K in keyof ObjectDecoderType<O>]: ObjectDecoderType<O>[K] }>;
|
|
13
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
14
|
+
// This is basically just equivalent to:
|
|
15
|
+
// ObjectDecoderType<O>
|
|
16
|
+
//
|
|
17
|
+
// But by "resolving" this with a mapped type, we remove the helper
|
|
18
|
+
// type names from the inferred type here, making this much easier to
|
|
19
|
+
// work with while developing.
|
|
20
|
+
|
|
21
|
+
export function exact<O extends { [key: string]: Decoder<any> }>(
|
|
22
|
+
mapping: O,
|
|
23
|
+
): Decoder<{ [K in keyof ObjectDecoderType<O>]: ObjectDecoderType<O>[K] }>;
|
|
24
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
25
|
+
// Ditto (see above)
|
|
26
|
+
|
|
27
|
+
export function inexact<O extends { [key: string]: Decoder<any> }>(
|
|
28
|
+
mapping: O,
|
|
29
|
+
): Decoder<
|
|
30
|
+
{ [K in keyof ObjectDecoderType<O>]: ObjectDecoderType<O>[K] } & {
|
|
31
|
+
[extra: string]: unknown;
|
|
32
|
+
}
|
|
33
|
+
>;
|