decoders 2.0.0 → 2.0.1

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/lib/unions.js CHANGED
@@ -1,160 +1,96 @@
1
- "use strict";
1
+ 'use strict'
2
2
 
3
- exports.__esModule = true;
4
- exports.either = void 0;
5
- exports.oneOf = oneOf;
6
- exports.taggedUnion = taggedUnion;
3
+ exports.__esModule = true
4
+ exports.either = void 0
5
+ exports.oneOf = oneOf
6
+ exports.taggedUnion = taggedUnion
7
7
 
8
- var _Decoder = require("../Decoder");
8
+ var _Decoder = require('../Decoder')
9
9
 
10
- var _utils = require("../_utils");
10
+ var _utils = require('../_utils')
11
11
 
12
- var _objects = require("./objects");
12
+ var _objects = require('./objects')
13
13
 
14
- var _utilities = require("./utilities");
14
+ var _utilities = require('./utilities')
15
15
 
16
- var EITHER_PREFIX = 'Either:\n';
17
- /**
18
- * Indents and adds a dash in front of this (potentially multiline) string.
19
- */
16
+ var EITHER_PREFIX = 'Either:\n'
20
17
 
21
18
  function itemize(s) {
22
- return '-' + (0, _utils.indent)(s).substring(1);
19
+ return '-' + (0, _utils.indent)(s).substring(1)
23
20
  }
24
- /**
25
- * Nests another error as an item under a new-to-be-created "Either error". If
26
- * the given subitem already is an "Either error" of itself, don't indent, but
27
- * just "inject" its items at the same error level, for nicely flattened either
28
- * expressions.
29
- *
30
- * Avoids:
31
- *
32
- * Either:
33
- * - Either:
34
- * - Must be P
35
- * - Either:
36
- * - Must be Q
37
- * - Must be R
38
- * - Must be S
39
- *
40
- * And "flattens" these to:
41
- *
42
- * Either:
43
- * - Must be P
44
- * - Must be Q
45
- * - Must be R
46
- * - Must be S
47
- *
48
- */
49
-
50
21
 
51
22
  function nest(errText) {
52
- return errText.startsWith(EITHER_PREFIX) ? errText.substr(EITHER_PREFIX.length) : itemize(errText);
53
- } // prettier-ignore
54
-
23
+ return errText.startsWith(EITHER_PREFIX) ? errText.substr(EITHER_PREFIX.length) : itemize(errText)
24
+ }
55
25
 
56
26
  function _either() {
57
27
  for (var _len = arguments.length, decoders = new Array(_len), _key = 0; _key < _len; _key++) {
58
- decoders[_key] = arguments[_key];
28
+ decoders[_key] = arguments[_key]
59
29
  }
60
30
 
61
31
  if (decoders.length === 0) {
62
- throw new Error('Pass at least one decoder to either()');
32
+ throw new Error('Pass at least one decoder to either()')
63
33
  }
64
34
 
65
35
  return (0, _Decoder.define)(function (blob, _, err) {
66
- // Collect errors here along the way
67
- var errors = [];
36
+ var errors = []
68
37
 
69
38
  for (var _i = 0; _i < decoders.length; _i++) {
70
- var result = decoders[_i].decode(blob);
39
+ var result = decoders[_i].decode(blob)
71
40
 
72
41
  if (result.ok) {
73
- return result;
42
+ return result
74
43
  } else {
75
- errors.push(result.error);
44
+ errors.push(result.error)
76
45
  }
77
- } // Decoding all alternatives failed, return the combined error message
78
-
46
+ }
79
47
 
80
- var text = EITHER_PREFIX + errors.map(function (err) {
81
- return nest((0, _utils.summarize)(err).join('\n'));
82
- }).join('\n');
83
- return err(text);
84
- });
48
+ var text =
49
+ EITHER_PREFIX +
50
+ errors
51
+ .map(function (err) {
52
+ return nest((0, _utils.summarize)(err).join('\n'))
53
+ })
54
+ .join('\n')
55
+ return err(text)
56
+ })
85
57
  }
86
- /**
87
- * Accepts values accepted by any of the given decoders.
88
- *
89
- * The decoders are tried on the input one by one, in the given order. The
90
- * first one that accepts the input "wins". If all decoders reject the input,
91
- * the input gets rejected.
92
- */
93
-
94
58
 
95
- var either = _either;
96
- /**
97
- * Accepts any value that is strictly-equal (using `===`) to one of the
98
- * specified values.
99
- */
59
+ var either = _either
100
60
 
101
- exports.either = either;
61
+ exports.either = either
102
62
 
