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.
Files changed (56) hide show
  1. package/CHANGELOG.md +11 -2
  2. package/README.md +234 -72
  3. package/_utils.js +1 -1
  4. package/_utils.js.flow +3 -3
  5. package/_utils.mjs +1 -1
  6. package/core/array.d.ts +3 -0
  7. package/core/array.js +12 -1
  8. package/core/array.js.flow +9 -2
  9. package/core/array.mjs +11 -2
  10. package/core/boolean.js +3 -3
  11. package/core/boolean.js.flow +2 -2
  12. package/core/boolean.mjs +2 -2
  13. package/core/composition.d.ts +5 -1
  14. package/core/composition.js +33 -5
  15. package/core/composition.js.flow +31 -5
  16. package/core/composition.mjs +31 -5
  17. package/core/date.js +3 -3
  18. package/core/date.js.flow +2 -2
  19. package/core/date.mjs +2 -2
  20. package/core/dispatch.d.ts +1 -1
  21. package/core/dispatch.js +8 -6
  22. package/core/dispatch.js.flow +9 -8
  23. package/core/dispatch.mjs +6 -5
  24. package/core/either.d.ts +63 -58
  25. package/core/either.js +30 -42
  26. package/core/either.js.flow +38 -84
  27. package/core/either.mjs +34 -34
  28. package/core/instanceOf.d.ts +1 -1
  29. package/core/json.js +3 -3
  30. package/core/json.js.flow +3 -3
  31. package/core/json.mjs +3 -3
  32. package/core/object.d.ts +5 -0
  33. package/core/object.js +59 -2
  34. package/core/object.js.flow +77 -21
  35. package/core/object.mjs +56 -3
  36. package/core/string.d.ts +3 -0
  37. package/core/string.js +15 -3
  38. package/core/string.js.flow +15 -2
  39. package/core/string.mjs +12 -3
  40. package/core/tuple.d.ts +28 -28
  41. package/core/tuple.js +28 -151
  42. package/core/tuple.js.flow +31 -191
  43. package/core/tuple.mjs +27 -141
  44. package/index.d.ts +17 -18
  45. package/index.js +33 -43
  46. package/index.js.flow +17 -18
  47. package/index.mjs +8 -9
  48. package/package.json +1 -1
  49. package/result.d.ts +2 -2
  50. package/result.js +9 -9
  51. package/result.js.flow +11 -11
  52. package/result.mjs +9 -9
  53. package/core/mapping.d.ts +0 -6
  54. package/core/mapping.js +0 -67
  55. package/core/mapping.js.flow +0 -62
  56. package/core/mapping.mjs +0 -58
package/core/object.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
2
 
3
3
  import { annotate, annotateObject, merge, updateText } from '../annotate.mjs';
4
- import { compose, map } from './composition.mjs';
4
+ import { compose, transform } from './composition.mjs';
5
5
  import { err, ok } from '../result.mjs';
6
6
 
