@evolu/common 7.4.1 → 8.0.0-next.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/README.md +4 -61
- package/dist/src/Array.d.ts +343 -102
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +181 -85
- package/dist/src/Assert.d.ts +57 -11
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +47 -11
- package/dist/src/BigInt.d.ts +6 -1
- package/dist/src/BigInt.d.ts.map +1 -1
- package/dist/src/BigInt.js +5 -0
- package/dist/src/Brand.d.ts +40 -12
- package/dist/src/Brand.d.ts.map +1 -1
- package/dist/src/Brand.js +5 -0
- package/dist/src/Buffer.d.ts +6 -1
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Buffer.js +7 -2
- package/dist/src/Cache.d.ts +10 -2
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +6 -0
- package/dist/src/Callbacks.d.ts +10 -7
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Callbacks.js +23 -13
- package/dist/src/Console.d.ts +361 -69
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +217 -117
- package/dist/src/Crypto.d.ts +70 -21
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +72 -27
- package/dist/src/Eq.d.ts +22 -2
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +21 -1
- package/dist/src/Error.d.ts +23 -12
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +27 -11
- package/dist/src/Function.d.ts +128 -56
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +118 -14
- package/dist/src/Identicon.d.ts +5 -0
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +6 -1
- package/dist/src/Lookup.d.ts +162 -0
- package/dist/src/Lookup.d.ts.map +1 -0
- package/dist/src/Lookup.js +200 -0
- package/dist/src/Microtask.d.ts +21 -0
- package/dist/src/Microtask.d.ts.map +1 -0
- package/dist/src/Microtask.js +37 -0
- package/dist/src/Number.d.ts +18 -4
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +23 -1
- package/dist/src/Object.d.ts +110 -5
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +108 -5
- package/dist/src/Option.d.ts +58 -0
- package/dist/src/Option.d.ts.map +1 -0
- package/dist/src/Option.js +43 -0
- package/dist/src/Order.d.ts +5 -0
- package/dist/src/Order.d.ts.map +1 -1
- package/dist/src/Order.js +8 -3
- package/dist/src/Platform.d.ts +36 -2
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +10 -6
- package/dist/src/Polyfills.d.ts +29 -0
- package/dist/src/Polyfills.d.ts.map +1 -0
- package/dist/src/Polyfills.js +329 -0
- package/dist/src/Random.d.ts +18 -7
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +9 -7
- package/dist/src/Redacted.d.ts +7 -4
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +5 -0
- package/dist/src/Ref.d.ts +31 -16
- package/dist/src/Ref.d.ts.map +1 -1
- package/dist/src/Ref.js +35 -7
- package/dist/src/RefCount.d.ts +62 -0
- package/dist/src/RefCount.d.ts.map +1 -0
- package/dist/src/RefCount.js +83 -0
- package/dist/src/Relation.d.ts +84 -29
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Relation.js +83 -105
- package/dist/src/Resource.d.ts +263 -0
- package/dist/src/Resource.d.ts.map +1 -0
- package/dist/src/Resource.js +389 -0
- package/dist/src/Result.d.ts +390 -374
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +142 -70
- package/dist/src/Schedule.d.ts +953 -0
- package/dist/src/Schedule.d.ts.map +1 -0
- package/dist/src/Schedule.js +1199 -0
- package/dist/src/Set.d.ts +181 -0
- package/dist/src/Set.d.ts.map +1 -0
- package/dist/src/Set.js +137 -0
- package/dist/src/Skiplist.d.ts +6 -1
- package/dist/src/Skiplist.d.ts.map +1 -1
- package/dist/src/Skiplist.js +5 -0
- package/dist/src/Sqlite.d.ts +160 -60
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +290 -190
- package/dist/src/Store.d.ts +36 -28
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +55 -15
- package/dist/src/String.d.ts +5 -0
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +5 -0
- package/dist/src/Task.d.ts +2274 -423
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +1499 -348
- package/dist/src/Test.d.ts +150 -0
- package/dist/src/Test.d.ts.map +1 -0
- package/dist/src/Test.js +97 -0
- package/dist/src/Time.d.ts +202 -48
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +199 -88
- package/dist/src/Tracer.d.ts +48 -0
- package/dist/src/Tracer.d.ts.map +1 -0
- package/dist/src/Tracer.js +6 -0
- package/dist/src/Type.d.ts +587 -209
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +370 -240
- package/dist/src/Types.d.ts +160 -6
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +22 -2
- package/dist/src/WebSocket.d.ts +130 -58
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +274 -113
- package/dist/src/Worker.d.ts +245 -60
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +220 -64
- package/dist/src/index.d.ts +25 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +19 -3
- package/dist/src/local-first/Db.d.ts +24 -213
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +621 -293
- package/dist/src/local-first/Error.d.ts +12 -0
- package/dist/src/local-first/Error.d.ts.map +1 -0
- package/dist/src/local-first/Error.js +6 -0
- package/dist/src/local-first/Evolu.d.ts +330 -285
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +472 -402
- package/dist/src/local-first/LocalAuth.d.ts +10 -10
- package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
- package/dist/src/local-first/LocalAuth.js +6 -1
- package/dist/src/local-first/Owner.d.ts +70 -27
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +27 -14
- package/dist/src/local-first/Protocol.d.ts +58 -50
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +253 -155
- package/dist/src/local-first/Query.d.ts +133 -43
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +139 -90
- package/dist/src/local-first/Relay.d.ts +34 -49
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Relay.js +59 -177
- package/dist/src/local-first/Schema.d.ts +139 -144
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +78 -163
- package/dist/src/local-first/Shared.d.ts +125 -0
- package/dist/src/local-first/Shared.d.ts.map +1 -0
- package/dist/src/local-first/Shared.js +569 -0
- package/dist/src/local-first/Storage.d.ts +54 -58
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +127 -179
- package/dist/src/local-first/Timestamp.d.ts +28 -35
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +24 -25
- package/dist/src/local-first/index.d.ts +2 -15
- package/dist/src/local-first/index.d.ts.map +1 -1
- package/dist/src/local-first/index.js +2 -15
- package/package.json +37 -24
- package/src/Array.ts +467 -106
- package/src/Assert.ts +87 -12
- package/src/BigInt.ts +7 -1
- package/src/Brand.ts +41 -12
- package/src/Buffer.ts +10 -4
- package/src/Cache.ts +11 -2
- package/src/Callbacks.ts +33 -23
- package/src/Console.ts +567 -178
- package/src/Crypto.ts +111 -62
- package/src/Eq.ts +30 -3
- package/src/Error.ts +50 -34
- package/src/Function.ts +140 -68
- package/src/Identicon.ts +7 -1
- package/src/Lookup.ts +429 -0
- package/src/Microtask.ts +58 -0
- package/src/Number.ts +40 -7
- package/src/Object.ts +155 -16
- package/src/Option.ts +74 -0
- package/src/Order.ts +11 -3
- package/src/Platform.ts +43 -7
- package/src/Polyfills.ts +520 -0
- package/src/Random.ts +25 -11
- package/src/Redacted.ts +8 -4
- package/src/Ref.ts +72 -21
- package/src/RefCount.ts +170 -0
- package/src/Relation.ts +188 -136
- package/src/Resource.ts +864 -0
- package/src/Result.ts +548 -381
- package/src/Schedule.ts +1471 -0
- package/src/Set.ts +247 -0
- package/src/Skiplist.ts +7 -1
- package/src/Sqlite.ts +409 -304
- package/src/Store.ts +94 -48
- package/src/String.ts +6 -0
- package/src/Task.ts +3696 -740
- package/src/Test.ts +202 -0
- package/src/Time.ts +357 -147
- package/src/Tracer.ts +54 -0
- package/src/Type.ts +866 -430
- package/src/Types.ts +202 -7
- package/src/WebSocket.ts +404 -167
- package/src/Worker.ts +527 -147
- package/src/index.ts +74 -3
- package/src/local-first/Db.ts +867 -597
- package/src/local-first/Error.ts +17 -0
- package/src/local-first/Evolu.ts +884 -824
- package/src/local-first/LocalAuth.ts +10 -10
- package/src/local-first/Owner.ts +94 -42
- package/src/local-first/Protocol.ts +441 -307
- package/src/local-first/Query.ts +243 -194
- package/src/local-first/Relay.ts +119 -273
- package/src/local-first/Schema.ts +284 -394
- package/src/local-first/Shared.ts +932 -0
- package/src/local-first/Storage.ts +211 -283
- package/src/local-first/Timestamp.ts +38 -45
- package/src/local-first/index.ts +2 -16
- package/dist/src/Instances.d.ts +0 -34
- package/dist/src/Instances.d.ts.map +0 -1
- package/dist/src/Instances.js +0 -44
- package/dist/src/Resources.d.ts +0 -118
- package/dist/src/Resources.d.ts.map +0 -1
- package/dist/src/Resources.js +0 -197
- package/dist/src/local-first/Platform.d.ts +0 -25
- package/dist/src/local-first/Platform.d.ts.map +0 -1
- package/dist/src/local-first/Platform.js +0 -1
- package/dist/src/local-first/Public.d.ts +0 -22
- package/dist/src/local-first/Public.d.ts.map +0 -1
- package/dist/src/local-first/Public.js +0 -15
- package/dist/src/local-first/PublicKysely.d.ts +0 -148
- package/dist/src/local-first/PublicKysely.d.ts.map +0 -1
- package/dist/src/local-first/PublicKysely.js +0 -184
- package/dist/src/local-first/Sync.d.ts +0 -112
- package/dist/src/local-first/Sync.d.ts.map +0 -1
- package/dist/src/local-first/Sync.js +0 -526
- package/src/Instances.ts +0 -92
- package/src/Resources.ts +0 -367
- package/src/local-first/Platform.ts +0 -27
- package/src/local-first/Public.ts +0 -42
- package/src/local-first/PublicKysely.ts +0 -239
- package/src/local-first/Sync.ts +0 -949
package/dist/src/Type.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime type validation, parsing, and branded types.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
1
6
|
import { utf8ToBytes } from "@noble/ciphers/utils.js";
|
|
2
7
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
3
8
|
import * as bip39 from "@scure/bip39";
|
|
4
9
|
import { wordlist } from "@scure/bip39/wordlists/english.js";
|
|
5
|
-
import {
|
|
6
|
-
import { isPlainObject } from "./Object.js";
|
|
10
|
+
import { exhaustiveCheck } from "./Function.js";
|
|
11
|
+
import { isFunction, isPlainObject } from "./Object.js";
|
|
7
12
|
import { hasNodeBuffer } from "./Platform.js";
|
|
8
13
|
import { err, getOrNull, getOrThrow, ok, trySync } from "./Result.js";
|
|
9
14
|
import { safelyStringifyUnknownValue } from "./String.js";
|
|
@@ -11,7 +16,7 @@ const EvoluTypeSymbol = Symbol("evolu.Type");
|
|
|
11
16
|
/**
|
|
12
17
|
* Checks if the given value is an {@link Type}.
|
|
13
18
|
*
|
|
14
|
-
* @
|
|
19
|
+
* @group Utilities
|
|
15
20
|
*/
|
|
16
21
|
export const isType = (value) => typeof value === "object" && value !== null && EvoluTypeSymbol in value;
|
|
17
22
|
const createType = (name, definition) => ({
|
|
@@ -36,9 +41,8 @@ const createType = (name, definition) => ({
|
|
|
36
41
|
if (result.ok) {
|
|
37
42
|
return { value: result.value };
|
|
38
43
|
}
|
|
39
|
-
cachedStandardSchemaFormatTypeError ??= createFormatTypeError();
|
|
40
44
|
return {
|
|
41
|
-
issues: typeErrorToStandardSchemaIssues(result.error
|
|
45
|
+
issues: typeErrorToStandardSchemaIssues(result.error),
|
|
42
46
|
};
|
|
43
47
|
},
|
|
44
48
|
types: {
|
|
@@ -61,7 +65,7 @@ const createType = (name, definition) => ({
|
|
|
61
65
|
* );
|
|
62
66
|
* ```
|
|
63
67
|
*
|
|
64
|
-
* @
|
|
68
|
+
* @group Utilities
|
|
65
69
|
*/
|
|
66
70
|
export const createTypeErrorFormatter = (format) => (error) => format({ ...error, value: safelyStringifyUnknownValue(error.value) });
|
|
67
71
|
/**
|
|
@@ -85,7 +89,7 @@ export const createTypeErrorFormatter = (format) => (error) => format({ ...error
|
|
|
85
89
|
* );
|
|
86
90
|
* ```
|
|
87
91
|
*
|
|
88
|
-
* @
|
|
92
|
+
* @group Base factories
|
|
89
93
|
*/
|
|
90
94
|
export const base = (name, fromUnknown) => createType(name, {
|
|
91
95
|
fromUnknown,
|
|
@@ -104,52 +108,66 @@ export const base = (name, fromUnknown) => createType(name, {
|
|
|
104
108
|
* createBaseTypeErrorFormatter<StringError>();
|
|
105
109
|
* ```
|
|
106
110
|
*
|
|
107
|
-
* @
|
|
111
|
+
* @group Utilities
|
|
108
112
|
*/
|
|
109
113
|
export const createBaseTypeErrorFormatter = () => createTypeErrorFormatter((error) => `A value ${error.value} is not a ${error.type.toLowerCase()}.`);
|
|
110
|
-
/** @
|
|
111
|
-
export const Unknown = base("Unknown", ok);
|
|
114
|
+
/** @group Base Types */
|
|
115
|
+
export const Unknown = /*#__PURE__*/ base("Unknown", ok);
|
|
112
116
|
/**
|
|
113
|
-
* @
|
|
114
|
-
* @
|
|
117
|
+
* @group Base Types
|
|
118
|
+
* @group String
|
|
115
119
|
*/
|
|
116
|
-
export const String = base("String", (value) => typeof value === "string"
|
|
120
|
+
export const String = /*#__PURE__*/ base("String", (value) => typeof value === "string"
|
|
117
121
|
? ok(value)
|
|
118
122
|
: err({ type: "String", value }));
|
|
119
|
-
export const formatStringError =
|
|
120
|
-
|
|
121
|
-
|
|
123
|
+
export const formatStringError =
|
|
124
|
+
/*#__PURE__*/ createBaseTypeErrorFormatter();
|
|
125
|
+
/** @group Base Types */
|
|
126
|
+
export const Number = /*#__PURE__*/ base("Number", (value) => typeof value === "number"
|
|
122
127
|
? ok(value)
|
|
123
128
|
: err({ type: "Number", value }));
|
|
124
|
-
export const formatNumberError =
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
export const formatNumberError =
|
|
130
|
+
/*#__PURE__*/ createBaseTypeErrorFormatter();
|
|
131
|
+
/** @group Base Types */
|
|
132
|
+
export const BigInt = /*#__PURE__*/ base("BigInt", (value) => typeof value === "bigint"
|
|
127
133
|
? ok(value)
|
|
128
134
|
: err({ type: "BigInt", value }));
|
|
129
|
-
export const formatBigIntError =
|
|
130
|
-
|
|
131
|
-
|
|
135
|
+
export const formatBigIntError =
|
|
136
|
+
/*#__PURE__*/ createBaseTypeErrorFormatter();
|
|
137
|
+
/** @group Base Types */
|
|
138
|
+
export const Boolean = /*#__PURE__*/ base("Boolean", (value) => typeof value === "boolean"
|
|
132
139
|
? ok(value)
|
|
133
140
|
: err({ type: "Boolean", value }));
|
|
134
|
-
export const formatBooleanError =
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
export const formatBooleanError =
|
|
142
|
+
/*#__PURE__*/ createBaseTypeErrorFormatter();
|
|
143
|
+
/** @group Base Types */
|
|
144
|
+
export const Undefined = /*#__PURE__*/ base("Undefined", (value) => value === undefined
|
|
137
145
|
? ok(value)
|
|
138
146
|
: err({ type: "Undefined", value }));
|
|
139
|
-
export const formatUndefinedError =
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
export const
|
|
143
|
-
|
|
144
|
-
|
|
147
|
+
export const formatUndefinedError =
|
|
148
|
+
/*#__PURE__*/ createBaseTypeErrorFormatter();
|
|
149
|
+
/** @group Base Types */
|
|
150
|
+
export const Null = /*#__PURE__*/ base("Null", (value) => value === null ? ok(value) : err({ type: "Null", value }));
|
|
151
|
+
export const formatNullError =
|
|
152
|
+
/*#__PURE__*/ createBaseTypeErrorFormatter();
|
|
153
|
+
/** @group Base Types */
|
|
154
|
+
export const Function = /*#__PURE__*/ base("Function", (value) => isFunction(value)
|
|
145
155
|
? ok(value)
|
|
146
156
|
: err({ type: "Function", value }));
|
|
147
|
-
export const formatFunctionError =
|
|
148
|
-
|
|
149
|
-
|
|
157
|
+
export const formatFunctionError =
|
|
158
|
+
/*#__PURE__*/ createBaseTypeErrorFormatter();
|
|
159
|
+
/** @group Base Types */
|
|
160
|
+
export const Uint8Array = /*#__PURE__*/ base("Uint8Array", (value) => Object.prototype.toString.call(value) === "[object Uint8Array]"
|
|
150
161
|
? ok(value)
|
|
151
162
|
: err({ type: "Uint8Array", value }));
|
|
152
|
-
export const formatUint8ArrayError =
|
|
163
|
+
export const formatUint8ArrayError =
|
|
164
|
+
/*#__PURE__*/ createBaseTypeErrorFormatter();
|
|
165
|
+
/** @group Base Types */
|
|
166
|
+
export const ArrayBuffer = /*#__PURE__*/ base("ArrayBuffer", (value) => Object.prototype.toString.call(value) === "[object ArrayBuffer]"
|
|
167
|
+
? ok(value)
|
|
168
|
+
: err({ type: "ArrayBuffer", value }));
|
|
169
|
+
export const formatArrayBufferError =
|
|
170
|
+
/*#__PURE__*/ createBaseTypeErrorFormatter();
|
|
153
171
|
/**
|
|
154
172
|
* `instanceof` {@link Type}.
|
|
155
173
|
*
|
|
@@ -168,7 +186,7 @@ export const formatUint8ArrayError = createBaseTypeErrorFormatter();
|
|
|
168
186
|
* const error = UserInstance.from({}); // err
|
|
169
187
|
* ```
|
|
170
188
|
*
|
|
171
|
-
* @
|
|
189
|
+
* @group Base factories
|
|
172
190
|
*/
|
|
173
191
|
export const instanceOf = (ctor) => ({
|
|
174
192
|
...base("InstanceOf", (value) => value instanceof ctor
|
|
@@ -176,13 +194,14 @@ export const instanceOf = (ctor) => ({
|
|
|
176
194
|
: err({ type: "InstanceOf", value, ctor: ctor.name })),
|
|
177
195
|
ctor,
|
|
178
196
|
});
|
|
179
|
-
export const formatInstanceOfError =
|
|
197
|
+
export const formatInstanceOfError =
|
|
198
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not an instance of ${error.ctor}.`);
|
|
180
199
|
/**
|
|
181
200
|
* JavaScript Date.
|
|
182
201
|
*
|
|
183
|
-
* @
|
|
202
|
+
* @group Base Types
|
|
184
203
|
*/
|
|
185
|
-
export const Date = instanceOf(globalThis.Date);
|
|
204
|
+
export const Date = /*#__PURE__*/ instanceOf(globalThis.Date);
|
|
186
205
|
/**
|
|
187
206
|
* Validates that an unknown value is an Evolu {@link Type} (i.e., satisfies
|
|
188
207
|
* `AnyType`).
|
|
@@ -195,13 +214,14 @@ export const Date = instanceOf(globalThis.Date);
|
|
|
195
214
|
* ```
|
|
196
215
|
*/
|
|
197
216
|
// TODO: Rename to TypeInstance or something like that.
|
|
198
|
-
export const EvoluType = base("EvoluType", (value) => isType(value)
|
|
217
|
+
export const EvoluType = /*#__PURE__*/ base("EvoluType", (value) => isType(value)
|
|
199
218
|
? ok(value)
|
|
200
219
|
: err({
|
|
201
220
|
type: "EvoluType",
|
|
202
221
|
value,
|
|
203
222
|
}));
|
|
204
|
-
export const formatIsTypeError =
|
|
223
|
+
export const formatIsTypeError =
|
|
224
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `Value ${error.value} is not a valid Evolu Type.`);
|
|
205
225
|
export function brand(name, parent, refine) {
|
|
206
226
|
const fromUnknown = refine
|
|
207
227
|
? (value) => {
|
|
@@ -232,12 +252,13 @@ export function brand(name, parent, refine) {
|
|
|
232
252
|
/**
|
|
233
253
|
* A three-letter ISO 4217 currency code (e.g., USD, EUR).
|
|
234
254
|
*
|
|
235
|
-
* @
|
|
255
|
+
* @group String
|
|
236
256
|
*/
|
|
237
|
-
export const CurrencyCode = brand("CurrencyCode", String, (value) => /^[A-Z]{3}$/.test(value)
|
|
257
|
+
export const CurrencyCode = /*#__PURE__*/ brand("CurrencyCode", String, (value) => /^[A-Z]{3}$/.test(value)
|
|
238
258
|
? ok(value)
|
|
239
259
|
: err({ type: "CurrencyCode", value }));
|
|
240
|
-
export const formatCurrencyCodeError =
|
|
260
|
+
export const formatCurrencyCodeError =
|
|
261
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `Invalid currency code: ${error.value}.`);
|
|
241
262
|
/**
|
|
242
263
|
* ISO 8601 date-time string.
|
|
243
264
|
*
|
|
@@ -257,9 +278,9 @@ export const formatCurrencyCodeError = createTypeErrorFormatter((error) => `Inva
|
|
|
257
278
|
* const error = DateIso.from("10000-01-01T00:00:00.000Z"); // err
|
|
258
279
|
* ```
|
|
259
280
|
*
|
|
260
|
-
* @
|
|
281
|
+
* @group String
|
|
261
282
|
*/
|
|
262
|
-
export const DateIso = brand("DateIso", String, (value) => {
|
|
283
|
+
export const DateIso = /*#__PURE__*/ brand("DateIso", String, (value) => {
|
|
263
284
|
if (value.length !== 24) {
|
|
264
285
|
return err({ type: "DateIso", value });
|
|
265
286
|
}
|
|
@@ -274,7 +295,8 @@ export const DateIso = brand("DateIso", String, (value) => {
|
|
|
274
295
|
}
|
|
275
296
|
return ok(value);
|
|
276
297
|
});
|
|
277
|
-
export const formatDateIsoError =
|
|
298
|
+
export const formatDateIsoError =
|
|
299
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not a valid ISO 8601 date string.`);
|
|
278
300
|
export const dateToDateIso = (value) => DateIso.fromParent(value.toISOString());
|
|
279
301
|
export const dateIsoToDate = (value) => new globalThis.Date(value);
|
|
280
302
|
/**
|
|
@@ -291,25 +313,28 @@ export const dateIsoToDate = (value) => new globalThis.Date(value);
|
|
|
291
313
|
* type TrimmedNonEmptyString = typeof TrimmedNonEmptyString.Type;
|
|
292
314
|
* ```
|
|
293
315
|
*
|
|
294
|
-
* @
|
|
316
|
+
* @group String
|
|
295
317
|
*/
|
|
296
318
|
export const trimmed = (parent) => brand("Trimmed", parent, (value) => value.trim().length === value.length
|
|
297
319
|
? ok(value)
|
|
298
320
|
: err({ type: "Trimmed", value }));
|
|
299
|
-
export const formatTrimmedError =
|
|
321
|
+
export const formatTrimmedError =
|
|
322
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be trimmed.`);
|
|
300
323
|
/**
|
|
301
324
|
* Trimmed string
|
|
302
325
|
*
|
|
303
326
|
* - Use `TrimmedString.is` to check if an unknown value is trimmed.
|
|
304
327
|
* - Use `TrimmedString.from` to check if a string is trimmed.
|
|
305
328
|
*
|
|
306
|
-
* @
|
|
329
|
+
* @group String
|
|
307
330
|
*/
|
|
308
|
-
export const TrimmedString = trimmed(String);
|
|
331
|
+
export const TrimmedString = /*#__PURE__*/ trimmed(String);
|
|
309
332
|
export const trim = (value) => value.trim();
|
|
310
333
|
/**
|
|
311
334
|
* Minimum length.
|
|
312
335
|
*
|
|
336
|
+
* Use numeric literal, not expression. See {@link BrandFactory}.
|
|
337
|
+
*
|
|
313
338
|
* ### Example
|
|
314
339
|
*
|
|
315
340
|
* ```ts
|
|
@@ -317,14 +342,17 @@ export const trim = (value) => value.trim();
|
|
|
317
342
|
* const NonEmptyString = minLength(1)(String);
|
|
318
343
|
* ```
|
|
319
344
|
*
|
|
320
|
-
* @
|
|
321
|
-
* @
|
|
345
|
+
* @group String
|
|
346
|
+
* @group Array
|
|
322
347
|
*/
|
|
323
348
|
export const minLength = (min) => (parent) => brand(`MinLength${min}`, parent, (value) => value.length >= min ? ok(value) : err({ type: "MinLength", value, min }));
|
|
324
|
-
export const formatMinLengthError =
|
|
349
|
+
export const formatMinLengthError =
|
|
350
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} does not meet the minimum length of ${error.min}.`);
|
|
325
351
|
/**
|
|
326
352
|
* Maximum length.
|
|
327
353
|
*
|
|
354
|
+
* Use numeric literal, not expression. See {@link BrandFactory}.
|
|
355
|
+
*
|
|
328
356
|
* ### Example
|
|
329
357
|
*
|
|
330
358
|
* ```ts
|
|
@@ -332,14 +360,17 @@ export const formatMinLengthError = createTypeErrorFormatter((error) => `The val
|
|
|
332
360
|
* const String100 = maxLength(100)(String);
|
|
333
361
|
* ```
|
|
334
362
|
*
|
|
335
|
-
* @
|
|
336
|
-
* @
|
|
363
|
+
* @group String
|
|
364
|
+
* @group Array
|
|
337
365
|
*/
|
|
338
366
|
export const maxLength = (max) => (parent) => brand(`MaxLength${max}`, parent, (value) => value.length <= max ? ok(value) : err({ type: "MaxLength", value, max }));
|
|
339
|
-
export const formatMaxLengthError =
|
|
367
|
+
export const formatMaxLengthError =
|
|
368
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} exceeds the maximum length of ${error.max}.`);
|
|
340
369
|
/**
|
|
341
370
|
* Exact length.
|
|
342
371
|
*
|
|
372
|
+
* Use numeric literal, not expression. See {@link BrandFactory}.
|
|
373
|
+
*
|
|
343
374
|
* ### Example
|
|
344
375
|
*
|
|
345
376
|
* ```ts
|
|
@@ -347,33 +378,36 @@ export const formatMaxLengthError = createTypeErrorFormatter((error) => `The val
|
|
|
347
378
|
* const Length1String = length(1)(String);
|
|
348
379
|
* ```
|
|
349
380
|
*
|
|
350
|
-
* @
|
|
351
|
-
* @
|
|
381
|
+
* @group String
|
|
382
|
+
* @group Array
|
|
352
383
|
*/
|
|
353
384
|
export const length = (exact) => (parent) => brand(`Length${exact}`, parent, (value) => value.length === exact
|
|
354
385
|
? ok(value)
|
|
355
386
|
: err({ type: "Length", value, exact }));
|
|
356
|
-
export const formatLengthError =
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
387
|
+
export const formatLengthError =
|
|
388
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} does not have the required length of ${error.exact}.`);
|
|
389
|
+
/** @group String */
|
|
390
|
+
export const NonEmptyString = /*#__PURE__*/ minLength(1)(String);
|
|
391
|
+
/** @group String */
|
|
392
|
+
export const String100 = /*#__PURE__*/ maxLength(100)(String);
|
|
393
|
+
/** @group String */
|
|
394
|
+
export const String1000 = /*#__PURE__*/ maxLength(1000)(String);
|
|
395
|
+
/** @group String */
|
|
396
|
+
export const NonEmptyString100 = /*#__PURE__*/ minLength(1)(String100);
|
|
397
|
+
/** @group String */
|
|
398
|
+
export const NonEmptyString1000 = /*#__PURE__*/ minLength(1)(String1000);
|
|
399
|
+
/** @group String */
|
|
400
|
+
export const NonEmptyTrimmedString = /*#__PURE__*/ minLength(1)(TrimmedString);
|
|
401
|
+
/** @group String */
|
|
402
|
+
export const TrimmedString100 = /*#__PURE__*/ maxLength(100)(TrimmedString);
|
|
403
|
+
/** @group String */
|
|
404
|
+
export const TrimmedString1000 = /*#__PURE__*/ maxLength(1000)(TrimmedString);
|
|
405
|
+
/** @group String */
|
|
406
|
+
export const NonEmptyTrimmedString100 =
|
|
407
|
+
/*#__PURE__*/ minLength(1)(TrimmedString100);
|
|
408
|
+
/** @group String */
|
|
409
|
+
export const NonEmptyTrimmedString1000 =
|
|
410
|
+
/*#__PURE__*/ minLength(1)(TrimmedString1000);
|
|
377
411
|
/**
|
|
378
412
|
* The mnemonic, also known as a "seed phrase," is a set of 12 words in a
|
|
379
413
|
* specific order chosen from a predefined list (BIP39). It provides a
|
|
@@ -381,12 +415,13 @@ export const NonEmptyTrimmedString1000 = minLength(1)(TrimmedString1000);
|
|
|
381
415
|
* safely on the user's device using cryptographically secure random number
|
|
382
416
|
* generation, ensuring it remains private and unique.
|
|
383
417
|
*
|
|
384
|
-
* @
|
|
418
|
+
* @group String
|
|
385
419
|
*/
|
|
386
|
-
export const Mnemonic = brand("Mnemonic", NonEmptyTrimmedString, (value) => bip39.validateMnemonic(value, wordlist)
|
|
420
|
+
export const Mnemonic = /*#__PURE__*/ brand("Mnemonic", NonEmptyTrimmedString, (value) => bip39.validateMnemonic(value, wordlist)
|
|
387
421
|
? ok(value)
|
|
388
422
|
: err({ type: "Mnemonic", value }));
|
|
389
|
-
export const formatMnemonicError =
|
|
423
|
+
export const formatMnemonicError =
|
|
424
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `Invalid BIP39 mnemonic: ${error.value}.`);
|
|
390
425
|
/**
|
|
391
426
|
* String matching a regular expression.
|
|
392
427
|
*
|
|
@@ -396,7 +431,7 @@ export const formatMnemonicError = createTypeErrorFormatter((error) => `Invalid
|
|
|
396
431
|
* const Alphanumeric = regex("Alphanumeric", /^[a-z0-9]+$/i)(String);
|
|
397
432
|
* ```
|
|
398
433
|
*
|
|
399
|
-
* @
|
|
434
|
+
* @group String
|
|
400
435
|
*/
|
|
401
436
|
export const regex = (name, pattern) => {
|
|
402
437
|
// Clone the regex to avoid shared state.
|
|
@@ -410,7 +445,8 @@ export const regex = (name, pattern) => {
|
|
|
410
445
|
: err({ type: "Regex", name, value, pattern });
|
|
411
446
|
});
|
|
412
447
|
};
|
|
413
|
-
export const formatRegexError =
|
|
448
|
+
export const formatRegexError =
|
|
449
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} does not match the pattern for ${error.name}: ${error.pattern}.`);
|
|
414
450
|
/**
|
|
415
451
|
* URL-safe string.
|
|
416
452
|
*
|
|
@@ -436,18 +472,18 @@ export const formatRegexError = createTypeErrorFormatter((error) => `The value $
|
|
|
436
472
|
* }
|
|
437
473
|
* ```
|
|
438
474
|
*
|
|
439
|
-
* @
|
|
475
|
+
* @group String
|
|
440
476
|
*/
|
|
441
|
-
export const UrlSafeString = regex("UrlSafeString", /^[A-Za-z0-9_-]+$/)(String);
|
|
477
|
+
export const UrlSafeString = /*#__PURE__*/ regex("UrlSafeString", /^[A-Za-z0-9_-]+$/)(String);
|
|
442
478
|
/**
|
|
443
479
|
* Base64Url without padding.
|
|
444
480
|
*
|
|
445
481
|
* Encode with {@link uint8ArrayToBase64Url}, decode with
|
|
446
482
|
* {@link base64UrlToUint8Array}.
|
|
447
483
|
*
|
|
448
|
-
* @
|
|
484
|
+
* @group String
|
|
449
485
|
*/
|
|
450
|
-
export const Base64Url = brand("Base64Url", String, (value) => {
|
|
486
|
+
export const Base64Url = /*#__PURE__*/ brand("Base64Url", String, (value) => {
|
|
451
487
|
// Round-trip validation ensures consistency across different base64url
|
|
452
488
|
// implementations (Node.js Buffer, native browser API, manual fallback).
|
|
453
489
|
// Only strings that decode and encode identically are accepted.
|
|
@@ -462,7 +498,8 @@ export const Base64Url = brand("Base64Url", String, (value) => {
|
|
|
462
498
|
? ok(value)
|
|
463
499
|
: err({ type: "Base64Url", value });
|
|
464
500
|
});
|
|
465
|
-
export const formatBase64UrlError =
|
|
501
|
+
export const formatBase64UrlError =
|
|
502
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not a valid Base64Url string.`);
|
|
466
503
|
const base64UrlOptions = { alphabet: "base64url", omitPadding: true };
|
|
467
504
|
/** Encodes a Uint8Array to a {@link Base64Url} string. */
|
|
468
505
|
export const uint8ArrayToBase64Url = hasNodeBuffer
|
|
@@ -500,29 +537,30 @@ export const base64UrlToUint8Array = hasNodeBuffer
|
|
|
500
537
|
return globalThis.Uint8Array.from(binaryString, (c) => c.charCodeAt(0));
|
|
501
538
|
};
|
|
502
539
|
/**
|
|
503
|
-
*
|
|
540
|
+
* Alphanumeric string for naming in file systems, URLs, and identifiers.
|
|
504
541
|
*
|
|
505
542
|
* Uses the same safe alphabet as {@link UrlSafeString} (letters, digits, `-`,
|
|
506
|
-
* `_`).
|
|
543
|
+
* `_`).
|
|
507
544
|
*
|
|
508
545
|
* The string must be between 1 and 64 characters.
|
|
509
546
|
*
|
|
510
547
|
* ### Example
|
|
511
548
|
*
|
|
512
549
|
* ```ts
|
|
513
|
-
* const result =
|
|
550
|
+
* const result = Name.from("data-report-123");
|
|
514
551
|
* if (result.ok) {
|
|
515
|
-
* console.log("Valid
|
|
552
|
+
* console.log("Valid Name string:", result.value);
|
|
516
553
|
* } else {
|
|
517
|
-
* console.error("Invalid
|
|
554
|
+
* console.error("Invalid Name string:", result.error);
|
|
518
555
|
* }
|
|
519
556
|
* ```
|
|
520
557
|
*
|
|
521
|
-
* @
|
|
558
|
+
* @group String
|
|
522
559
|
*/
|
|
523
|
-
export const
|
|
560
|
+
export const Name = /*#__PURE__*/ brand("Name", UrlSafeString, (value) => value.length >= 1 && value.length <= 64
|
|
524
561
|
? ok(value)
|
|
525
|
-
: err({ type: "
|
|
562
|
+
: err({ type: "Name", value }));
|
|
563
|
+
export const testName = /*#__PURE__*/ Name.orThrow("Name");
|
|
526
564
|
/**
|
|
527
565
|
* Trimmed string between 8 and 64 characters, branded as `SimplePassword`.
|
|
528
566
|
*
|
|
@@ -545,9 +583,10 @@ export const SimpleName = brand("SimpleName", UrlSafeString, (value) => value.le
|
|
|
545
583
|
* // |> brand("SimplePassword", %)
|
|
546
584
|
* ```
|
|
547
585
|
*
|
|
548
|
-
* @
|
|
586
|
+
* @group String
|
|
549
587
|
*/
|
|
550
|
-
export const SimplePassword = brand("SimplePassword",
|
|
588
|
+
export const SimplePassword = /*#__PURE__*/ brand("SimplePassword",
|
|
589
|
+
/*#__PURE__*/ minLength(8)(/*#__PURE__*/ maxLength(64)(TrimmedString)));
|
|
551
590
|
export const formatSimplePasswordError = (formatTypeError) => createTypeErrorFormatter((error) => `Invalid password: ${formatTypeError(error.parentError)}`);
|
|
552
591
|
/**
|
|
553
592
|
* Evolu Id: 16 bytes encoded as a 22‑character Base64Url string.
|
|
@@ -565,19 +604,19 @@ export const formatSimplePasswordError = (formatTypeError) => createTypeErrorFor
|
|
|
565
604
|
* copied (logs, URLs, exports); only use it when you explicitly want insertion
|
|
566
605
|
* locality for very large write‑heavy tables and accept timestamp exposure.
|
|
567
606
|
*
|
|
568
|
-
*
|
|
607
|
+
* ## Future
|
|
569
608
|
*
|
|
570
609
|
* A possible hybrid masked‑time approach (`timestamp ^ H(cluster_id, timestamp
|
|
571
610
|
*
|
|
572
611
|
* > > N)`) could provide locality without exposing raw creation time. See
|
|
573
612
|
* > > https://brooker.co.za/blog/2025/10/22/uuidv7.html
|
|
574
613
|
*
|
|
575
|
-
* @
|
|
614
|
+
* @group String
|
|
576
615
|
*/
|
|
577
|
-
export const Id = brand("Id", String, (value) => value.length === 22 && Base64Url.fromParent(value).ok
|
|
616
|
+
export const Id = /*#__PURE__*/ brand("Id", String, (value) => value.length === 22 && Base64Url.fromParent(value).ok
|
|
578
617
|
? ok(value)
|
|
579
618
|
: err({ type: "Id", value }));
|
|
580
|
-
export const formatIdError = createTypeErrorFormatter((error) => `The value ${error.value} is not a valid Id.`);
|
|
619
|
+
export const formatIdError = /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not a valid Id.`);
|
|
581
620
|
/**
|
|
582
621
|
* Creates a random {@link Id}. This is the recommended default.
|
|
583
622
|
*
|
|
@@ -626,7 +665,7 @@ export const createId = (deps) => {
|
|
|
626
665
|
* external string from the generated {@link Id}. If you need to preserve the
|
|
627
666
|
* original external ID, store it in a separate column.
|
|
628
667
|
*
|
|
629
|
-
* @
|
|
668
|
+
* @group String
|
|
630
669
|
*/
|
|
631
670
|
export const createIdFromString = (value) => {
|
|
632
671
|
const hash = sha256(utf8ToBytes(value));
|
|
@@ -661,7 +700,7 @@ export const createIdAsUuidv7 = (deps) => {
|
|
|
661
700
|
id[5] = globalThis.Number(timestamp & 0xffn);
|
|
662
701
|
id[6] = (id[6] & 0x0f) | 0x70;
|
|
663
702
|
id[8] = (id[8] & 0x3f) | 0x80;
|
|
664
|
-
return id;
|
|
703
|
+
return uint8ArrayToBase64Url(id);
|
|
665
704
|
};
|
|
666
705
|
/**
|
|
667
706
|
* Creates a branded {@link Id} Type for a table's primary key.
|
|
@@ -676,7 +715,7 @@ export const createIdAsUuidv7 = (deps) => {
|
|
|
676
715
|
* type TodoId = typeof TodoId.Type;
|
|
677
716
|
* ```
|
|
678
717
|
*
|
|
679
|
-
* @
|
|
718
|
+
* @group String
|
|
680
719
|
*/
|
|
681
720
|
export const id = (table) => {
|
|
682
721
|
const fromUnknown = (value) => {
|
|
@@ -697,9 +736,11 @@ export const id = (table) => {
|
|
|
697
736
|
table,
|
|
698
737
|
};
|
|
699
738
|
};
|
|
700
|
-
export const formatTableIdError =
|
|
739
|
+
export const formatTableIdError =
|
|
740
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `Invalid Id for table ${error.table}: ${error.value}.`);
|
|
701
741
|
/** Binary representation of an {@link Id}. */
|
|
702
|
-
export const IdBytes = brand("IdBytes",
|
|
742
|
+
export const IdBytes = /*#__PURE__*/ brand("IdBytes",
|
|
743
|
+
/*#__PURE__*/ length(16)(Uint8Array));
|
|
703
744
|
export const idBytesTypeValueLength = 16;
|
|
704
745
|
export const idToIdBytes = (id) =>
|
|
705
746
|
// Id is Base64Url (validated by Id.from), cast is safe
|
|
@@ -719,10 +760,11 @@ uint8ArrayToBase64Url(idBytes);
|
|
|
719
760
|
* const errorResult = PositiveNumber.from(-5); // err
|
|
720
761
|
* ```
|
|
721
762
|
*
|
|
722
|
-
* @
|
|
763
|
+
* @group Number
|
|
723
764
|
*/
|
|
724
765
|
export const positive = (parent) => brand("Positive", parent, (value) => value > 0 ? ok(value) : err({ type: "Positive", value }));
|
|
725
|
-
export const formatPositiveError =
|
|
766
|
+
export const formatPositiveError =
|
|
767
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be positive (> 0).`);
|
|
726
768
|
/**
|
|
727
769
|
* Negative number (< 0).
|
|
728
770
|
*
|
|
@@ -732,10 +774,11 @@ export const formatPositiveError = createTypeErrorFormatter((error) => `The valu
|
|
|
732
774
|
* const NegativeNumber = negative(Number);
|
|
733
775
|
* ```
|
|
734
776
|
*
|
|
735
|
-
* @
|
|
777
|
+
* @group Number
|
|
736
778
|
*/
|
|
737
779
|
export const negative = (parent) => brand("Negative", parent, (value) => value < 0 ? ok(value) : err({ type: "Negative", value }));
|
|
738
|
-
export const formatNegativeError =
|
|
780
|
+
export const formatNegativeError =
|
|
781
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be negative (< 0).`);
|
|
739
782
|
/**
|
|
740
783
|
* Non-positive number (≤ 0).
|
|
741
784
|
*
|
|
@@ -745,12 +788,13 @@ export const formatNegativeError = createTypeErrorFormatter((error) => `The valu
|
|
|
745
788
|
* const NonPositiveNumber = nonPositive(Number);
|
|
746
789
|
* ```
|
|
747
790
|
*
|
|
748
|
-
* @
|
|
791
|
+
* @group Number
|
|
749
792
|
*/
|
|
750
793
|
export const nonPositive = (parent) => brand("NonPositive", parent, (value) => value <= 0
|
|
751
794
|
? ok(value)
|
|
752
795
|
: err({ type: "NonPositive", value }));
|
|
753
|
-
export const formatNonPositiveError =
|
|
796
|
+
export const formatNonPositiveError =
|
|
797
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be non-positive (≤ 0).`);
|
|
754
798
|
/**
|
|
755
799
|
* Non-negative number (≥ 0).
|
|
756
800
|
*
|
|
@@ -760,133 +804,156 @@ export const formatNonPositiveError = createTypeErrorFormatter((error) => `The v
|
|
|
760
804
|
* const NonNegativeNumber = nonNegative(Number);
|
|
761
805
|
* ```
|
|
762
806
|
*
|
|
763
|
-
* @
|
|
807
|
+
* @group Number
|
|
764
808
|
*/
|
|
765
809
|
export const nonNegative = (parent) => brand("NonNegative", parent, (value) => value >= 0
|
|
766
810
|
? ok(value)
|
|
767
811
|
: err({ type: "NonNegative", value }));
|
|
768
|
-
export const formatNonNegativeError =
|
|
812
|
+
export const formatNonNegativeError =
|
|
813
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be non-negative (≥ 0).`);
|
|
769
814
|
/**
|
|
770
815
|
* Non-negative number (≥ 0).
|
|
771
816
|
*
|
|
772
|
-
* @
|
|
817
|
+
* @group Number
|
|
773
818
|
*/
|
|
774
|
-
export const NonNegativeNumber = nonNegative(Number);
|
|
819
|
+
export const NonNegativeNumber = /*#__PURE__*/ nonNegative(Number);
|
|
775
820
|
/**
|
|
776
821
|
* Positive number (> 0).
|
|
777
822
|
*
|
|
778
|
-
* @
|
|
823
|
+
* @group Number
|
|
779
824
|
*/
|
|
780
|
-
export const PositiveNumber = positive(NonNegativeNumber);
|
|
825
|
+
export const PositiveNumber = /*#__PURE__*/ positive(NonNegativeNumber);
|
|
781
826
|
/**
|
|
782
827
|
* Non-positive number (≤ 0).
|
|
783
828
|
*
|
|
784
|
-
* @
|
|
829
|
+
* @group Number
|
|
785
830
|
*/
|
|
786
|
-
export const NonPositiveNumber = nonPositive(Number);
|
|
831
|
+
export const NonPositiveNumber = /*#__PURE__*/ nonPositive(Number);
|
|
787
832
|
/**
|
|
788
833
|
* Negative number (< 0).
|
|
789
834
|
*
|
|
790
|
-
* @
|
|
835
|
+
* @group Number
|
|
791
836
|
*/
|
|
792
|
-
export const NegativeNumber = negative(NonPositiveNumber);
|
|
837
|
+
export const NegativeNumber = /*#__PURE__*/ negative(NonPositiveNumber);
|
|
793
838
|
/**
|
|
794
839
|
* Integer within the safe range of JavaScript numbers.
|
|
795
840
|
*
|
|
796
841
|
* ### Example
|
|
797
842
|
*
|
|
798
843
|
* ```ts
|
|
799
|
-
* const Int =
|
|
844
|
+
* const Int = safeInt(Number);
|
|
800
845
|
* ```
|
|
801
846
|
*
|
|
802
|
-
*
|
|
847
|
+
* Note: This helper was previously named `int`. A Next.js regression produced
|
|
848
|
+
* runtime `int is not defined`, so we keep the implementation under the
|
|
849
|
+
* `safeInt` alias.
|
|
850
|
+
*
|
|
851
|
+
* @group Number
|
|
803
852
|
*/
|
|
804
|
-
|
|
853
|
+
const safeInt = (parent) => brand("Int", parent, (value) => globalThis.Number.isSafeInteger(value)
|
|
805
854
|
? ok(value)
|
|
806
855
|
: err({ type: "Int", value }));
|
|
807
|
-
export const formatIntError = createTypeErrorFormatter((error) => `The value ${error.value} must be an integer.`);
|
|
856
|
+
export const formatIntError = /*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be an integer.`);
|
|
808
857
|
/**
|
|
809
858
|
* Integer within the safe range of JavaScript numbers.
|
|
810
859
|
*
|
|
811
|
-
* @
|
|
860
|
+
* @group Number
|
|
812
861
|
*/
|
|
813
|
-
export const Int =
|
|
862
|
+
export const Int = /*#__PURE__*/ safeInt(Number);
|
|
814
863
|
/**
|
|
815
864
|
* Non-negative integer (≥ 0).
|
|
816
865
|
*
|
|
817
|
-
* @
|
|
866
|
+
* @group Number
|
|
818
867
|
*/
|
|
819
|
-
export const NonNegativeInt = nonNegative(Int);
|
|
868
|
+
export const NonNegativeInt = /*#__PURE__*/ nonNegative(Int);
|
|
869
|
+
/** Minimum {@link NonNegativeInt} value (0). */
|
|
870
|
+
export const zeroNonNegativeInt = /*#__PURE__*/ NonNegativeInt.orThrow(0);
|
|
820
871
|
/**
|
|
821
872
|
* Positive integer (> 0).
|
|
822
873
|
*
|
|
823
|
-
* @
|
|
874
|
+
* @group Number
|
|
824
875
|
*/
|
|
825
|
-
export const PositiveInt = positive(NonNegativeInt);
|
|
826
|
-
/**
|
|
827
|
-
export const
|
|
876
|
+
export const PositiveInt = /*#__PURE__*/ positive(NonNegativeInt);
|
|
877
|
+
/** {@link PositiveInt} value 1. */
|
|
878
|
+
export const onePositiveInt = /*#__PURE__*/ PositiveInt.orThrow(1);
|
|
879
|
+
/** Maximum {@link PositiveInt} value (MAX_SAFE_INTEGER). */
|
|
880
|
+
export const maxPositiveInt = /*#__PURE__*/ PositiveInt.orThrow(globalThis.Number.MAX_SAFE_INTEGER);
|
|
828
881
|
/**
|
|
829
882
|
* Non-positive integer (≤ 0).
|
|
830
883
|
*
|
|
831
|
-
* @
|
|
884
|
+
* @group Number
|
|
832
885
|
*/
|
|
833
|
-
export const NonPositiveInt = nonPositive(Int);
|
|
886
|
+
export const NonPositiveInt = /*#__PURE__*/ nonPositive(Int);
|
|
834
887
|
/**
|
|
835
888
|
* Negative integer (< 0).
|
|
836
889
|
*
|
|
837
|
-
* @
|
|
890
|
+
* @group Number
|
|
838
891
|
*/
|
|
839
|
-
export const NegativeInt = negative(NonPositiveInt);
|
|
892
|
+
export const NegativeInt = /*#__PURE__*/ negative(NonPositiveInt);
|
|
840
893
|
/**
|
|
841
894
|
* Number greater than a specified value.
|
|
842
895
|
*
|
|
843
|
-
* @
|
|
896
|
+
* Use numeric literal, not expression. See {@link BrandFactory}.
|
|
897
|
+
*
|
|
898
|
+
* @group Number
|
|
844
899
|
*/
|
|
845
900
|
export const greaterThan = (min) => (parent) => brand(`GreaterThan${min}`, parent, (value) => value > min ? ok(value) : err({ type: "GreaterThan", value, min }));
|
|
846
|
-
export const formatGreaterThanError =
|
|
901
|
+
export const formatGreaterThanError =
|
|
902
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not > ${error.min}.`);
|
|
847
903
|
/**
|
|
848
904
|
* Number less than a specified value.
|
|
849
905
|
*
|
|
850
|
-
* @
|
|
906
|
+
* Use numeric literal, not expression. See {@link BrandFactory}.
|
|
907
|
+
*
|
|
908
|
+
* @group Number
|
|
851
909
|
*/
|
|
852
910
|
export const lessThan = (max) => (parent) => brand(`LessThan${max}`, parent, (value) => value < max ? ok(value) : err({ type: "LessThan", value, max }));
|
|
853
|
-
export const formatLessThanError =
|
|
911
|
+
export const formatLessThanError =
|
|
912
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not < ${error.max}.`);
|
|
854
913
|
/**
|
|
855
914
|
* Number ≥ a specified value.
|
|
856
915
|
*
|
|
857
|
-
* @
|
|
916
|
+
* Use numeric literal, not expression. See {@link BrandFactory}.
|
|
917
|
+
*
|
|
918
|
+
* @group Number
|
|
858
919
|
*/
|
|
859
920
|
export const greaterThanOrEqualTo = (min) => (parent) => brand(`GreaterThanOrEqualTo${min}`, parent, (value) => value >= min
|
|
860
921
|
? ok(value)
|
|
861
922
|
: err({ type: "GreaterThanOrEqualTo", value, min }));
|
|
862
|
-
export const formatGreaterThanOrEqualToError =
|
|
923
|
+
export const formatGreaterThanOrEqualToError =
|
|
924
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not >= ${error.min}.`);
|
|
863
925
|
/**
|
|
864
926
|
* Number ≤ a specified value.
|
|
865
927
|
*
|
|
866
|
-
* @
|
|
928
|
+
* Use numeric literal, not expression. See {@link BrandFactory}.
|
|
929
|
+
*
|
|
930
|
+
* @group Number
|
|
867
931
|
*/
|
|
868
932
|
export const lessThanOrEqualTo = (max) => (parent) => brand(`LessThanOrEqualTo${max}`, parent, (value) => value <= max ? ok(value) : err({ type: "LessThanOrEqualTo", value, max }));
|
|
869
|
-
export const formatLessThanOrEqualToError =
|
|
933
|
+
export const formatLessThanOrEqualToError =
|
|
934
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not <= ${error.max}.`);
|
|
870
935
|
/**
|
|
871
936
|
* Number that is not NaN.
|
|
872
937
|
*
|
|
873
|
-
* @
|
|
938
|
+
* @group Number
|
|
874
939
|
*/
|
|
875
940
|
export const nonNaN = (parent) => brand("NonNaN", parent, (value) => !globalThis.Number.isNaN(value)
|
|
876
941
|
? ok(value)
|
|
877
942
|
: err({ type: "NonNaN", value }));
|
|
878
|
-
export const formatNonNaNError =
|
|
879
|
-
|
|
880
|
-
|
|
943
|
+
export const formatNonNaNError =
|
|
944
|
+
/*#__PURE__*/ createTypeErrorFormatter(() => `The value must not be NaN.`);
|
|
945
|
+
/** @group Number */
|
|
946
|
+
export const NonNaNNumber = /*#__PURE__*/ nonNaN(Number);
|
|
881
947
|
/**
|
|
882
948
|
* Finite number.
|
|
883
949
|
*
|
|
884
|
-
* @
|
|
950
|
+
* @group Number
|
|
885
951
|
*/
|
|
886
952
|
export const finite = (parent) => brand("Finite", parent, (value) => globalThis.Number.isFinite(value)
|
|
887
953
|
? ok(value)
|
|
888
954
|
: err({ type: "Finite", value }));
|
|
889
|
-
export const formatFiniteError =
|
|
955
|
+
export const formatFiniteError =
|
|
956
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} must be finite.`);
|
|
890
957
|
/**
|
|
891
958
|
* Finite number.
|
|
892
959
|
*
|
|
@@ -898,21 +965,26 @@ export const formatFiniteError = createTypeErrorFormatter((error) => `The value
|
|
|
898
965
|
* finite (e.g., `Infinity`, `-Infinity`, or `NaN`). Using `FiniteNumber` helps
|
|
899
966
|
* prevent these unexpected behaviors when working with JSON serialization.
|
|
900
967
|
*
|
|
901
|
-
* @
|
|
968
|
+
* @group Number
|
|
902
969
|
*/
|
|
903
|
-
export const FiniteNumber = finite(Number);
|
|
970
|
+
export const FiniteNumber = /*#__PURE__*/ finite(Number);
|
|
904
971
|
/**
|
|
905
972
|
* Number that is a multiple of a divisor.
|
|
906
973
|
*
|
|
907
|
-
* @
|
|
974
|
+
* Use numeric literal, not expression. See {@link BrandFactory}.
|
|
975
|
+
*
|
|
976
|
+
* @group Number
|
|
908
977
|
*/
|
|
909
978
|
export const multipleOf = (divisor) => (parent) => brand(`MultipleOf${divisor}`, parent, (value) => value % divisor === 0
|
|
910
979
|
? ok(value)
|
|
911
980
|
: err({ type: "MultipleOf", value, divisor }));
|
|
912
|
-
export const formatMultipleOfError =
|
|
981
|
+
export const formatMultipleOfError =
|
|
982
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not a multiple of ${error.divisor}.`);
|
|
913
983
|
/**
|
|
914
984
|
* Number within a range, inclusive.
|
|
915
985
|
*
|
|
986
|
+
* Use numeric literal, not expression. See {@link BrandFactory}.
|
|
987
|
+
*
|
|
916
988
|
* ### Example
|
|
917
989
|
*
|
|
918
990
|
* ```ts
|
|
@@ -921,12 +993,13 @@ export const formatMultipleOfError = createTypeErrorFormatter((error) => `The va
|
|
|
921
993
|
* const errorResult = Between1And10.from(11); // err
|
|
922
994
|
* ```
|
|
923
995
|
*
|
|
924
|
-
* @
|
|
996
|
+
* @group Number
|
|
925
997
|
*/
|
|
926
998
|
export const between = (min, max) => (parent) => brand(`Between${min}-${max}`, parent, (value) => value >= min && value <= max
|
|
927
999
|
? ok(value)
|
|
928
1000
|
: err({ type: "Between", value, min, max }));
|
|
929
|
-
export const formatBetweenError =
|
|
1001
|
+
export const formatBetweenError =
|
|
1002
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not between ${error.min} and ${error.max}, inclusive.`);
|
|
930
1003
|
/**
|
|
931
1004
|
* Literal {@link Type}.
|
|
932
1005
|
*
|
|
@@ -942,7 +1015,7 @@ export const formatBetweenError = createTypeErrorFormatter((error) => `The value
|
|
|
942
1015
|
*
|
|
943
1016
|
* TODO: Add JsonValue
|
|
944
1017
|
*
|
|
945
|
-
* @
|
|
1018
|
+
* @group Base factories
|
|
946
1019
|
*/
|
|
947
1020
|
export const literal = (expected) => {
|
|
948
1021
|
const fromUnknown = (value) => value === expected
|
|
@@ -956,11 +1029,12 @@ export const literal = (expected) => {
|
|
|
956
1029
|
expected,
|
|
957
1030
|
};
|
|
958
1031
|
};
|
|
959
|
-
export const formatLiteralError =
|
|
1032
|
+
export const formatLiteralError =
|
|
1033
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not strictly equal to the expected literal: ${globalThis.String(error.expected)}.`);
|
|
960
1034
|
/**
|
|
961
1035
|
* Array of a specific {@link Type}.
|
|
962
1036
|
*
|
|
963
|
-
*
|
|
1037
|
+
* ### Example
|
|
964
1038
|
*
|
|
965
1039
|
* ```ts
|
|
966
1040
|
* const NumberArray = array(Number);
|
|
@@ -969,8 +1043,8 @@ export const formatLiteralError = createTypeErrorFormatter((error) => `The value
|
|
|
969
1043
|
* const result2 = NumberArray.from(["a", "b"]); // err(...)
|
|
970
1044
|
* ```
|
|
971
1045
|
*
|
|
972
|
-
* @
|
|
973
|
-
* @
|
|
1046
|
+
* @group Base factories
|
|
1047
|
+
* @group Array
|
|
974
1048
|
*/
|
|
975
1049
|
export const array = (element) => {
|
|
976
1050
|
const fromUnknown = (value) => {
|
|
@@ -1043,7 +1117,7 @@ export const formatArrayError = (formatTypeError) => createTypeErrorFormatter((e
|
|
|
1043
1117
|
* const result2 = NumberSet.from(new Set(["a", "b"])); // err(...)
|
|
1044
1118
|
* ```
|
|
1045
1119
|
*
|
|
1046
|
-
* @
|
|
1120
|
+
* @group Base factories
|
|
1047
1121
|
*/
|
|
1048
1122
|
export const set = (element) => {
|
|
1049
1123
|
const fromUnknown = (value) => {
|
|
@@ -1128,8 +1202,8 @@ export const formatSetError = (formatTypeError) => createTypeErrorFormatter((err
|
|
|
1128
1202
|
* StringToNumberRecord.from({ a: "x", b: 2 });
|
|
1129
1203
|
* ```
|
|
1130
1204
|
*
|
|
1131
|
-
* @
|
|
1132
|
-
* @
|
|
1205
|
+
* @group Base factories
|
|
1206
|
+
* @group Object
|
|
1133
1207
|
*/
|
|
1134
1208
|
export const record = (keyType, valueType) => {
|
|
1135
1209
|
const fromUnknown = (value) => {
|
|
@@ -1375,6 +1449,9 @@ export const formatObjectWithRecordError = (formatTypeError) => createTypeErrorF
|
|
|
1375
1449
|
return `Invalid value at index key ${error.reason.key}: ${formatTypeError(error.reason.error)}`;
|
|
1376
1450
|
}
|
|
1377
1451
|
});
|
|
1452
|
+
export function typed(tag, props) {
|
|
1453
|
+
return object({ type: literal(tag), ...props });
|
|
1454
|
+
}
|
|
1378
1455
|
export function union(...args) {
|
|
1379
1456
|
/**
|
|
1380
1457
|
* Good First Issue:
|
|
@@ -1420,6 +1497,75 @@ export const formatUnionError = (formatTypeError) => createTypeErrorFormatter((e
|
|
|
1420
1497
|
return `Value ${error.value} does not match any member of the union.\nErrors:\n${formattedErrors}`;
|
|
1421
1498
|
});
|
|
1422
1499
|
export const isUnionType = (t) => t.name === "Union" && Array.isArray(t.members);
|
|
1500
|
+
/**
|
|
1501
|
+
* Creates a {@link Type} for {@link Result} values.
|
|
1502
|
+
*
|
|
1503
|
+
* Use for validating serialized Results from storage, APIs, or message passing.
|
|
1504
|
+
*
|
|
1505
|
+
* ### Example
|
|
1506
|
+
*
|
|
1507
|
+
* ```ts
|
|
1508
|
+
* const SyncResponse = result(
|
|
1509
|
+
* object({ timestamp: NonNegativeInt }),
|
|
1510
|
+
* typed("SyncError", { message: String }),
|
|
1511
|
+
* );
|
|
1512
|
+
*
|
|
1513
|
+
* // Validate response from worker or API
|
|
1514
|
+
* const validated = SyncResponse.from(JSON.parse(message));
|
|
1515
|
+
* if (!validated.ok) return validated; // validation error
|
|
1516
|
+
* // validated.value is Result<{ timestamp }, SyncError>
|
|
1517
|
+
* ```
|
|
1518
|
+
*
|
|
1519
|
+
* @group Composite factories
|
|
1520
|
+
*/
|
|
1521
|
+
export const result = (okType, errType) => union(object({ ok: literal(true), value: okType }), object({ ok: literal(false), error: errType }));
|
|
1522
|
+
/**
|
|
1523
|
+
* A {@link result} type for `Result<unknown, unknown>`.
|
|
1524
|
+
*
|
|
1525
|
+
* Useful for serializing Results where the value and error types are unknown.
|
|
1526
|
+
*
|
|
1527
|
+
* @group Composite factories
|
|
1528
|
+
*/
|
|
1529
|
+
export const UnknownResult = /*#__PURE__*/ result(Unknown, Unknown);
|
|
1530
|
+
/**
|
|
1531
|
+
* Creates a {@link Type} for {@link NextResult} with three outcomes.
|
|
1532
|
+
*
|
|
1533
|
+
* Validates results where the producer responds with:
|
|
1534
|
+
*
|
|
1535
|
+
* - `Ok<A>` — produced a value
|
|
1536
|
+
* - `Err<Done<D>>` — completed normally with a done value
|
|
1537
|
+
* - `Err<E>` — failed with an error
|
|
1538
|
+
*
|
|
1539
|
+
* ### Example
|
|
1540
|
+
*
|
|
1541
|
+
* ```ts
|
|
1542
|
+
* const MyNextResult = nextResult(Item, MyError, Summary);
|
|
1543
|
+
*
|
|
1544
|
+
* const validated = MyNextResult.fromUnknown(data);
|
|
1545
|
+
* if (!validated.ok) return validated;
|
|
1546
|
+
*
|
|
1547
|
+
* const result = validated.value;
|
|
1548
|
+
* if (result.ok) {
|
|
1549
|
+
* console.log(result.value);
|
|
1550
|
+
* } else if (result.error.type === "Done") {
|
|
1551
|
+
* console.log("Done:", result.error.done);
|
|
1552
|
+
* } else {
|
|
1553
|
+
* console.error(result.error);
|
|
1554
|
+
* }
|
|
1555
|
+
* ```
|
|
1556
|
+
*
|
|
1557
|
+
* @group Composite factories
|
|
1558
|
+
*/
|
|
1559
|
+
export const nextResult = (valueType, errorType, doneType) => result(valueType, union(errorType, typed("Done", { done: doneType })));
|
|
1560
|
+
/**
|
|
1561
|
+
* A {@link nextResult} type for `NextResult<unknown, unknown, unknown>`.
|
|
1562
|
+
*
|
|
1563
|
+
* Useful for checking if a value is a {@link NextResult} via
|
|
1564
|
+
* `UnknownNextResult.is(value)`.
|
|
1565
|
+
*
|
|
1566
|
+
* @group Composite factories
|
|
1567
|
+
*/
|
|
1568
|
+
export const UnknownNextResult = /*#__PURE__*/ nextResult(Unknown, Unknown, Unknown);
|
|
1423
1569
|
/**
|
|
1424
1570
|
* Recursive {@link Type}.
|
|
1425
1571
|
*
|
|
@@ -1453,7 +1599,7 @@ export const isUnionType = (t) => t.name === "Union" && Array.isArray(t.members)
|
|
|
1453
1599
|
* );
|
|
1454
1600
|
* ```
|
|
1455
1601
|
*
|
|
1456
|
-
* @
|
|
1602
|
+
* @group Base factories
|
|
1457
1603
|
*/
|
|
1458
1604
|
export const recursive = (create) => {
|
|
1459
1605
|
let type;
|
|
@@ -1494,7 +1640,7 @@ export const recursive = (create) => {
|
|
|
1494
1640
|
* NullOrString.from(42); // err(...)
|
|
1495
1641
|
* ```
|
|
1496
1642
|
*
|
|
1497
|
-
* @
|
|
1643
|
+
* @group Base factories
|
|
1498
1644
|
*/
|
|
1499
1645
|
export const nullOr = (type) => union(Null, type);
|
|
1500
1646
|
/**
|
|
@@ -1509,7 +1655,7 @@ export const nullOr = (type) => union(Null, type);
|
|
|
1509
1655
|
* UndefinedOrString.from(42); // err(...)
|
|
1510
1656
|
* ```
|
|
1511
1657
|
*
|
|
1512
|
-
* @
|
|
1658
|
+
* @group Base factories
|
|
1513
1659
|
*/
|
|
1514
1660
|
export const undefinedOr = (type) => union(Undefined, type);
|
|
1515
1661
|
/**
|
|
@@ -1528,7 +1674,7 @@ export const undefinedOr = (type) => union(Undefined, type);
|
|
|
1528
1674
|
* NullishOrString.from(42); // err(...)
|
|
1529
1675
|
* ```
|
|
1530
1676
|
*
|
|
1531
|
-
* @
|
|
1677
|
+
* @group Base factories
|
|
1532
1678
|
*/
|
|
1533
1679
|
export const nullishOr = (type) => union(Undefined, Null, type);
|
|
1534
1680
|
/**
|
|
@@ -1545,7 +1691,7 @@ export const nullishOr = (type) => union(Undefined, Null, type);
|
|
|
1545
1691
|
* const error = NameAndAge.from(["Alice", -10]); // err
|
|
1546
1692
|
* ```
|
|
1547
1693
|
*
|
|
1548
|
-
* @
|
|
1694
|
+
* @group Base factories
|
|
1549
1695
|
*/
|
|
1550
1696
|
export const tuple = (...elements) => {
|
|
1551
1697
|
const fromUnknown = (value) => {
|
|
@@ -1631,42 +1777,44 @@ export const formatTupleError = (formatTypeError) => createTypeErrorFormatter((e
|
|
|
1631
1777
|
*
|
|
1632
1778
|
* https://www.sqlite.org/c3ref/int64.html
|
|
1633
1779
|
*
|
|
1634
|
-
* @
|
|
1780
|
+
* @group Number
|
|
1635
1781
|
*/
|
|
1636
|
-
export const Int64 = brand("Int64", BigInt, (value) => value >= -9223372036854775808n && value <= 9223372036854775807n
|
|
1782
|
+
export const Int64 = /*#__PURE__*/ brand("Int64", BigInt, (value) => value >= -9223372036854775808n && value <= 9223372036854775807n
|
|
1637
1783
|
? ok(value)
|
|
1638
1784
|
: err({ type: "Int64", value }));
|
|
1639
|
-
export const formatInt64Error =
|
|
1785
|
+
export const formatInt64Error =
|
|
1786
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not a valid 64-bit signed integer (Int64).`);
|
|
1640
1787
|
/**
|
|
1641
1788
|
* Stringified {@link Int64}.
|
|
1642
1789
|
*
|
|
1643
|
-
* @
|
|
1790
|
+
* @group String
|
|
1644
1791
|
*/
|
|
1645
|
-
export const Int64String = brand("Int64", NonEmptyTrimmedString, (value) => trySync(() => {
|
|
1792
|
+
export const Int64String = /*#__PURE__*/ brand("Int64", NonEmptyTrimmedString, (value) => trySync(() => {
|
|
1646
1793
|
const maybeInt = globalThis.BigInt(value);
|
|
1647
1794
|
Int64.orThrow(maybeInt);
|
|
1648
1795
|
return value;
|
|
1649
1796
|
}, () => ({ type: "Int64String", value })));
|
|
1650
|
-
export const formatInt64StringError =
|
|
1797
|
+
export const formatInt64StringError =
|
|
1798
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `The value ${error.value} is not a valid Int64 string.`);
|
|
1651
1799
|
/**
|
|
1652
1800
|
* JSON-compatible value: string, {@link FiniteNumber}, boolean, null,
|
|
1653
1801
|
* {@link JsonArray}, or {@link JsonObject}.
|
|
1654
1802
|
*
|
|
1655
|
-
* @
|
|
1803
|
+
* @group Base Types
|
|
1656
1804
|
*/
|
|
1657
|
-
export const JsonValue = recursive(() => union(String, FiniteNumber, Boolean, Null, JsonArray, JsonObject));
|
|
1805
|
+
export const JsonValue = /*#__PURE__*/ recursive(() => union(String, FiniteNumber, Boolean, Null, JsonArray, JsonObject));
|
|
1658
1806
|
/**
|
|
1659
1807
|
* JSON-compatible array of {@link JsonValue} elements.
|
|
1660
1808
|
*
|
|
1661
|
-
* @
|
|
1809
|
+
* @group Array
|
|
1662
1810
|
*/
|
|
1663
|
-
export const JsonArray = array(JsonValue);
|
|
1811
|
+
export const JsonArray = /*#__PURE__*/ array(JsonValue);
|
|
1664
1812
|
/**
|
|
1665
1813
|
* JSON-compatible object with string keys and {@link JsonValue} values.
|
|
1666
1814
|
*
|
|
1667
|
-
* @
|
|
1815
|
+
* @group Object
|
|
1668
1816
|
*/
|
|
1669
|
-
export const JsonObject = record(String, JsonValue);
|
|
1817
|
+
export const JsonObject = /*#__PURE__*/ record(String, JsonValue);
|
|
1670
1818
|
export const parseJson = (value) => trySync(() => JSON.parse(value), (error) => ({
|
|
1671
1819
|
type: `Json`,
|
|
1672
1820
|
value,
|
|
@@ -1682,15 +1830,16 @@ export const parseJson = (value) => trySync(() => JSON.parse(value), (error) =>
|
|
|
1682
1830
|
* const error = Json.from("invalid json"); // err
|
|
1683
1831
|
* ```
|
|
1684
1832
|
*
|
|
1685
|
-
* @
|
|
1833
|
+
* @group String
|
|
1686
1834
|
*/
|
|
1687
|
-
export const Json = brand("Json", String, (value) => {
|
|
1835
|
+
export const Json = /*#__PURE__*/ brand("Json", String, (value) => {
|
|
1688
1836
|
const result = parseJson(value);
|
|
1689
1837
|
if (!result.ok)
|
|
1690
1838
|
return result;
|
|
1691
1839
|
return ok(value);
|
|
1692
1840
|
});
|
|
1693
|
-
export const formatJsonError =
|
|
1841
|
+
export const formatJsonError =
|
|
1842
|
+
/*#__PURE__*/ createTypeErrorFormatter((error) => `Invalid JSON: ${error.value}. Error: ${error.message}`);
|
|
1694
1843
|
export const jsonValueToJson = (value) => JSON.stringify(value);
|
|
1695
1844
|
export const jsonToJsonValue = (value) => JSON.parse(value);
|
|
1696
1845
|
/**
|
|
@@ -1713,7 +1862,7 @@ export const jsonToJsonValue = (value) => JSON.parse(value);
|
|
|
1713
1862
|
* name: NonEmptyString100,
|
|
1714
1863
|
* age: FiniteNumber,
|
|
1715
1864
|
* });
|
|
1716
|
-
*
|
|
1865
|
+
* interface Person extends InferType<typeof Person> {}
|
|
1717
1866
|
*
|
|
1718
1867
|
* const [PersonJson, personToPersonJson, personJsonToPerson] = json(
|
|
1719
1868
|
* Person,
|
|
@@ -1738,11 +1887,7 @@ export const json = (type, name) => {
|
|
|
1738
1887
|
return validationResult;
|
|
1739
1888
|
return ok(value);
|
|
1740
1889
|
});
|
|
1741
|
-
return [
|
|
1742
|
-
BrandedJsonType,
|
|
1743
|
-
jsonValueToJson,
|
|
1744
|
-
jsonToJsonValue,
|
|
1745
|
-
];
|
|
1890
|
+
return [BrandedJsonType, jsonValueToJson, jsonToJsonValue];
|
|
1746
1891
|
};
|
|
1747
1892
|
/**
|
|
1748
1893
|
* Optional {@link Type}.
|
|
@@ -1799,7 +1944,7 @@ export const isOptionalType = (x) => typeof x === "object" && x != null && "name
|
|
|
1799
1944
|
* PartialUser.from({ age: -5 });
|
|
1800
1945
|
* ```
|
|
1801
1946
|
*
|
|
1802
|
-
* @
|
|
1947
|
+
* @group Object
|
|
1803
1948
|
*/
|
|
1804
1949
|
export const partial = (props) => {
|
|
1805
1950
|
const optionalProps = {};
|
|
@@ -1816,7 +1961,7 @@ export const partial = (props) => {
|
|
|
1816
1961
|
* entirely, or set it to `null`, or set it to the non-null member of the
|
|
1817
1962
|
* union.
|
|
1818
1963
|
*
|
|
1819
|
-
* @
|
|
1964
|
+
* @group Object
|
|
1820
1965
|
*/
|
|
1821
1966
|
export const nullableToOptional = (props) => {
|
|
1822
1967
|
const transformedProps = {};
|
|
@@ -1836,9 +1981,9 @@ export const nullableToOptional = (props) => {
|
|
|
1836
1981
|
/**
|
|
1837
1982
|
* Create a new `object` {@link Type} by omitting some keys.
|
|
1838
1983
|
*
|
|
1839
|
-
* @
|
|
1984
|
+
* @group Object
|
|
1840
1985
|
*/
|
|
1841
|
-
export
|
|
1986
|
+
export const omit = (objectType, ...keys) => {
|
|
1842
1987
|
const newProps = {};
|
|
1843
1988
|
for (const key in objectType.props) {
|
|
1844
1989
|
if (!keys.includes(key)) {
|
|
@@ -1847,18 +1992,7 @@ export function omit(objectType, ...keys) {
|
|
|
1847
1992
|
}
|
|
1848
1993
|
}
|
|
1849
1994
|
return object(newProps);
|
|
1850
|
-
}
|
|
1851
|
-
export const maxMutationSize = 655360;
|
|
1852
|
-
/**
|
|
1853
|
-
* Evolu has to limit the maximum mutation size. Otherwise, sync couldn't use
|
|
1854
|
-
* the `maxProtocolMessageRangesSize`. The max size is 640KB in bytes, measured
|
|
1855
|
-
* via MessagePack. Evolu Protocol DbChange will be smaller thanks to various
|
|
1856
|
-
* optimizations.
|
|
1857
|
-
*/
|
|
1858
|
-
export const validMutationSize = (type) => brand("ValidMutationSize", type, (value) => pack(value).byteLength <= maxMutationSize
|
|
1859
|
-
? ok(value)
|
|
1860
|
-
: err({ type: "ValidMutationSize", value }));
|
|
1861
|
-
export const formatValidMutationSizeError = createTypeErrorFormatter((error) => `The mutation size exceeds the maximum limit of ${maxMutationSize} bytes. The provided mutation has a size of ${pack(error.value).byteLength} bytes.`);
|
|
1995
|
+
};
|
|
1862
1996
|
/**
|
|
1863
1997
|
* Formats Evolu Type errors into user-friendly messages.
|
|
1864
1998
|
*
|
|
@@ -1937,7 +2071,7 @@ export const formatValidMutationSizeError = createTypeErrorFormatter((error) =>
|
|
|
1937
2071
|
* };
|
|
1938
2072
|
* ```
|
|
1939
2073
|
*
|
|
1940
|
-
* @
|
|
2074
|
+
* @group Utilities
|
|
1941
2075
|
*/
|
|
1942
2076
|
export const createFormatTypeError = (extraFormatter) => {
|
|
1943
2077
|
const formatTypeError = (error) => {
|
|
@@ -1962,6 +2096,8 @@ export const createFormatTypeError = (extraFormatter) => {
|
|
|
1962
2096
|
return formatFunctionError(error);
|
|
1963
2097
|
case "Uint8Array":
|
|
1964
2098
|
return formatUint8ArrayError(error);
|
|
2099
|
+
case "ArrayBuffer":
|
|
2100
|
+
return formatArrayBufferError(error);
|
|
1965
2101
|
case "InstanceOf":
|
|
1966
2102
|
return formatInstanceOfError(error);
|
|
1967
2103
|
case "EvoluType":
|
|
@@ -2020,8 +2156,6 @@ export const createFormatTypeError = (extraFormatter) => {
|
|
|
2020
2156
|
return formatInt64StringError(error);
|
|
2021
2157
|
case "Json":
|
|
2022
2158
|
return formatJsonError(error);
|
|
2023
|
-
case "ValidMutationSize":
|
|
2024
|
-
return formatValidMutationSizeError(error);
|
|
2025
2159
|
// Composite Types
|
|
2026
2160
|
case "SimplePassword":
|
|
2027
2161
|
return formatSimplePasswordError(formatTypeError)(error);
|
|
@@ -2052,82 +2186,78 @@ export const createFormatTypeError = (extraFormatter) => {
|
|
|
2052
2186
|
* Converts an Evolu {@link TypeError} to Standard Schema V1 issues format.
|
|
2053
2187
|
*
|
|
2054
2188
|
* This function recursively converts Evolu's typed errors into the Standard
|
|
2055
|
-
* Schema issue format with proper path tracking for nested structures.
|
|
2189
|
+
* Schema issue format with proper path tracking for nested structures. The
|
|
2190
|
+
* `message` field contains the JSON-serialized typed error, which users can
|
|
2191
|
+
* deserialize and format using appropriate {@link TypeErrorFormatter}s.
|
|
2056
2192
|
*
|
|
2057
|
-
* @
|
|
2193
|
+
* @group Utilities
|
|
2058
2194
|
*/
|
|
2059
|
-
export const typeErrorToStandardSchemaIssues = (error,
|
|
2195
|
+
export const typeErrorToStandardSchemaIssues = (error, path = []) => {
|
|
2060
2196
|
if (error.type === "Array") {
|
|
2061
2197
|
const arrayError = error;
|
|
2062
2198
|
if (arrayError.reason.kind === "NotArray") {
|
|
2063
|
-
return [{ message:
|
|
2199
|
+
return [{ message: JSON.stringify(error), path }];
|
|
2064
2200
|
}
|
|
2065
|
-
return typeErrorToStandardSchemaIssues(arrayError.reason.error,
|
|
2201
|
+
return typeErrorToStandardSchemaIssues(arrayError.reason.error, [...path, arrayError.reason.index]);
|
|
2066
2202
|
}
|
|
2067
2203
|
if (error.type === "Set") {
|
|
2068
2204
|
const setError = error;
|
|
2069
2205
|
if (setError.reason.kind === "NotSet") {
|
|
2070
|
-
return [{ message:
|
|
2206
|
+
return [{ message: JSON.stringify(error), path }];
|
|
2071
2207
|
}
|
|
2072
|
-
return typeErrorToStandardSchemaIssues(setError.reason.error,
|
|
2208
|
+
return typeErrorToStandardSchemaIssues(setError.reason.error, [...path, setError.reason.index]);
|
|
2073
2209
|
}
|
|
2074
2210
|
if (error.type === "Object") {
|
|
2075
2211
|
const objectError = error;
|
|
2076
2212
|
if (objectError.reason.kind === "NotObject" ||
|
|
2077
2213
|
objectError.reason.kind === "ExtraKeys") {
|
|
2078
|
-
return [{ message:
|
|
2214
|
+
return [{ message: JSON.stringify(error), path }];
|
|
2079
2215
|
}
|
|
2080
2216
|
const issues = [];
|
|
2081
2217
|
for (const [key, propError] of Object.entries(objectError.reason.errors)) {
|
|
2082
|
-
issues.push(...typeErrorToStandardSchemaIssues(propError,
|
|
2218
|
+
issues.push(...typeErrorToStandardSchemaIssues(propError, [...path, key]));
|
|
2083
2219
|
}
|
|
2084
2220
|
return issues;
|
|
2085
2221
|
}
|
|
2086
2222
|
if (error.type === "ObjectWithRecord") {
|
|
2087
2223
|
const objectWithRecordError = error;
|
|
2088
2224
|
if (objectWithRecordError.reason.kind === "NotObject") {
|
|
2089
|
-
return [{ message:
|
|
2225
|
+
return [{ message: JSON.stringify(error), path }];
|
|
2090
2226
|
}
|
|
2091
2227
|
if (objectWithRecordError.reason.kind === "IndexKey" ||
|
|
2092
2228
|
objectWithRecordError.reason.kind === "IndexValue") {
|
|
2093
|
-
return typeErrorToStandardSchemaIssues(objectWithRecordError.reason.error,
|
|
2229
|
+
return typeErrorToStandardSchemaIssues(objectWithRecordError.reason.error, [...path, objectWithRecordError.reason.key]);
|
|
2094
2230
|
}
|
|
2095
2231
|
const issues = [];
|
|
2096
2232
|
for (const [key, propError] of Object.entries(objectWithRecordError.reason.errors)) {
|
|
2097
|
-
issues.push(...typeErrorToStandardSchemaIssues(propError,
|
|
2233
|
+
issues.push(...typeErrorToStandardSchemaIssues(propError, [...path, key]));
|
|
2098
2234
|
}
|
|
2099
2235
|
return issues;
|
|
2100
2236
|
}
|
|
2101
2237
|
if (error.type === "Record") {
|
|
2102
2238
|
const recordError = error;
|
|
2103
2239
|
if (recordError.reason.kind === "NotRecord") {
|
|
2104
|
-
return [{ message:
|
|
2240
|
+
return [{ message: JSON.stringify(error), path }];
|
|
2105
2241
|
}
|
|
2106
|
-
return typeErrorToStandardSchemaIssues(recordError.reason.error,
|
|
2242
|
+
return typeErrorToStandardSchemaIssues(recordError.reason.error, [...path, recordError.reason.key]);
|
|
2107
2243
|
}
|
|
2108
2244
|
if (error.type === "Tuple") {
|
|
2109
2245
|
const tupleError = error;
|
|
2110
2246
|
if (tupleError.reason.kind === "InvalidLength") {
|
|
2111
|
-
return [{ message:
|
|
2247
|
+
return [{ message: JSON.stringify(error), path }];
|
|
2112
2248
|
}
|
|
2113
|
-
return typeErrorToStandardSchemaIssues(tupleError.reason.error,
|
|
2249
|
+
return typeErrorToStandardSchemaIssues(tupleError.reason.error, [...path, tupleError.reason.index]);
|
|
2114
2250
|
}
|
|
2115
2251
|
if (error.type === "Union") {
|
|
2116
2252
|
const unionError = error;
|
|
2117
|
-
return unionError.errors.flatMap((err) => typeErrorToStandardSchemaIssues(err,
|
|
2253
|
+
return unionError.errors.flatMap((err) => typeErrorToStandardSchemaIssues(err, path));
|
|
2118
2254
|
}
|
|
2119
2255
|
if (error.type === "Brand") {
|
|
2120
2256
|
const brandError = error;
|
|
2121
2257
|
if ("parentError" in brandError) {
|
|
2122
|
-
return typeErrorToStandardSchemaIssues(brandError.parentError,
|
|
2258
|
+
return typeErrorToStandardSchemaIssues(brandError.parentError, path);
|
|
2123
2259
|
}
|
|
2124
|
-
return [{ message:
|
|
2260
|
+
return [{ message: JSON.stringify(error), path }];
|
|
2125
2261
|
}
|
|
2126
|
-
return [{ message:
|
|
2262
|
+
return [{ message: JSON.stringify(error), path }];
|
|
2127
2263
|
};
|
|
2128
|
-
/**
|
|
2129
|
-
* Shared formatter cache for Standard Schema integration - avoids circular
|
|
2130
|
-
* dependency by lazily creating the formatter on first use rather than during
|
|
2131
|
-
* module initialization.
|
|
2132
|
-
*/
|
|
2133
|
-
let cachedStandardSchemaFormatTypeError;
|