103
63
  function oneOf(constants) {
104
64
  return (0, _Decoder.define)(function (blob, ok, err) {
105
65
  var winner = constants.find(function (c) {
106
- return c === blob;
107
- });
66
+ return c === blob
67
+ })
108
68
 
109
69
  if (winner !== undefined) {
110
- return ok(winner);
70
+ return ok(winner)
111
71
  }
112
72
 
113
- return err("Must be one of " + constants.map(function (value) {
114
- return JSON.stringify(value);
115
- }).join(', '));
116
- });
73
+ return err(
74
+ 'Must be one of ' +
75
+ constants
76
+ .map(function (value) {
77
+ return JSON.stringify(value)
78
+ })
79
+ .join(', ')
80
+ )
81
+ })
117
82
  }
118
- /**
119
- * If you are decoding tagged unions you may want to use the `taggedUnion()`
120
- * decoder instead of the general purpose `either()` decoder to get better
121
- * error messages and better performance.
122
- *
123
- * This decoder is optimized for [tagged
124
- * unions](https://en.wikipedia.org/wiki/Tagged_union), i.e. a union of
125
- * objects where one field is used as the discriminator.
126
- *
127
- * ```ts
128
- * const A = object({ tag: constant('A'), foo: string });
129
- * const B = object({ tag: constant('B'), bar: number });
130
- *
131
- * const AorB = taggedUnion('tag', { A, B });
132
- * // ^^^
133
- * ```
134
- *
135
- * Decoding now works in two steps:
136
- *
137
- * 1. Look at the `'tag'` field in the incoming object (this is the field
138
- * that decides which decoder will be used)
139
- * 2. If the value is `'A'`, then decoder `A` will be used. If it's `'B'`, then
140
- * decoder `B` will be used. Otherwise, this will fail.
141
- *
142
- * This is effectively equivalent to `either(A, B)`, but will provide better
143
- * error messages and is more performant at runtime because it doesn't have to
144
- * try all decoders one by one.
145
- */
146
-
147
83
 
148
84
  function taggedUnion(field, mapping) {
149
- var _object;
85
+ var _object
150
86
 
151
- var base = (0, _objects.object)((_object = {}, _object[field] = (0, _utilities.prep)(String, oneOf(Object.keys(mapping))), _object)).transform(function (o) {
152
- return o[field];
153
- });
87
+ var base = (0, _objects.object)(((_object = {}), (_object[field] = (0, _utilities.prep)(String, oneOf(Object.keys(mapping)))), _object)).transform(function (o) {
88
+ return o[field]
89
+ })
154
90
  return base.peek_UNSTABLE(function (_ref) {
155
91
  var blob = _ref[0],
156
- key = _ref[1];
157
- var decoder = mapping[key];
158
- return decoder.decode(blob);
159
- });
160
- }
92
+ key = _ref[1]
93
+ var decoder = mapping[key]
94
+ return decoder.decode(blob)
95
+ })
96
+ }
@@ -13,7 +13,7 @@ const EITHER_PREFIX = 'Either:\n';
13
13
  * Indents and adds a dash in front of this (potentially multiline) string.
14
14
  */
15
15
  function itemize(s: string): string {
16
- return '-' + indent(s).substring(1);
16
+ return `-${indent(s).substring(1)}`;
17
17
  }
18
18
 
19
19
  /**
package/lib/unions.mjs CHANGED
@@ -1,146 +1,83 @@
1
- import { define } from '../Decoder.mjs';
2
- import { indent, summarize } from '../_utils.mjs';
3
- import { object } from './objects.mjs';
4
- import { prep } from './utilities.mjs';
5
- var EITHER_PREFIX = 'Either:\n';
6
- /**
7
- * Indents and adds a dash in front of this (potentially multiline) string.
8
- */
1
+ import { define } from '../Decoder.mjs'
2
+ import { indent, summarize } from '../_utils.mjs'
3
+ import { object } from './objects.mjs'
4
+ import { prep } from './utilities.mjs'
5
+ var EITHER_PREFIX = 'Either:\n'
9
6
 
10
7
  function itemize(s) {
11
- return '-' + indent(s).substring(1);
8
+ return '-' + indent(s).substring(1)
12
9
  }
13
- /**
14
- * Nests another error as an item under a new-to-be-created "Either error". If
15
- * the given subitem already is an "Either error" of itself, don't indent, but
16
- * just "inject" its items at the same error level, for nicely flattened either
17
- * expressions.
18
- *
19
- * Avoids:
20
- *
21
- * Either:
22
- * - Either:
23
- * - Must be P
24
- * - Either:
25
- * - Must be Q
26
- * - Must be R
27
- * - Must be S
28
- *
29
- * And "flattens" these to:
30
- *
31
- * Either:
32
- * - Must be P
33
- * - Must be Q
34
- * - Must be R
35
- * - Must be S
36
- *
37
- */
38
-
39
10
 
