decoders 1.26.0-beta2 → 2.0.0-beta11

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 (128) hide show
  1. package/CHANGELOG.md +52 -6
  2. package/Decoder.d.ts +28 -0
  3. package/Decoder.js +213 -0
  4. package/Decoder.js.flow +238 -0
  5. package/Decoder.mjs +206 -0
  6. package/NotSupportedTSVersion.d.ts +1 -0
  7. package/README.md +105 -961
  8. package/_utils.d.ts +9 -0
  9. package/_utils.js +102 -0
  10. package/_utils.js.flow +93 -0
  11. package/_utils.mjs +89 -0
  12. package/annotate.d.ts +62 -0
  13. package/annotate.js +161 -0
  14. package/annotate.js.flow +218 -0
  15. package/annotate.mjs +144 -0
  16. package/format.d.ts +4 -0
  17. package/format.js +151 -0
  18. package/format.js.flow +126 -0
  19. package/format.mjs +140 -0
  20. package/index.d.ts +40 -0
  21. package/index.js +90 -0
  22. package/index.js.flow +44 -0
  23. package/index.mjs +11 -0
  24. package/{ts/helpers.d.ts → lib/_helpers.d.ts} +0 -0
  25. package/lib/arrays.d.ts +37 -0
  26. package/lib/arrays.js +138 -0
  27. package/lib/arrays.js.flow +138 -0
  28. package/lib/arrays.mjs +123 -0
  29. package/lib/basics.d.ts +14 -0
  30. package/lib/basics.js +109 -0
  31. package/lib/basics.js.flow +85 -0
  32. package/lib/basics.mjs +85 -0
  33. package/{ts/boolean.d.ts → lib/booleans.d.ts} +1 -1
  34. package/lib/booleans.js +35 -0
  35. package/lib/booleans.js.flow +22 -0
  36. package/lib/booleans.mjs +25 -0
  37. package/{ts/date.d.ts → lib/dates.d.ts} +1 -1
  38. package/lib/dates.js +44 -0
  39. package/lib/dates.js.flow +40 -0
  40. package/lib/dates.mjs +34 -0
  41. package/{ts → lib}/json.d.ts +1 -1
  42. package/lib/json.js +55 -0
  43. package/lib/json.js.flow +50 -0
  44. package/lib/json.mjs +40 -0
  45. package/{ts/number.d.ts → lib/numbers.d.ts} +2 -1
  46. package/lib/numbers.js +52 -0
  47. package/lib/numbers.js.flow +49 -0
  48. package/lib/numbers.mjs +42 -0
  49. package/{ts/object.d.ts → lib/objects.d.ts} +11 -6
  50. package/lib/objects.js +240 -0
  51. package/lib/objects.js.flow +246 -0
  52. package/lib/objects.mjs +223 -0
  53. package/lib/strings.d.ts +13 -0
  54. package/lib/strings.js +101 -0
  55. package/lib/strings.js.flow +90 -0
  56. package/lib/strings.mjs +82 -0
  57. package/lib/unions.d.ts +78 -0
  58. package/lib/unions.js +161 -0
  59. package/lib/unions.js.flow +158 -0
  60. package/lib/unions.mjs +145 -0
  61. package/lib/utilities.d.ts +10 -0
  62. package/lib/utilities.js +94 -0
  63. package/lib/utilities.js.flow +84 -0
  64. package/lib/utilities.mjs +79 -0
  65. package/package.json +79 -28
  66. package/result.d.ts +16 -0
  67. package/result.js +34 -0
  68. package/result.js.flow +26 -0
  69. package/result.mjs +27 -0
  70. package/cjs/array.js +0 -133
  71. package/cjs/array.js.flow +0 -106
  72. package/cjs/boolean.js +0 -42
  73. package/cjs/boolean.js.flow +0 -28
  74. package/cjs/constants.js +0 -67
  75. package/cjs/constants.js.flow +0 -45
  76. package/cjs/date.js +0 -42
  77. package/cjs/date.js.flow +0 -38
  78. package/cjs/describe.js +0 -22
  79. package/cjs/describe.js.flow +0 -17
  80. package/cjs/dispatch.js +0 -58
  81. package/cjs/dispatch.js.flow +0 -57
  82. package/cjs/either.js +0 -85
  83. package/cjs/either.js.flow +0 -131
  84. package/cjs/fail.js +0 -19
  85. package/cjs/fail.js.flow +0 -13
  86. package/cjs/guard.js +0 -30
  87. package/cjs/guard.js.flow +0 -36
  88. package/cjs/index.js +0 -397
  89. package/cjs/index.js.flow +0 -56
  90. package/cjs/instanceOf.js +0 -17
  91. package/cjs/instanceOf.js.flow +0 -21
  92. package/cjs/json.js +0 -33
  93. package/cjs/json.js.flow +0 -28
  94. package/cjs/lazy.js +0 -18
  95. package/cjs/lazy.js.flow +0 -15
  96. package/cjs/mapping.js +0 -113
  97. package/cjs/mapping.js.flow +0 -71
  98. package/cjs/number.js +0 -38
  99. package/cjs/number.js.flow +0 -35
  100. package/cjs/object.js +0 -254
  101. package/cjs/object.js.flow +0 -211
  102. package/cjs/optional.js +0 -52
  103. package/cjs/optional.js.flow +0 -42
  104. package/cjs/string.js +0 -93
  105. package/cjs/string.js.flow +0 -81
  106. package/cjs/tuple.js +0 -199
  107. package/cjs/tuple.js.flow +0 -221
  108. package/cjs/types.js +0 -3
  109. package/cjs/types.js.flow +0 -26
  110. package/cjs/utils.js +0 -70
  111. package/cjs/utils.js.flow +0 -58
  112. package/es/index.js +0 -1039
  113. package/ts/array.d.ts +0 -5
  114. package/ts/constants.d.ts +0 -11
  115. package/ts/describe.d.ts +0 -3
  116. package/ts/dispatch.d.ts +0 -8
  117. package/ts/either.d.ts +0 -61
  118. package/ts/fail.d.ts +0 -3
  119. package/ts/guard.d.ts +0 -7
  120. package/ts/index.d.ts +0 -38
  121. package/ts/instanceOf.d.ts +0 -3
  122. package/ts/lazy.d.ts +0 -3
  123. package/ts/mapping.d.ts +0 -4
  124. package/ts/optional.d.ts +0 -5
  125. package/ts/string.d.ts +0 -7
  126. package/ts/tuple.d.ts +0 -30
  127. package/ts/types.d.ts +0 -18
  128. package/ts/utils.d.ts +0 -13
