decoders 2.1.0 → 2.2.0-test2
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/annotate-0PUmWHxH.d.ts +33 -0
- package/chunk-BPSZE2VX.js +13 -0
- package/chunk-RUMDX66L.js +179 -0
- package/dist/annotate-0PUmWHxH.d.mts +33 -0
- package/dist/annotate-0PUmWHxH.d.ts +33 -0
- package/dist/chunk-BPSZE2VX.js +13 -0
- package/dist/chunk-BPSZE2VX.js.map +1 -0
- package/dist/chunk-HBFFQIIN.mjs +13 -0
- package/dist/chunk-HBFFQIIN.mjs.map +1 -0
- package/dist/chunk-RUMDX66L.js +179 -0
- package/dist/chunk-RUMDX66L.js.map +1 -0
- package/dist/chunk-ZTKFAKRL.mjs +179 -0
- package/dist/chunk-ZTKFAKRL.mjs.map +1 -0
- package/dist/format.d.mts +9 -0
- package/dist/format.d.ts +9 -0
- package/dist/format.js +13 -0
- package/dist/format.js.map +1 -0
- package/dist/format.mjs +13 -0
- package/dist/format.mjs.map +1 -0
- package/dist/index.d.mts +454 -0
- package/dist/index.d.ts +454 -0
- package/dist/index.js +659 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +659 -0
- package/dist/index.mjs.map +1 -0
- package/dist/result.d.mts +26 -0
- package/dist/result.d.ts +26 -0
- package/dist/result.js +9 -0
- package/dist/result.js.map +1 -0
- package/dist/result.mjs +9 -0
- package/dist/result.mjs.map +1 -0
- package/format.d.ts +7 -4
- package/format.js +12 -116
- package/index.d.ts +454 -40
- package/index.js +659 -67
- package/package.json +163 -100
- package/result.d.ts +25 -15
- package/result.js +6 -18
- 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.js.flow +0 -128
- package/format.mjs +0 -110
- 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.js.flow +0 -26
- package/result.mjs +0 -15
package/lib/objects.js.flow
DELETED
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
// @flow strict
|
|
2
|
-
|
|
3
|
-
import { annotateObject, merge, updateText } from '../annotate';
|
|
4
|
-
import { define } from '../Decoder';
|
|
5
|
-
import { subtract } from '../_utils';
|
|
6
|
-
import type { Annotation } from '../annotate';
|
|
7
|
-
import type { _Any as AnyDecoder } from '../_utils';
|
|
8
|
-
import type { Decoder, DecodeResult } from '../Decoder';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Accepts any "plain old JavaScript object", but doesn't validate its keys or
|
|
12
|
-
* values further.
|
|
13
|
-
*/
|
|
14
|
-
export const pojo: Decoder<{| [string]: mixed |}> = define((blob, ok, err) =>
|
|
15
|
-
blob !== null &&
|
|
16
|
-
blob !== undefined &&
|
|
17
|
-
typeof blob === 'object' &&
|
|
18
|
-
// This still seems to be the only reliable way to determine whether
|
|
19
|
-
// something is a pojo... ¯\_(ツ)_/¯
|
|
20
|
-
// $FlowFixMe[method-unbinding]
|
|
21
|
-
Object.prototype.toString.call(blob) === '[object Object]'
|
|
22
|
-
? ok(
|
|
23
|
-
// NOTE:
|
|
24
|
-
// Since Flow 0.98, typeof o === 'object' refines to
|
|
25
|
-
// {| +[string]: mixed |}
|
|
26
|
-
// instead of
|
|
27
|
-
// {| [string]: mixed |}
|
|
28
|
-
//
|
|
29
|
-
// For rationale, see https://github.com/facebook/flow/issues/7685.
|
|
30
|
-
// In this case, we don't want to output a read-only version of
|
|
31
|
-
// the object because it's up to the user of decoders to
|
|
32
|
-
// determine what they want to do with the decoded output. If they
|
|
33
|
-
// want to write items into the array, that's fine! The fastest
|
|
34
|
-
// way to turn a read-only Object to a writeable one in ES6 seems
|
|
35
|
-
// to be to use object-spread. (Going off this benchmark:
|
|
36
|
-
// https://thecodebarbarian.com/object-assign-vs-object-spread.html)
|
|
37
|
-
// $FlowFixMe[incompatible-variance]
|
|
38
|
-
blob,
|
|
39
|
-
)
|
|
40
|
-
: err('Must be an object'),
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Accepts objects with fields matching the given decoders. Extra fields that
|
|
45
|
-
* exist on the input object are ignored and will not be returned.
|
|
46
|
-
*/
|
|
47
|
-
export function object<O: { +[field: string]: AnyDecoder, ... }>(
|
|
48
|
-
decodersByKey: O,
|
|
49
|
-
): Decoder<$ObjMap<O, <T>(Decoder<T>) => T>> {
|
|
50
|
-
// Compute this set at decoder definition time
|
|
51
|
-
const knownKeys = new Set(Object.keys(decodersByKey));
|
|
52
|
-
|
|
53
|
-
return pojo.then((plainObj, ok, err) => {
|
|
54
|
-
const actualKeys = new Set(Object.keys(plainObj));
|
|
55
|
-
|
|
56
|
-
// At this point, "missingKeys" will also include all fields that may
|
|
57
|
-
// validly be optional. We'll let the underlying decoder decide and
|
|
58
|
-
// remove the key from this missing set if the decoder accepts the
|
|
59
|
-
// value.
|
|
60
|
-
const missingKeys = subtract(knownKeys, actualKeys);
|
|
61
|
-
|
|
62
|
-
let record = {};
|
|
63
|
-
let errors: { [key: string]: Annotation } | null = null;
|
|
64
|
-
|
|
65
|
-
Object.keys(decodersByKey).forEach((key) => {
|
|
66
|
-
const decoder = decodersByKey[key];
|
|
67
|
-
const rawValue = plainObj[key];
|
|
68
|
-
const result: DecodeResult<mixed> = decoder.decode(rawValue);
|
|
69
|
-
|
|
70
|
-
if (result.ok) {
|
|
71
|
-
const value = result.value;
|
|
72
|
-
if (value !== undefined) {
|
|
73
|
-
record[key] = value;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// If this succeeded, remove the key from the missing keys
|
|
77
|
-
// tracker
|
|
78
|
-
missingKeys.delete(key);
|
|
79
|
-
} else {
|
|
80
|
-
const ann = result.error;
|
|
81
|
-
|
|
82
|
-
// Keep track of the annotation, but don't return just yet. We
|
|
83
|
-
// want to collect more error information.
|
|
84
|
-
if (rawValue === undefined) {
|
|
85
|
-
// Explicitly add it to the missing set if the value is
|
|
86
|
-
// undefined. This covers explicit undefineds to be
|
|
87
|
-
// treated the same as implicit undefineds (aka missing
|
|
88
|
-
// keys).
|
|
89
|
-
missingKeys.add(key);
|
|
90
|
-
} else {
|
|
91
|
-
if (errors === null) {
|
|
92
|
-
errors = {};
|
|
93
|
-
}
|
|
94
|
-
errors[key] = ann;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
// Deal with errors now. There are two classes of errors we want to
|
|
100
|
-
// report. First of all, we want to report any inline errors in this
|
|
101
|
-
// object. Lastly, any fields that are missing should be annotated on
|
|
102
|
-
// the outer object itself.
|
|
103
|
-
if (errors || missingKeys.size > 0) {
|
|
104
|
-
let objAnn = annotateObject(plainObj);
|
|
105
|
-
|
|
106
|
-
if (errors) {
|
|
107
|
-
objAnn = merge(objAnn, errors);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (missingKeys.size > 0) {
|
|
111
|
-
const errMsg = Array.from(missingKeys)
|
|
112
|
-
.map((key) => `"${key}"`)
|
|
113
|
-
.join(', ');
|
|
114
|
-
const pluralized = missingKeys.size > 1 ? 'keys' : 'key';
|
|
115
|
-
objAnn = updateText(objAnn, `Missing ${pluralized}: ${errMsg}`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return err(objAnn);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return ok(record);
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Like `object()`, but will reject inputs that contain extra fields that are
|
|
127
|
-
* not specified explicitly.
|
|
128
|
-
*/
|
|
129
|
-
export function exact<O: { +[field: string]: AnyDecoder, ... }>(
|
|
130
|
-
decodersByKey: O,
|
|
131
|
-
): Decoder<$ObjMap<$Exact<O>, <T>(Decoder<T>) => T>> {
|
|
132
|
-
// Compute this set at decoder definition time
|
|
133
|
-
const allowedKeys = new Set(Object.keys(decodersByKey));
|
|
134
|
-
|
|
135
|
-
// Check the inputted object for any unexpected extra keys
|
|
136
|
-
const checked = pojo.reject((plainObj) => {
|
|
137
|
-
const actualKeys = new Set(Object.keys(plainObj));
|
|
138
|
-
const extraKeys = subtract(actualKeys, allowedKeys);
|
|
139
|
-
return extraKeys.size > 0
|
|
140
|
-
? `Unexpected extra keys: ${Array.from(extraKeys).join(', ')}`
|
|
141
|
-
: // Don't reject
|
|
142
|
-
null;
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
// Defer to the "object" decoder for doing the real decoding work. Since
|
|
146
|
-
// we made sure there are no superfluous keys in this structure, it's now
|
|
147
|
-
// safe to force-cast it to an $Exact<> type.
|
|
148
|
-
return checked.then(object(decodersByKey).decode);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Like `object()`, but will pass through any extra fields on the input object
|
|
153
|
-
* unvalidated that will thus be of `unknown` type statically.
|
|
154
|
-
*/
|
|
155
|
-
export function inexact<O: { +[field: string]: AnyDecoder }>(
|
|
156
|
-
decodersByKey: O,
|
|
157
|
-
): Decoder<$ObjMap<O, <T>(Decoder<T>) => T> & { +[string]: mixed }> {
|
|
158
|
-
return pojo.then((plainObj) => {
|
|
159
|
-
const allkeys = new Set(Object.keys(plainObj));
|
|
160
|
-
const decoder = object(decodersByKey).transform(
|
|
161
|
-
(safepart: $ObjMap<O, <T>(Decoder<T>) => T>) => {
|
|
162
|
-
const safekeys = new Set(Object.keys(decodersByKey));
|
|
163
|
-
|
|
164
|
-
// To account for hard-coded keys that aren't part of the input
|
|
165
|
-
safekeys.forEach((k) => allkeys.add(k));
|
|
166
|
-
|
|
167
|
-
const rv = {};
|
|
168
|
-
allkeys.forEach((k) => {
|
|
169
|
-
if (safekeys.has(k)) {
|
|
170
|
-
const value = safepart[k];
|
|
171
|
-
if (value !== undefined) {
|
|
172
|
-
rv[k] = value;
|
|
173
|
-
}
|
|
174
|
-
} else {
|
|
175
|
-
rv[k] = plainObj[k];
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
return rv;
|
|
179
|
-
},
|
|
180
|
-
);
|
|
181
|
-
return decoder.decode(plainObj);
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Accepts objects where all values match the given decoder, and returns the
|
|
187
|
-
* result as a `Record<string, T>`.
|
|
188
|
-
*
|
|
189
|
-
* The main difference between `object()` and `dict()` is that you'd typically
|
|
190
|
-
* use `object()` if this is a record-like object, where all field names are
|
|
191
|
-
* known and the values are heterogeneous. Whereas with `dict()` the keys are
|
|
192
|
-
* typically dynamic and the values homogeneous, like in a dictionary,
|
|
193
|
-
* a lookup table, or a cache.
|
|
194
|
-
*/
|
|
195
|
-
export function dict<T>(decoder: Decoder<T>): Decoder<{ [string]: T }> {
|
|
196
|
-
return pojo.then((plainObj, ok, err) => {
|
|
197
|
-
let rv: { [key: string]: T } = {};
|
|
198
|
-
let errors: { [key: string]: Annotation } | null = null;
|
|
199
|
-
|
|
200
|
-
Object.keys(plainObj).forEach((key: string) => {
|
|
201
|
-
const value = plainObj[key];
|
|
202
|
-
const result = decoder.decode(value);
|
|
203
|
-
if (result.ok) {
|
|
204
|
-
if (errors === null) {
|
|
205
|
-
rv[key] = result.value;
|
|
206
|
-
}
|
|
207
|
-
} else {
|
|
208
|
-
rv = {}; // Clear the success value so it can get garbage collected early
|
|
209
|
-
if (errors === null) {
|
|
210
|
-
errors = {};
|
|
211
|
-
}
|
|
212
|
-
errors[key] = result.error;
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
if (errors !== null) {
|
|
217
|
-
return err(merge(annotateObject(plainObj), errors));
|
|
218
|
-
} else {
|
|
219
|
-
return ok(rv);
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Similar to `dict()`, but returns the result as a `Map<string, T>` (an [ES6
|
|
226
|
-
* Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map))
|
|
227
|
-
* instead.
|
|
228
|
-
*/
|
|
229
|
-
export function mapping<T>(decoder: Decoder<T>): Decoder<Map<string, T>> {
|
|
230
|
-
return dict(decoder).transform(
|
|
231
|
-
(obj) =>
|
|
232
|
-
new Map(
|
|
233
|
-
// This is effectively Object.entries(obj), but in a way that Flow
|
|
234
|
-
// will know the types are okay
|
|
235
|
-
Object.keys(obj).map((key) => [key, obj[key]]),
|
|
236
|
-
),
|
|
237
|
-
);
|
|
238
|
-
}
|
package/lib/objects.mjs
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { annotateObject, merge, updateText } from '../annotate.mjs'
|
|
2
|
-
import { define } from '../Decoder.mjs'
|
|
3
|
-
import { subtract } from '../_utils.mjs'
|
|
4
|
-
|
|
5
|
-
export var pojo = define(function (blob, ok, err) {
|
|
6
|
-
return blob !== null && blob !== undefined && typeof blob === 'object' && Object.prototype.toString.call(blob) === '[object Object]' ? ok(blob) : err('Must be an object')
|
|
7
|
-
})
|
|
8
|
-
|
|
9
|
-
export function object(decodersByKey) {
|
|
10
|
-
var knownKeys = new Set(Object.keys(decodersByKey))
|
|
11
|
-
return pojo.then(function (plainObj, ok, err) {
|
|
12
|
-
var actualKeys = new Set(Object.keys(plainObj))
|
|
13
|
-
var missingKeys = subtract(knownKeys, actualKeys)
|
|
14
|
-
var record = {}
|
|
15
|
-
var errors = null
|
|
16
|
-
Object.keys(decodersByKey).forEach(function (key) {
|
|
17
|
-
var decoder = decodersByKey[key]
|
|
18
|
-
var rawValue = plainObj[key]
|
|
19
|
-
var result = decoder.decode(rawValue)
|
|
20
|
-
if (result.ok) {
|
|
21
|
-
var value = result.value
|
|
22
|
-
if (value !== undefined) {
|
|
23
|
-
record[key] = value
|
|
24
|
-
}
|
|
25
|
-
missingKeys['delete'](key)
|
|
26
|
-
} else {
|
|
27
|
-
var ann = result.error
|
|
28
|
-
if (rawValue === undefined) {
|
|
29
|
-
missingKeys.add(key)
|
|
30
|
-
} else {
|
|
31
|
-
if (errors === null) {
|
|
32
|
-
errors = {}
|
|
33
|
-
}
|
|
34
|
-
errors[key] = ann
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
})
|
|
38
|
-
if (errors || missingKeys.size > 0) {
|
|
39
|
-
var objAnn = annotateObject(plainObj)
|
|
40
|
-
if (errors) {
|
|
41
|
-
objAnn = merge(objAnn, errors)
|
|
42
|
-
}
|
|
43
|
-
if (missingKeys.size > 0) {
|
|
44
|
-
var errMsg = Array.from(missingKeys)
|
|
45
|
-
.map(function (key) {
|
|
46
|
-
return '"' + key + '"'
|
|
47
|
-
})
|
|
48
|
-
.join(', ')
|
|
49
|
-
var pluralized = missingKeys.size > 1 ? 'keys' : 'key'
|
|
50
|
-
objAnn = updateText(objAnn, 'Missing ' + pluralized + ': ' + errMsg)
|
|
51
|
-
}
|
|
52
|
-
return err(objAnn)
|
|
53
|
-
}
|
|
54
|
-
return ok(record)
|
|
55
|
-
})
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function exact(decodersByKey) {
|
|
59
|
-
var allowedKeys = new Set(Object.keys(decodersByKey))
|
|
60
|
-
var checked = pojo.reject(function (plainObj) {
|
|
61
|
-
var actualKeys = new Set(Object.keys(plainObj))
|
|
62
|
-
var extraKeys = subtract(actualKeys, allowedKeys)
|
|
63
|
-
return extraKeys.size > 0 ? 'Unexpected extra keys: ' + Array.from(extraKeys).join(', ') : null
|
|
64
|
-
})
|
|
65
|
-
return checked.then(object(decodersByKey).decode)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function inexact(decodersByKey) {
|
|
69
|
-
return pojo.then(function (plainObj) {
|
|
70
|
-
var allkeys = new Set(Object.keys(plainObj))
|
|
71
|
-
var decoder = object(decodersByKey).transform(function (safepart) {
|
|
72
|
-
var safekeys = new Set(Object.keys(decodersByKey))
|
|
73
|
-
safekeys.forEach(function (k) {
|
|
74
|
-
return allkeys.add(k)
|
|
75
|
-
})
|
|
76
|
-
var rv = {}
|
|
77
|
-
allkeys.forEach(function (k) {
|
|
78
|
-
if (safekeys.has(k)) {
|
|
79
|
-
var value = safepart[k]
|
|
80
|
-
if (value !== undefined) {
|
|
81
|
-
rv[k] = value
|
|
82
|
-
}
|
|
83
|
-
} else {
|
|
84
|
-
rv[k] = plainObj[k]
|
|
85
|
-
}
|
|
86
|
-
})
|
|
87
|
-
return rv
|
|
88
|
-
})
|
|
89
|
-
return decoder.decode(plainObj)
|
|
90
|
-
})
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function dict(decoder) {
|
|
94
|
-
return pojo.then(function (plainObj, ok, err) {
|
|
95
|
-
var rv = {}
|
|
96
|
-
var errors = null
|
|
97
|
-
Object.keys(plainObj).forEach(function (key) {
|
|
98
|
-
var value = plainObj[key]
|
|
99
|
-
var result = decoder.decode(value)
|
|
100
|
-
if (result.ok) {
|
|
101
|
-
if (errors === null) {
|
|
102
|
-
rv[key] = result.value
|
|
103
|
-
}
|
|
104
|
-
} else {
|
|
105
|
-
rv = {}
|
|
106
|
-
if (errors === null) {
|
|
107
|
-
errors = {}
|
|
108
|
-
}
|
|
109
|
-
errors[key] = result.error
|
|
110
|
-
}
|
|
111
|
-
})
|
|
112
|
-
if (errors !== null) {
|
|
113
|
-
return err(merge(annotateObject(plainObj), errors))
|
|
114
|
-
} else {
|
|
115
|
-
return ok(rv)
|
|
116
|
-
}
|
|
117
|
-
})
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function mapping(decoder) {
|
|
121
|
-
return dict(decoder).transform(function (obj) {
|
|
122
|
-
return new Map(
|
|
123
|
-
Object.keys(obj).map(function (key) {
|
|
124
|
-
return [key, obj[key]]
|
|
125
|
-
})
|
|
126
|
-
)
|
|
127
|
-
})
|
|
128
|
-
}
|
package/lib/strings.d.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { Decoder } from '../Decoder';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Accepts and returns strings.
|
|
5
|
-
*/
|
|
6
|
-
export const string: Decoder<string>;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Like `string`, but will reject the empty string or strings containing only whitespace.
|
|
10
|
-
*/
|
|
11
|
-
export const nonEmptyString: Decoder<string>;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Accepts and returns strings that match the given regular expression.
|
|
15
|
-
*/
|
|
16
|
-
export function regex(regex: RegExp, msg: string): Decoder<string>;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Accepts and returns strings that are syntactically valid email addresses.
|
|
20
|
-
* (This will not mean that the email address actually exist.)
|
|
21
|
-
*/
|
|
22
|
-
export const email: Decoder<string>;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Accepts strings that are valid URLs, returns the value as a URL instance.
|
|
26
|
-
*/
|
|
27
|
-
export const url: Decoder<URL>;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Accepts strings that are valid URLs, but only HTTPS ones. Returns the value
|
|
31
|
-
* as a URL instance.
|
|
32
|
-
*/
|
|
33
|
-
export const httpsUrl: Decoder<URL>;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Accepts strings that are valid
|
|
37
|
-
* [UUIDs](https://en.wikipedia.org/wiki/universally_unique_identifier)
|
|
38
|
-
* (universally unique identifier).
|
|
39
|
-
*/
|
|
40
|
-
export const uuid: Decoder<string>;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Like `uuid`, but only accepts
|
|
44
|
-
* [UUIDv1](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_%28date-time_and_MAC_address%29)
|
|
45
|
-
* strings.
|
|
46
|
-
*/
|
|
47
|
-
export const uuidv1: Decoder<string>;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Like `uuid`, but only accepts
|
|
51
|
-
* [UUIDv4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_%28random%29)
|
|
52
|
-
* strings.
|
|
53
|
-
*/
|
|
54
|
-
export const uuidv4: Decoder<string>;
|
package/lib/strings.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
exports.__esModule = true
|
|
4
|
-
exports.nonEmptyString = exports.httpsUrl = exports.email = void 0
|
|
5
|
-
exports.regex = regex
|
|
6
|
-
exports.uuidv4 = exports.uuidv1 = exports.uuid = exports.url = exports.string = void 0
|
|
7
|
-
var _Decoder = require('../Decoder')
|
|
8
|
-
var _unions = require('./unions')
|
|
9
|
-
var _utilities = require('./utilities')
|
|
10
|
-
|
|
11
|
-
var url_re = /^([A-Za-z]{3,9}(?:[+][A-Za-z]{3,9})?):\/\/(?:([-;:&=+$,\w]+)@)?(?:([A-Za-z0-9.-]+)(?::([0-9]{2,5}))?)(\/(?:[-+~%/.,\w]*)?(?:\?[-+=&;%@.,/\w]*)?(?:#[.,!/\w]*)?)?$/
|
|
12
|
-
|
|
13
|
-
var string = (0, _Decoder.define)(function (blob, ok, err) {
|
|
14
|
-
return typeof blob === 'string' ? ok(blob) : err('Must be string')
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
exports.string = string
|
|
18
|
-
var nonEmptyString = regex(/\S/, 'Must be non-empty string')
|
|
19
|
-
|
|
20
|
-
exports.nonEmptyString = nonEmptyString
|
|
21
|
-
function regex(regex, msg) {
|
|
22
|
-
return string.refine(function (s) {
|
|
23
|
-
return regex.test(s)
|
|
24
|
-
}, msg)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
var email = regex(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, 'Must be email')
|
|
28
|
-
|
|
29
|
-
exports.email = email
|
|
30
|
-
var url = (0, _unions.either)(
|
|
31
|
-
regex(url_re, 'Must be URL').transform(function (value) {
|
|
32
|
-
return new URL(value)
|
|
33
|
-
}),
|
|
34
|
-
(0, _utilities.instanceOf)(URL)
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
exports.url = url
|
|
38
|
-
var httpsUrl = url.refine(function (value) {
|
|
39
|
-
return value.protocol === 'https:'
|
|
40
|
-
}, 'Must be an HTTPS URL')
|
|
41
|
-
|
|
42
|
-
exports.httpsUrl = httpsUrl
|
|
43
|
-
var uuid = regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, 'Must be uuid')
|
|
44
|
-
|
|
45
|
-
exports.uuid = uuid
|
|
46
|
-
var uuidv1 = uuid.refine(function (value) {
|
|
47
|
-
return value[14] === '1'
|
|
48
|
-
}, 'Must be uuidv1')
|
|
49
|
-
|
|
50
|
-
exports.uuidv1 = uuidv1
|
|
51
|
-
var uuidv4 = uuid.refine(function (value) {
|
|
52
|
-
return value[14] === '4'
|
|
53
|
-
}, 'Must be uuidv4')
|
|
54
|
-
exports.uuidv4 = uuidv4
|
package/lib/strings.js.flow
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
// @flow strict
|
|
2
|
-
|
|
3
|
-
import { define } from '../Decoder';
|
|
4
|
-
import { either } from './unions';
|
|
5
|
-
import { instanceOf } from './utilities';
|
|
6
|
-
import type { Decoder } from '../Decoder';
|
|
7
|
-
|
|
8
|
-
/** Match groups in this regex:
|
|
9
|
-
* \1 - the scheme
|
|
10
|
-
* \2 - the username/password (optional)
|
|
11
|
-
* \3 - the host
|
|
12
|
-
* \4 - the port (optional)
|
|
13
|
-
* \5 - the path (optional)
|
|
14
|
-
*/
|
|
15
|
-
const url_re =
|
|
16
|
-
/^([A-Za-z]{3,9}(?:[+][A-Za-z]{3,9})?):\/\/(?:([-;:&=+$,\w]+)@)?(?:([A-Za-z0-9.-]+)(?::([0-9]{2,5}))?)(\/(?:[-+~%/.,\w]*)?(?:\?[-+=&;%@.,/\w]*)?(?:#[.,!/\w]*)?)?$/;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Accepts and returns strings.
|
|
20
|
-
*/
|
|
21
|
-
export const string: Decoder<string> = define((blob, ok, err) =>
|
|
22
|
-
typeof blob === 'string' ? ok(blob) : err('Must be string'),
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Like `string`, but will reject the empty string or strings containing only whitespace.
|
|
27
|
-
*/
|
|
28
|
-
export const nonEmptyString: Decoder<string> = regex(/\S/, 'Must be non-empty string');
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Accepts and returns strings that match the given regular expression.
|
|
32
|
-
*/
|
|
33
|
-
export function regex(regex: RegExp, msg: string): Decoder<string> {
|
|
34
|
-
return string.refine((s) => regex.test(s), msg);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Accepts and returns strings that are syntactically valid email addresses.
|
|
39
|
-
* (This will not mean that the email address actually exist.)
|
|
40
|
-
*/
|
|
41
|
-
export const email: Decoder<string> = regex(
|
|
42
|
-
// The almost perfect email regex, taken from https://emailregex.com/
|
|
43
|
-
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
|
44
|
-
'Must be email',
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Accepts strings that are valid URLs, returns the value as a URL instance.
|
|
49
|
-
*/
|
|
50
|
-
export const url: Decoder<URL> = either(
|
|
51
|
-
regex(url_re, 'Must be URL').transform((value) => new URL(value)),
|
|
52
|
-
instanceOf(URL),
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Accepts strings that are valid URLs, but only HTTPS ones. Returns the value
|
|
57
|
-
* as a URL instance.
|
|
58
|
-
*/
|
|
59
|
-
export const httpsUrl: Decoder<URL> = url.refine(
|
|
60
|
-
(value) => value.protocol === 'https:',
|
|
61
|
-
'Must be an HTTPS URL',
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Accepts strings that are valid
|
|
66
|
-
* [UUIDs](https://en.wikipedia.org/wiki/universally_unique_identifier)
|
|
67
|
-
* (universally unique identifier).
|
|
68
|
-
*/
|
|
69
|
-
export const uuid: Decoder<string> = regex(
|
|
70
|
-
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
|
|
71
|
-
'Must be uuid',
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Like `uuid`, but only accepts
|
|
76
|
-
* [UUIDv1](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_%28date-time_and_MAC_address%29)
|
|
77
|
-
* strings.
|
|
78
|
-
*/
|
|
79
|
-
export const uuidv1: Decoder<string> =
|
|
80
|
-
// https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address)
|
|
81
|
-
uuid.refine((value) => value[14] === '1', 'Must be uuidv1');
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Like `uuid`, but only accepts
|
|
85
|
-
* [UUIDv4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_%28random%29)
|
|
86
|
-
* strings.
|
|
87
|
-
*/
|
|
88
|
-
export const uuidv4: Decoder<string> =
|
|
89
|
-
// https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
|
|
90
|
-
uuid.refine((value) => value[14] === '4', 'Must be uuidv4');
|
package/lib/strings.mjs
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { define } from '../Decoder.mjs'
|
|
2
|
-
import { either } from './unions.mjs'
|
|
3
|
-
import { instanceOf } from './utilities.mjs'
|
|
4
|
-
|
|
5
|
-
var url_re = /^([A-Za-z]{3,9}(?:[+][A-Za-z]{3,9})?):\/\/(?:([-;:&=+$,\w]+)@)?(?:([A-Za-z0-9.-]+)(?::([0-9]{2,5}))?)(\/(?:[-+~%/.,\w]*)?(?:\?[-+=&;%@.,/\w]*)?(?:#[.,!/\w]*)?)?$/
|
|
6
|
-
|
|
7
|
-
export var string = define(function (blob, ok, err) {
|
|
8
|
-
return typeof blob === 'string' ? ok(blob) : err('Must be string')
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
export var nonEmptyString = regex(/\S/, 'Must be non-empty string')
|
|
12
|
-
|
|
13
|
-
export function regex(regex, msg) {
|
|
14
|
-
return string.refine(function (s) {
|
|
15
|
-
return regex.test(s)
|
|
16
|
-
}, msg)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export var email = regex(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, 'Must be email')
|
|
20
|
-
|
|
21
|
-
export var url = either(
|
|
22
|
-
regex(url_re, 'Must be URL').transform(function (value) {
|
|
23
|
-
return new URL(value)
|
|
24
|
-
}),
|
|
25
|
-
instanceOf(URL)
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
export var httpsUrl = url.refine(function (value) {
|
|
29
|
-
return value.protocol === 'https:'
|
|
30
|
-
}, 'Must be an HTTPS URL')
|
|
31
|
-
|
|
32
|
-
export var uuid = regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, 'Must be uuid')
|
|
33
|
-
|
|
34
|
-
export var uuidv1 = uuid.refine(function (value) {
|
|
35
|
-
return value[14] === '1'
|
|
36
|
-
}, 'Must be uuidv1')
|
|
37
|
-
|
|
38
|
-
export var uuidv4 = uuid.refine(function (value) {
|
|
39
|
-
return value[14] === '4'
|
|
40
|
-
}, 'Must be uuidv4')
|
package/lib/unions.d.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { Decoder, DecoderType, Scalar } from '../Decoder';
|
|
2
|
-
|
|
3
|
-
export type Values<T extends object> = T[keyof T];
|
|
4
|
-
|
|
5
|
-
export type DecoderTypes<T> = T extends ReadonlyArray<Decoder<infer U>> ? U : never;
|
|
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
|
-
*/
|
|
14
|
-
export function either<T extends ReadonlyArray<Decoder<any>>>(
|
|
15
|
-
...args: T
|
|
16
|
-
): Decoder<DecoderTypes<T>>;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Accepts any value that is strictly-equal (using `===`) to one of the
|
|
20
|
-
* specified values.
|
|
21
|
-
*/
|
|
22
|
-
export function oneOf<T extends Scalar>(constants: readonly T[]): Decoder<T>;
|
|
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
|
-
*/
|
|
52
|
-
export function taggedUnion<O extends Record<string, Decoder<any>>>(
|
|
53
|
-
field: string,
|
|
54
|
-
mapping: O,
|
|
55
|
-
): Decoder<Values<{ [key in keyof O]: DecoderType<O[key]> }>>;
|