40
11
  function nest(errText) {
41
- return errText.startsWith(EITHER_PREFIX) ? errText.substr(EITHER_PREFIX.length) : itemize(errText);
42
- } // prettier-ignore
43
-
12
+ return errText.startsWith(EITHER_PREFIX) ? errText.substr(EITHER_PREFIX.length) : itemize(errText)
13
+ }
44
14
 
45
15
  function _either() {
46
16
  for (var _len = arguments.length, decoders = new Array(_len), _key = 0; _key < _len; _key++) {
47
- decoders[_key] = arguments[_key];
17
+ decoders[_key] = arguments[_key]
48
18
  }
49
19
 
50
20
  if (decoders.length === 0) {
51
- throw new Error('Pass at least one decoder to either()');
21
+ throw new Error('Pass at least one decoder to either()')
52
22
  }
53
23
 
54
24
  return define(function (blob, _, err) {
55
- // Collect errors here along the way
56
- var errors = [];
25
+ var errors = []
57
26
 
58
27
  for (var _i = 0; _i < decoders.length; _i++) {
59
- var result = decoders[_i].decode(blob);
28
+ var result = decoders[_i].decode(blob)
60
29
 
61
30
  if (result.ok) {
62
- return result;
31
+ return result
63
32
  } else {
64
- errors.push(result.error);
33
+ errors.push(result.error)
65
34
  }
66
- } // Decoding all alternatives failed, return the combined error message
67
-
35
+ }
68
36
 
69
- var text = EITHER_PREFIX + errors.map(function (err) {
70
- return nest(summarize(err).join('\n'));
71
- }).join('\n');
72
- return err(text);
73
- });
37
+ var text =
38
+ EITHER_PREFIX +
39
+ errors
40
+ .map(function (err) {
41
+ return nest(summarize(err).join('\n'))
42
+ })
43
+ .join('\n')
44
+ return err(text)
45
+ })
74
46
  }
75
- /**
76
- * Accepts values accepted by any of the given decoders.
77
- *
78
- * The decoders are tried on the input one by one, in the given order. The
79
- * first one that accepts the input "wins". If all decoders reject the input,
80
- * the input gets rejected.
81
- */
82
-
83
47
 
84
- export var either = _either;
85
- /**
86
- * Accepts any value that is strictly-equal (using `===`) to one of the
87
- * specified values.
88
- */
48
+ export var either = _either
89
49
 
90
50
  export function oneOf(constants) {
91
51
  return define(function (blob, ok, err) {
92
52
  var winner = constants.find(function (c) {
93
- return c === blob;
94
- });
53
+ return c === blob
54
+ })
95
55
 
96
56
  if (winner !== undefined) {
97
- return ok(winner);
57
+ return ok(winner)
98
58
  }
99
59
 
100
- return err("Must be one of " + constants.map(function (value) {
101
- return JSON.stringify(value);
102
- }).join(', '));
103
- });
60
+ return err(
61
+ 'Must be one of ' +
62
+ constants
63
+ .map(function (value) {
64
+ return JSON.stringify(value)
65
+ })
66
+ .join(', ')
67
+ )
68
+ })
104
69
  }
105
- /**
106
- * If you are decoding tagged unions you may want to use the `taggedUnion()`
107
- * decoder instead of the general purpose `either()` decoder to get better
108
- * error messages and better performance.
109
- *
110
- * This decoder is optimized for [tagged
111
- * unions](https://en.wikipedia.org/wiki/Tagged_union), i.e. a union of
112
- * objects where one field is used as the discriminator.
113
- *
114
- * ```ts
115
- * const A = object({ tag: constant('A'), foo: string });
116
- * const B = object({ tag: constant('B'), bar: number });
117
- *
118
- * const AorB = taggedUnion('tag', { A, B });
119
- * // ^^^
120
- * ```
121
- *
122
- * Decoding now works in two steps:
123
- *
124
- * 1. Look at the `'tag'` field in the incoming object (this is the field
125
- * that decides which decoder will be used)
126
- * 2. If the value is `'A'`, then decoder `A` will be used. If it's `'B'`, then
127
- * decoder `B` will be used. Otherwise, this will fail.
128
- *
129
- * This is effectively equivalent to `either(A, B)`, but will provide better
130
- * error messages and is more performant at runtime because it doesn't have to
131
- * try all decoders one by one.
132
- */
133
70
 