package/format.mjs ADDED
@@ -0,0 +1,140 @@
1
+ import { summarize as _summarize, asDate, INDENT, indent, isMultiline } from './_utils.mjs';
2
+
3
+ function serializeString(s, width) {
4
+ if (width === void 0) {
5
+ width = 80;
6
+ }
7
+
8
+ // Full string
9
+ // Abbreviated to $maxlen i.e. "Vincent Driess..." [truncated]
10
+ var ser = JSON.stringify(s);
11
+
12
+ if (ser.length <= width) {
13
+ return ser;
14
+ } // Cut off a bit
15
+
16
+
17
+ var truncated = s.substring(0, width - 15) + '...';
18
+ ser = JSON.stringify(truncated) + ' [truncated]';
19
+ return ser;
20
+ }
21
+
22
+ function serializeArray(annotation, prefix) {
23
+ var items = annotation.items;
24
+
25
+ if (items.length === 0) {
26
+ return '[]';
27
+ }
28
+
29
+ var result = [];
30
+ items.forEach(function (item) {
31
+ var _serializeAnnotation = serializeAnnotation(item, prefix + INDENT),
32
+ ser = _serializeAnnotation[0],
33
+ ann = _serializeAnnotation[1];
34
+
35
+ result.push(prefix + INDENT + ser + ',');
36
+
37
+ if (ann !== undefined) {
38
+ result.push(indent(ann, prefix + INDENT));
39
+ }
40
+ });
41
+ return ['['].concat(result, [prefix + ']']).join('\n');
42
+ }
43
+
44
+ function serializeObject(annotation, prefix) {
45
+ var fields = annotation.fields;
46
+ var fieldNames = Object.keys(fields);
47
+
48
+ if (fieldNames.length === 0) {
49
+ return '{}';
50
+ }
51
+
52
+ var result = [];
53
+ fieldNames.forEach(function (key) {
54
+ var valueAnnotation = fields[key];
55
+ var kser = serializeValue(key);
56
+ var valPrefix = prefix + INDENT + ' '.repeat(kser.length + 2);
57
+
58
+ var _serializeAnnotation2 = serializeAnnotation(valueAnnotation, prefix + INDENT),
59
+ vser = _serializeAnnotation2[0],
60
+ vann = _serializeAnnotation2[1];
61
+
62
+ result.push(prefix + INDENT + kser + ': ' + vser + ',');
63
+
64
+ if (vann !== undefined) {
65
+ result.push(indent(vann, valPrefix));
66
+ }
67
+ });
68
+ return ['{'].concat(result, [prefix + '}']).join('\n');
69
+ }
70
+
71
+ export function serializeValue(value) {
72
+ // istanbul ignore else
73
+ if (typeof value === 'string') {
74
+ return serializeString(value);
75
+ } else if (typeof value === 'number' || typeof value === 'boolean') {
76
+ return value.toString();
77
+ } else if (value === null) {
78
+ return 'null';
79
+ } else if (value === undefined) {
80
+ return 'undefined';
81
+ } else {
82
+ var valueAsDate = asDate(value);
83
+
84
+ if (valueAsDate !== null) {
85
+ return "new Date(" + JSON.stringify(valueAsDate.toISOString()) + ")";
86
+ } else if (value instanceof Date) {
87
+ // NOTE: Using `instanceof Date` is unreliable way of checking dates.
88
+ // If this case occurs (and it didn't pass the prior asDate())
89
+ // check, then this must be the case where it's an invalid date.
90
+ return '(Invalid Date)';
91
+ } else {
92
+ return '(unserializable)';
93
+ }
94
+ }
95
+ }
96
+ export function serializeAnnotation(ann, prefix) {
97
+ if (prefix === void 0) {
98
+ prefix = '';
99
+ }
100
+
101
+ // The serialized data (the input object echoed back)
102
+ var serialized;
103
+
104
+ if (ann.type === 'array') {
105
+ serialized = serializeArray(ann, prefix);
106
+ } else if (ann.type === 'object') {
107
+ serialized = serializeObject(ann, prefix);
108
+ } else if (ann.type === 'function') {
109
+ serialized = '<function>';
110
+ } else if (ann.type === 'circular-ref') {
111
+ serialized = '<circular ref>';
112
+ } else if (ann.type === 'unknown') {
113
+ serialized = '???';
114
+ } else {
115
+ serialized = serializeValue(ann.value);
116
+ }
117
+
118
+ var text = ann.text;
119
+
120
+ if (text !== undefined) {
121
+ var sep = '^'.repeat(isMultiline(serialized) ? 1 : serialized.length);
122
+ return [serialized, [sep, text].join(isMultiline(text) ? '\n' : ' ')];
123
+ } else {
124
+ return [serialized, undefined];
125
+ }
126
+ }
127
+ export function formatInline(ann) {
128
+ var _serializeAnnotation3 = serializeAnnotation(ann),
129
+ serialized = _serializeAnnotation3[0],
130
+ annotation = _serializeAnnotation3[1];
131
+
132
+ if (annotation !== undefined) {
133
+ return serialized + '\n' + annotation;
134
+ } else {
135
+ return serialized;
136
+ }
137
+ }
138
+ export function formatShort(ann) {
139
+ return _summarize(ann, []).join('\n');
140
+ }
package/index.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ export { DecodeResult, Decoder, DecoderType, Scalar, define } from './Decoder';
2
+ export { JSONValue, JSONObject, JSONArray } from './lib/json';
3
+
4
+ export {
5
+ always,
6
+ constant,
7
+ hardcoded,
8
+ maybe,
9
+ mixed,
10
+ nullable,
11
+ null_,
12
+ optional,
13
+ undefined_,
14
+ unknown,
15
+ } from './lib/basics';
16
+ export { array, nonEmptyArray, poja, set, tuple } from './lib/arrays';
17
+ export { boolean, numericBoolean, truthy } from './lib/booleans';
18
+ export { date, iso8601 } from './lib/dates';
19
+ export { dict, exact, inexact, mapping, object, pojo } from './lib/objects';
20
+ export { either, oneOf, taggedUnion, dispatch } from './lib/unions';
21
+ export {
22
+ email,
23
+ httpsUrl,
24
+ nonEmptyString,
25
+ regex,
26
+ string,
27
+ url,
28
+ uuid,
29
+ uuidv1,
30
+ uuidv4,
31
+ } from './lib/strings';
32
+ export { fail, instanceOf, lazy, never, prep } from './lib/utilities';
33
+ export {
34
+ anyNumber,
35
+ integer,
36
+ number,
37
+ positiveInteger,
38
+ positiveNumber,
39
+ } from './lib/numbers';
40
+ export { json, jsonObject, jsonArray } from './lib/json';
package/index.js ADDED
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.uuidv4 = exports.uuidv1 = exports.uuid = exports.url = exports.unknown = exports.undefined_ = exports.tuple = exports.truthy = exports.taggedUnion = exports.string = exports.set = exports.regex = exports.prep = exports.positiveNumber = exports.positiveInteger = exports.pojo = exports.poja = exports.optional = exports.oneOf = exports.object = exports.numericBoolean = exports.number = exports.nullable = exports.null_ = exports.nonEmptyString = exports.nonEmptyArray = exports.never = exports.mixed = exports.maybe = exports.mapping = exports.lazy = exports.jsonObject = exports.jsonArray = exports.json = exports.iso8601 = exports.integer = exports.instanceOf = exports.inexact = exports.httpsUrl = exports.hardcoded = exports.fail = exports.exact = exports.email = exports.either = exports.dispatch = exports.dict = exports.define = exports.date = exports.constant = exports["boolean"] = exports.array = exports.anyNumber = exports.always = void 0;
5
+
6
+ var _Decoder = require("./Decoder");
7
+
8
+ exports.define = _Decoder.define;
9
+
10
+ var _basics = require("./lib/basics");
11
+
12
+ exports.always = _basics.always;
13
+ exports.constant = _basics.constant;
14
+ exports.hardcoded = _basics.hardcoded;
15
+ exports.maybe = _basics.maybe;
16
+ exports.mixed = _basics.mixed;
17
+ exports.nullable = _basics.nullable;
18
+ exports.null_ = _basics.null_;
19
+ exports.optional = _basics.optional;
20
+ exports.undefined_ = _basics.undefined_;
21
+ exports.unknown = _basics.unknown;
22
+
23
+ var _arrays = require("./lib/arrays");
24
+
25
+ exports.array = _arrays.array;
26
+ exports.nonEmptyArray = _arrays.nonEmptyArray;
27
+ exports.poja = _arrays.poja;
28
+ exports.set = _arrays.set;
29
+ exports.tuple = _arrays.tuple;
30
+
31
+ var _booleans = require("./lib/booleans");
32
+
33
+ exports["boolean"] = _booleans["boolean"];
34
+ exports.numericBoolean = _booleans.numericBoolean;
35
+ exports.truthy = _booleans.truthy;
36
+
37
+ var _dates = require("./lib/dates");
38
+
39
+ exports.date = _dates.date;
40
+ exports.iso8601 = _dates.iso8601;
41
+
42
+ var _objects = require("./lib/objects");
43
+
44
+ exports.dict = _objects.dict;
45
+ exports.exact = _objects.exact;
46
+ exports.inexact = _objects.inexact;
47
+ exports.mapping = _objects.mapping;
48
+ exports.object = _objects.object;
49
+ exports.pojo = _objects.pojo;
50
+
51
+ var _unions = require("./lib/unions");
52
+
53
+ exports.either = _unions.either;
54
+ exports.oneOf = _unions.oneOf;
55
+ exports.taggedUnion = _unions.taggedUnion;
56
+ exports.dispatch = _unions.dispatch;
57
+
58
+ var _strings = require("./lib/strings");
59
+
60
+ exports.email = _strings.email;
61
+ exports.httpsUrl = _strings.httpsUrl;
62
+ exports.nonEmptyString = _strings.nonEmptyString;
63
+ exports.regex = _strings.regex;
64
+ exports.string = _strings.string;
65
+ exports.url = _strings.url;
66
+ exports.uuid = _strings.uuid;
67
+ exports.uuidv1 = _strings.uuidv1;
68
+ exports.uuidv4 = _strings.uuidv4;
69
+
70
+ var _utilities = require("./lib/utilities");
71
+
72
+ exports.fail = _utilities.fail;
73
+ exports.instanceOf = _utilities.instanceOf;
74
+ exports.lazy = _utilities.lazy;
75
+ exports.never = _utilities.never;
76
+ exports.prep = _utilities.prep;
77
+
78
+ var _numbers = require("./lib/numbers");
79
+
80
+ exports.anyNumber = _numbers.anyNumber;
81
+ exports.integer = _numbers.integer;
82
+ exports.number = _numbers.number;
83
+ exports.positiveInteger = _numbers.positiveInteger;
84
+ exports.positiveNumber = _numbers.positiveNumber;
85
+
86
+ var _json = require("./lib/json");
87
+
88
+ exports.json = _json.json;
89
+ exports.jsonObject = _json.jsonObject;
90
+ exports.jsonArray = _json.jsonArray;
package/index.js.flow ADDED
@@ -0,0 +1,44 @@
1
+ // @flow strict
2
+
3
+ export type { Decoder, DecodeResult, DecoderType, Scalar } from './Decoder';
4
+ export type { JSONValue, JSONObject, JSONArray } from './lib/json';
5
+
6
+ export { define } from './Decoder';
7
+
8
+ export {
9
+ always,
10
+ constant,
11
+ hardcoded,
12
+ maybe,
13
+ mixed,
14
+ nullable,
15
+ null_,
16
+ optional,
17
+ undefined_,
18
+ unknown,
19
+ } from './lib/basics';
20
+ export { array, nonEmptyArray, poja, set, tuple } from './lib/arrays';
21
+ export { boolean, numericBoolean, truthy } from './lib/booleans';
22
+ export { date, iso8601 } from './lib/dates';
23
+ export { dict, exact, inexact, mapping, object, pojo } from './lib/objects';
24
+ export { either, oneOf, taggedUnion, dispatch } from './lib/unions';
25
+ export {
26
+ email,
27
+ httpsUrl,
28
+ nonEmptyString,
29
+ regex,
30
+ string,
31
+ url,
32
+ uuid,
33
+ uuidv1,
34
+ uuidv4,
35
+ } from './lib/strings';
36
+ export { fail, instanceOf, lazy, never, prep } from './lib/utilities';
37
+ export {
38
+ anyNumber,
39
+ integer,
40
+ number,
41
+ positiveInteger,
42
+ positiveNumber,
43
+ } from './lib/numbers';
44
+ export { json, jsonObject, jsonArray } from './lib/json';
package/index.mjs ADDED
@@ -0,0 +1,11 @@
1
+ export { define } from './Decoder.mjs';
2
+ export { always, constant, hardcoded, maybe, mixed, nullable, null_, optional, undefined_, unknown } from './lib/basics.mjs';
3
+ export { array, nonEmptyArray, poja, set, tuple } from './lib/arrays.mjs';
4
+ export { boolean, numericBoolean, truthy } from './lib/booleans.mjs';
5
+ export { date, iso8601 } from './lib/dates.mjs';
6
+ export { dict, exact, inexact, mapping, object, pojo } from './lib/objects.mjs';
7
+ export { either, oneOf, taggedUnion, dispatch } from './lib/unions.mjs';
8
+ export { email, httpsUrl, nonEmptyString, regex, string, url, uuid, uuidv1, uuidv4 } from './lib/strings.mjs';
9
+ export { fail, instanceOf, lazy, never, prep } from './lib/utilities.mjs';
10
+ export { anyNumber, integer, number, positiveInteger, positiveNumber } from './lib/numbers.mjs';
11
+ export { json, jsonObject, jsonArray } from './lib/json.mjs';
File without changes
@@ -0,0 +1,37 @@
1
+ /// <reference lib="es6" />
2
+
3
+ import { Decoder } from '../Decoder';
4
+
5
+ export const poja: Decoder<unknown[]>;
6
+ export function array<T>(decoder: Decoder<T>): Decoder<T[]>;
7
+ export function nonEmptyArray<T>(decoder: Decoder<T>): Decoder<[T, ...T[]]>;
8
+ export function set<T>(decoder: Decoder<T>): Decoder<Set<T>>;
9
+
10
+ export function tuple<A>(a: Decoder<A>): Decoder<[A]>;
11
+ export function tuple<A, B>(a: Decoder<A>, b: Decoder<B>): Decoder<[A, B]>;
12
+ export function tuple<A, B, C>(
13
+ a: Decoder<A>,
14
+ b: Decoder<B>,
15
+ c: Decoder<C>,
16
+ ): Decoder<[A, B, C]>;
17
+ export function tuple<A, B, C, D>(
18
+ a: Decoder<A>,
19
+ b: Decoder<B>,
20
+ c: Decoder<C>,
21
+ d: Decoder<D>,
22
+ ): Decoder<[A, B, C, D]>;
23
+ export function tuple<A, B, C, D, E>(
24
+ a: Decoder<A>,
25
+ b: Decoder<B>,
26
+ c: Decoder<C>,
27
+ d: Decoder<D>,
28
+ e: Decoder<E>,
29
+ ): Decoder<[A, B, C, D, E]>;
30
+ export function tuple<A, B, C, D, E, F>(
31
+ a: Decoder<A>,
32
+ b: Decoder<B>,
33
+ c: Decoder<C>,
34
+ d: Decoder<D>,
35
+ e: Decoder<E>,
36
+ f: Decoder<F>,
37
+ ): Decoder<[A, B, C, D, E, F]>;
package/lib/arrays.js ADDED
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.array = array;
5
+ exports.nonEmptyArray = nonEmptyArray;
6
+ exports.poja = void 0;
7
+ exports.set = set;
8
+ exports.tuple = void 0;
9
+
10
+ var _annotate = require("../annotate");
11
+
12
+ var _Decoder = require("../Decoder");
13
+
14
+ /**
15
+ * Accepts any array, but doesn't validate its items further.
16
+ *
17
+ * "poja" means "plain old JavaScript array", a play on `pojo()`.
18
+ */
19
+ var poja = (0, _Decoder.define)(function (blob, ok, err) {
20
+ if (!Array.isArray(blob)) {
21
+ return err('Must be an array');
22
+ }
23
+
24
+ return ok( // NOTE: Since Flow 0.98, Array.isArray() returns $ReadOnlyArray<mixed>
25
+ // instead of Array<mixed>. For rationale, see
26
+ // https://github.com/facebook/flow/issues/7684. In this case, we
27
+ // don't want to output read-only types because it's up to the user of
28
+ // decoders to determine what they want to do with the decoded output.
29
+ // If they want to write items into the array, that's fine!
30
+ // The fastest way to turn a read-only array into a normal array in
31
+ // Javascript is to use .slice() on it, see this benchmark:
32
+ // http://jsben.ch/lO6C5
33
+ blob.slice());
34
+ });
35
+ /**
36
+ * Given an array of Result instances, loop over them all and return:
37
+ * - An [index, err] tuple, indicating the (index of the) first Err instance
38
+ * encountered; or
39
+ * - a new Ok with an array of all unwrapped Ok'ed values
40
+ */
41
+
42
+ exports.poja = poja;
43
+
44
+ function all(items, blobs, // TODO: Make this less ugly
45
+ ok, err) {
46
+ var results = [];
47
+
48
+ for (var index = 0; index < items.length; ++index) {
49
+ var result = items[index];
50
+
51
+ if (result.ok) {
52
+ results.push(result.value);
53
+ } else {
54
+ var ann = result.error; // Rewrite the annotation to include the index information, and inject it into the original blob
55
+
56
+ var clone = [].concat(blobs);
57
+ clone.splice(index, 1, (0, _annotate.annotate)(ann, ann.text ? ann.text + " (at index " + index + ")" : "index " + index));
58
+ return err((0, _annotate.annotate)(clone));
59
+ }
60
+ }
61
+
62
+ return ok(results);
63
+ }
64
+ /**
65
+ * Accepts arrays of whatever the given decoder accepts.
66
+ */
67
+
68
+
69
+ function array(decoder) {
70
+ return poja.then(function (blobs, ok, err) {
71
+ var results = blobs.map(decoder.decode);
72
+ return all(results, blobs, ok, err);
73
+ });
74
+ }
75
+ /**
76
+ * Like `array()`, but will reject arrays with 0 elements.
77
+ */
78
+
79
+
80
+ function nonEmptyArray(decoder) {
81
+ return array(decoder).refine(function (arr) {
82
+ return arr.length > 0;
83
+ }, 'Must be non-empty array');
84
+ }
85
+ /**
86
+ * Similar to `array()`, but returns the result as an [ES6
87
+ * Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set).
88
+ */
89
+
90
+
91
+ function set(decoder) {
92
+ return array(decoder).transform(function (items) {
93
+ return new Set(items);
94
+ });
95
+ }
96
+
97
+ var ntuple = function ntuple(n) {
98
+ return poja.refine(function (arr) {
99
+ return arr.length === n;
100
+ }, "Must be a " + n + "-tuple");
101
+ }; // prettier-ignore
102
+
103
+
104
+ /**
105
+ * Accepts a tuple (an array with exactly _n_ items) of values accepted by the
106
+ * _n_ given decoders.
107
+ */
108
+ function _tuple() {
109
+ for (var _len = arguments.length, decoders = new Array(_len), _key = 0; _key < _len; _key++) {
110
+ decoders[_key] = arguments[_key];
111
+ }
112
+
113
+ return ntuple(decoders.length).then(function (blobs, ok, err) {
114
+ var allOk = true;
115
+ var rvs = decoders.map(function (decoder, i) {
116
+ var blob = blobs[i];
117
+ var result = decoder.decode(blob);
118
+
119
+ if (result.ok) {
120
+ return result.value;
121
+ } else {
122
+ allOk = false;
123
+ return result.error;
124
+ }
125
+ });
126
+
127
+ if (allOk) {
128
+ return ok(rvs);
129
+ } else {
130
+ // If a decoder error has happened while unwrapping all the
131
+ // results, try to construct a good error message
132
+ return err((0, _annotate.annotate)(rvs));
133
+ }
134
+ });
135
+ }
136
+
137
+ var tuple = _tuple;
138
+ exports.tuple = tuple;
@@ -0,0 +1,138 @@
1
+ // @flow strict
2
+
3
+ import { annotate } from '../annotate';
4
+ import { define } from '../Decoder';
5
+ import type { _Any } from '../_utils';
6
+ import type { Annotation } from '../annotate';
7
+ import type { Decoder, DecodeResult } from '../Decoder';
8
+
9
+ /**
10
+ * Accepts any array, but doesn't validate its items further.
11
+ *
12
+ * "poja" means "plain old JavaScript array", a play on `pojo()`.
13
+ */
14
+ export const poja: Decoder<Array<mixed>> = define((blob, ok, err) => {
15
+ if (!Array.isArray(blob)) {
16
+ return err('Must be an array');
17
+ }
18
+ return ok(
19
+ // NOTE: Since Flow 0.98, Array.isArray() returns $ReadOnlyArray<mixed>
20
+ // instead of Array<mixed>. For rationale, see
21
+ // https://github.com/facebook/flow/issues/7684. In this case, we
22
+ // don't want to output read-only types because it's up to the user of
23
+ // decoders to determine what they want to do with the decoded output.
24
+ // If they want to write items into the array, that's fine!
25
+ // The fastest way to turn a read-only array into a normal array in
26
+ // Javascript is to use .slice() on it, see this benchmark:
27
+ // http://jsben.ch/lO6C5
28
+ blob.slice(),
29
+ );
30
+ });
31
+
32
+ /**
33
+ * Given an array of Result instances, loop over them all and return:
34
+ * - An [index, err] tuple, indicating the (index of the) first Err instance
35
+ * encountered; or
36
+ * - a new Ok with an array of all unwrapped Ok'ed values
37
+ */
38
+ function all<T>(
39
+ items: $ReadOnlyArray<DecodeResult<T>>,
40
+ blobs: $ReadOnlyArray<mixed>,
41
+
42
+ // TODO: Make this less ugly
43
+ ok: (Array<T>) => DecodeResult<Array<T>>,
44
+ err: (Annotation) => DecodeResult<Array<T>>,
45
+ ): DecodeResult<Array<T>> {
46
+ const results: Array<T> = [];
47
+ for (let index = 0; index < items.length; ++index) {
48
+ const result = items[index];
49
+ if (result.ok) {
50
+ results.push(result.value);
51
+ } else {
52
+ const ann = result.error;
53
+
54
+ // Rewrite the annotation to include the index information, and inject it into the original blob
55
+ const clone = [...blobs];
56
+ clone.splice(
57
+ index,
58
+ 1,
59
+ annotate(
60
+ ann,
61
+ ann.text ? `${ann.text} (at index ${index})` : `index ${index}`,
62
+ ),
63
+ );
64
+
65
+ return err(annotate(clone));
66
+ }
67
+ }
68
+ return ok(results);
69
+ }
70
+
71
+ /**
72
+ * Accepts arrays of whatever the given decoder accepts.
73
+ */
74
+ export function array<T>(decoder: Decoder<T>): Decoder<Array<T>> {
75
+ return poja.then((blobs: $ReadOnlyArray<mixed>, ok, err) => {
76
+ const results = blobs.map(decoder.decode);
77
+ return all(results, blobs, ok, err);
78
+ });
79
+ }
80
+
81
+ /**
82
+ * Like `array()`, but will reject arrays with 0 elements.
83
+ */
84
+ export function nonEmptyArray<T>(decoder: Decoder<T>): Decoder<Array<T>> {
85
+ return array(decoder).refine((arr) => arr.length > 0, 'Must be non-empty array');
86
+ }
87
+
88
+ /**
89
+ * Similar to `array()`, but returns the result as an [ES6
90
+ * Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set).
91
+ */
92
+ export function set<T>(decoder: Decoder<T>): Decoder<Set<T>> {
93
+ return array(decoder).transform((items) => new Set(items));
94
+ }
95
+
96
+ const ntuple = (n: number) =>
97
+ poja.refine((arr) => arr.length === n, `Must be a ${n}-tuple`);
98
+
99
+ // prettier-ignore
100
+ interface TupleFuncSignature {
101
+ <A>(a: Decoder<A>): Decoder<[A]>;
102
+ <A, B>(a: Decoder<A>, b: Decoder<B>): Decoder<[A, B]>;
103
+ <A, B, C>(a: Decoder<A>, b: Decoder<B>, c: Decoder<C>): Decoder<[A, B, C]>;
104
+ <A, B, C, D>(a: Decoder<A>, b: Decoder<B>, c: Decoder<C>, d: Decoder<D>): Decoder<[A, B, C, D]>;
105
+ <A, B, C, D, E>(a: Decoder<A>, b: Decoder<B>, c: Decoder<C>, d: Decoder<D>, e: Decoder<E>): Decoder<[A, B, C, D, E]>;
106
+ <A, B, C, D, E, F>(a: Decoder<A>, b: Decoder<B>, c: Decoder<C>, d: Decoder<D>, e: Decoder<E>, f: Decoder<F>): Decoder<[A, B, C, D, E, F]>;
107
+ }
108
+
109
+ /**
110
+ * Accepts a tuple (an array with exactly _n_ items) of values accepted by the
111
+ * _n_ given decoders.
112
+ */
113
+ function _tuple(...decoders: $ReadOnlyArray<Decoder<mixed>>): Decoder<Array<mixed>> {
114
+ return ntuple(decoders.length).then((blobs, ok, err) => {
115
+ let allOk = true;
116
+
117
+ const rvs = decoders.map((decoder, i) => {
118
+ const blob = blobs[i];
119
+ const result = decoder.decode(blob);
120
+ if (result.ok) {
121
+ return result.value;
122
+ } else {
123
+ allOk = false;
124
+ return result.error;
125
+ }
126
+ });
127
+
128
+ if (allOk) {
129
+ return ok(rvs);
130
+ } else {
131
+ // If a decoder error has happened while unwrapping all the
132
+ // results, try to construct a good error message
133
+ return err(annotate(rvs));
134
+ }
135
+ });
136
+ }
137
+
138
+ export const tuple: TupleFuncSignature = (_tuple: _Any);