decoders 2.0.0 → 2.0.2

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/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## v2.0.2
2
+
3
+ - ![](./docs/assets/tiny-ts-logo.png) Fix TypeScript types for `formatShort` and
4
+ `formatInline` helper functions
5
+
6
+ ## v2.0.1
7
+
8
+ - ![](./docs/assets/tiny-ts-logo.png) **TypeScript-only:** Fix definition of JSONObject
9
+ to reflect that its values might always be `undefined` as well.
10
+
11
+ - ![](./docs/assets/tiny-ts-logo.png) **TypeScript-only:** Changed return types of
12
+ `{ [key: string]: T }` to `Record<string, T>`.
13
+
14
+ - ![](./docs/assets/tiny-ts-logo.png) **TypeScript-only:** Fine-tune the type of
15
+ [`instanceOf()`](https://decoders.cc/api.html#instanceOf).
16
+
1
17
  ## v2.0.0
2
18
 
3
19
  This is a breaking change, which brings numerous benefits:
package/Decoder.js CHANGED
@@ -1,210 +1,104 @@
1
- "use strict";
1
+ 'use strict'
2
2
 
3
- exports.__esModule = true;
4
- exports.define = define;
3
+ exports.__esModule = true
4
+ exports.define = define
5
5
 
6
- var _annotate = require("./annotate");
6
+ var _annotate = require('./annotate')
7
7
 
8
- var _format = require("./format");
8
+ var _format = require('./format')
9
9
 
10
- var _result = require("./result");
10
+ var _result = require('./result')
11
11
 
12
12
  function noThrow(fn) {
13
13
  return function (t) {
14
14
  try {
15
- var v = fn(t);
16
- return (0, _result.ok)(v);
15
+ var v = fn(t)
16
+ return (0, _result.ok)(v)
17
17
  } catch (e) {
18
- return (0, _result.err)((0, _annotate.annotate)(t, e instanceof Error ? e.message : String(e)));
18
+ return (0, _result.err)((0, _annotate.annotate)(t, e instanceof Error ? e.message : String(e)))
19
19
  }
20
- };
20
+ }
21
21
  }
22
22
 
23
23
  function format(err, formatter) {
24
- var formatted = formatter(err); // Formatter functions may return a string or an error for convenience of
25
- // writing them. If it already returns an Error, return it unmodified. If
26
- // it returns a string, wrap it in a "Decoding error" instance.
24
+ var formatted = formatter(err)
27
25
 
28
26
  if (typeof formatted === 'string') {
29
- var _err = new Error('\n' + formatted);
27
+ var _err = new Error('\n' + formatted)
30
28
 
31
- _err.name = 'Decoding error';
32
- return _err;
29
+ _err.name = 'Decoding error'
30
+ return _err
33
31
  } else {
34
- return formatted;
32
+ return formatted
35
33
  }
36
34
  }
37
- /**
38
- * Defines a new `Decoder<T>`, by implementing a custom acceptance function.
39
- * The function receives three arguments:
40
- *
41
- * 1. `blob` - the raw/unknown input (aka your external data)
42
- * 2. `ok` - Call `ok(value)` to accept the input and return ``value``
43
- * 3. `err` - Call `err(message)` to reject the input with error ``message``
44
- *
45
- * The expected return value should be a `DecodeResult<T>`, which can be
46
- * obtained by returning the result of calling the provided `ok` or `err`
47
- * helper functions. Please note that `ok()` and `err()` don't perform side
48
- * effects! You'll need to _return_ those values.
49
- */
50
-
51
35
 
52
36
  function define(fn) {
53
- /**
54
- * Verifies the untrusted/unknown input and either accepts or rejects it.
55
- *
56
- * Contrasted with `.verify()`, calls to `.decode()` will never fail and
57
- * instead return a result type.
58
- */
59
37
  function decode(blob) {
60
38
  return fn(blob, _result.ok, function (msg) {
61
- return (0, _result.err)(typeof msg === 'string' ? (0, _annotate.annotate)(blob, msg) : msg);
62
- });
39
+ return (0, _result.err)(typeof msg === 'string' ? (0, _annotate.annotate)(blob, msg) : msg)
40
+ })
63
41
  }
