decoders 2.1.0 → 2.2.0-test
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/README.md +12 -12
- package/dist/annotate-0PUmWHxH.d.cts +33 -0
- package/dist/annotate-0PUmWHxH.d.ts +33 -0
- package/dist/chunk-2C72BP5L.cjs +179 -0
- package/dist/chunk-2C72BP5L.cjs.map +1 -0
- package/dist/chunk-BPSZE2VX.js +13 -0
- package/dist/chunk-BPSZE2VX.js.map +1 -0
- package/dist/chunk-Q3YXBCTD.cjs +13 -0
- package/dist/chunk-Q3YXBCTD.cjs.map +1 -0
- package/dist/chunk-RUMDX66L.js +179 -0
- package/dist/chunk-RUMDX66L.js.map +1 -0
- package/dist/format.cjs +13 -0
- package/dist/format.cjs.map +1 -0
- package/dist/format.d.cts +9 -0
- package/dist/format.d.ts +9 -0
- package/dist/format.js +13 -0
- package/dist/format.js.map +1 -0
- package/dist/index.cjs +659 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +454 -0
- package/dist/index.d.ts +454 -0
- package/dist/index.js +659 -0
- package/dist/index.js.map +1 -0
- package/dist/result.cjs +9 -0
- package/dist/result.cjs.map +1 -0
- package/dist/result.d.cts +26 -0
- package/dist/result.d.ts +26 -0
- package/dist/result.js +9 -0
- package/dist/result.js.map +1 -0
- package/format.cjs +13 -0
- package/package.json +163 -100
- package/result.cjs +9 -0
- package/CHANGELOG.md +0 -670
- package/Decoder.d.ts +0 -94
- package/Decoder.js +0 -105
- package/Decoder.js.flow +0 -286
- package/Decoder.mjs +0 -101
- package/NotSupportedTSVersion.d.ts +0 -1
- package/_utils.d.ts +0 -9
- package/_utils.js +0 -80
- package/_utils.js.flow +0 -107
- package/_utils.mjs +0 -70
- package/annotate.d.ts +0 -62
- package/annotate.js +0 -145
- package/annotate.js.flow +0 -218
- package/annotate.mjs +0 -131
- package/format.d.ts +0 -6
- package/format.js +0 -117
- package/format.js.flow +0 -128
- package/format.mjs +0 -110
- package/index.d.ts +0 -40
- package/index.js +0 -67
- package/index.js.flow +0 -44
- package/index.mjs +0 -11
- package/lib/_helpers.d.ts +0 -79
- package/lib/arrays.d.ts +0 -59
- package/lib/arrays.js +0 -85
- package/lib/arrays.js.flow +0 -138
- package/lib/arrays.mjs +0 -75
- package/lib/basics.d.ts +0 -93
- package/lib/basics.js +0 -74
- package/lib/basics.js.flow +0 -124
- package/lib/basics.mjs +0 -60
- package/lib/booleans.d.ts +0 -16
- package/lib/booleans.js +0 -21
- package/lib/booleans.js.flow +0 -22
- package/lib/booleans.mjs +0 -15
- package/lib/dates.d.ts +0 -15
- package/lib/dates.js +0 -23
- package/lib/dates.js.flow +0 -40
- package/lib/dates.mjs +0 -17
- package/lib/json.d.ts +0 -35
- package/lib/json.js +0 -25
- package/lib/json.js.flow +0 -50
- package/lib/json.mjs +0 -18
- package/lib/numbers.d.ts +0 -31
- package/lib/numbers.js +0 -34
- package/lib/numbers.js.flow +0 -46
- package/lib/numbers.mjs +0 -25
- package/lib/objects.d.ts +0 -76
- package/lib/objects.js +0 -138
- package/lib/objects.js.flow +0 -238
- package/lib/objects.mjs +0 -128
- package/lib/strings.d.ts +0 -54
- package/lib/strings.js +0 -54
- package/lib/strings.js.flow +0 -90
- package/lib/strings.mjs +0 -40
- package/lib/unions.d.ts +0 -55
- package/lib/unions.js +0 -82
- package/lib/unions.js.flow +0 -155
- package/lib/unions.mjs +0 -75
- package/lib/utilities.d.ts +0 -40
- package/lib/utilities.js +0 -44
- package/lib/utilities.js.flow +0 -65
- package/lib/utilities.mjs +0 -35
- package/result.d.ts +0 -16
- package/result.js +0 -21
- package/result.js.flow +0 -26
- package/result.mjs +0 -15
package/Decoder.d.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
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 DecodeResult<T> = Result<T, Annotation>;
|
|
7
|
-
|
|
8
|
-
export type AcceptanceFn<T, InputT = unknown> = (
|
|
9
|
-
blob: InputT,
|
|
10
|
-
ok: (value: T) => DecodeResult<T>,
|
|
11
|
-
err: (msg: string | Annotation) => DecodeResult<T>,
|
|
12
|
-
) => DecodeResult<T>;
|
|
13
|
-
|
|
14
|
-
export interface Decoder<T> {
|
|
15
|
-
/**
|
|
16
|
-
* Verifies untrusted input. Either returns a value, or throws a decoding
|
|
17
|
-
* error.
|
|
18
|
-
*/
|
|
19
|
-
verify(blob: unknown, formatterFn?: (ann: Annotation) => string | Error): T;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Verifies untrusted input. Either returns a value, or returns undefined.
|
|
23
|
-
*/
|
|
24
|
-
value(blob: unknown): T | undefined;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Verifies untrusted input. Always returns a DecodeResult, which is either
|
|
28
|
-
* an "ok" value or an "error" annotation.
|
|
29
|
-
*/
|
|
30
|
-
decode(blob: unknown): DecodeResult<T>;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Build a new decoder from the the current one, with an extra acceptance
|
|
34
|
-
* criterium.
|
|
35
|
-
*/
|
|
36
|
-
refine<N extends T>(predicate: (value: T) => value is N, msg: string): Decoder<N>;
|
|
37
|
-
refine(predicate: (value: T) => boolean, msg: string): Decoder<T>;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Build a new decoder from the current one, with an extra rejection
|
|
41
|
-
* criterium.
|
|
42
|
-
*/
|
|
43
|
-
reject(rejectFn: (value: T) => string | Annotation | null): Decoder<T>;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Build a new decoder from the current one, modifying its outputted value.
|
|
47
|
-
*/
|
|
48
|
-
transform<V>(transformFn: (value: T) => V): Decoder<V>;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Build a new decoder from the current one, with a mutated error message
|
|
52
|
-
* in case of a rejection.
|
|
53
|
-
*/
|
|
54
|
-
describe(message: string): Decoder<T>;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Chain together the current decoder with another acceptance function.
|
|
58
|
-
*/
|
|
59
|
-
then<V>(next: AcceptanceFn<V, T>): Decoder<V>;
|
|
60
|
-
|
|
61
|
-
// Experimental APIs (please don't rely on these yet)
|
|
62
|
-
peek_UNSTABLE<V>(next: AcceptanceFn<V, [unknown, T]>): Decoder<V>;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Helper type to return the "type" of a Decoder.
|
|
67
|
-
*
|
|
68
|
-
* You can use it on types:
|
|
69
|
-
*
|
|
70
|
-
* DecoderType<Decoder<string>> // string
|
|
71
|
-
* DecoderType<Decoder<number[]>> // number[]
|
|
72
|
-
*
|
|
73
|
-
* Or on "values", by using the `typeof` keyword:
|
|
74
|
-
*
|
|
75
|
-
* DecoderType<typeof string> // string
|
|
76
|
-
* DecoderType<typeof truthy> // boolean
|
|
77
|
-
*
|
|
78
|
-
*/
|
|
79
|
-
export type DecoderType<T> = T extends Decoder<infer V> ? V : never;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Defines a new `Decoder<T>`, by implementing a custom acceptance function.
|
|
83
|
-
* The function receives three arguments:
|
|
84
|
-
*
|
|
85
|
-
* 1. `blob` - the raw/unknown input (aka your external data)
|
|
86
|
-
* 2. `ok` - Call `ok(value)` to accept the input and return ``value``
|
|
87
|
-
* 3. `err` - Call `err(message)` to reject the input with error ``message``
|
|
88
|
-
*
|
|
89
|
-
* The expected return value should be a `DecodeResult<T>`, which can be
|
|
90
|
-
* obtained by returning the result of calling the provided `ok` or `err`
|
|
91
|
-
* helper functions. Please note that `ok()` and `err()` don't perform side
|
|
92
|
-
* effects! You'll need to _return_ those values.
|
|
93
|
-
*/
|
|
94
|
-
export function define<T>(fn: AcceptanceFn<T>): Decoder<T>;
|
package/Decoder.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
exports.__esModule = true
|
|
4
|
-
exports.define = define
|
|
5
|
-
var _annotate = require('./annotate')
|
|
6
|
-
var _format = require('./format')
|
|
7
|
-
var _result = require('./result')
|
|
8
|
-
|
|
9
|
-
function noThrow(fn) {
|
|
10
|
-
return function (t) {
|
|
11
|
-
try {
|
|
12
|
-
var v = fn(t)
|
|
13
|
-
return (0, _result.ok)(v)
|
|
14
|
-
} catch (e) {
|
|
15
|
-
return (0, _result.err)((0, _annotate.annotate)(t, e instanceof Error ? e.message : String(e)))
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
function format(err, formatter) {
|
|
20
|
-
var formatted = formatter(err)
|
|
21
|
-
if (typeof formatted === 'string') {
|
|
22
|
-
var _err = new Error('\n' + formatted)
|
|
23
|
-
_err.name = 'Decoding error'
|
|
24
|
-
return _err
|
|
25
|
-
} else {
|
|
26
|
-
return formatted
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function define(fn) {
|
|
31
|
-
function decode(blob) {
|
|
32
|
-
return fn(blob, _result.ok, function (msg) {
|
|
33
|
-
return (0, _result.err)(typeof msg === 'string' ? (0, _annotate.annotate)(blob, msg) : msg)
|
|
34
|
-
})
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function verify(blob, formatter) {
|
|
38
|
-
if (formatter === void 0) {
|
|
39
|
-
formatter = _format.formatInline
|
|
40
|
-
}
|
|
41
|
-
var result = decode(blob)
|
|
42
|
-
if (result.ok) {
|
|
43
|
-
return result.value
|
|
44
|
-
} else {
|
|
45
|
-
throw format(result.error, formatter)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function value(blob) {
|
|
50
|
-
return decode(blob).value
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function transform(transformFn) {
|
|
54
|
-
return then(noThrow(transformFn))
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function refine(predicateFn, errmsg) {
|
|
58
|
-
return reject(function (value) {
|
|
59
|
-
return predicateFn(value) ? null : errmsg
|
|
60
|
-
})
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function then(next) {
|
|
64
|
-
return define(function (blob, ok, err) {
|
|
65
|
-
var result = decode(blob)
|
|
66
|
-
return result.ok ? next(result.value, ok, err) : result
|
|
67
|
-
})
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function reject(rejectFn) {
|
|
71
|
-
return then(function (value, ok, err) {
|
|
72
|
-
var errmsg = rejectFn(value)
|
|
73
|
-
return errmsg === null ? ok(value) : err(typeof errmsg === 'string' ? (0, _annotate.annotate)(value, errmsg) : errmsg)
|
|
74
|
-
})
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function describe(message) {
|
|
78
|
-
return define(function (blob, _, err) {
|
|
79
|
-
var result = decode(blob)
|
|
80
|
-
if (result.ok) {
|
|
81
|
-
return result
|
|
82
|
-
} else {
|
|
83
|
-
return err((0, _annotate.annotate)(result.error, message))
|
|
84
|
-
}
|
|
85
|
-
})
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function peek_UNSTABLE(next) {
|
|
89
|
-
return define(function (blob, ok, err) {
|
|
90
|
-
var result = decode(blob)
|
|
91
|
-
return result.ok ? next([blob, result.value], ok, err) : result
|
|
92
|
-
})
|
|
93
|
-
}
|
|
94
|
-
return Object.freeze({
|
|
95
|
-
verify: verify,
|
|
96
|
-
value: value,
|
|
97
|
-
decode: decode,
|
|
98
|
-
transform: transform,
|
|
99
|
-
refine: refine,
|
|
100
|
-
reject: reject,
|
|
101
|
-
describe: describe,
|
|
102
|
-
then: then,
|
|
103
|
-
peek_UNSTABLE: peek_UNSTABLE,
|
|
104
|
-
})
|
|
105
|
-
}
|
package/Decoder.js.flow
DELETED
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
// @flow strict
|
|
2
|
-
|
|
3
|
-
import { annotate } from './annotate';
|
|
4
|
-
import { formatInline } from './format';
|
|
5
|
-
import { err as makeErr, ok as makeOk } from './result';
|
|
6
|
-
import type { Annotation } from './annotate';
|
|
7
|
-
import type { Formatter } from './format';
|
|
8
|
-
import type { Result } from './result';
|
|
9
|
-
|
|
10
|
-
export type Scalar = string | number | boolean | symbol | void | null;
|
|
11
|
-
|
|
12
|
-
export type DecodeResult<T> = Result<T, Annotation>;
|
|
13
|
-
|
|
14
|
-
export type AcceptanceFn<T, InputT = mixed> = (
|
|
15
|
-
blob: InputT,
|
|
16
|
-
ok: (value: T) => DecodeResult<T>,
|
|
17
|
-
err: (msg: string | Annotation) => DecodeResult<T>,
|
|
18
|
-
) => DecodeResult<T>;
|
|
19
|
-
|
|
20
|
-
export type Decoder<T> = {|
|
|
21
|
-
/**
|
|
22
|
-
* Verifies untrusted input. Either returns a value, or throws a decoding
|
|
23
|
-
* error.
|
|
24
|
-
*/
|
|
25
|
-
verify(blob: mixed, formatter?: Formatter): T,
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Verifies untrusted input. Either returns a value, or returns undefined.
|
|
29
|
-
*/
|
|
30
|
-
value(blob: mixed): T | void,
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Verifies untrusted input. Always returns a DecodeResult, which is either
|
|
34
|
-
* an "ok" value or an "error" annotation.
|
|
35
|
-
*/
|
|
36
|
-
decode(blob: mixed): DecodeResult<T>,
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Build a new decoder from the the current one, with an extra acceptance
|
|
40
|
-
* criterium.
|
|
41
|
-
*/
|
|
42
|
-
refine(predicateFn: (value: T) => boolean, errmsg: string): Decoder<T>,
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Build a new decoder from the current one, with an extra rejection
|
|
46
|
-
* criterium.
|
|
47
|
-
*/
|
|
48
|
-
reject(rejectFn: (value: T) => string | Annotation | null): Decoder<T>,
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Build a new decoder from the current one, modifying its outputted value.
|
|
52
|
-
*/
|
|
53
|
-
transform<V>(transformFn: (value: T) => V): Decoder<V>,
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Build a new decoder from the current one, with a mutated error message
|
|
57
|
-
* in case of a rejection.
|
|
58
|
-
*/
|
|
59
|
-
describe(message: string): Decoder<T>,
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Chain together the current decoder with another acceptance function.
|
|
63
|
-
*/
|
|
64
|
-
then<V>(next: AcceptanceFn<V, T>): Decoder<V>,
|
|
65
|
-
|
|
66
|
-
// Experimental APIs (please don't rely on these yet)
|
|
67
|
-
peek_UNSTABLE<V>(next: AcceptanceFn<V, [mixed, T]>): Decoder<V>,
|
|
68
|
-
|};
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Helper type to return the "type" of a Decoder.
|
|
72
|
-
*
|
|
73
|
-
* You can use it on types:
|
|
74
|
-
*
|
|
75
|
-
* DecoderType<Decoder<string>> // string
|
|
76
|
-
* DecoderType<Decoder<number[]>> // number[]
|
|
77
|
-
*
|
|
78
|
-
* Or on "values", by using the `typeof` keyword:
|
|
79
|
-
*
|
|
80
|
-
* DecoderType<typeof string> // string
|
|
81
|
-
* DecoderType<typeof truthy> // boolean
|
|
82
|
-
*
|
|
83
|
-
*/
|
|
84
|
-
export type DecoderType<D> = $Call<<T>(Decoder<T>) => T, D>;
|
|
85
|
-
|
|
86
|
-
function noThrow<T, V>(fn: (value: T) => V): (T) => DecodeResult<V> {
|
|
87
|
-
return (t) => {
|
|
88
|
-
try {
|
|
89
|
-
const v = fn(t);
|
|
90
|
-
return makeOk(v);
|
|
91
|
-
} catch (e) {
|
|
92
|
-
return makeErr(annotate(t, e instanceof Error ? e.message : String(e)));
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function format(err: Annotation, formatter: Formatter): Error {
|
|
98
|
-
const formatted = formatter(err);
|
|
99
|
-
|
|
100
|
-
// Formatter functions may return a string or an error for convenience of
|
|
101
|
-
// writing them. If it already returns an Error, return it unmodified. If
|
|
102
|
-
// it returns a string, wrap it in a "Decoding error" instance.
|
|
103
|
-
if (typeof formatted === 'string') {
|
|
104
|
-
const err = new Error(`\n${formatted}`);
|
|
105
|
-
err.name = 'Decoding error';
|
|
106
|
-
return err;
|
|
107
|
-
} else {
|
|
108
|
-
return formatted;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Defines a new `Decoder<T>`, by implementing a custom acceptance function.
|
|
114
|
-
* The function receives three arguments:
|
|
115
|
-
*
|
|
116
|
-
* 1. `blob` - the raw/unknown input (aka your external data)
|
|
117
|
-
* 2. `ok` - Call `ok(value)` to accept the input and return ``value``
|
|
118
|
-
* 3. `err` - Call `err(message)` to reject the input with error ``message``
|
|
119
|
-
*
|
|
120
|
-
* The expected return value should be a `DecodeResult<T>`, which can be
|
|
121
|
-
* obtained by returning the result of calling the provided `ok` or `err`
|
|
122
|
-
* helper functions. Please note that `ok()` and `err()` don't perform side
|
|
123
|
-
* effects! You'll need to _return_ those values.
|
|
124
|
-
*/
|
|
125
|
-
export function define<T>(fn: AcceptanceFn<T>): Decoder<T> {
|
|
126
|
-
/**
|
|
127
|
-
* Verifies the untrusted/unknown input and either accepts or rejects it.
|
|
128
|
-
*
|
|
129
|
-
* Contrasted with `.verify()`, calls to `.decode()` will never fail and
|
|
130
|
-
* instead return a result type.
|
|
131
|
-
*/
|
|
132
|
-
function decode(blob: mixed): DecodeResult<T> {
|
|
133
|
-
return fn(blob, makeOk, (msg: Annotation | string) =>
|
|
134
|
-
makeErr(typeof msg === 'string' ? annotate(blob, msg) : msg),
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Verifies the untrusted/unknown input and either accepts or rejects it.
|
|
140
|
-
* When accepted, returns a value of type `T`. Otherwise fail with
|
|
141
|
-
* a runtime error.
|
|
142
|
-
*/
|
|
143
|
-
function verify(blob: mixed, formatter: Formatter = formatInline): T {
|
|
144
|
-
const result = decode(blob);
|
|
145
|
-
if (result.ok) {
|
|
146
|
-
return result.value;
|
|
147
|
-
} else {
|
|
148
|
-
throw format(result.error, formatter);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Verifies the untrusted/unknown input and either accepts or rejects it.
|
|
154
|
-
* When accepted, returns the decoded `T` value directly. Otherwise returns
|
|
155
|
-
* `undefined`.
|
|
156
|
-
*
|
|
157
|
-
* Use this when you're not interested in programmatically handling the
|
|
158
|
-
* error message.
|
|
159
|
-
*/
|
|
160
|
-
function value(blob: mixed): T | void {
|
|
161
|
-
return decode(blob).value;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Accepts any value the given decoder accepts, and on success, will call
|
|
166
|
-
* the given function **on the decoded result**. If the transformation
|
|
167
|
-
* function throws an error, the whole decoder will fail using the error
|
|
168
|
-
* message as the failure reason.
|
|
169
|
-
*/
|
|
170
|
-
function transform<V>(transformFn: (T) => V): Decoder<V> {
|
|
171
|
-
return then(noThrow(transformFn));
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Adds an extra predicate to a decoder. The new decoder is like the
|
|
176
|
-
* original decoder, but only accepts values that also meet the
|
|
177
|
-
* predicate.
|
|
178
|
-
*/
|
|
179
|
-
function refine(predicateFn: (value: T) => boolean, errmsg: string): Decoder<T> {
|
|
180
|
-
return reject((value) =>
|
|
181
|
-
predicateFn(value)
|
|
182
|
-
? // Don't reject
|
|
183
|
-
null
|
|
184
|
-
: // Reject with the given error message
|
|
185
|
-
errmsg,
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Chain together the current decoder with another.
|
|
191
|
-
*
|
|
192
|
-
* > _**NOTE:** This is an advanced, low-level, API. It's not recommended
|
|
193
|
-
* > to reach for this construct unless there is no other way. Most cases can
|
|
194
|
-
* > be covered more elegantly by `.transform()` or `.refine()` instead._
|
|
195
|
-
*
|
|
196
|
-
* If the current decoder accepts an input, the resulting ``T`` value will
|
|
197
|
-
* get passed into the given ``next`` acceptance function to further decide
|
|
198
|
-
* whether or not the value should get accepted or rejected.
|
|
199
|
-
*
|
|
200
|
-
* This works similar to how you would `define()` a new decoder, except
|
|
201
|
-
* that the ``blob`` param will now be ``T`` (a known type), rather than
|
|
202
|
-
* ``unknown``. This will allow the function to make a stronger assumption
|
|
203
|
-
* about its input and avoid re-refining inputs.
|
|
204
|
-
*
|
|
205
|
-
* If it helps, you can think of `define(...)` as equivalent to
|
|
206
|
-
* `unknown.then(...)`.
|
|
207
|
-
*/
|
|
208
|
-
function then<V>(next: AcceptanceFn<V, T>): Decoder<V> {
|
|
209
|
-
return define((blob, ok, err) => {
|
|
210
|
-
const result = decode(blob);
|
|
211
|
-
return result.ok ? next(result.value, ok, err) : result;
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Adds an extra predicate to a decoder. The new decoder is like the
|
|
217
|
-
* original decoder, but only accepts values that aren't rejected by the
|
|
218
|
-
* given function.
|
|
219
|
-
*
|
|
220
|
-
* The given function can return `null` to accept the decoded value, or
|
|
221
|
-
* return a specific error message to reject.
|
|
222
|
-
*
|
|
223
|
-
* Unlike `.refine()`, you can use this function to return a dynamic error
|
|
224
|
-
* message.
|
|
225
|
-
*/
|
|
226
|
-
function reject(rejectFn: (value: T) => string | Annotation | null): Decoder<T> {
|
|
227
|
-
return then((value, ok, err) => {
|
|
228
|
-
const errmsg = rejectFn(value);
|
|
229
|
-
return errmsg === null
|
|
230
|
-
? ok(value)
|
|
231
|
-
: err(typeof errmsg === 'string' ? annotate(value, errmsg) : errmsg);
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Uses the given decoder, but will use an alternative error message in
|
|
237
|
-
* case it rejects. This can be used to simplify or shorten otherwise
|
|
238
|
-
* long or low-level/technical errors.
|
|
239
|
-
*/
|
|
240
|
-
function describe(message: string): Decoder<T> {
|
|
241
|
-
return define((blob, _, err) => {
|
|
242
|
-
// Decode using the given decoder...
|
|
243
|
-
const result = decode(blob);
|
|
244
|
-
if (result.ok) {
|
|
245
|
-
return result;
|
|
246
|
-
} else {
|
|
247
|
-
// ...but in case of error, annotate this with the custom given
|
|
248
|
-
// message instead
|
|
249
|
-
return err(annotate(result.error, message));
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* WARNING: This is an EXPERIMENTAL API that will likely change in the
|
|
256
|
-
* future. Please DO NOT rely on it.
|
|
257
|
-
*
|
|
258
|
-
* Chain together the current decoder with another, but also pass along
|
|
259
|
-
* the original input.
|
|
260
|
-
*
|
|
261
|
-
* This is like `.then()`, but instead of this function receiving just
|
|
262
|
-
* the decoded result ``T``, it also receives the original input.
|
|
263
|
-
*
|
|
264
|
-
* This is an advanced, low-level, decoder.
|
|
265
|
-
*/
|
|
266
|
-
function peek_UNSTABLE<V>(next: AcceptanceFn<V, [mixed, T]>): Decoder<V> {
|
|
267
|
-
return define((blob, ok, err) => {
|
|
268
|
-
const result = decode(blob);
|
|
269
|
-
return result.ok ? next([blob, result.value], ok, err) : result;
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
return Object.freeze({
|
|
274
|
-
verify,
|
|
275
|
-
value,
|
|
276
|
-
decode,
|
|
277
|
-
transform,
|
|
278
|
-
refine,
|
|
279
|
-
reject,
|
|
280
|
-
describe,
|
|
281
|
-
then,
|
|
282
|
-
|
|
283
|
-
// EXPERIMENTAL - please DO NOT rely on this method
|
|
284
|
-
peek_UNSTABLE,
|
|
285
|
-
});
|
|
286
|
-
}
|
package/Decoder.mjs
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { annotate } from './annotate.mjs'
|
|
2
|
-
import { formatInline } from './format.mjs'
|
|
3
|
-
import { err as makeErr, ok as makeOk } from './result.mjs'
|
|
4
|
-
|
|
5
|
-
function noThrow(fn) {
|
|
6
|
-
return function (t) {
|
|
7
|
-
try {
|
|
8
|
-
var v = fn(t)
|
|
9
|
-
return makeOk(v)
|
|
10
|
-
} catch (e) {
|
|
11
|
-
return makeErr(annotate(t, e instanceof Error ? e.message : String(e)))
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
function format(err, formatter) {
|
|
16
|
-
var formatted = formatter(err)
|
|
17
|
-
if (typeof formatted === 'string') {
|
|
18
|
-
var _err = new Error('\n' + formatted)
|
|
19
|
-
_err.name = 'Decoding error'
|
|
20
|
-
return _err
|
|
21
|
-
} else {
|
|
22
|
-
return formatted
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function define(fn) {
|
|
27
|
-
function decode(blob) {
|
|
28
|
-
return fn(blob, makeOk, function (msg) {
|
|
29
|
-
return makeErr(typeof msg === 'string' ? annotate(blob, msg) : msg)
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function verify(blob, formatter) {
|
|
34
|
-
if (formatter === void 0) {
|
|
35
|
-
formatter = formatInline
|
|
36
|
-
}
|
|
37
|
-
var result = decode(blob)
|
|
38
|
-
if (result.ok) {
|
|
39
|
-
return result.value
|
|
40
|
-
} else {
|
|
41
|
-
throw format(result.error, formatter)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function value(blob) {
|
|
46
|
-
return decode(blob).value
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function transform(transformFn) {
|
|
50
|
-
return then(noThrow(transformFn))
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function refine(predicateFn, errmsg) {
|
|
54
|
-
return reject(function (value) {
|
|
55
|
-
return predicateFn(value) ? null : errmsg
|
|
56
|
-
})
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function then(next) {
|
|
60
|
-
return define(function (blob, ok, err) {
|
|
61
|
-
var result = decode(blob)
|
|
62
|
-
return result.ok ? next(result.value, ok, err) : result
|
|
63
|
-
})
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function reject(rejectFn) {
|
|
67
|
-
return then(function (value, ok, err) {
|
|
68
|
-
var errmsg = rejectFn(value)
|
|
69
|
-
return errmsg === null ? ok(value) : err(typeof errmsg === 'string' ? annotate(value, errmsg) : errmsg)
|
|
70
|
-
})
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function describe(message) {
|
|
74
|
-
return define(function (blob, _, err) {
|
|
75
|
-
var result = decode(blob)
|
|
76
|
-
if (result.ok) {
|
|
77
|
-
return result
|
|
78
|
-
} else {
|
|
79
|
-
return err(annotate(result.error, message))
|
|
80
|
-
}
|
|
81
|
-
})
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function peek_UNSTABLE(next) {
|
|
85
|
-
return define(function (blob, ok, err) {
|
|
86
|
-
var result = decode(blob)
|
|
87
|
-
return result.ok ? next([blob, result.value], ok, err) : result
|
|
88
|
-
})
|
|
89
|
-
}
|
|
90
|
-
return Object.freeze({
|
|
91
|
-
verify: verify,
|
|
92
|
-
value: value,
|
|
93
|
-
decode: decode,
|
|
94
|
-
transform: transform,
|
|
95
|
-
refine: refine,
|
|
96
|
-
reject: reject,
|
|
97
|
-
describe: describe,
|
|
98
|
-
then: then,
|
|
99
|
-
peek_UNSTABLE: peek_UNSTABLE,
|
|
100
|
-
})
|
|
101
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"Package `decoders` requires TypeScript >= 4.1.0"
|
package/_utils.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Annotation } from './annotate';
|
|
2
|
-
|
|
3
|
-
export function asDate(value: unknown): Date | null;
|
|
4
|
-
export function isMultiline(s: string): boolean;
|
|
5
|
-
export function indent(s: string, prefix?: string): string;
|
|
6
|
-
export function summarize(
|
|
7
|
-
ann: Annotation,
|
|
8
|
-
keypath?: ReadonlyArray<number | string>,
|
|
9
|
-
): string[];
|
package/_utils.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
exports.__esModule = true
|
|
4
|
-
exports.INDENT = void 0
|
|
5
|
-
exports.asDate = asDate
|
|
6
|
-
exports.indent = indent
|
|
7
|
-
exports.isMultiline = isMultiline
|
|
8
|
-
exports.subtract = subtract
|
|
9
|
-
exports.summarize = summarize
|
|
10
|
-
var INDENT = ' '
|
|
11
|
-
|
|
12
|
-
exports.INDENT = INDENT
|
|
13
|
-
function subtract(xs, ys) {
|
|
14
|
-
var result = new Set()
|
|
15
|
-
xs.forEach(function (x) {
|
|
16
|
-
if (!ys.has(x)) {
|
|
17
|
-
result.add(x)
|
|
18
|
-
}
|
|
19
|
-
})
|
|
20
|
-
return result
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function asDate(value) {
|
|
24
|
-
return !!value && Object.prototype.toString.call(value) === '[object Date]' && !isNaN(value) ? value : null
|
|
25
|
-
}
|
|
26
|
-
function isMultiline(s) {
|
|
27
|
-
return s.indexOf('\n') >= 0
|
|
28
|
-
}
|
|
29
|
-
function indent(s, prefix) {
|
|
30
|
-
if (prefix === void 0) {
|
|
31
|
-
prefix = INDENT
|
|
32
|
-
}
|
|
33
|
-
if (isMultiline(s)) {
|
|
34
|
-
return s
|
|
35
|
-
.split('\n')
|
|
36
|
-
.map(function (line) {
|
|
37
|
-
return '' + prefix + line
|
|
38
|
-
})
|
|
39
|
-
.join('\n')
|
|
40
|
-
} else {
|
|
41
|
-
return '' + prefix + s
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function summarize(ann, keypath) {
|
|
46
|
-
if (keypath === void 0) {
|
|
47
|
-
keypath = []
|
|
48
|
-
}
|
|
49
|
-
var result = []
|
|
50
|
-
if (ann.type === 'array') {
|
|
51
|
-
var items = ann.items
|
|
52
|
-
var index = 0
|
|
53
|
-
items.forEach(function (ann) {
|
|
54
|
-
summarize(ann, [].concat(keypath, [index++])).forEach(function (item) {
|
|
55
|
-
return result.push(item)
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
} else if (ann.type === 'object') {
|
|
59
|
-
var fields = ann.fields
|
|
60
|
-
Object.keys(fields).forEach(function (key) {
|
|
61
|
-
var value = fields[key]
|
|
62
|
-
summarize(value, [].concat(keypath, [key])).forEach(function (item) {
|
|
63
|
-
return result.push(item)
|
|
64
|
-
})
|
|
65
|
-
})
|
|
66
|
-
}
|
|
67
|
-
var text = ann.text
|
|
68
|
-
if (!text) {
|
|
69
|
-
return result
|
|
70
|
-
}
|
|
71
|
-
var prefix
|
|
72
|
-
if (keypath.length === 0) {
|
|
73
|
-
prefix = ''
|
|
74
|
-
} else if (keypath.length === 1) {
|
|
75
|
-
prefix = typeof keypath[0] === 'number' ? 'Value at index ' + keypath[0] + ': ' : 'Value at key ' + JSON.stringify(keypath[0]) + ': '
|
|
76
|
-
} else {
|
|
77
|
-
prefix = 'Value at keypath ' + keypath.map(String).join('.') + ': '
|
|
78
|
-
}
|
|
79
|
-
return [].concat(result, ['' + prefix + text])
|
|
80
|
-
}
|