decoders 2.0.0-beta1 → 2.0.0-beta13

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 (165) hide show
  1. package/CHANGELOG.md +53 -5
  2. package/Decoder.d.ts +94 -0
  3. package/Decoder.js +222 -0
  4. package/Decoder.js.flow +286 -0
  5. package/Decoder.mjs +215 -0
  6. package/NotSupportedTSVersion.d.ts +1 -0
  7. package/README.md +124 -961
  8. package/_utils.d.ts +9 -0
  9. package/{cjs/_utils.js → _utils.js} +12 -18
  10. package/{cjs/_utils.js.flow → _utils.js.flow} +15 -19
  11. package/{es/_utils.js → _utils.mjs} +11 -15
  12. package/{ts/annotate.d.ts → annotate.d.ts} +25 -21
  13. package/{cjs/annotate.js → annotate.js} +0 -0
  14. package/{cjs/annotate.js.flow → annotate.js.flow} +0 -0
  15. package/{es/annotate.js → annotate.mjs} +0 -0
  16. package/format.d.ts +6 -0
  17. package/{cjs/format/inline.js → format.js} +7 -2
  18. package/{cjs/format/inline.js.flow → format.js.flow} +9 -3
  19. package/{es/format/inline.js → format.mjs} +5 -2
  20. package/index.d.ts +40 -0
  21. package/index.js +89 -0
  22. package/index.js.flow +44 -0
  23. package/index.mjs +11 -0
  24. package/{ts → lib}/_helpers.d.ts +0 -0
  25. package/lib/arrays.d.ts +59 -0
  26. package/lib/arrays.js +139 -0
  27. package/lib/arrays.js.flow +138 -0
  28. package/lib/arrays.mjs +124 -0
  29. package/lib/basics.d.ts +93 -0
  30. package/lib/basics.js +144 -0
  31. package/lib/basics.js.flow +124 -0
  32. package/lib/basics.mjs +120 -0
  33. package/lib/booleans.d.ts +16 -0
  34. package/lib/booleans.js +35 -0
  35. package/lib/booleans.js.flow +22 -0
  36. package/lib/booleans.mjs +25 -0
  37. package/lib/dates.d.ts +15 -0
  38. package/lib/dates.js +44 -0
  39. package/lib/dates.js.flow +40 -0
  40. package/lib/dates.mjs +34 -0
  41. package/lib/json.d.ts +35 -0
  42. package/lib/json.js +55 -0
  43. package/lib/json.js.flow +50 -0
  44. package/lib/json.mjs +40 -0
  45. package/lib/numbers.d.ts +31 -0
  46. package/lib/numbers.js +51 -0
  47. package/lib/numbers.js.flow +48 -0
  48. package/lib/numbers.mjs +41 -0
  49. package/lib/objects.d.ts +75 -0
  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 +56 -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 +55 -0
  58. package/lib/unions.js +160 -0
  59. package/lib/unions.js.flow +155 -0
  60. package/lib/unions.mjs +146 -0
  61. package/lib/utilities.d.ts +34 -0
  62. package/lib/utilities.js +75 -0
  63. package/lib/utilities.js.flow +65 -0
  64. package/lib/utilities.mjs +60 -0
  65. package/package.json +79 -29
  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/_guard.js +0 -26
  71. package/cjs/_guard.js.flow +0 -20
  72. package/cjs/_types.js +0 -1
  73. package/cjs/_types.js.flow +0 -20
  74. package/cjs/format/index.js +0 -12
  75. package/cjs/format/index.js.flow +0 -4
  76. package/cjs/format/short.js +0 -10
  77. package/cjs/format/short.js.flow +0 -8
  78. package/cjs/index.js +0 -120
  79. package/cjs/index.js.flow +0 -63
  80. package/cjs/result.js +0 -172
  81. package/cjs/result.js.flow +0 -166
  82. package/cjs/stdlib/array.js +0 -108
  83. package/cjs/stdlib/array.js.flow +0 -103
  84. package/cjs/stdlib/boolean.js +0 -44
  85. package/cjs/stdlib/boolean.js.flow +0 -29
  86. package/cjs/stdlib/composition.js +0 -56
  87. package/cjs/stdlib/composition.js.flow +0 -43
  88. package/cjs/stdlib/constants.js +0 -69
  89. package/cjs/stdlib/constants.js.flow +0 -46
  90. package/cjs/stdlib/date.js +0 -46
  91. package/cjs/stdlib/date.js.flow +0 -40
  92. package/cjs/stdlib/describe.js +0 -26
  93. package/cjs/stdlib/describe.js.flow +0 -17
  94. package/cjs/stdlib/dispatch.js +0 -62
  95. package/cjs/stdlib/dispatch.js.flow +0 -58
  96. package/cjs/stdlib/either.js +0 -117
  97. package/cjs/stdlib/either.js.flow +0 -151
  98. package/cjs/stdlib/fail.js +0 -21
  99. package/cjs/stdlib/fail.js.flow +0 -12
  100. package/cjs/stdlib/instanceOf.js +0 -19
  101. package/cjs/stdlib/instanceOf.js.flow +0 -20
  102. package/cjs/stdlib/json.js +0 -31
  103. package/cjs/stdlib/json.js.flow +0 -28
  104. package/cjs/stdlib/lazy.js +0 -16
  105. package/cjs/stdlib/lazy.js.flow +0 -15
  106. package/cjs/stdlib/mapping.js +0 -67
  107. package/cjs/stdlib/mapping.js.flow +0 -54
  108. package/cjs/stdlib/number.js +0 -40
  109. package/cjs/stdlib/number.js.flow +0 -34
  110. package/cjs/stdlib/object.js +0 -194
  111. package/cjs/stdlib/object.js.flow +0 -203
  112. package/cjs/stdlib/optional.js +0 -54
  113. package/cjs/stdlib/optional.js.flow +0 -41
  114. package/cjs/stdlib/string.js +0 -98
  115. package/cjs/stdlib/string.js.flow +0 -82
  116. package/cjs/stdlib/tuple.js +0 -173
  117. package/cjs/stdlib/tuple.js.flow +0 -220
  118. package/es/_guard.js +0 -15
  119. package/es/_types.js +0 -0
  120. package/es/format/index.js +0 -2
  121. package/es/format/short.js +0 -4
  122. package/es/index.js +0 -37
  123. package/es/result.js +0 -139
  124. package/es/stdlib/array.js +0 -91
  125. package/es/stdlib/boolean.js +0 -28
  126. package/es/stdlib/composition.js +0 -42
  127. package/es/stdlib/constants.js +0 -46
  128. package/es/stdlib/date.js +0 -28
  129. package/es/stdlib/describe.js +0 -16
  130. package/es/stdlib/dispatch.js +0 -51
  131. package/es/stdlib/either.js +0 -90
  132. package/es/stdlib/fail.js +0 -11
  133. package/es/stdlib/instanceOf.js +0 -8
  134. package/es/stdlib/json.js +0 -15
  135. package/es/stdlib/lazy.js +0 -11
  136. package/es/stdlib/mapping.js +0 -54
  137. package/es/stdlib/number.js +0 -25
  138. package/es/stdlib/object.js +0 -175
  139. package/es/stdlib/optional.js +0 -38
  140. package/es/stdlib/string.js +0 -76
  141. package/es/stdlib/tuple.js +0 -155
  142. package/ts/_guard.d.ts +0 -7
  143. package/ts/_types.d.ts +0 -16
  144. package/ts/_utils.d.ts +0 -13
  145. package/ts/array.d.ts +0 -5
  146. package/ts/boolean.d.ts +0 -5
  147. package/ts/constants.d.ts +0 -11
  148. package/ts/date.d.ts +0 -4
  149. package/ts/describe.d.ts +0 -3
  150. package/ts/dispatch.d.ts +0 -8
  151. package/ts/either.d.ts +0 -61
  152. package/ts/fail.d.ts +0 -3
  153. package/ts/index.d.ts +0 -42
  154. package/ts/inline.d.ts +0 -3
  155. package/ts/instanceOf.d.ts +0 -3
  156. package/ts/json.d.ts +0 -11
  157. package/ts/lazy.d.ts +0 -3
  158. package/ts/mapping.d.ts +0 -4
  159. package/ts/number.d.ts +0 -6
  160. package/ts/object.d.ts +0 -33
  161. package/ts/optional.d.ts +0 -5
  162. package/ts/result.d.ts +0 -39
  163. package/ts/short.d.ts +0 -3
  164. package/ts/string.d.ts +0 -7
  165. package/ts/tuple.d.ts +0 -30