64
- /**
65
- * Verifies the untrusted/unknown input and either accepts or rejects it.
66
- * When accepted, returns a value of type `T`. Otherwise fail with
67
- * a runtime error.
68
- */
69
-
70
42
 
71
43
  function verify(blob, formatter) {
72
44
  if (formatter === void 0) {
73
- formatter = _format.formatInline;
45
+ formatter = _format.formatInline
74
46
  }
75
47
 
76
- var result = decode(blob);
48
+ var result = decode(blob)
77
49
 
78
50
  if (result.ok) {
79
- return result.value;
51
+ return result.value
80
52
  } else {
81
- throw format(result.error, formatter);
53
+ throw format(result.error, formatter)
82
54
  }
83
55
  }
84
- /**
85
- * Verifies the untrusted/unknown input and either accepts or rejects it.
86
- * When accepted, returns the decoded `T` value directly. Otherwise returns
87
- * `undefined`.
88
- *
89
- * Use this when you're not interested in programmatically handling the
90
- * error message.
91
- */
92
-
93
56
 
94
57
  function value(blob) {
95
- return decode(blob).value;
58
+ return decode(blob).value
96
59
  }
97
- /**
98
- * Accepts any value the given decoder accepts, and on success, will call
99
- * the given function **on the decoded result**. If the transformation
100
- * function throws an error, the whole decoder will fail using the error
101
- * message as the failure reason.
102
- */
103
-
104
60
 
105
61
  function transform(transformFn) {
106
- return then(noThrow(transformFn));
62
+ return then(noThrow(transformFn))
107
63
  }
108
- /**
109
- * Adds an extra predicate to a decoder. The new decoder is like the
110
- * original decoder, but only accepts values that also meet the
111
- * predicate.
112
- */
113
-
114
64
 
115
65
  function refine(predicateFn, errmsg) {
116
66
  return reject(function (value) {
117
- return predicateFn(value) ? // Don't reject
118
- null : // Reject with the given error message
119
- errmsg;
120
- });
67
+ return predicateFn(value) ? null : errmsg
68
+ })
121
69
  }
122
- /**
123
- * Chain together the current decoder with another.
124
- *
125
- * > _**NOTE:** This is an advanced, low-level, API. It's not recommended
126
- * > to reach for this construct unless there is no other way. Most cases can
127
- * > be covered more elegantly by `.transform()` or `.refine()` instead._
128
- *
129
- * If the current decoder accepts an input, the resulting ``T`` value will
130
- * get passed into the given ``next`` acceptance function to further decide
131
- * whether or not the value should get accepted or rejected.
132
- *
133
- * This works similar to how you would `define()` a new decoder, except
134
- * that the ``blob`` param will now be ``T`` (a known type), rather than
135
- * ``unknown``. This will allow the function to make a stronger assumption
136
- * about its input and avoid re-refining inputs.
137
- *
138
- * If it helps, you can think of `define(...)` as equivalent to
139
- * `unknown.then(...)`.
140
- */
141
-
142
70
 
143
71
  function then(next) {
144
72
  return define(function (blob, ok, err) {
145
- var result = decode(blob);
146
- return result.ok ? next(result.value, ok, err) : result;
147
- });
73
+ var result = decode(blob)
74
+ return result.ok ? next(result.value, ok, err) : result
75
+ })
148
76
  }
149
- /**
150
- * Adds an extra predicate to a decoder. The new decoder is like the
151
- * original decoder, but only accepts values that aren't rejected by the
152
- * given function.
153
- *
154
- * The given function can return `null` to accept the decoded value, or
155
- * return a specific error message to reject.
156
- *
157
- * Unlike `.refine()`, you can use this function to return a dynamic error
158
- * message.
159
- */
160
-
161
77
 
162
78
  function reject(rejectFn) {
163
79
  return then(function (value, ok, err) {
164
- var errmsg = rejectFn(value);
165
- return errmsg === null ? ok(value) : err(typeof errmsg === 'string' ? (0, _annotate.annotate)(value, errmsg) : errmsg);
166
- });
80
+ var errmsg = rejectFn(value)
81
+ return errmsg === null ? ok(value) : err(typeof errmsg === 'string' ? (0, _annotate.annotate)(value, errmsg) : errmsg)
82
+ })
167
83
  }
