decoders 2.0.0-beta4 → 2.0.0-beta8
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 +10 -0
- package/NotSupportedTSVersion.d.ts +1 -0
- package/README.md +728 -343
- package/_guard.d.ts +7 -0
- package/_guard.js +2 -6
- package/_guard.js.flow +3 -3
- package/{_esm/_guard.js → _guard.mjs} +3 -3
- package/_types.d.ts +13 -0
- package/{_esm/_types.js → _types.mjs} +0 -0
- package/_utils.d.ts +10 -0
- package/{_esm/_utils.js → _utils.mjs} +0 -0
- package/annotate.d.ts +62 -0
- package/{_esm/annotate.js → annotate.mjs} +0 -0
- package/core/_helpers.d.ts +79 -0
- package/core/array.d.ts +5 -0
- package/core/array.js +7 -11
- package/core/array.js.flow +6 -9
- package/{_esm/core/array.js → core/array.mjs} +9 -9
- package/core/boolean.d.ts +5 -0
- package/core/boolean.js +4 -8
- package/core/boolean.js.flow +3 -5
- package/{_esm/core/boolean.js → core/boolean.mjs} +6 -6
- package/core/composition.d.ts +14 -0
- package/core/composition.js +9 -11
- package/core/composition.js.flow +13 -8
- package/{_esm/core/composition.js → core/composition.mjs} +10 -8
- package/core/constants.d.ts +11 -0
- package/core/constants.js +6 -10
- package/core/constants.js.flow +7 -9
- package/{_esm/core/constants.js → core/constants.mjs} +7 -7
- package/core/date.d.ts +4 -0
- package/core/date.js +3 -7
- package/core/date.js.flow +2 -4
- package/{_esm/core/date.js → core/date.mjs} +6 -6
- package/core/describe.d.ts +3 -0
- package/core/describe.js +2 -6
- package/core/describe.js.flow +2 -2
- package/{_esm/core/describe.js → core/describe.mjs} +3 -3
- package/core/dispatch.d.ts +8 -0
- package/core/dispatch.js +9 -13
- package/core/dispatch.js.flow +8 -8
- package/{_esm/core/dispatch.js → core/dispatch.mjs} +10 -10
- package/core/either.d.ts +61 -0
- package/core/either.js +7 -11
- package/core/either.js.flow +6 -6
- package/{_esm/core/either.js → core/either.mjs} +8 -8
- package/core/fail.d.ts +3 -0
- package/core/fail.js +2 -6
- package/core/fail.js.flow +2 -2
- package/{_esm/core/fail.js → core/fail.mjs} +3 -3
- package/core/instanceOf.d.ts +3 -0
- package/core/instanceOf.js +2 -6
- package/core/instanceOf.js.flow +3 -3
- package/core/instanceOf.mjs +8 -0
- package/core/json.d.ts +11 -0
- package/core/json.mjs +15 -0
- package/core/lazy.d.ts +3 -0
- package/{_esm/core/lazy.js → core/lazy.mjs} +0 -0
- package/core/mapping.d.ts +6 -0
- package/core/mapping.js +23 -23
- package/core/mapping.js.flow +25 -17
- package/{_esm/core/mapping.js → core/mapping.mjs} +26 -22
- package/core/number.d.ts +6 -0
- package/core/number.js +9 -13
- package/core/number.js.flow +18 -12
- package/core/number.mjs +25 -0
- package/core/object.d.ts +33 -0
- package/core/object.js +7 -11
- package/core/object.js.flow +7 -7
- package/{_esm/core/object.js → core/object.mjs} +9 -9
- package/core/optional.d.ts +5 -0
- package/core/optional.js +4 -8
- package/core/optional.js.flow +3 -3
- package/{_esm/core/optional.js → core/optional.mjs} +6 -6
- package/core/string.d.ts +10 -0
- package/core/string.js +18 -48
- package/core/string.js.flow +16 -39
- package/core/string.mjs +49 -0
- package/core/tuple.d.ts +30 -0
- package/core/tuple.js +12 -8
- package/core/tuple.js.flow +25 -29
- package/{_esm/core/tuple.js → core/tuple.mjs} +16 -12
- package/format.d.ts +4 -0
- package/{format/inline.js → format.js} +6 -1
- package/{_esm/format/inline.js.flow → format.js.flow} +6 -2
- package/{_esm/format/inline.js → format.mjs} +4 -1
- package/index.d.ts +43 -0
- package/index.js +3 -2
- package/index.js.flow +2 -2
- package/{_esm/index.js → index.mjs} +19 -19
- package/package.json +15 -3
- package/result.d.ts +39 -0
- package/result.js +3 -78
- package/result.js.flow +4 -76
- package/{_esm/result.js → result.mjs} +3 -64
- package/_esm/_guard.js.flow +0 -20
- package/_esm/_types.js.flow +0 -20
- package/_esm/_utils.js.flow +0 -97
- package/_esm/annotate.js.flow +0 -218
- package/_esm/core/array.js.flow +0 -103
- package/_esm/core/boolean.js.flow +0 -29
- package/_esm/core/composition.js.flow +0 -43
- package/_esm/core/constants.js.flow +0 -46
- package/_esm/core/date.js.flow +0 -40
- package/_esm/core/describe.js.flow +0 -17
- package/_esm/core/dispatch.js.flow +0 -58
- package/_esm/core/either.js.flow +0 -151
- package/_esm/core/fail.js.flow +0 -12
- package/_esm/core/instanceOf.js +0 -8
- package/_esm/core/instanceOf.js.flow +0 -20
- package/_esm/core/json.js +0 -15
- package/_esm/core/json.js.flow +0 -28
- package/_esm/core/lazy.js.flow +0 -15
- package/_esm/core/mapping.js.flow +0 -54
- package/_esm/core/number.js +0 -25
- package/_esm/core/number.js.flow +0 -34
- package/_esm/core/object.js.flow +0 -203
- package/_esm/core/optional.js.flow +0 -41
- package/_esm/core/string.js +0 -76
- package/_esm/core/string.js.flow +0 -82
- package/_esm/core/tuple.js.flow +0 -215
- package/_esm/format/index.js +0 -2
- package/_esm/format/index.js.flow +0 -4
- package/_esm/format/short.js +0 -4
- package/_esm/format/short.js.flow +0 -8
- package/_esm/index.js.flow +0 -63
- package/_esm/result.js.flow +0 -170
- package/format/index.js +0 -12
- package/format/index.js.flow +0 -4
- package/format/inline.js.flow +0 -122
- package/format/short.js +0 -10
- package/format/short.js.flow +0 -8
package/core/object.js
CHANGED
|
@@ -6,15 +6,11 @@ exports.inexact = inexact;
|
|
|
6
6
|
exports.object = object;
|
|
7
7
|
exports.pojo = void 0;
|
|
8
8
|
|
|
9
|
-
var Result = _interopRequireWildcard(require("../result"));
|
|
10
|
-
|
|
11
9
|
var _annotate = require("../annotate");
|
|
12
10
|
|
|
13
11
|
var _composition = require("./composition");
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
13
|
+
var _result = require("../result");
|
|
18
14
|
|
|
19
15
|
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
20
16
|
|
|
@@ -36,7 +32,7 @@ function subtract(xs, ys) {
|
|
|
36
32
|
}
|
|
37
33
|
|
|
38
34
|
var pojo = function pojo(blob) {
|
|
39
|
-
return isPojo(blob) ?
|
|
35
|
+
return isPojo(blob) ? (0, _result.ok)( // NOTE:
|
|
40
36
|
// Since Flow 0.98, typeof o === 'object' refines to
|
|
41
37
|
// {| +[string]: mixed |}
|
|
42
38
|
// instead of
|
|
@@ -50,7 +46,7 @@ var pojo = function pojo(blob) {
|
|
|
50
46
|
// way to turn a read-only Object to a writeable one in ES6 seems
|
|
51
47
|
// to be to use object-spread. (Going off this benchmark:
|
|
52
48
|
// https://thecodebarbarian.com/object-assign-vs-object-spread.html)
|
|
53
|
-
_extends({}, blob)) :
|
|
49
|
+
_extends({}, blob)) : (0, _result.err)((0, _annotate.annotate)(blob, 'Must be an object'));
|
|
54
50
|
};
|
|
55
51
|
/**
|
|
56
52
|
* Given a mapping of fields-to-decoders, builds a decoder for an object type.
|
|
@@ -139,10 +135,10 @@ function object(mapping) {
|
|
|
139
135
|
objAnn = (0, _annotate.updateText)(objAnn, "Missing " + pluralized + ": " + errMsg);
|
|
140
136
|
}
|
|
141
137
|
|
|
142
|
-
return
|
|
138
|
+
return (0, _result.err)(objAnn);
|
|
143
139
|
}
|
|
144
140
|
|
|
145
|
-
return
|
|
141
|
+
return (0, _result.ok)(record);
|
|
146
142
|
});
|
|
147
143
|
}
|
|
148
144
|
|
|
@@ -154,10 +150,10 @@ function exact(mapping) {
|
|
|
154
150
|
var superfluous = subtract(actual, allowed);
|
|
155
151
|
|
|
156
152
|
if (superfluous.size > 0) {
|
|
157
|
-
return
|
|
153
|
+
return (0, _result.err)((0, _annotate.annotate)(blob, "Superfluous keys: " + Array.from(superfluous).join(', ')));
|
|
158
154
|
}
|
|
159
155
|
|
|
160
|
-
return
|
|
156
|
+
return (0, _result.ok)(blob);
|
|
161
157
|
}); // Defer to the "object" decoder for doing the real decoding work. Since
|
|
162
158
|
// we made sure there are no superfluous keys in this structure, it's now
|
|
163
159
|
// safe to force-cast it to an $Exact<> type.
|
package/core/object.js.flow
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
|
|
3
|
-
import * as Result from '../result';
|
|
4
3
|
import { annotate, annotateObject, merge, updateText } from '../annotate';
|
|
5
4
|
import { compose, map } from './composition';
|
|
5
|
+
import { err, ok } from '../result';
|
|
6
6
|
import type { Annotation } from '../annotate';
|
|
7
7
|
import type { Decoder, DecoderType } from '../_types';
|
|
8
8
|
|
|
@@ -36,7 +36,7 @@ function subtract(xs: Set<string>, ys: Set<string>): Set<string> {
|
|
|
36
36
|
|
|
37
37
|
export const pojo: Decoder<{| [string]: mixed |}> = (blob: mixed) => {
|
|
38
38
|
return isPojo(blob)
|
|
39
|
-
?
|
|
39
|
+
? ok(
|
|
40
40
|
// NOTE:
|
|
41
41
|
// Since Flow 0.98, typeof o === 'object' refines to
|
|
42
42
|
// {| +[string]: mixed |}
|
|
@@ -53,7 +53,7 @@ export const pojo: Decoder<{| [string]: mixed |}> = (blob: mixed) => {
|
|
|
53
53
|
// https://thecodebarbarian.com/object-assign-vs-object-spread.html)
|
|
54
54
|
{ ...blob },
|
|
55
55
|
)
|
|
56
|
-
:
|
|
56
|
+
: err(annotate(blob, 'Must be an object'));
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
/**
|
|
@@ -144,10 +144,10 @@ export function object<O: { +[field: string]: AnyDecoder, ... }>(
|
|
|
144
144
|
objAnn = updateText(objAnn, `Missing ${pluralized}: ${errMsg}`);
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
return
|
|
147
|
+
return err(objAnn);
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
return
|
|
150
|
+
return ok(record);
|
|
151
151
|
});
|
|
152
152
|
}
|
|
153
153
|
|
|
@@ -160,11 +160,11 @@ export function exact<O: { +[field: string]: AnyDecoder, ... }>(
|
|
|
160
160
|
const actual = new Set(Object.keys(blob));
|
|
161
161
|
const superfluous = subtract(actual, allowed);
|
|
162
162
|
if (superfluous.size > 0) {
|
|
163
|
-
return
|
|
163
|
+
return err(
|
|
164
164
|
annotate(blob, `Superfluous keys: ${Array.from(superfluous).join(', ')}`),
|
|
165
165
|
);
|
|
166
166
|
}
|
|
167
|
-
return
|
|
167
|
+
return ok(blob);
|
|
168
168
|
});
|
|
169
169
|
|
|
170
170
|
// Defer to the "object" decoder for doing the real decoding work. Since
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { annotate, annotateObject, merge, updateText } from '../annotate.mjs';
|
|
4
|
+
import { compose, map } from './composition.mjs';
|
|
5
|
+
import { err, ok } from '../result.mjs';
|
|
6
6
|
|
|
7
7
|
function isPojo(o) {
|
|
8
8
|
return o !== null && o !== undefined && typeof o === 'object' && // This still seems to be the only reliable way to determine whether
|
|
@@ -22,7 +22,7 @@ function subtract(xs, ys) {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export var pojo = function pojo(blob) {
|
|
25
|
-
return isPojo(blob) ?
|
|
25
|
+
return isPojo(blob) ? ok( // NOTE:
|
|
26
26
|
// Since Flow 0.98, typeof o === 'object' refines to
|
|
27
27
|
// {| +[string]: mixed |}
|
|
28
28
|
// instead of
|
|
@@ -36,7 +36,7 @@ export var pojo = function pojo(blob) {
|
|
|
36
36
|
// way to turn a read-only Object to a writeable one in ES6 seems
|
|
37
37
|
// to be to use object-spread. (Going off this benchmark:
|
|
38
38
|
// https://thecodebarbarian.com/object-assign-vs-object-spread.html)
|
|
39
|
-
_extends({}, blob)) :
|
|
39
|
+
_extends({}, blob)) : err(annotate(blob, 'Must be an object'));
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
42
42
|
* Given a mapping of fields-to-decoders, builds a decoder for an object type.
|
|
@@ -122,10 +122,10 @@ export function object(mapping) {
|
|
|
122
122
|
objAnn = updateText(objAnn, "Missing " + pluralized + ": " + errMsg);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
return
|
|
125
|
+
return err(objAnn);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
return
|
|
128
|
+
return ok(record);
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
131
|
export function exact(mapping) {
|
|
@@ -136,10 +136,10 @@ export function exact(mapping) {
|
|
|
136
136
|
var superfluous = subtract(actual, allowed);
|
|
137
137
|
|
|
138
138
|
if (superfluous.size > 0) {
|
|
139
|
-
return
|
|
139
|
+
return err(annotate(blob, "Superfluous keys: " + Array.from(superfluous).join(', ')));
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
return
|
|
142
|
+
return ok(blob);
|
|
143
143
|
}); // Defer to the "object" decoder for doing the real decoding work. Since
|
|
144
144
|
// we made sure there are no superfluous keys in this structure, it's now
|
|
145
145
|
// safe to force-cast it to an $Exact<> type.
|
package/core/optional.js
CHANGED
|
@@ -5,17 +5,13 @@ exports.maybe = maybe;
|
|
|
5
5
|
exports.nullable = nullable;
|
|
6
6
|
exports.optional = optional;
|
|
7
7
|
|
|
8
|
-
var Result = _interopRequireWildcard(require("../result"));
|
|
9
|
-
|
|
10
8
|
var _annotate = require("../annotate");
|
|
11
9
|
|
|
12
10
|
var _either = require("./either");
|
|
13
11
|
|
|
14
|
-
var
|
|
15
|
-
|
|
16
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
12
|
+
var _result = require("../result");
|
|
17
13
|
|
|
18
|
-
|
|
14
|
+
var _constants = require("./constants");
|
|
19
15
|
|
|
20
16
|
/**
|
|
21
17
|
* Builds a Decoder that returns Ok for either `undefined` or `T` values,
|
|
@@ -41,8 +37,8 @@ function nullable(decoder) {
|
|
|
41
37
|
|
|
42
38
|
|
|
43
39
|
var undefined_or_null = function undefined_or_null(blob) {
|
|
44
|
-
return blob === undefined || blob === null ?
|
|
45
|
-
|
|
40
|
+
return blob === undefined || blob === null ? (0, _result.ok)(blob) : // Combine error message into a single line
|
|
41
|
+
(0, _result.err)((0, _annotate.annotate)(blob, 'Must be undefined or null'));
|
|
46
42
|
};
|
|
47
43
|
/**
|
|
48
44
|
* Decoder that only returns Ok for `null` or `undefined` inputs.
|
package/core/optional.js.flow
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
|
|
3
|
-
import * as Result from '../result';
|
|
4
3
|
import { annotate } from '../annotate';
|
|
5
4
|
import { either } from './either';
|
|
5
|
+
import { err, ok } from '../result';
|
|
6
6
|
import { null_, undefined_ } from './constants';
|
|
7
7
|
import type { Decoder } from '../_types';
|
|
8
8
|
|
|
@@ -29,9 +29,9 @@ export function nullable<T>(decoder: Decoder<T>): Decoder<null | T> {
|
|
|
29
29
|
*/
|
|
30
30
|
const undefined_or_null: Decoder<null | void> = (blob: mixed) =>
|
|
31
31
|
blob === undefined || blob === null
|
|
32
|
-
?
|
|
32
|
+
? ok(blob)
|
|
33
33
|
: // Combine error message into a single line
|
|
34
|
-
|
|
34
|
+
err(annotate(blob, 'Must be undefined or null'));
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Decoder that only returns Ok for `null` or `undefined` inputs.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { null_, undefined_ } from './constants';
|
|
1
|
+
import { annotate } from '../annotate.mjs';
|
|
2
|
+
import { either } from './either.mjs';
|
|
3
|
+
import { err, ok } from '../result.mjs';
|
|
4
|
+
import { null_, undefined_ } from './constants.mjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Builds a Decoder that returns Ok for either `undefined` or `T` values,
|
|
@@ -25,8 +25,8 @@ export function nullable(decoder) {
|
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
27
|
var undefined_or_null = function undefined_or_null(blob) {
|
|
28
|
-
return blob === undefined || blob === null ?
|
|
29
|
-
|
|
28
|
+
return blob === undefined || blob === null ? ok(blob) : // Combine error message into a single line
|
|
29
|
+
err(annotate(blob, 'Must be undefined or null'));
|
|
30
30
|
};
|
|
31
31
|
/**
|
|
32
32
|
* Decoder that only returns Ok for `null` or `undefined` inputs.
|
package/core/string.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
|
|
3
|
+
import { Decoder } from '../_types';
|
|
4
|
+
|
|
5
|
+
export const string: Decoder<string>;
|
|
6
|
+
export const nonEmptyString: Decoder<string>;
|
|
7
|
+
export function regex(regex: RegExp, msg: string): Decoder<string>;
|
|
8
|
+
export const email: Decoder<string>;
|
|
9
|
+
export const url: Decoder<URL>;
|
|
10
|
+
export const httpsUrl: Decoder<URL>;
|
package/core/string.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.nonEmptyString = exports.email = void 0;
|
|
4
|
+
exports.nonEmptyString = exports.httpsUrl = exports.email = void 0;
|
|
5
5
|
exports.regex = regex;
|
|
6
6
|
exports.url = exports.string = void 0;
|
|
7
7
|
|
|
8
|
-
var Result = _interopRequireWildcard(require("../result"));
|
|
9
|
-
|
|
10
8
|
var _annotate = require("../annotate");
|
|
11
9
|
|
|
12
|
-
var
|
|
10
|
+
var _either = require("./either");
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
var _result = require("../result");
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
var _instanceOf = require("./instanceOf");
|
|
15
|
+
|
|
16
|
+
var _composition = require("./composition");
|
|
17
17
|
|
|
18
18
|
/** Match groups in this regex:
|
|
19
19
|
* \1 - the scheme
|
|
@@ -22,15 +22,13 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
22
22
|
* \4 - the port (optional)
|
|
23
23
|
* \5 - the path (optional)
|
|
24
24
|
*/
|
|
25
|
-
var url_re = /^([A-Za-z]{3,9}(?:[+][A-Za-z]{3,9})?):\/\/(?:([-;:&=+$,\w]+)@)?(?:([A-Za-z0-9.-]+)(?::([0-9]{2,5}))?)(\/(?:[-+~%/.,\w]*)?(?:\?[-+=&;%@.,\w]*)?(?:#[.,!/\w]*)?)?$/;
|
|
26
|
-
|
|
27
|
-
var DEFAULT_SCHEMES = ['https'];
|
|
25
|
+
var url_re = /^([A-Za-z]{3,9}(?:[+][A-Za-z]{3,9})?):\/\/(?:([-;:&=+$,\w]+)@)?(?:([A-Za-z0-9.-]+)(?::([0-9]{2,5}))?)(\/(?:[-+~%/.,\w]*)?(?:\?[-+=&;%@.,\w]*)?(?:#[.,!/\w]*)?)?$/;
|
|
28
26
|
/**
|
|
29
27
|
* Decoder that only returns Ok for string inputs. Err otherwise.
|
|
30
28
|
*/
|
|
31
29
|
|
|
32
30
|
var string = function string(blob) {
|
|
33
|
-
return typeof blob === 'string' ?
|
|
31
|
+
return typeof blob === 'string' ? (0, _result.ok)(blob) : (0, _result.err)((0, _annotate.annotate)(blob, 'Must be string'));
|
|
34
32
|
};
|
|
35
33
|
/**
|
|
36
34
|
* Decoder that only returns Ok for non-empty string inputs. Err otherwise.
|
|
@@ -48,9 +46,9 @@ var nonEmptyString = regex(/\S/, 'Must be non-empty string');
|
|
|
48
46
|
exports.nonEmptyString = nonEmptyString;
|
|
49
47
|
|
|
50
48
|
function regex(regex, msg) {
|
|
51
|
-
return (0, _composition.
|
|
49
|
+
return (0, _composition.predicate)(string, function (s) {
|
|
52
50
|
return regex.test(s);
|
|
53
|
-
}, msg)
|
|
51
|
+
}, msg);
|
|
54
52
|
}
|
|
55
53
|
/**
|
|
56
54
|
* Decoder that only returns Ok for string inputs that match the almost perfect
|
|
@@ -59,40 +57,12 @@ function regex(regex, msg) {
|
|
|
59
57
|
|
|
60
58
|
|
|
61
59
|
var email = regex(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, 'Must be email');
|
|
62
|
-
/**
|
|
63
|
-
* Decoder that only returns Ok for string inputs that match URLs of the
|
|
64
|
-
* expected scheme. Defaults to only accept HTTPS URLs. Err otherwise.
|
|
65
|
-
*
|
|
66
|
-
* Variants that can be used:
|
|
67
|
-
*
|
|
68
|
-
* - url() accepts only https:// URLs
|
|
69
|
-
* - url([]) accepts any URL scheme
|
|
70
|
-
* - url(['http']) accepts only HTTP
|
|
71
|
-
* - url(['https', 'git+ssh']) accepts both https:// and git+ssh:// URLs
|
|
72
|
-
*/
|
|
73
|
-
|
|
74
60
|
exports.email = email;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (!matches) {
|
|
85
|
-
return Result.err((0, _annotate.annotate)(value, 'Must be URL'));
|
|
86
|
-
} else {
|
|
87
|
-
var scheme = matches[1];
|
|
88
|
-
|
|
89
|
-
if (schemes.length === 0 || schemes.includes(scheme.toLowerCase())) {
|
|
90
|
-
return Result.ok(value);
|
|
91
|
-
} else {
|
|
92
|
-
return Result.err((0, _annotate.annotate)(value, "URL scheme must be any of: " + schemes.join(', ')));
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
exports.url = url;
|
|
61
|
+
var url = (0, _either.either)((0, _composition.map)(regex(url_re, 'Must be URL'), function (value) {
|
|
62
|
+
return new URL(value);
|
|
63
|
+
}), (0, _instanceOf.instanceOf)(URL));
|
|
64
|
+
exports.url = url;
|
|
65
|
+
var httpsUrl = (0, _composition.predicate)(url, function (value) {
|
|
66
|
+
return value.protocol === 'https:';
|
|
67
|
+
}, 'Must be an HTTPS URL');
|
|
68
|
+
exports.httpsUrl = httpsUrl;
|
package/core/string.js.flow
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
|
|
3
|
-
import * as Result from '../result';
|
|
4
3
|
import { annotate } from '../annotate';
|
|
5
|
-
import {
|
|
4
|
+
import { either } from './either';
|
|
5
|
+
import { err, ok } from '../result';
|
|
6
|
+
import { instanceOf } from './instanceOf';
|
|
7
|
+
import { map, predicate } from './composition';
|
|
6
8
|
import type { Decoder } from '../_types';
|
|
7
9
|
|
|
8
10
|
/** Match groups in this regex:
|
|
@@ -15,16 +17,11 @@ import type { Decoder } from '../_types';
|
|
|
15
17
|
const url_re =
|
|
16
18
|
/^([A-Za-z]{3,9}(?:[+][A-Za-z]{3,9})?):\/\/(?:([-;:&=+$,\w]+)@)?(?:([A-Za-z0-9.-]+)(?::([0-9]{2,5}))?)(\/(?:[-+~%/.,\w]*)?(?:\?[-+=&;%@.,\w]*)?(?:#[.,!/\w]*)?)?$/;
|
|
17
19
|
|
|
18
|
-
// The URL schemes the url() decoder accepts by default
|
|
19
|
-
const DEFAULT_SCHEMES = ['https'];
|
|
20
|
-
|
|
21
20
|
/**
|
|
22
21
|
* Decoder that only returns Ok for string inputs. Err otherwise.
|
|
23
22
|
*/
|
|
24
23
|
export const string: Decoder<string> = (blob: mixed) => {
|
|
25
|
-
return typeof blob === 'string'
|
|
26
|
-
? Result.ok(blob)
|
|
27
|
-
: Result.err(annotate(blob, 'Must be string'));
|
|
24
|
+
return typeof blob === 'string' ? ok(blob) : err(annotate(blob, 'Must be string'));
|
|
28
25
|
};
|
|
29
26
|
|
|
30
27
|
/**
|
|
@@ -38,10 +35,7 @@ export const nonEmptyString: Decoder<string> = regex(/\S/, 'Must be non-empty st
|
|
|
38
35
|
* before testing the regex.
|
|
39
36
|
*/
|
|
40
37
|
export function regex(regex: RegExp, msg: string): Decoder<string> {
|
|
41
|
-
return
|
|
42
|
-
string,
|
|
43
|
-
predicate((s) => regex.test(s), msg),
|
|
44
|
-
);
|
|
38
|
+
return predicate(string, (s) => regex.test(s), msg);
|
|
45
39
|
}
|
|
46
40
|
|
|
47
41
|
/**
|
|
@@ -53,30 +47,13 @@ export const email: Decoder<string> = regex(
|
|
|
53
47
|
'Must be email',
|
|
54
48
|
);
|
|
55
49
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
*/
|
|
67
|
-
export const url = (schemes: $ReadOnlyArray<string> = DEFAULT_SCHEMES): Decoder<string> =>
|
|
68
|
-
compose(string, (value: string) => {
|
|
69
|
-
const matches = value.match(url_re);
|
|
70
|
-
if (!matches) {
|
|
71
|
-
return Result.err(annotate(value, 'Must be URL'));
|
|
72
|
-
} else {
|
|
73
|
-
const scheme = matches[1];
|
|
74
|
-
if (schemes.length === 0 || schemes.includes(scheme.toLowerCase())) {
|
|
75
|
-
return Result.ok(value);
|
|
76
|
-
} else {
|
|
77
|
-
return Result.err(
|
|
78
|
-
annotate(value, `URL scheme must be any of: ${schemes.join(', ')}`),
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
});
|
|
50
|
+
export const url: Decoder<URL> = either(
|
|
51
|
+
map(regex(url_re, 'Must be URL'), (value) => new URL(value)),
|
|
52
|
+
instanceOf(URL),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
export const httpsUrl: Decoder<URL> = predicate(
|
|
56
|
+
url,
|
|
57
|
+
(value) => value.protocol === 'https:',
|
|
58
|
+
'Must be an HTTPS URL',
|
|
59
|
+
);
|
package/core/string.mjs
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { annotate } from '../annotate.mjs';
|
|
2
|
+
import { either } from './either.mjs';
|
|
3
|
+
import { err, ok } from '../result.mjs';
|
|
4
|
+
import { instanceOf } from './instanceOf.mjs';
|
|
5
|
+
import { map, predicate } from './composition.mjs';
|
|
6
|
+
|
|
7
|
+
/** Match groups in this regex:
|
|
8
|
+
* \1 - the scheme
|
|
9
|
+
* \2 - the username/password (optional)
|
|
10
|
+
* \3 - the host
|
|
11
|
+
* \4 - the port (optional)
|
|
12
|
+
* \5 - the path (optional)
|
|
13
|
+
*/
|
|
14
|
+
var url_re = /^([A-Za-z]{3,9}(?:[+][A-Za-z]{3,9})?):\/\/(?:([-;:&=+$,\w]+)@)?(?:([A-Za-z0-9.-]+)(?::([0-9]{2,5}))?)(\/(?:[-+~%/.,\w]*)?(?:\?[-+=&;%@.,\w]*)?(?:#[.,!/\w]*)?)?$/;
|
|
15
|
+
/**
|
|
16
|
+
* Decoder that only returns Ok for string inputs. Err otherwise.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export var string = function string(blob) {
|
|
20
|
+
return typeof blob === 'string' ? ok(blob) : err(annotate(blob, 'Must be string'));
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Decoder that only returns Ok for non-empty string inputs. Err otherwise.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export var nonEmptyString = regex(/\S/, 'Must be non-empty string');
|
|
27
|
+
/**
|
|
28
|
+
* Decoder that only returns Ok for string inputs that match the regular
|
|
29
|
+
* expression. Err otherwise. Will always validate that the input is a string
|
|
30
|
+
* before testing the regex.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
export function regex(regex, msg) {
|
|
34
|
+
return predicate(string, function (s) {
|
|
35
|
+
return regex.test(s);
|
|
36
|
+
}, msg);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Decoder that only returns Ok for string inputs that match the almost perfect
|
|
40
|
+
* email regex, taken from http://emailregex.com. Err otherwise.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
export var email = regex(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, 'Must be email');
|
|
44
|
+
export var url = either(map(regex(url_re, 'Must be URL'), function (value) {
|
|
45
|
+
return new URL(value);
|
|
46
|
+
}), instanceOf(URL));
|
|
47
|
+
export var httpsUrl = predicate(url, function (value) {
|
|
48
|
+
return value.protocol === 'https:';
|
|
49
|
+
}, 'Must be an HTTPS URL');
|
package/core/tuple.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Decoder } from '../_types';
|
|
2
|
+
|
|
3
|
+
export function tuple1<T1>(d1: Decoder<T1>): Decoder<[T1]>;
|
|
4
|
+
export function tuple2<T1, T2>(d1: Decoder<T1>, d2: Decoder<T2>): Decoder<[T1, T2]>;
|
|
5
|
+
export function tuple3<T1, T2, T3>(
|
|
6
|
+
d1: Decoder<T1>,
|
|
7
|
+
d2: Decoder<T2>,
|
|
8
|
+
d3: Decoder<T3>,
|
|
9
|
+
): Decoder<[T1, T2, T3]>;
|
|
10
|
+
export function tuple4<T1, T2, T3, T4>(
|
|
11
|
+
d1: Decoder<T1>,
|
|
12
|
+
d2: Decoder<T2>,
|
|
13
|
+
d3: Decoder<T3>,
|
|
14
|
+
d4: Decoder<T4>,
|
|
15
|
+
): Decoder<[T1, T2, T3, T4]>;
|
|
16
|
+
export function tuple5<T1, T2, T3, T4, T5>(
|
|
17
|
+
d1: Decoder<T1>,
|
|
18
|
+
d2: Decoder<T2>,
|
|
19
|
+
d3: Decoder<T3>,
|
|
20
|
+
d4: Decoder<T4>,
|
|
21
|
+
d5: Decoder<T5>,
|
|
22
|
+
): Decoder<[T1, T2, T3, T4, T5]>;
|
|
23
|
+
export function tuple6<T1, T2, T3, T4, T5, T6>(
|
|
24
|
+
d1: Decoder<T1>,
|
|
25
|
+
d2: Decoder<T2>,
|
|
26
|
+
d3: Decoder<T3>,
|
|
27
|
+
d4: Decoder<T4>,
|
|
28
|
+
d5: Decoder<T5>,
|
|
29
|
+
d6: Decoder<T6>,
|
|
30
|
+
): Decoder<[T1, T2, T3, T4, T5, T6]>;
|
package/core/tuple.js
CHANGED
|
@@ -16,10 +16,14 @@ var _result = require("../result");
|
|
|
16
16
|
|
|
17
17
|
var _array = require("./array");
|
|
18
18
|
|
|
19
|
+
function okOrErr(result) {
|
|
20
|
+
return result.type === 'ok' ? result.value : result.error;
|
|
21
|
+
}
|
|
22
|
+
|
|
19
23
|
var ntuple = function ntuple(n) {
|
|
20
|
-
return (0, _composition.
|
|
24
|
+
return (0, _composition.predicate)(_array.poja, function (arr) {
|
|
21
25
|
return arr.length === n;
|
|
22
|
-
}, "Must be a " + n + "-tuple")
|
|
26
|
+
}, "Must be a " + n + "-tuple");
|
|
23
27
|
};
|
|
24
28
|
/**
|
|
25
29
|
* Builds a Decoder that returns Ok for 1-tuple of [T], given a Decoder for T.
|
|
@@ -37,7 +41,7 @@ function tuple1(decoder1) {
|
|
|
37
41
|
} catch (e) {
|
|
38
42
|
// If a decoder error has happened while unwrapping all the
|
|
39
43
|
// results, try to construct a good error message
|
|
40
|
-
return (0, _result.err)((0, _annotate.annotate)([(
|
|
44
|
+
return (0, _result.err)((0, _annotate.annotate)([okOrErr(result1)]));
|
|
41
45
|
}
|
|
42
46
|
});
|
|
43
47
|
}
|
|
@@ -59,7 +63,7 @@ function tuple2(decoder1, decoder2) {
|
|
|
59
63
|
} catch (e) {
|
|
60
64
|
// If a decoder error has happened while unwrapping all the
|
|
61
65
|
// results, try to construct a good error message
|
|
62
|
-
return (0, _result.err)((0, _annotate.annotate)([(
|
|
66
|
+
return (0, _result.err)((0, _annotate.annotate)([okOrErr(result1), okOrErr(result2)]));
|
|
63
67
|
}
|
|
64
68
|
});
|
|
65
69
|
}
|
|
@@ -83,7 +87,7 @@ function tuple3(decoder1, decoder2, decoder3) {
|
|
|
83
87
|
} catch (e) {
|
|
84
88
|
// If a decoder error has happened while unwrapping all the
|
|
85
89
|
// results, try to construct a good error message
|
|
86
|
-
return (0, _result.err)((0, _annotate.annotate)([(
|
|
90
|
+
return (0, _result.err)((0, _annotate.annotate)([okOrErr(result1), okOrErr(result2), okOrErr(result3)]));
|
|
87
91
|
}
|
|
88
92
|
});
|
|
89
93
|
}
|
|
@@ -109,7 +113,7 @@ function tuple4(decoder1, decoder2, decoder3, decoder4) {
|
|
|
109
113
|
} catch (e) {
|
|
110
114
|
// If a decoder error has happened while unwrapping all the
|
|
111
115
|
// results, try to construct a good error message
|
|
112
|
-
return (0, _result.err)((0, _annotate.annotate)([(
|
|
116
|
+
return (0, _result.err)((0, _annotate.annotate)([okOrErr(result1), okOrErr(result2), okOrErr(result3), okOrErr(result4)]));
|
|
113
117
|
}
|
|
114
118
|
});
|
|
115
119
|
}
|
|
@@ -137,7 +141,7 @@ function tuple5(decoder1, decoder2, decoder3, decoder4, decoder5) {
|
|
|
137
141
|
} catch (e) {
|
|
138
142
|
// If a decoder error has happened while unwrapping all the
|
|
139
143
|
// results, try to construct a good error message
|
|
140
|
-
return (0, _result.err)((0, _annotate.annotate)([(
|
|
144
|
+
return (0, _result.err)((0, _annotate.annotate)([okOrErr(result1), okOrErr(result2), okOrErr(result3), okOrErr(result4), okOrErr(result5)]));
|
|
141
145
|
}
|
|
142
146
|
});
|
|
143
147
|
}
|
|
@@ -167,7 +171,7 @@ function tuple6(decoder1, decoder2, decoder3, decoder4, decoder5, decoder6) {
|
|
|
167
171
|
} catch (e) {
|
|
168
172
|
// If a decoder error has happened while unwrapping all the
|
|
169
173
|
// results, try to construct a good error message
|
|
170
|
-
return (0, _result.err)((0, _annotate.annotate)([(
|
|
174
|
+
return (0, _result.err)((0, _annotate.annotate)([okOrErr(result1), okOrErr(result2), okOrErr(result3), okOrErr(result4), okOrErr(result5), okOrErr(result6)]));
|
|
171
175
|
}
|
|
172
176
|
});
|
|
173
177
|
}
|