@@ -0,0 +1,124 @@
1
+ // @flow strict
2
+
3
+ import { define } from '../Decoder';
4
+ import { either } from './unions';
5
+ import type { _Any } from '../_utils';
6
+ import type { Decoder, Scalar } from '../Decoder';
7
+
8
+ /**
9
+ * Accepts and returns only the literal `null` value.
10
+ */
11
+ export const null_: Decoder<null> = define((blob, ok, err) =>
12
+ blob === null ? ok(blob) : err('Must be null'),
13
+ );
14
+
15
+ /**
16
+ * Accepts and returns only the literal `undefined` value.
17
+ */
18
+ export const undefined_: Decoder<void> = define((blob, ok, err) =>
19
+ blob === undefined ? ok(blob) : err('Must be undefined'),
20
+ );
21
+
22
+ const undefined_or_null: Decoder<null | void> = define((blob, ok, err) =>
23
+ blob === undefined || blob === null
24
+ ? ok(blob)
25
+ : // Combine error message into a single line for readability
26
+ err('Must be undefined or null'),
27
+ );
28
+
29
+ interface Maybeish<E> {
30
+ <T>(decoder: Decoder<T>): Decoder<E | T>;
31
+ <T, V>(
32
+ decoder: Decoder<T>,
33
+ defaultValue: (() => V) | V,
34
+ ): Decoder<$NonMaybeType<T> | V>;
35
+ }
36
+
37
+ function _maybeish<E>(emptyCase: Decoder<E>): Maybeish<E> {
38
+ function _inner(decoder /* defaultValue */) {
39
+ const rv = either(emptyCase, decoder);
40
+ if (
41
+ // If a default value is provided...
42
+ arguments.length >= 2
43
+ ) {
44
+ // ...then return the default value
45
+ const _defaultValue = arguments[1];
46
+ const defaultValue =
47
+ typeof _defaultValue === 'function' ? _defaultValue() : _defaultValue;
48
+ return rv.transform((value) => value ?? defaultValue);
49
+ } else {
50
+ // Otherwise the "normal" empty case
51
+ return rv;
52
+ }
53
+ }
54
+
55
+ return (_inner: _Any);
56
+ }
57
+
58
+ /**
59
+ * Accepts whatever the given decoder accepts, or `null`.
60
+ *
61
+ * If a default value is explicitly provided, return that instead in the `null`
62
+ * case.
63
+ */
64
+ export const nullable: Maybeish<null> = _maybeish(null_);
65
+
66
+ /**
67
+ * Accepts whatever the given decoder accepts, or `undefined`.
68
+ *
69
+ * If a default value is explicitly provided, return that instead in the
70
+ * `undefined` case.
71
+ */
72
+ export const optional: Maybeish<void> = _maybeish(undefined_);
73
+
74
+ /**
75
+ * Accepts whatever the given decoder accepts, or `null`, or `undefined`.
76
+ *
77
+ * If a default value is explicitly provided, return that instead in the
78
+ * `null`/`undefined` case.
79
+ */
80
+ export const maybe: Maybeish<null | void> = _maybeish(undefined_or_null);
81
+
82
+ /**
83
+ * Accepts only the given constant value.
84
+ */
85
+ export function constant<T: Scalar>(value: T): Decoder<T> {
86
+ return define((blob, ok, err) =>
87
+ blob === value ? ok(value) : err(`Must be constant ${String(value)}`),
88
+ );
89
+ }
90
+
91
+ /**
92
+ * Accepts anything, completely ignores it, and always returns the provided
93
+ * value instead.
94
+ *
95
+ * This is useful to manually add extra fields to object decoders.
96
+ */
97
+ export function always<T>(value: (() => T) | T): Decoder<T> {
98
+ return define(
99
+ typeof value === 'function'
100
+ ? (blob /* ignored */, ok, _) =>
101
+ // $FlowFixMe[incompatible-use]
102
+ ok(value())
103
+ : (blob /* ignored */, ok, _) => ok(value),
104
+ );
105
+ }
106
+
107
+ /**
108
+ * Alias of always.
109
+ */
110
+ export const hardcoded: <T>(T) => Decoder<T> = always;
111
+
112
+ /**
113
+ * Accepts anything and returns it unchanged.
114
+ *
115
+ * Useful for situation in which you don't know or expect a specific type. Of
116
+ * course, the downside is that you won't know the type of the value statically
117
+ * and you'll have to further refine it yourself.
118
+ */
119
+ export const unknown: Decoder<mixed> = define((blob, ok, _) => ok(blob));
120
+
121
+ /**
122
+ * Alias of unknown.
123
+ */
124
+ export const mixed: Decoder<mixed> = unknown;
package/lib/basics.mjs ADDED
@@ -0,0 +1,120 @@
1
+ import { define } from '../Decoder.mjs';
2
+ import { either } from './unions.mjs';
3
+
4
+ /**
5
+ * Accepts and returns only the literal `null` value.
6
+ */
7
+ export var null_ = define(function (blob, ok, err) {
8
+ return blob === null ? ok(blob) : err('Must be null');
9
+ });
10
+ /**
11
+ * Accepts and returns only the literal `undefined` value.
12
+ */
13
+
14
+ export var undefined_ = define(function (blob, ok, err) {
15
+ return blob === undefined ? ok(blob) : err('Must be undefined');
16
+ });
17
+ var undefined_or_null = define(function (blob, ok, err) {
18
+ return blob === undefined || blob === null ? ok(blob) : // Combine error message into a single line for readability
19
+ err('Must be undefined or null');
20
+ });
21
+
22
+ function _maybeish(emptyCase) {
23
+ function _inner(decoder
24
+ /* defaultValue */
25
+ ) {
26
+ var rv = either(emptyCase, decoder);
27
+
28
+ if ( // If a default value is provided...
29
+ arguments.length >= 2) {
30
+ // ...then return the default value
31
+ var _defaultValue = arguments[1];
32
+
33
+ var _defaultValue2 = typeof _defaultValue === 'function' ? _defaultValue() : _defaultValue;
34
+
35
+ return rv.transform(function (value) {
36
+ return value != null ? value : _defaultValue2;
37
+ });
38
+ } else {
39
+ // Otherwise the "normal" empty case
40
+ return rv;
41
+ }
42
+ }
43
+
44
+ return _inner;
45
+ }
46
+ /**
47
+ * Accepts whatever the given decoder accepts, or `null`.
48
+ *
49
+ * If a default value is explicitly provided, return that instead in the `null`
50
+ * case.
51
+ */
52
+
53
+
54
+ export var nullable = _maybeish(null_);
55
+ /**
56
+ * Accepts whatever the given decoder accepts, or `undefined`.
57
+ *
58
+ * If a default value is explicitly provided, return that instead in the
59
+ * `undefined` case.
60
+ */
61
+
62
+ export var optional = _maybeish(undefined_);
63
+ /**
64
+ * Accepts whatever the given decoder accepts, or `null`, or `undefined`.
65
+ *
66
+ * If a default value is explicitly provided, return that instead in the
67
+ * `null`/`undefined` case.
68
+ */
69
+
70
+ export var maybe = _maybeish(undefined_or_null);
71
+ /**
72
+ * Accepts only the given constant value.
73
+ */
74
+
75
+ export function constant(value) {
76
+ return define(function (blob, ok, err) {
77
+ return blob === value ? ok(value) : err("Must be constant " + String(value));
78
+ });
79
+ }
80
+ /**
81
+ * Accepts anything, completely ignores it, and always returns the provided
82
+ * value instead.
83
+ *
84
+ * This is useful to manually add extra fields to object decoders.
85
+ */
86
+
87
+ export function always(value) {
88
+ return define(typeof value === 'function' ? function (blob
89
+ /* ignored */
90
+ , ok, _) {
91
+ return (// $FlowFixMe[incompatible-use]
92
+ ok(value())
93
+ );
94
+ } : function (blob
95
+ /* ignored */
96
+ , ok, _) {
97
+ return ok(value);
98
+ });
99
+ }
100
+ /**
101
+ * Alias of always.
102
+ */
103
+
104
+ export var hardcoded = always;
105
+ /**
106
+ * Accepts anything and returns it unchanged.
107
+ *
108
+ * Useful for situation in which you don't know or expect a specific type. Of
109
+ * course, the downside is that you won't know the type of the value statically
110
+ * and you'll have to further refine it yourself.
111
+ */
112
+
113
+ export var unknown = define(function (blob, ok, _) {
114
+ return ok(blob);
115
+ });
116
+ /**
117
+ * Alias of unknown.
118
+ */
119
+
120
+ export var mixed = unknown;
@@ -0,0 +1,16 @@
1
+ import { Decoder } from '../Decoder';
2
+
3
+ /**
4
+ * Accepts and returns booleans.
5
+ */
6
+ export const boolean: Decoder<boolean>;
7
+
8
+ /**
9
+ * Accepts anything and will return its "truth" value. Will never reject.
10
+ */
11
+ export const truthy: Decoder<boolean>;
12
+
13
+ /**
14
+ * Accepts numbers, but return their boolean representation.
15
+ */
16
+ export const numericBoolean: Decoder<boolean>;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.truthy = exports.numericBoolean = exports["boolean"] = void 0;
5
+
6
+ var _Decoder = require("../Decoder");
7
+
8
+ var _numbers = require("./numbers");
9
+
10
+ /**
11
+ * Accepts and returns booleans.
12
+ */
13
+ var _boolean = (0, _Decoder.define)(function (blob, ok, err) {
14
+ return typeof blob === 'boolean' ? ok(blob) : err('Must be boolean');
15
+ });
16
+ /**
17
+ * Accepts anything and will return its "truth" value. Will never reject.
18
+ */
19
+
20
+
21
+ exports["boolean"] = _boolean;
22
+ var truthy = (0, _Decoder.define)(function (blob, ok, _) {
23
+ return ok(!!blob);
24
+ });
25
+ /**
26
+ * Accepts numbers, but return their boolean representation.
27
+ */
28
+
29
+ exports.truthy = truthy;
30
+
31
+ var numericBoolean = _numbers.number.transform(function (n) {
32
+ return !!n;
33
+ });
34
+
35
+ exports.numericBoolean = numericBoolean;
@@ -0,0 +1,22 @@
1
+ // @flow strict
2
+
3
+ import { define } from '../Decoder';
4
+ import { number } from './numbers';
5
+ import type { Decoder } from '../Decoder';
6
+
7
+ /**
8
+ * Accepts and returns booleans.
9
+ */
10
+ export const boolean: Decoder<boolean> = define((blob, ok, err) => {
11
+ return typeof blob === 'boolean' ? ok(blob) : err('Must be boolean');
12
+ });
13
+
14
+ /**
15
+ * Accepts anything and will return its "truth" value. Will never reject.
16
+ */
17
+ export const truthy: Decoder<boolean> = define((blob, ok, _) => ok(!!blob));
18
+
19
+ /**
20
+ * Accepts numbers, but return their boolean representation.
21
+ */
22
+ export const numericBoolean: Decoder<boolean> = number.transform((n) => !!n);
@@ -0,0 +1,25 @@
1
+ import { define } from '../Decoder.mjs';
2
+ import { number } from './numbers.mjs';
3
+
4
+ /**
5
+ * Accepts and returns booleans.
6
+ */
7
+ var _boolean = define(function (blob, ok, err) {
8
+ return typeof blob === 'boolean' ? ok(blob) : err('Must be boolean');
9
+ });
10
+ /**
11
+ * Accepts anything and will return its "truth" value. Will never reject.
12
+ */
13
+
14
+
15
+ export { _boolean as boolean };
16
+ export var truthy = define(function (blob, ok, _) {
17
+ return ok(!!blob);
18
+ });
19
+ /**
20
+ * Accepts numbers, but return their boolean representation.
21
+ */
22
+
23
+ export var numericBoolean = number.transform(function (n) {
24
+ return !!n;
25
+ });
package/lib/dates.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { Decoder } from '../Decoder';
2
+
3
+ /**
4
+ * Accepts and returns `Date` instances.
5
+ */
6
+ export const date: Decoder<Date>;
7
+
8
+ /**
9
+ * Accepts [ISO8601](https://en.wikipedia.org/wiki/ISO_8601)-formatted strings,
10
+ * returns them as `Date` instances.
11
+ *
12
+ * This is very useful for working with dates in APIs: serialize them as
13
+ * `.toISOString()` when sending, decode them with `iso8601` when receiving.
14
+ */
15
+ export const iso8601: Decoder<Date>;
package/lib/dates.js ADDED
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.iso8601 = exports.date = void 0;
5
+
6
+ var _utils = require("../_utils");
7
+
8
+ var _Decoder = require("../Decoder");
9
+
10
+ var _strings = require("./strings");
11
+
12
+ // Only matches the shape. This "over-matches" some values that still aren't
13
+ // valid dates (like 9999-99-99), but those will be caught by JS Date's
14
+ // internal validations
15
+ var iso8601_re = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:[.]\d+)?(?:Z|[+-]\d{2}:?\d{2})$/;
16
+ /**
17
+ * Accepts and returns `Date` instances.
18
+ */
19
+
20
+ var date = (0, _Decoder.define)(function (blob, ok, err) {
21
+ var date = (0, _utils.asDate)(blob);
22
+ return date !== null ? ok(date) : err('Must be a Date');
23
+ });
24
+ /**
25
+ * Accepts [ISO8601](https://en.wikipedia.org/wiki/ISO_8601)-formatted strings,
26
+ * returns them as `Date` instances.
27
+ *
28
+ * This is very useful for working with dates in APIs: serialize them as
29
+ * `.toISOString()` when sending, decode them with `iso8601` when receiving.
30
+ */
31
+
32
+ exports.date = date;
33
+ var iso8601 = // Input itself needs to match the ISO8601 regex...
34
+ (0, _strings.regex)(iso8601_re, 'Must be ISO8601 format').transform( // Make sure it is a _valid_ date
35
+ function (value) {
36
+ var date = new Date(value);
37
+
38
+ if (isNaN(date.getTime())) {
39
+ throw new Error('Must be valid date/time value');
40
+ }
41
+
42
+ return date;
43
+ });
44
+ exports.iso8601 = iso8601;
@@ -0,0 +1,40 @@
1
+ // @flow strict
2
+
3
+ import { asDate } from '../_utils';
4
+ import { define } from '../Decoder';
5
+ import { regex } from './strings';
6
+ import type { Decoder } from '../Decoder';
7
+
8
+ // Only matches the shape. This "over-matches" some values that still aren't
9
+ // valid dates (like 9999-99-99), but those will be caught by JS Date's
10
+ // internal validations
11
+ const iso8601_re =
12
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:[.]\d+)?(?:Z|[+-]\d{2}:?\d{2})$/;
13
+
14
+ /**
15
+ * Accepts and returns `Date` instances.
16
+ */
17
+ export const date: Decoder<Date> = define((blob, ok, err) => {
18
+ const date = asDate(blob);
19
+ return date !== null ? ok(date) : err('Must be a Date');
20
+ });
21
+
22
+ /**
23
+ * Accepts [ISO8601](https://en.wikipedia.org/wiki/ISO_8601)-formatted strings,
24
+ * returns them as `Date` instances.
25
+ *
26
+ * This is very useful for working with dates in APIs: serialize them as
27
+ * `.toISOString()` when sending, decode them with `iso8601` when receiving.
28
+ */
29
+ export const iso8601: Decoder<Date> =
30
+ // Input itself needs to match the ISO8601 regex...
31
+ regex(iso8601_re, 'Must be ISO8601 format').transform(
32
+ // Make sure it is a _valid_ date
33
+ (value: string) => {
34
+ const date = new Date(value);
35
+ if (isNaN(date.getTime())) {
36
+ throw new Error('Must be valid date/time value');
37
+ }
38
+ return date;
39
+ },
40
+ );
package/lib/dates.mjs ADDED
@@ -0,0 +1,34 @@
1
+ import { asDate } from '../_utils.mjs';
2
+ import { define } from '../Decoder.mjs';
3
+ import { regex } from './strings.mjs';
4
+ // Only matches the shape. This "over-matches" some values that still aren't
5
+ // valid dates (like 9999-99-99), but those will be caught by JS Date's
6
+ // internal validations
7
+ var iso8601_re = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:[.]\d+)?(?:Z|[+-]\d{2}:?\d{2})$/;
8
+ /**
9
+ * Accepts and returns `Date` instances.
10
+ */
11
+
12
+ export var date = define(function (blob, ok, err) {
13
+ var date = asDate(blob);
14
+ return date !== null ? ok(date) : err('Must be a Date');
15
+ });
16
+ /**
17
+ * Accepts [ISO8601](https://en.wikipedia.org/wiki/ISO_8601)-formatted strings,
18
+ * returns them as `Date` instances.
19
+ *
20
+ * This is very useful for working with dates in APIs: serialize them as
21
+ * `.toISOString()` when sending, decode them with `iso8601` when receiving.
22
+ */
23
+
24
+ export var iso8601 = // Input itself needs to match the ISO8601 regex...
25
+ regex(iso8601_re, 'Must be ISO8601 format').transform( // Make sure it is a _valid_ date
26
+ function (value) {
27
+ var date = new Date(value);
28
+
29
+ if (isNaN(date.getTime())) {
30
+ throw new Error('Must be valid date/time value');
31
+ }
32
+
33
+ return date;
34
+ });
package/lib/json.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ import { Decoder } from '../Decoder';
2
+
3
+ export type JSONValue = null | string | number | boolean | JSONObject | JSONArray;
4
+ export interface JSONObject {
5
+ [key: string]: JSONValue;
6
+ }
7
+ export type JSONArray = JSONValue[];
8
+
9
+ /**
10
+ * Accepts any value that's a valid JSON value.
11
+ *
12
+ * In other words: any value returned by `JSON.parse()` should decode without
13
+ * failure.
14
+ *
15
+ * ```typescript
16
+ * type JSONValue =
17
+ * | null
18
+ * | string
19
+ * | number
20
+ * | boolean
21
+ * | { [string]: JSONValue }
22
+ * | JSONValue[]
23
+ * ```
24
+ */
25
+ export const json: Decoder<JSONValue>;
26
+
27
+ /**
28
+ * Like `json`, but will only decode when the JSON value is an array.
29
+ */
30
+ export const jsonArray: Decoder<JSONArray>;
31
+
32
+ /**
33
+ * Like `json`, but will only decode when the JSON value is an object.
34
+ */
35
+ export const jsonObject: Decoder<JSONObject>;
package/lib/json.js ADDED
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.jsonObject = exports.jsonArray = exports.json = void 0;
5
+
6
+ var _arrays = require("./arrays");
7
+
8
+ var _booleans = require("./booleans");
9
+
10
+ var _objects = require("./objects");
11
+
12
+ var _unions = require("./unions");
13
+
14
+ var _utilities = require("./utilities");
15
+
16
+ var _basics = require("./basics");
17
+
18
+ var _numbers = require("./numbers");
19
+
20
+ var _strings = require("./strings");
21
+
22
+ /**
23
+ * Like `json`, but will only decode when the JSON value is an object.
24
+ */
25
+ var jsonObject = (0, _utilities.lazy)(function () {
26
+ return (0, _objects.dict)(json);
27
+ });
28
+ /**
29
+ * Like `json`, but will only decode when the JSON value is an array.
30
+ */
31
+
32
+ exports.jsonObject = jsonObject;
33
+ var jsonArray = (0, _utilities.lazy)(function () {
34
+ return (0, _arrays.array)(json);
35
+ });
36
+ /**
37
+ * Accepts any value that's a valid JSON value.
38
+ *
39
+ * In other words: any value returned by `JSON.parse()` should decode without
40
+ * failure.
41
+ *
42
+ * ```typescript
43
+ * type JSONValue =
44
+ * | null
45
+ * | string
46
+ * | number
47
+ * | boolean
48
+ * | { [string]: JSONValue }
49
+ * | JSONValue[]
50
+ * ```
51
+ */
52
+
53
+ exports.jsonArray = jsonArray;
54
+ var json = (0, _unions.either)(_basics.null_, _strings.string, _numbers.number, _booleans["boolean"], jsonObject, jsonArray).describe('Must be valid JSON value');
55
+ exports.json = json;
@@ -0,0 +1,50 @@
1
+ // @flow strict
2
+
3
+ import { array } from './arrays';
4
+ import { boolean } from './booleans';
5
+ import { dict } from './objects';
6
+ import { either } from './unions';
7
+ import { lazy } from './utilities';
8
+ import { null_ } from './basics';
9
+ import { number } from './numbers';
10
+ import { string } from './strings';
11
+ import type { Decoder } from '../Decoder';
12
+
13
+ export type JSONValue = null | string | number | boolean | JSONObject | JSONArray;
14
+ export type JSONObject = { [string]: JSONValue };
15
+ export type JSONArray = Array<JSONValue>;
16
+
17
+ /**
18
+ * Like `json`, but will only decode when the JSON value is an object.
19
+ */
20
+ export const jsonObject: Decoder<JSONObject> = lazy(() => dict(json));
21
+
22
+ /**
23
+ * Like `json`, but will only decode when the JSON value is an array.
24
+ */
25
+ export const jsonArray: Decoder<JSONArray> = lazy(() => array(json));
26
+
27
+ /**
28
+ * Accepts any value that's a valid JSON value.
29
+ *
30
+ * In other words: any value returned by `JSON.parse()` should decode without
31
+ * failure.
32
+ *
33
+ * ```typescript
34
+ * type JSONValue =
35
+ * | null
36
+ * | string
37
+ * | number
38
+ * | boolean
39
+ * | { [string]: JSONValue }
40
+ * | JSONValue[]
41
+ * ```
42
+ */
43
+ export const json: Decoder<JSONValue> = either(
44
+ null_,
45
+ string,
46
+ number,
47
+ boolean,
48
+ jsonObject,
49
+ jsonArray,
50
+ ).describe('Must be valid JSON value');
package/lib/json.mjs ADDED
@@ -0,0 +1,40 @@
1
+ import { array } from './arrays.mjs';
2
+ import { boolean as _boolean } from './booleans.mjs';
3
+ import { dict } from './objects.mjs';
4
+ import { either } from './unions.mjs';
5
+ import { lazy } from './utilities.mjs';
6
+ import { null_ } from './basics.mjs';
7
+ import { number } from './numbers.mjs';
8
+ import { string } from './strings.mjs';
9
+
10
+ /**
11
+ * Like `json`, but will only decode when the JSON value is an object.
12
+ */
13
+ export var jsonObject = lazy(function () {
14
+ return dict(json);
15
+ });
16
+ /**
17
+ * Like `json`, but will only decode when the JSON value is an array.
18
+ */
19
+
20
+ export var jsonArray = lazy(function () {
21
+ return array(json);
22
+ });
23
+ /**
24
+ * Accepts any value that's a valid JSON value.
25
+ *
26
+ * In other words: any value returned by `JSON.parse()` should decode without
27
+ * failure.
28
+ *
29
+ * ```typescript
30
+ * type JSONValue =
31
+ * | null
32
+ * | string
33
+ * | number
34
+ * | boolean
35
+ * | { [string]: JSONValue }
36
+ * | JSONValue[]
37
+ * ```
38
+ */
39
+
40
+ export var json = either(null_, string, number, _boolean, jsonObject, jsonArray).describe('Must be valid JSON value');