168
- /**
169
- * Uses the given decoder, but will use an alternative error message in
170
- * case it rejects. This can be used to simplify or shorten otherwise
171
- * long or low-level/technical errors.
172
- */
173
-
174
84
 
175
85
  function describe(message) {
176
86
  return define(function (blob, _, err) {
177
- // Decode using the given decoder...
178
- var result = decode(blob);
87
+ var result = decode(blob)
179
88
 
180
89
  if (result.ok) {
181
- return result;
90
+ return result
182
91
  } else {
183
- // ...but in case of error, annotate this with the custom given
184
- // message instead
185
- return err((0, _annotate.annotate)(result.error, message));
92
+ return err((0, _annotate.annotate)(result.error, message))
186
93
  }
187
- });
94
+ })
188
95
  }
189
- /**
190
- * WARNING: This is an EXPERIMENTAL API that will likely change in the
191
- * future. Please DO NOT rely on it.
192
- *
193
- * Chain together the current decoder with another, but also pass along
194
- * the original input.
195
- *
196
- * This is like `.then()`, but instead of this function receiving just
197
- * the decoded result ``T``, it also receives the original input.
198
- *
199
- * This is an advanced, low-level, decoder.
200
- */
201
-
202
96
 
203
97
  function peek_UNSTABLE(next) {
204
98
  return define(function (blob, ok, err) {
205
- var result = decode(blob);
206
- return result.ok ? next([blob, result.value], ok, err) : result;
207
- });
99
+ var result = decode(blob)
100
+ return result.ok ? next([blob, result.value], ok, err) : result
101
+ })
208
102
  }
209
103
 
210
104
  return Object.freeze({
@@ -216,7 +110,6 @@ function define(fn) {
216
110
  reject: reject,
217
111
  describe: describe,
218
112
  then: then,
219
- // EXPERIMENTAL - please DO NOT rely on this method
220
- peek_UNSTABLE: peek_UNSTABLE
221
- });
222
- }
113
+ peek_UNSTABLE: peek_UNSTABLE,
114
+ })
115
+ }
package/Decoder.js.flow CHANGED
@@ -101,7 +101,7 @@ function format(err: Annotation, formatter: Formatter): Error {
101
101
  // writing them. If it already returns an Error, return it unmodified. If
102
102
  // it returns a string, wrap it in a "Decoding error" instance.
103
103
  if (typeof formatted === 'string') {
104
- const err = new Error('\n' + formatted);
104
+ const err = new Error(`\n${formatted}`);
105
105
  err.name = 'Decoding error';
106
106
  return err;
107
107
  } else {
package/Decoder.mjs CHANGED
@@ -1,203 +1,97 @@
1
- import { annotate } from './annotate.mjs';
2
- import { formatInline } from './format.mjs';
3
- import { err as makeErr, ok as makeOk } from './result.mjs';
1
+ import { annotate } from './annotate.mjs'
2
+ import { formatInline } from './format.mjs'
3
+ import { err as makeErr, ok as makeOk } from './result.mjs'
4
4
 
5
5
  function noThrow(fn) {
6
6
  return function (t) {
7
7
  try {
8
- var v = fn(t);
9
- return makeOk(v);
8
+ var v = fn(t)
9
+ return makeOk(v)
10
10
  } catch (e) {
11
- return makeErr(annotate(t, e instanceof Error ? e.message : String(e)));
11
+ return makeErr(annotate(t, e instanceof Error ? e.message : String(e)))
12
12
  }
13
- };
13
+ }
14
14
  }
15
15
 
16
16
  function format(err, formatter) {
17
- var formatted = formatter(err); // Formatter functions may return a string or an error for convenience of
18
- // writing them. If it already returns an Error, return it unmodified. If
19
- // it returns a string, wrap it in a "Decoding error" instance.
17
+ var formatted = formatter(err)
20
18
 
21
19
  if (typeof formatted === 'string') {
22
- var _err = new Error('\n' + formatted);
20
+ var _err = new Error('\n' + formatted)
23
21
 
24
- _err.name = 'Decoding error';
25
- return _err;
22
+ _err.name = 'Decoding error'
23
+ return _err
26
24
  } else {
27
- return formatted;
25
+ return formatted
28
26
  }
29
27
  }
30
- /**
31
- * Defines a new `Decoder<T>`, by implementing a custom acceptance function.
32
- * The function receives three arguments:
33
- *
34
- * 1. `blob` - the raw/unknown input (aka your external data)
35
- * 2. `ok` - Call `ok(value)` to accept the input and return ``value``
36
- * 3. `err` - Call `err(message)` to reject the input with error ``message``
37
- *
38
- * The expected return value should be a `DecodeResult<T>`, which can be
39
- * obtained by returning the result of calling the provided `ok` or `err`
40
- * helper functions. Please note that `ok()` and `err()` don't perform side
41
- * effects! You'll need to _return_ those values.
42
- */
43
-
44
28
 
45
29
  export function define(fn) {
46
- /**
47
- * Verifies the untrusted/unknown input and either accepts or rejects it.
48
- *
49
- * Contrasted with `.verify()`, calls to `.decode()` will never fail and
50
- * instead return a result type.
51
- */
52
30
  function decode(blob) {
53
31
  return fn(blob, makeOk, function (msg) {
54
- return makeErr(typeof msg === 'string' ? annotate(blob, msg) : msg);
55
- });
32
+ return makeErr(typeof msg === 'string' ? annotate(blob, msg) : msg)
33
+ })
56
34
  }