7
7
  function isPojo(o) {
@@ -74,7 +74,7 @@ export function object(mapping) {
74
74
  var rawValue = blob[key];
75
75
  var result = decoder(rawValue);
76
76
 
77
- if (result.type === 'ok') {
77
+ if (result.ok) {
78
78
  var value = result.value;
79
79
 
80
80
  if (value !== undefined) {
@@ -150,7 +150,7 @@ export function exact(mapping) {
150
150
  export function inexact(mapping) {
151
151
  return compose(pojo, function (blob) {
152
152
  var allkeys = new Set(Object.keys(blob));
153
- var decoder = map(object(mapping), function (safepart) {
153
+ var decoder = transform(object(mapping), function (safepart) {
154
154
  var safekeys = new Set(Object.keys(mapping)); // To account for hard-coded keys that aren't part of the input
155
155
 
156
156
  safekeys.forEach(function (k) {
@@ -172,4 +172,57 @@ export function inexact(mapping) {
172
172
  });
173
173
  return decoder(blob);
174
174
  });
175
+ }
176
+ /**
177
+ * Like mapping(), but returns an object rather than a Map instance.
178
+ */
179
+
180
+ export function dict(decoder) {
181
+ return compose(pojo, function (blob) {
182
+ var rv = {};
183
+ var errors = null;
184
+ Object.keys(blob).forEach(function (key) {
185
+ var value = blob[key];
186
+ var result = decoder(value);
187
+
188
+ if (result.ok) {
189
+ if (errors === null) {
190
+ rv[key] = result.value;
191
+ }
192
+ } else {
193
+ rv = {}; // Clear the success value so it can get garbage collected early
194
+
195
+ if (errors === null) {
196
+ errors = {};
197
+ }
198
+
199
+ errors[key] = result.error;
200
+ }
201
+ });
202
+
203
+ if (errors !== null) {
204
+ return err(merge(annotateObject(blob), errors));
205
+ } else {
206
+ return ok(rv);
207
+ }
208
+ });
209
+ }
210
+ /**
211
+ * Given an object, will decode a Map of string keys to whatever values.
212
+ *
213
+ * For example, given a decoder for a Person, we can verify a Person lookup
214
+ * table structure (of type Map<string, Person>) like so:
215
+ *
216
+ * mapping(person)
217
+ *
218
+ */
219
+
220
+ export function mapping(decoder) {
221
+ return transform(dict(decoder), function (obj) {
222
+ return new Map( // This is effectively Object.entries(obj), but in a way that Flow
223
+ // will know the types are okay
224
+ Object.keys(obj).map(function (key) {
225
+ return [key, obj[key]];
226
+ }));
227
+ });
175
228
  }
package/core/string.d.ts CHANGED
@@ -8,3 +8,6 @@ export function regex(regex: RegExp, msg: string): Decoder<string>;
8
8
  export const email: Decoder<string>;
9
9
  export const url: Decoder<URL>;
10
10
  export const httpsUrl: Decoder<URL>;
11
+ export const uuid: Decoder<string>;
12
+ export const uuidv1: Decoder<string>;
13
+ export const uuidv4: Decoder<string>;
package/core/string.js CHANGED
@@ -3,7 +3,7 @@
3
3
  exports.__esModule = true;
4
4
  exports.nonEmptyString = exports.httpsUrl = exports.email = void 0;
5
5
  exports.regex = regex;
6
- exports.url = exports.string = void 0;
6
+ exports.uuidv4 = exports.uuidv1 = exports.uuid = exports.url = exports.string = void 0;
7
7
 
8
8
  var _annotate = require("../annotate");
9
9
 
@@ -58,11 +58,23 @@ function regex(regex, msg) {
58
58
 
59
59
  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');
60
60
  exports.email = email;
61
- var url = (0, _either.either)((0, _composition.map)(regex(url_re, 'Must be URL'), function (value) {
61
+ var url = (0, _either.either)((0, _composition.transform)(regex(url_re, 'Must be URL'), function (value) {
62
62
  return new URL(value);
63
63
  }), (0, _instanceOf.instanceOf)(URL));
64
64
  exports.url = url;
65
65
  var httpsUrl = (0, _composition.predicate)(url, function (value) {
66
66
  return value.protocol === 'https:';
67
67
  }, 'Must be an HTTPS URL');
68
- exports.httpsUrl = httpsUrl;
68
+ exports.httpsUrl = httpsUrl;
69
+ 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');
70
+ exports.uuid = uuid;
71
+ var uuidv1 = // https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address)
72
+ (0, _composition.predicate)(uuid, function (value) {
73
+ return value[14] === '1';
74
+ }, 'Must be uuidv1');
75
+ exports.uuidv1 = uuidv1;
76
+ var uuidv4 = // https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
77
+ (0, _composition.predicate)(uuid, function (value) {
78
+ return value[14] === '4';
79
+ }, 'Must be uuidv4');
80
+ exports.uuidv4 = uuidv4;
@@ -4,7 +4,7 @@ import { annotate } from '../annotate';
4
4
  import { either } from './either';
5
5
  import { err, ok } from '../result';
6
6
  import { instanceOf } from './instanceOf';
7
- import { map, predicate } from './composition';
7
+ import { predicate, transform } from './composition';
8
8
  import type { Decoder } from '../_types';
9
9
 
10
10
  /** Match groups in this regex:
@@ -48,7 +48,7 @@ export const email: Decoder<string> = regex(
48
48
  );
49
49
 
50
50
  export const url: Decoder<URL> = either(
51
- map(regex(url_re, 'Must be URL'), (value) => new URL(value)),
51
+ transform(regex(url_re, 'Must be URL'), (value) => new URL(value)),
52
52
  instanceOf(URL),
53
53
  );
54
54
 
@@ -57,3 +57,16 @@ export const httpsUrl: Decoder<URL> = predicate(
57
57
  (value) => value.protocol === 'https:',
58
58
  'Must be an HTTPS URL',
59
59
  );
60
+
61
+ export const uuid: Decoder<string> = regex(
62
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
63
+ 'Must be uuid',
64
+ );
65
+
66
+ export const uuidv1: Decoder<string> =
67
+ // https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address)
68
+ predicate(uuid, (value) => value[14] === '1', 'Must be uuidv1');
69
+
70
+ export const uuidv4: Decoder<string> =
71
+ // https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
72
+ predicate(uuid, (value) => value[14] === '4', 'Must be uuidv4');
package/core/string.mjs CHANGED
@@ -2,7 +2,7 @@ import { annotate } from '../annotate.mjs';
2
2
  import { either } from './either.mjs';
3
3
  import { err, ok } from '../result.mjs';
4
4
  import { instanceOf } from './instanceOf.mjs';
5
- import { map, predicate } from './composition.mjs';
5
+ import { predicate, transform } from './composition.mjs';
6
6
 
7
7
  /** Match groups in this regex:
8
8
  * \1 - the scheme
@@ -41,9 +41,18 @@ export function regex(regex, msg) {
41
41
  */
42
42
 
43
43
  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');
44
- export var url = either(map(regex(url_re, 'Must be URL'), function (value) {
44
+ export var url = either(transform(regex(url_re, 'Must be URL'), function (value) {
45
45
  return new URL(value);
46
46
  }), instanceOf(URL));
47
47
  export var httpsUrl = predicate(url, function (value) {
48
48
  return value.protocol === 'https:';
49
- }, 'Must be an HTTPS URL');
49
+ }, 'Must be an HTTPS URL');
50
+ 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');
51
+ export var uuidv1 = // https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address)
52
+ predicate(uuid, function (value) {
53
+ return value[14] === '1';
54
+ }, 'Must be uuidv1');
55
+ export var uuidv4 = // https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
56
+ predicate(uuid, function (value) {
57
+ return value[14] === '4';
58
+ }, 'Must be uuidv4');
package/core/tuple.d.ts CHANGED
@@ -1,30 +1,30 @@
1
1
  import { Decoder } from '../_types';
2
2
 
3
- export function tuple1<T1>(d1: Decoder<T1>): Decoder<[T1]>;
4
- export function tuple2<T1, T2>(d1: Decoder<T1>, d2: Decoder<T2>): Decoder<[T1, T2]>;
5
- export function tuple3<T1, T2, T3>(
6
- d1: Decoder<T1>,
7
- d2: Decoder<T2>,
8
- d3: Decoder<T3>,
9
- ): Decoder<[T1, T2, T3]>;
10
- export function tuple4<T1, T2, T3, T4>(
11
- d1: Decoder<T1>,
12
- d2: Decoder<T2>,
13
- d3: Decoder<T3>,
14
- d4: Decoder<T4>,
15
- ): Decoder<[T1, T2, T3, T4]>;
16
- export function tuple5<T1, T2, T3, T4, T5>(
17
- d1: Decoder<T1>,
18
- d2: Decoder<T2>,
19
- d3: Decoder<T3>,
20
- d4: Decoder<T4>,
21
- d5: Decoder<T5>,
22
- ): Decoder<[T1, T2, T3, T4, T5]>;
23
- export function tuple6<T1, T2, T3, T4, T5, T6>(
24
- d1: Decoder<T1>,
25
- d2: Decoder<T2>,
26
- d3: Decoder<T3>,
27
- d4: Decoder<T4>,
28
- d5: Decoder<T5>,
29
- d6: Decoder<T6>,
30
- ): Decoder<[T1, T2, T3, T4, T5, T6]>;
3
+ export function tuple<A>(a: Decoder<A>): Decoder<[A]>;
4
+ export function tuple<A, B>(a: Decoder<A>, b: Decoder<B>): Decoder<[A, B]>;
5
+ export function tuple<A, B, C>(
6
+ a: Decoder<A>,
7
+ b: Decoder<B>,
8
+ c: Decoder<C>,
9
+ ): Decoder<[A, B, C]>;
10
+ export function tuple<A, B, C, D>(
11
+ a: Decoder<A>,
12
+ b: Decoder<B>,
13
+ c: Decoder<C>,
14
+ d: Decoder<D>,
15
+ ): Decoder<[A, B, C, D]>;
16
+ export function tuple<A, B, C, D, E>(
17
+ a: Decoder<A>,
18
+ b: Decoder<B>,
19
+ c: Decoder<C>,
20
+ d: Decoder<D>,
21
+ e: Decoder<E>,
22
+ ): Decoder<[A, B, C, D, E]>;
23
+ export function tuple<A, B, C, D, E, F>(
24
+ a: Decoder<A>,
25
+ b: Decoder<B>,
26
+ c: Decoder<C>,
27
+ d: Decoder<D>,
28
+ e: Decoder<E>,
29
+ f: Decoder<F>,
30
+ ): Decoder<[A, B, C, D, E, F]>;
package/core/tuple.js CHANGED
@@ -1,12 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports.tuple1 = tuple1;
5
- exports.tuple2 = tuple2;
6
- exports.tuple3 = tuple3;
7
- exports.tuple4 = tuple4;
8
- exports.tuple5 = tuple5;
9
- exports.tuple6 = tuple6;
4
+ exports.tuple = void 0;
10
5
 
11
6
  var _annotate = require("../annotate");
12
7
 
@@ -16,162 +11,44 @@ var _result = require("../result");
16
11
 
17
12
  var _array = require("./array");
18
13
 
19
- function okOrErr(result) {
20
- return result.type === 'ok' ? result.value : result.error;
21
- }
22
-
23
14
  var ntuple = function ntuple(n) {
24
15
  return (0, _composition.predicate)(_array.poja, function (arr) {
25
16
  return arr.length === n;
26
17
  }, "Must be a " + n + "-tuple");
27
- };
28
- /**
29
- * Builds a Decoder that returns Ok for 1-tuple of [T], given a Decoder for T.
30
- * Err otherwise.
31
- */
32
-
33
-
34
- function tuple1(decoder1) {
35
- return (0, _composition.compose)(ntuple(1), function (blobs) {
36
- var blob1 = blobs[0];
37
- var result1 = decoder1(blob1);
38
-
39
- try {
40
- return (0, _result.ok)([(0, _result.unwrap)(result1)]);
41
- } catch (e) {
42
- // If a decoder error has happened while unwrapping all the
43
- // results, try to construct a good error message
44
- return (0, _result.err)((0, _annotate.annotate)([okOrErr(result1)]));
45
- }
46
- });
47
- }
48
- /**
49
- * Builds a Decoder that returns Ok for 2-tuples of [T1, T2], given Decoders
50
- * for T1 and T2. Err otherwise.
51
- */
52
-
18
+ }; // prettier-ignore
53
19
 
54
- function tuple2(decoder1, decoder2) {
55
- return (0, _composition.compose)(ntuple(2), function (blobs) {
56
- var blob1 = blobs[0],
57
- blob2 = blobs[1];
58
- var result1 = decoder1(blob1);
59
- var result2 = decoder2(blob2);
60
20
 
61
- try {
62
- return (0, _result.ok)([(0, _result.unwrap)(result1), (0, _result.unwrap)(result2)]);
63
- } catch (e) {
64
- // If a decoder error has happened while unwrapping all the
65
- // results, try to construct a good error message
66
- return (0, _result.err)((0, _annotate.annotate)([okOrErr(result1), okOrErr(result2)]));
67
- }
68
- });
69
- }
70
21
  /**
71
- * Builds a Decoder that returns Ok for 3-tuples of [T1, T2, T3], given
72
- * Decoders for T1, T2, and T3. Err otherwise.
22
+ * Accepts n-tuples [A, B, C, ...] matching the given decoders A, B, C, ...
73
23
  */
74
-
75
-
76
- function tuple3(decoder1, decoder2, decoder3) {
77
- return (0, _composition.compose)(ntuple(3), function (blobs) {
78
- var blob1 = blobs[0],
79
- blob2 = blobs[1],
80
- blob3 = blobs[2];
81
- var result1 = decoder1(blob1);
82
- var result2 = decoder2(blob2);
83
- var result3 = decoder3(blob3);
84
-
85
- try {
86
- return (0, _result.ok)([(0, _result.unwrap)(result1), (0, _result.unwrap)(result2), (0, _result.unwrap)(result3)]);
87
- } catch (e) {
24
+ function _tuple() {
25
+ for (var _len = arguments.length, decoders = new Array(_len), _key = 0; _key < _len; _key++) {
26
+ decoders[_key] = arguments[_key];
27
+ }
28
+
29
+ return (0, _composition.compose)(ntuple(decoders.length), function (blobs) {
30
+ var allOk = true;
31
+ var rvs = decoders.map(function (decoder, i) {
32
+ var blob = blobs[i];
33
+ var result = decoder(blob);
34
+
35
+ if (result.ok) {
36
+ return result.value;
37
+ } else {
38
+ allOk = false;
39
+ return result.error;
40
+ }
41
+ });
42
+
43
+ if (allOk) {
44
+ return (0, _result.ok)(rvs);
45
+ } else {
88
46
  // If a decoder error has happened while unwrapping all the
89
47
  // results, try to construct a good error message
90
- return (0, _result.err)((0, _annotate.annotate)([okOrErr(result1), okOrErr(result2), okOrErr(result3)]));
48
+ return (0, _result.err)((0, _annotate.annotate)(rvs));
91
49
  }
92
50
  });
93
51
  }
94
- /**
95
- * Builds a Decoder that returns Ok for 4-tuples of [T1, T2, T3, T4], given
96
- * Decoders for T1, T2, T3, and T4. Err otherwise.
97
- */
98
-
99
52
 
100
- function tuple4(decoder1, decoder2, decoder3, decoder4) {
101
- return (0, _composition.compose)(ntuple(4), function (blobs) {
102
- var blob1 = blobs[0],
103
- blob2 = blobs[1],
104
- blob3 = blobs[2],
105
- blob4 = blobs[3];
106
- var result1 = decoder1(blob1);
107
- var result2 = decoder2(blob2);
108
- var result3 = decoder3(blob3);
109
- var result4 = decoder4(blob4);
110
-
111
- try {
112
- return (0, _result.ok)([(0, _result.unwrap)(result1), (0, _result.unwrap)(result2), (0, _result.unwrap)(result3), (0, _result.unwrap)(result4)]);
113
- } catch (e) {
114
- // If a decoder error has happened while unwrapping all the
115
- // results, try to construct a good error message
116
- return (0, _result.err)((0, _annotate.annotate)([okOrErr(result1), okOrErr(result2), okOrErr(result3), okOrErr(result4)]));
117
- }
118
- });
119
- }
120
- /**
121
- * Builds a Decoder that returns Ok for 5-tuples of [T1, T2, T3, T4, T5], given
122
- * Decoders for T1, T2, T3, T4, and T5. Err otherwise.
123
- */
124
-
125
-
126
- function tuple5(decoder1, decoder2, decoder3, decoder4, decoder5) {
127
- return (0, _composition.compose)(ntuple(5), function (blobs) {
128
- var blob1 = blobs[0],
129
- blob2 = blobs[1],
130
- blob3 = blobs[2],
131
- blob4 = blobs[3],
132
- blob5 = blobs[4];
133
- var result1 = decoder1(blob1);
134
- var result2 = decoder2(blob2);
135
- var result3 = decoder3(blob3);
136
- var result4 = decoder4(blob4);
137
- var result5 = decoder5(blob5);
138
-
139
- try {
140
- return (0, _result.ok)([(0, _result.unwrap)(result1), (0, _result.unwrap)(result2), (0, _result.unwrap)(result3), (0, _result.unwrap)(result4), (0, _result.unwrap)(result5)]);
141
- } catch (e) {
142
- // If a decoder error has happened while unwrapping all the
143
- // results, try to construct a good error message
144
- return (0, _result.err)((0, _annotate.annotate)([okOrErr(result1), okOrErr(result2), okOrErr(result3), okOrErr(result4), okOrErr(result5)]));
145
- }
146
- });
147
- }
148
- /**
149
- * Builds a Decoder that returns Ok for 5-tuples of [T1, T2, T3, T4, T5], given
150
- * Decoders for T1, T2, T3, T4, T5, and T6. Err otherwise.
151
- */
152
-
153
-
154
- function tuple6(decoder1, decoder2, decoder3, decoder4, decoder5, decoder6) {
155
- return (0, _composition.compose)(ntuple(6), function (blobs) {
156
- var blob1 = blobs[0],
157
- blob2 = blobs[1],
158
- blob3 = blobs[2],
159
- blob4 = blobs[3],
160
- blob5 = blobs[4],
161
- blob6 = blobs[5];
162
- var result1 = decoder1(blob1);
163
- var result2 = decoder2(blob2);
164
- var result3 = decoder3(blob3);
165
- var result4 = decoder4(blob4);
166
- var result5 = decoder5(blob5);
167
- var result6 = decoder6(blob6);
168
-
169
- try {
170
- return (0, _result.ok)([(0, _result.unwrap)(result1), (0, _result.unwrap)(result2), (0, _result.unwrap)(result3), (0, _result.unwrap)(result4), (0, _result.unwrap)(result5), (0, _result.unwrap)(result6)]);
171
- } catch (e) {
172
- // If a decoder error has happened while unwrapping all the
173
- // results, try to construct a good error message
174
- return (0, _result.err)((0, _annotate.annotate)([okOrErr(result1), okOrErr(result2), okOrErr(result3), okOrErr(result4), okOrErr(result5), okOrErr(result6)]));
175
- }
176
- });
177
- }
53
+ var tuple = _tuple;
54
+ exports.tuple = tuple;