134
71
  export function taggedUnion(field, mapping) {
135
- var _object;
72
+ var _object
136
73
 
137
- var base = object((_object = {}, _object[field] = prep(String, oneOf(Object.keys(mapping))), _object)).transform(function (o) {
138
- return o[field];
139
- });
74
+ var base = object(((_object = {}), (_object[field] = prep(String, oneOf(Object.keys(mapping)))), _object)).transform(function (o) {
75
+ return o[field]
76
+ })
140
77
  return base.peek_UNSTABLE(function (_ref) {
141
78
  var blob = _ref[0],
142
- key = _ref[1];
143
- var decoder = mapping[key];
144
- return decoder.decode(blob);
145
- });
146
- }
79
+ key = _ref[1]
80
+ var decoder = mapping[key]
81
+ return decoder.decode(blob)
82
+ })
83
+ }
@@ -1,9 +1,15 @@
1
1
  import { Decoder } from '../Decoder';
2
2
 
3
+ export interface Klass<T> extends Function {
4
+ new (...args: readonly any[]): T;
5
+ }
6
+
7
+ export type Instance<K> = K extends Klass<infer T> ? T : never;
8
+
3
9
  /**
4
10
  * Accepts any value that is an ``instanceof`` the given class.
5
11
  */
6
- export function instanceOf<T>(klass: new (...args: readonly any[]) => T): Decoder<T>;
12
+ export function instanceOf<K extends Klass<any>>(klass: K): Decoder<Instance<K>>;
7
13
 
8
14
  /**
9
15
  * Lazily evaluate the given decoder. This is useful to build self-referential
package/lib/utilities.js CHANGED
@@ -1,75 +1,48 @@
1
- "use strict";
1
+ 'use strict'
2
2
 
3
- exports.__esModule = true;
4
- exports.fail = void 0;
5
- exports.instanceOf = instanceOf;
6
- exports.lazy = lazy;
7
- exports.never = never;
8
- exports.prep = prep;
3
+ exports.__esModule = true
4
+ exports.fail = void 0
5
+ exports.instanceOf = instanceOf
6
+ exports.lazy = lazy
7
+ exports.never = never
8
+ exports.prep = prep
9
9
 
10
- var _annotate = require("../annotate");
10
+ var _annotate = require('../annotate')
11
11
 
12
- var _Decoder = require("../Decoder");
12
+ var _Decoder = require('../Decoder')
13
13
 
14
- /**
15
- * Accepts any value that is an ``instanceof`` the given class.
16
- */
17
14
  function instanceOf(klass) {
18
15
  return (0, _Decoder.define)(function (blob, ok, err) {
19
- return blob instanceof klass ? ok(blob) : err("Must be " + // $FlowFixMe[incompatible-use] - klass.name is fine?
20
- klass.name + " instance");
21
- });
16
+ return blob instanceof klass ? ok(blob) : err('Must be ' + klass.name + ' instance')
17
+ })
22
18
  }
23
- /**
24
- * Lazily evaluate the given decoder. This is useful to build self-referential
25
- * types for recursive data structures.
26
- */
27
-
28
19
 
29
20
  function lazy(decoderFn) {
30
21
  return (0, _Decoder.define)(function (blob) {
31
- return decoderFn().decode(blob);
32
- });
22
+ return decoderFn().decode(blob)
23
+ })
33
24
  }
34
- /**
35
- * Pre-process the data input before passing it into the decoder. This gives
36
- * you the ability to arbitrarily customize the input on the fly before passing
37
- * it to the decoder. Of course, the input value at that point is still of
38
- * ``unknown`` type, so you will have to deal with that accordingly.
39
- */
40
-
41
25
 
42
26
  function prep(mapperFn, decoder) {
43
27
  return (0, _Decoder.define)(function (originalInput, _, err) {
44
- var blob;
28
+ var blob
45
29
 
46
30
  try {
47
- blob = mapperFn(originalInput);
31
+ blob = mapperFn(originalInput)
48
32
  } catch (e) {
49
- return err((0, _annotate.annotate)(originalInput, e.message));
33
+ return err((0, _annotate.annotate)(originalInput, e.message))
50
34
  }
51
35
 
52
- var r = decoder.decode(blob);
53
- return r.ok ? r : err((0, _annotate.annotate)(originalInput, r.error.text)); // ^^^^^^^^^^^^^
54
- // Annotates the _original_ input value
55
- // (instead of echoing back blob)
56
- });
36
+ var r = decoder.decode(blob)
37
+ return r.ok ? r : err((0, _annotate.annotate)(originalInput, r.error.text))
38
+ })
57
39
  }