57
- /**
58
- * Verifies the untrusted/unknown input and either accepts or rejects it.
59
- * When accepted, returns a value of type `T`. Otherwise fail with
60
- * a runtime error.
61
- */
62
-
63
35
 
64
36
  function verify(blob, formatter) {
65
37
  if (formatter === void 0) {
66
- formatter = formatInline;
38
+ formatter = formatInline
67
39
  }
68
40
 
69
- var result = decode(blob);
41
+ var result = decode(blob)
70
42
 
71
43
  if (result.ok) {
72
- return result.value;
44
+ return result.value
73
45
  } else {
74
- throw format(result.error, formatter);
46
+ throw format(result.error, formatter)
75
47
  }
76
48
  }
77
- /**
78
- * Verifies the untrusted/unknown input and either accepts or rejects it.
79
- * When accepted, returns the decoded `T` value directly. Otherwise returns
80
- * `undefined`.
81
- *
82
- * Use this when you're not interested in programmatically handling the
83
- * error message.
84
- */
85
-
86
49
 
87
50
  function value(blob) {
88
- return decode(blob).value;
51
+ return decode(blob).value
89
52
  }
90
- /**
91
- * Accepts any value the given decoder accepts, and on success, will call
92
- * the given function **on the decoded result**. If the transformation
93
- * function throws an error, the whole decoder will fail using the error
94
- * message as the failure reason.
95
- */
96
-
97
53
 
98
54
  function transform(transformFn) {
99
- return then(noThrow(transformFn));
55
+ return then(noThrow(transformFn))
100
56
  }
101
- /**
102
- * Adds an extra predicate to a decoder. The new decoder is like the
103
- * original decoder, but only accepts values that also meet the
104
- * predicate.
105
- */
106
-
107
57
 
108
58
  function refine(predicateFn, errmsg) {
109
59
  return reject(function (value) {
110
- return predicateFn(value) ? // Don't reject
111
- null : // Reject with the given error message
112
- errmsg;
113
- });
60
+ return predicateFn(value) ? null : errmsg
61
+ })
114
62
  }
115
- /**
116
- * Chain together the current decoder with another.
117
- *
118
- * > _**NOTE:** This is an advanced, low-level, API. It's not recommended
119
- * > to reach for this construct unless there is no other way. Most cases can
120
- * > be covered more elegantly by `.transform()` or `.refine()` instead._
121
- *
122
- * If the current decoder accepts an input, the resulting ``T`` value will
123
- * get passed into the given ``next`` acceptance function to further decide
124
- * whether or not the value should get accepted or rejected.
125
- *
126
- * This works similar to how you would `define()` a new decoder, except
127
- * that the ``blob`` param will now be ``T`` (a known type), rather than
128
- * ``unknown``. This will allow the function to make a stronger assumption
129
- * about its input and avoid re-refining inputs.
130
- *
131
- * If it helps, you can think of `define(...)` as equivalent to
132
- * `unknown.then(...)`.
133
- */
134
-
135
63
 
136
64
  function then(next) {
137
65
  return define(function (blob, ok, err) {
138
- var result = decode(blob);
139
- return result.ok ? next(result.value, ok, err) : result;
140
- });
66
+ var result = decode(blob)
67
+ return result.ok ? next(result.value, ok, err) : result
68
+ })
141
69
  }
142
- /**
143
- * Adds an extra predicate to a decoder. The new decoder is like the
144
- * original decoder, but only accepts values that aren't rejected by the
145
- * given function.
146
- *
147
- * The given function can return `null` to accept the decoded value, or
148
- * return a specific error message to reject.
149
- *
150
- * Unlike `.refine()`, you can use this function to return a dynamic error
151
- * message.
152
- */
153
-
154
70
 
155
71
  function reject(rejectFn) {
156
72
  return then(function (value, ok, err) {
157
- var errmsg = rejectFn(value);
158
- return errmsg === null ? ok(value) : err(typeof errmsg === 'string' ? annotate(value, errmsg) : errmsg);
159
- });
73
+ var errmsg = rejectFn(value)
74
+ return errmsg === null ? ok(value) : err(typeof errmsg === 'string' ? annotate(value, errmsg) : errmsg)
75
+ })
160
76
  }
161
- /**
162
- * Uses the given decoder, but will use an alternative error message in
163
- * case it rejects. This can be used to simplify or shorten otherwise
164
- * long or low-level/technical errors.
165
- */
166
-
167
77
 
168
78
  function describe(message) {
169
79
  return define(function (blob, _, err) {
170
- // Decode using the given decoder...
171
- var result = decode(blob);
80
+ var result = decode(blob)
172
81
 
173
82
  if (result.ok) {
174
- return result;
83
+ return result
175
84
  } else {
176
- // ...but in case of error, annotate this with the custom given
177
- // message instead
178
- return err(annotate(result.error, message));
85
+ return err(annotate(result.error, message))
179
86
  }
180
- });
87
+ })
181
88
  }
182
- /**
183
- * WARNING: This is an EXPERIMENTAL API that will likely change in the
184
- * future. Please DO NOT rely on it.
185
- *
186
- * Chain together the current decoder with another, but also pass along
187
- * the original input.
188
- *
189
- * This is like `.then()`, but instead of this function receiving just
190
- * the decoded result ``T``, it also receives the original input.
191
- *
192
- * This is an advanced, low-level, decoder.
193
- */
194
-
195
89
 
196
90
  function peek_UNSTABLE(next) {
197
91
  return define(function (blob, ok, err) {
198
- var result = decode(blob);
199
- return result.ok ? next([blob, result.value], ok, err) : result;
200
- });
92
+ var result = decode(blob)
93
+ return result.ok ? next([blob, result.value], ok, err) : result
94
+ })
201
95
  }
202
96
 
203
97
  return Object.freeze({
@@ -209,7 +103,6 @@ export function define(fn) {
209
103
  reject: reject,
210
104
  describe: describe,
211
105
  then: then,
212
- // EXPERIMENTAL - please DO NOT rely on this method
213
- peek_UNSTABLE: peek_UNSTABLE
214
- });
215
- }
106
+ peek_UNSTABLE: peek_UNSTABLE,
107
+ })
108
+ }
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- <img alt="Decoders logo" src="./docs/assets/logo@2x.png" style="width: 100%; max-width: 830px; max-height: 248px" width="830" height="248" /><br />
1
+ <img alt="Decoders logo" src="./docs/assets/logo@2x.png" style="width: 100%; max-width: 830px; max-height: 248px" width="830" /><br />
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/decoders.svg)](https://www.npmjs.com/package/decoders)
4
4
  [![Build Status](https://github.com/nvie/decoders/workflows/test/badge.svg)](https://github.com/nvie/decoders/actions)