58
- /**
59
- * Rejects all inputs, and always fails with the given error message. May be
60
- * useful for explicitly disallowing keys, or for testing purposes.
61
- */
62
-
63
40
 
64
41
  function never(msg) {
65
42
  return (0, _Decoder.define)(function (_, __, err) {
66
- return err(msg);
67
- });
43
+ return err(msg)
44
+ })
68
45
  }
69
- /**
70
- * Alias of never().
71
- */
72
-
73
46
 
74
- var fail = never;
75
- exports.fail = fail;
47
+ var fail = never
48
+ exports.fail = fail
package/lib/utilities.mjs CHANGED
@@ -1,60 +1,37 @@
1
- import { annotate } from '../annotate.mjs';
2
- import { define } from '../Decoder.mjs';
1
+ import { annotate } from '../annotate.mjs'
2
+ import { define } from '../Decoder.mjs'
3
3
 
4
- /**
5
- * Accepts any value that is an ``instanceof`` the given class.
6
- */
7
4
  export function instanceOf(klass) {
8
5
  return define(function (blob, ok, err) {
9
- return blob instanceof klass ? ok(blob) : err("Must be " + // $FlowFixMe[incompatible-use] - klass.name is fine?
10
- klass.name + " instance");
11
- });
6
+ return blob instanceof klass ? ok(blob) : err('Must be ' + klass.name + ' instance')
7
+ })
12
8
  }
13
- /**
14
- * Lazily evaluate the given decoder. This is useful to build self-referential
15
- * types for recursive data structures.
16
- */
17
9
 
18
10
  export function lazy(decoderFn) {
19
11
  return define(function (blob) {
20
- return decoderFn().decode(blob);
21
- });
12
+ return decoderFn().decode(blob)
13
+ })
22
14
  }
23
- /**
24
- * Pre-process the data input before passing it into the decoder. This gives
25
- * you the ability to arbitrarily customize the input on the fly before passing
26
- * it to the decoder. Of course, the input value at that point is still of
27
- * ``unknown`` type, so you will have to deal with that accordingly.
28
- */
29
15
 
30
16
  export function prep(mapperFn, decoder) {
31
17
  return define(function (originalInput, _, err) {
32
- var blob;
18
+ var blob
33
19
 
34
20
  try {
35
- blob = mapperFn(originalInput);
21
+ blob = mapperFn(originalInput)
36
22
  } catch (e) {
37
- return err(annotate(originalInput, e.message));
23
+ return err(annotate(originalInput, e.message))
38
24
  }
39
25
 
40
- var r = decoder.decode(blob);
41
- return r.ok ? r : err(annotate(originalInput, r.error.text)); // ^^^^^^^^^^^^^
42
- // Annotates the _original_ input value
43
- // (instead of echoing back blob)
44
- });
26
+ var r = decoder.decode(blob)
27
+ return r.ok ? r : err(annotate(originalInput, r.error.text))
28
+ })
45
29
  }
46
- /**
47
- * Rejects all inputs, and always fails with the given error message. May be
48
- * useful for explicitly disallowing keys, or for testing purposes.
49
- */
50
30
 
51
31
  export function never(msg) {
52
32
  return define(function (_, __, err) {
53
- return err(msg);
54
- });
33
+ return err(msg)
34
+ })
55
35
  }
56
- /**
57
- * Alias of never().
58
- */
59
36
 
60
- export var fail = never;
37
+ export var fail = never
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "decoders",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Elegant and battle-tested validation library for type-safe input data (for TypeScript and Flow)",
5
5
  "license": "MIT",
6
6
  "repository": {
package/result.js CHANGED
@@ -1,34 +1,21 @@
1
- "use strict";
1
+ 'use strict'
2
2
 
3
- exports.__esModule = true;
4
- exports.err = err;
5
- exports.ok = ok;
3
+ exports.__esModule = true
4
+ exports.err = err
5
+ exports.ok = ok
6
6
 
7
- /**
8
- * Result <value> <error>
9
- * = Ok <value>
10
- * | Err <error>
11
- */
12
-
13
- /**
14
- * Create a new Result instance representing a successful computation.
15
- */
16
7
  function ok(value) {
17
8
  return {
18
9
  ok: true,
19
10
  value: value,
20
- error: undefined
21
- };
11
+ error: undefined,
12
+ }
22
13
  }
23
- /**
24
- * Create a new Result instance representing a failed computation.
25
- */
26
-
27
14
 
28
15
  function err(error) {
29
16
  return {
30
17
  ok: false,
31
18
  value: undefined,
32
- error: error
33
- };
34
- }
19
+ error: error,
20
+ }
21
+ }