@evolu/common 8.4.0 → 8.6.0
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/dist/src/Array.d.ts +191 -94
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +91 -40
- package/dist/src/Assert.d.ts +233 -30
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +151 -30
- package/dist/src/BigInt.d.ts +3 -3
- package/dist/src/BigInt.js +3 -3
- package/dist/src/Brand.d.ts +7 -7
- package/dist/src/Buffer.d.ts +12 -4
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Cache.d.ts +8 -3
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +8 -3
- package/dist/src/Callbacks.d.ts +8 -4
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Console.d.ts +45 -30
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +32 -21
- package/dist/src/Crypto.d.ts +13 -8
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +6 -3
- package/dist/src/Eq.d.ts +107 -58
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +308 -112
- package/dist/src/Function.d.ts +54 -24
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +34 -17
- package/dist/src/Http.d.ts +52 -19
- package/dist/src/Http.d.ts.map +1 -1
- package/dist/src/Identicon.d.ts +9 -4
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +9 -4
- package/dist/src/LeakDetector.d.ts.map +1 -1
- package/dist/src/LeakDetector.js +4 -1
- package/dist/src/LockManager.d.ts +12 -10
- package/dist/src/LockManager.d.ts.map +1 -1
- package/dist/src/Lookup.d.ts +4 -2
- package/dist/src/Lookup.d.ts.map +1 -1
- package/dist/src/Lookup.js +5 -2
- package/dist/src/Number.d.ts +28 -24
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +16 -17
- package/dist/src/Object.d.ts +89 -47
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +88 -41
- package/dist/src/Option.d.ts +14 -5
- package/dist/src/Option.d.ts.map +1 -1
- package/dist/src/Option.js +14 -5
- package/dist/src/Order.d.ts +12 -12
- package/dist/src/Order.js +12 -12
- package/dist/src/Platform.d.ts +2 -2
- package/dist/src/Platform.js +1 -0
- package/dist/src/Random.d.ts +7 -4
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Redacted.d.ts +13 -6
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +4 -2
- package/dist/src/Ref.d.ts +4 -4
- package/dist/src/Relation.d.ts +5 -7
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Relation.js +3 -3
- package/dist/src/Resource.d.ts +27 -12
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +9 -3
- package/dist/src/Result.d.ts +258 -114
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +74 -39
- package/dist/src/Schedule.d.ts +233 -116
- package/dist/src/Schedule.d.ts.map +1 -1
- package/dist/src/Schedule.js +204 -110
- package/dist/src/Set.d.ts +43 -24
- package/dist/src/Set.d.ts.map +1 -1
- package/dist/src/Set.js +25 -13
- package/dist/src/Sqlite.d.ts +4 -4
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +18 -15
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +3 -1
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +1 -1
- package/dist/src/Task.d.ts +555 -264
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +278 -168
- package/dist/src/Test.d.ts +10 -4
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +11 -4
- package/dist/src/Time.d.ts +27 -17
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +25 -8
- package/dist/src/Type.d.ts +1218 -372
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +1056 -379
- package/dist/src/Types.d.ts +95 -40
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +13 -4
- package/dist/src/WebSocket.d.ts +14 -6
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +8 -0
- package/dist/src/Worker.d.ts +10 -6
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +1 -1
- package/dist/src/intl/_en.d.ts +3 -1
- package/dist/src/intl/_en.d.ts.map +1 -1
- package/dist/src/intl/_en.js +17 -3
- package/dist/src/intl/ar.d.ts +3 -1
- package/dist/src/intl/ar.d.ts.map +1 -1
- package/dist/src/intl/ar.js +15 -2
- package/dist/src/intl/bn.d.ts +3 -1
- package/dist/src/intl/bn.d.ts.map +1 -1
- package/dist/src/intl/bn.js +16 -3
- package/dist/src/intl/ca.d.ts +3 -1
- package/dist/src/intl/ca.d.ts.map +1 -1
- package/dist/src/intl/ca.js +16 -3
- package/dist/src/intl/cs.d.ts +3 -1
- package/dist/src/intl/cs.d.ts.map +1 -1
- package/dist/src/intl/cs.js +16 -3
- package/dist/src/intl/da.d.ts +3 -1
- package/dist/src/intl/da.d.ts.map +1 -1
- package/dist/src/intl/da.js +16 -3
- package/dist/src/intl/de.d.ts +3 -1
- package/dist/src/intl/de.d.ts.map +1 -1
- package/dist/src/intl/de.js +16 -3
- package/dist/src/intl/el.d.ts +3 -1
- package/dist/src/intl/el.d.ts.map +1 -1
- package/dist/src/intl/el.js +16 -3
- package/dist/src/intl/es.d.ts +3 -1
- package/dist/src/intl/es.d.ts.map +1 -1
- package/dist/src/intl/es.js +16 -3
- package/dist/src/intl/fa.d.ts +3 -1
- package/dist/src/intl/fa.d.ts.map +1 -1
- package/dist/src/intl/fa.js +16 -3
- package/dist/src/intl/fi.d.ts +3 -1
- package/dist/src/intl/fi.d.ts.map +1 -1
- package/dist/src/intl/fi.js +16 -3
- package/dist/src/intl/fil.d.ts +3 -1
- package/dist/src/intl/fil.d.ts.map +1 -1
- package/dist/src/intl/fil.js +16 -3
- package/dist/src/intl/fr.d.ts +3 -1
- package/dist/src/intl/fr.d.ts.map +1 -1
- package/dist/src/intl/fr.js +16 -3
- package/dist/src/intl/he.d.ts +3 -1
- package/dist/src/intl/he.d.ts.map +1 -1
- package/dist/src/intl/he.js +16 -3
- package/dist/src/intl/hi.d.ts +3 -1
- package/dist/src/intl/hi.d.ts.map +1 -1
- package/dist/src/intl/hi.js +16 -3
- package/dist/src/intl/hr.d.ts +3 -1
- package/dist/src/intl/hr.d.ts.map +1 -1
- package/dist/src/intl/hr.js +16 -3
- package/dist/src/intl/hu.d.ts +2 -1
- package/dist/src/intl/hu.d.ts.map +1 -1
- package/dist/src/intl/hu.js +15 -3
- package/dist/src/intl/id.d.ts +3 -1
- package/dist/src/intl/id.d.ts.map +1 -1
- package/dist/src/intl/id.js +16 -3
- package/dist/src/intl/it.d.ts +3 -1
- package/dist/src/intl/it.d.ts.map +1 -1
- package/dist/src/intl/it.js +16 -3
- package/dist/src/intl/ja.d.ts +3 -1
- package/dist/src/intl/ja.d.ts.map +1 -1
- package/dist/src/intl/ja.js +16 -3
- package/dist/src/intl/ko.d.ts +3 -1
- package/dist/src/intl/ko.d.ts.map +1 -1
- package/dist/src/intl/ko.js +16 -3
- package/dist/src/intl/ml.d.ts +3 -1
- package/dist/src/intl/ml.d.ts.map +1 -1
- package/dist/src/intl/ml.js +16 -3
- package/dist/src/intl/mr.d.ts +3 -1
- package/dist/src/intl/mr.d.ts.map +1 -1
- package/dist/src/intl/mr.js +16 -3
- package/dist/src/intl/ms.d.ts +3 -1
- package/dist/src/intl/ms.d.ts.map +1 -1
- package/dist/src/intl/ms.js +15 -2
- package/dist/src/intl/nb.d.ts +2 -1
- package/dist/src/intl/nb.d.ts.map +1 -1
- package/dist/src/intl/nb.js +14 -2
- package/dist/src/intl/nl.d.ts +3 -1
- package/dist/src/intl/nl.d.ts.map +1 -1
- package/dist/src/intl/nl.js +16 -3
- package/dist/src/intl/pa.d.ts +3 -1
- package/dist/src/intl/pa.d.ts.map +1 -1
- package/dist/src/intl/pa.js +16 -3
- package/dist/src/intl/pl.d.ts +2 -0
- package/dist/src/intl/pl.d.ts.map +1 -1
- package/dist/src/intl/pl.js +15 -2
- package/dist/src/intl/pt-BR.d.ts +3 -1
- package/dist/src/intl/pt-BR.d.ts.map +1 -1
- package/dist/src/intl/pt-BR.js +16 -3
- package/dist/src/intl/pt.d.ts +3 -1
- package/dist/src/intl/pt.d.ts.map +1 -1
- package/dist/src/intl/pt.js +15 -2
- package/dist/src/intl/ro.d.ts +3 -1
- package/dist/src/intl/ro.d.ts.map +1 -1
- package/dist/src/intl/ro.js +16 -3
- package/dist/src/intl/sk.d.ts +3 -1
- package/dist/src/intl/sk.d.ts.map +1 -1
- package/dist/src/intl/sk.js +15 -2
- package/dist/src/intl/sl.d.ts +3 -1
- package/dist/src/intl/sl.d.ts.map +1 -1
- package/dist/src/intl/sl.js +16 -3
- package/dist/src/intl/sv.d.ts +3 -1
- package/dist/src/intl/sv.d.ts.map +1 -1
- package/dist/src/intl/sv.js +16 -3
- package/dist/src/intl/sw.d.ts +1 -0
- package/dist/src/intl/sw.d.ts.map +1 -1
- package/dist/src/intl/sw.js +14 -2
- package/dist/src/intl/ta.d.ts +3 -1
- package/dist/src/intl/ta.d.ts.map +1 -1
- package/dist/src/intl/ta.js +16 -3
- package/dist/src/intl/te.d.ts +3 -1
- package/dist/src/intl/te.d.ts.map +1 -1
- package/dist/src/intl/te.js +16 -3
- package/dist/src/intl/th.d.ts +3 -1
- package/dist/src/intl/th.d.ts.map +1 -1
- package/dist/src/intl/th.js +16 -3
- package/dist/src/intl/tr.d.ts +3 -1
- package/dist/src/intl/tr.d.ts.map +1 -1
- package/dist/src/intl/tr.js +16 -3
- package/dist/src/intl/uk.d.ts +3 -1
- package/dist/src/intl/uk.d.ts.map +1 -1
- package/dist/src/intl/uk.js +16 -3
- package/dist/src/intl/ur.d.ts +3 -1
- package/dist/src/intl/ur.d.ts.map +1 -1
- package/dist/src/intl/ur.js +15 -2
- package/dist/src/intl/vi.d.ts +3 -1
- package/dist/src/intl/vi.d.ts.map +1 -1
- package/dist/src/intl/vi.js +16 -3
- package/dist/src/intl/zh-CN.d.ts +3 -1
- package/dist/src/intl/zh-CN.d.ts.map +1 -1
- package/dist/src/intl/zh-CN.js +16 -3
- package/dist/src/intl/zh-TW.d.ts +3 -1
- package/dist/src/intl/zh-TW.d.ts.map +1 -1
- package/dist/src/intl/zh-TW.js +16 -3
- package/dist/src/local-first/Db.js +3 -2
- package/dist/src/local-first/Evolu.d.ts +47 -24
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +1 -0
- package/dist/src/local-first/Owner.d.ts +18 -14
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +14 -11
- package/dist/src/local-first/Protocol.d.ts +5 -5
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +35 -29
- package/dist/src/local-first/Query.d.ts +34 -21
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +27 -14
- package/dist/src/local-first/Relay.d.ts +12 -5
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Relay.js +1 -1
- package/dist/src/local-first/Schema.d.ts +19 -11
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +11 -6
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +4 -2
- package/dist/src/local-first/Storage.d.ts +4 -2
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +1 -1
- package/package.json +3 -4
- package/src/Array.ts +195 -95
- package/src/Assert.ts +337 -31
- package/src/BigInt.ts +3 -3
- package/src/Brand.ts +7 -7
- package/src/Buffer.ts +12 -4
- package/src/Cache.ts +8 -3
- package/src/Callbacks.ts +8 -4
- package/src/Console.ts +45 -30
- package/src/Crypto.ts +13 -8
- package/src/Eq.ts +450 -122
- package/src/Function.ts +54 -24
- package/src/Http.ts +52 -19
- package/src/Identicon.ts +9 -4
- package/src/LeakDetector.ts +4 -3
- package/src/LockManager.ts +12 -10
- package/src/Lookup.ts +5 -2
- package/src/Number.ts +28 -24
- package/src/Object.ts +115 -49
- package/src/Option.ts +14 -5
- package/src/Order.ts +12 -12
- package/src/Platform.ts +3 -2
- package/src/Random.ts +7 -4
- package/src/Redacted.ts +13 -6
- package/src/Ref.ts +4 -4
- package/src/Relation.ts +8 -10
- package/src/Resource.ts +36 -15
- package/src/Result.ts +263 -119
- package/src/Schedule.ts +233 -116
- package/src/Set.ts +43 -24
- package/src/Sqlite.ts +18 -15
- package/src/Store.ts +3 -1
- package/src/String.ts +1 -1
- package/src/Task.ts +566 -286
- package/src/Test.ts +11 -4
- package/src/Time.ts +36 -19
- package/src/Type.ts +2191 -590
- package/src/Types.ts +108 -40
- package/src/WebSocket.ts +22 -6
- package/src/Worker.ts +11 -7
- package/src/intl/_en.ts +20 -4
- package/src/intl/ar.ts +17 -2
- package/src/intl/bn.ts +19 -4
- package/src/intl/ca.ts +19 -4
- package/src/intl/cs.ts +19 -4
- package/src/intl/da.ts +19 -4
- package/src/intl/de.ts +19 -4
- package/src/intl/el.ts +19 -4
- package/src/intl/es.ts +19 -4
- package/src/intl/fa.ts +19 -4
- package/src/intl/fi.ts +19 -4
- package/src/intl/fil.ts +19 -4
- package/src/intl/fr.ts +19 -4
- package/src/intl/he.ts +19 -4
- package/src/intl/hi.ts +19 -4
- package/src/intl/hr.ts +19 -4
- package/src/intl/hu.ts +18 -4
- package/src/intl/id.ts +19 -4
- package/src/intl/it.ts +19 -4
- package/src/intl/ja.ts +19 -4
- package/src/intl/ko.ts +19 -4
- package/src/intl/ml.ts +19 -4
- package/src/intl/mr.ts +19 -4
- package/src/intl/ms.ts +17 -2
- package/src/intl/nb.ts +16 -2
- package/src/intl/nl.ts +19 -4
- package/src/intl/pa.ts +19 -4
- package/src/intl/pl.ts +18 -2
- package/src/intl/pt-BR.ts +19 -4
- package/src/intl/pt.ts +17 -2
- package/src/intl/ro.ts +19 -4
- package/src/intl/sk.ts +17 -2
- package/src/intl/sl.ts +19 -4
- package/src/intl/sv.ts +19 -4
- package/src/intl/sw.ts +15 -2
- package/src/intl/ta.ts +19 -4
- package/src/intl/te.ts +19 -4
- package/src/intl/th.ts +19 -4
- package/src/intl/tr.ts +19 -4
- package/src/intl/uk.ts +19 -4
- package/src/intl/ur.ts +17 -2
- package/src/intl/vi.ts +19 -3
- package/src/intl/zh-CN.ts +19 -4
- package/src/intl/zh-TW.ts +19 -4
- package/src/local-first/Db.ts +2 -1
- package/src/local-first/Evolu.ts +48 -24
- package/src/local-first/Owner.ts +18 -14
- package/src/local-first/Protocol.ts +45 -35
- package/src/local-first/Query.ts +40 -24
- package/src/local-first/Relay.ts +13 -6
- package/src/local-first/Schema.ts +19 -11
- package/src/local-first/Shared.ts +4 -2
- package/src/local-first/Storage.ts +4 -2
- package/src/local-first/Timestamp.ts +1 -1
package/dist/src/Type.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
-
import type
|
|
2
|
+
import { type AtLeastTwoReadonlyArray, type NonEmptyReadonlyArray } from "./Array.ts";
|
|
3
3
|
import type { Brand } from "./Brand.ts";
|
|
4
4
|
import type { RandomBytesDep } from "./Crypto.ts";
|
|
5
5
|
import { type Thunk } from "./Function.ts";
|
|
6
6
|
import { type Result } from "./Result.ts";
|
|
7
7
|
import type { TimeDep } from "./Time.ts";
|
|
8
|
-
import { type CompileTimeError, type IsUnion, type Literal, type Simplify, type ValueWithLength, type WidenLiteral } from "./Types.ts";
|
|
8
|
+
import { type CompileTimeError, type IsSameType, type IsUnion, type Literal, type Simplify, type ValueWithLength, type WidenLiteral } from "./Types.ts";
|
|
9
9
|
/**
|
|
10
10
|
* A runtime representation of a TypeScript type, including its encoded input,
|
|
11
11
|
* semantic output, structured errors, and canonical encoding.
|
|
@@ -77,12 +77,12 @@ export interface Type<Name extends TypeName, in out Input, in out Output, Error
|
|
|
77
77
|
* ### Example
|
|
78
78
|
*
|
|
79
79
|
* ```ts
|
|
80
|
-
* import { PositiveInt } from "@evolu/common";
|
|
80
|
+
* import { assertOk, PositiveInt } from "@evolu/common";
|
|
81
81
|
*
|
|
82
82
|
* const value: unknown = 42;
|
|
83
83
|
* const result = PositiveInt.fromUnknown(value);
|
|
84
84
|
*
|
|
85
|
-
*
|
|
85
|
+
* assertOk(result, 42);
|
|
86
86
|
* ```
|
|
87
87
|
*/
|
|
88
88
|
readonly fromUnknown: (value: unknown, options?: ValidationOptions) => Result<Output, Errors>;
|
|
@@ -98,12 +98,25 @@ export interface Type<Name extends TypeName, in out Input, in out Output, Error
|
|
|
98
98
|
* ### Example
|
|
99
99
|
*
|
|
100
100
|
* ```ts
|
|
101
|
-
* import {
|
|
101
|
+
* import {
|
|
102
|
+
* assertEqual,
|
|
103
|
+
* assertType,
|
|
104
|
+
* Data,
|
|
105
|
+
* assertErr,
|
|
106
|
+
* String,
|
|
107
|
+
* } from "@evolu/common";
|
|
102
108
|
*
|
|
103
109
|
* const result = String.fromUnknown(42);
|
|
104
110
|
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
111
|
+
* assertErr(result);
|
|
112
|
+
* assertType(Data, result.error);
|
|
113
|
+
* assertEqual(result.error, {
|
|
114
|
+
* type: "TypeOf",
|
|
115
|
+
* expected: "String",
|
|
116
|
+
* value: 42,
|
|
117
|
+
* });
|
|
118
|
+
* assertEqual(
|
|
119
|
+
* String.formatError(result.error),
|
|
107
120
|
* "A value 42 is not a string.",
|
|
108
121
|
* );
|
|
109
122
|
* ```
|
|
@@ -119,14 +132,20 @@ export interface Type<Name extends TypeName, in out Input, in out Output, Error
|
|
|
119
132
|
* ### Example
|
|
120
133
|
*
|
|
121
134
|
* ```ts
|
|
122
|
-
* import {
|
|
135
|
+
* import {
|
|
136
|
+
* assertFalse,
|
|
137
|
+
* assertType,
|
|
138
|
+
* assertTrue,
|
|
139
|
+
* Int64FromInt64String,
|
|
140
|
+
* type Int64,
|
|
141
|
+
* } from "@evolu/common";
|
|
123
142
|
*
|
|
124
143
|
* const values: ReadonlyArray<unknown> = [42n, "42", null];
|
|
125
144
|
* const integers = values.filter(Int64FromInt64String.is);
|
|
126
145
|
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
146
|
+
* assertType<Array<Int64>, typeof integers>();
|
|
147
|
+
* assertTrue(Int64FromInt64String.is(42n));
|
|
148
|
+
* assertFalse(Int64FromInt64String.is("42"));
|
|
130
149
|
* ```
|
|
131
150
|
*/
|
|
132
151
|
readonly is: (value: unknown) => value is Output;
|
|
@@ -151,6 +170,8 @@ export interface Type<Name extends TypeName, in out Input, in out Output, Error
|
|
|
151
170
|
*
|
|
152
171
|
* ```ts
|
|
153
172
|
* import {
|
|
173
|
+
* assertOk,
|
|
174
|
+
* assertType,
|
|
154
175
|
* flatMapResult,
|
|
155
176
|
* NonEmptyTrimmedString100,
|
|
156
177
|
* object,
|
|
@@ -183,10 +204,11 @@ export interface Type<Name extends TypeName, in out Input, in out Output, Error
|
|
|
183
204
|
* const note = TrimmedString.orThrow("Remember oat milk");
|
|
184
205
|
* const result = saveTodo(title, note);
|
|
185
206
|
*
|
|
186
|
-
*
|
|
187
|
-
* Result<typeof Todo.Output, MaxLengthError<100> | MinLengthError<1
|
|
207
|
+
* assertType<
|
|
208
|
+
* Result<typeof Todo.Output, MaxLengthError<100> | MinLengthError<1>>,
|
|
209
|
+
* typeof result
|
|
188
210
|
* >();
|
|
189
|
-
*
|
|
211
|
+
* assertOk(result, { title, note });
|
|
190
212
|
* ```
|
|
191
213
|
*/
|
|
192
214
|
readonly from: [CustomFrom] extends [never] ? [Parent] extends [infer P extends TypeNode] ? FromOperation<Output, Error, P> : TypeOperationFn<"from", Output, Output, never> : CustomFrom;
|
|
@@ -201,11 +223,15 @@ export interface Type<Name extends TypeName, in out Input, in out Output, Error
|
|
|
201
223
|
* ### Example
|
|
202
224
|
*
|
|
203
225
|
* ```ts
|
|
204
|
-
* import {
|
|
226
|
+
* import {
|
|
227
|
+
* assertEqual,
|
|
228
|
+
* Int64,
|
|
229
|
+
* Int64FromInt64String,
|
|
230
|
+
* } from "@evolu/common";
|
|
205
231
|
*
|
|
206
232
|
* const value = Int64.orThrow(42n);
|
|
207
233
|
*
|
|
208
|
-
*
|
|
234
|
+
* assertEqual(Int64FromInt64String.to(value), "42");
|
|
209
235
|
* ```
|
|
210
236
|
*/
|
|
211
237
|
readonly to: [Parent] extends [infer P extends TypeNode] ? ToOperation<Output, CanonicalInput, P> : (value: Output) => CanonicalInput;
|
|
@@ -228,7 +254,12 @@ export interface Type<Name extends TypeName, in out Input, in out Output, Error
|
|
|
228
254
|
* ### Example
|
|
229
255
|
*
|
|
230
256
|
* ```ts
|
|
231
|
-
* import {
|
|
257
|
+
* import {
|
|
258
|
+
* assertEqual,
|
|
259
|
+
* getOrThrow,
|
|
260
|
+
* minLength,
|
|
261
|
+
* String,
|
|
262
|
+
* } from "@evolu/common";
|
|
232
263
|
*
|
|
233
264
|
* const NonEmptyString = minLength(1)(String);
|
|
234
265
|
*
|
|
@@ -237,8 +268,8 @@ export interface Type<Name extends TypeName, in out Input, in out Output, Error
|
|
|
237
268
|
* // Equivalent because `from.parent` is this Type's deepest `from` operation:
|
|
238
269
|
* const sameValue = getOrThrow(NonEmptyString.from.parent("Evolu"));
|
|
239
270
|
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
271
|
+
* assertEqual(value, "Evolu");
|
|
272
|
+
* assertEqual(sameValue, value);
|
|
242
273
|
* ```
|
|
243
274
|
*/
|
|
244
275
|
readonly orThrow: TypeOperationFn<"orThrow", Input, Output, never>;
|
|
@@ -261,7 +292,12 @@ export interface Type<Name extends TypeName, in out Input, in out Output, Error
|
|
|
261
292
|
* ### Example
|
|
262
293
|
*
|
|
263
294
|
* ```ts
|
|
264
|
-
* import {
|
|
295
|
+
* import {
|
|
296
|
+
* assertEqual,
|
|
297
|
+
* getOrNull,
|
|
298
|
+
* minLength,
|
|
299
|
+
* String,
|
|
300
|
+
* } from "@evolu/common";
|
|
265
301
|
*
|
|
266
302
|
* const NonEmptyString = minLength(1)(String);
|
|
267
303
|
*
|
|
@@ -270,9 +306,9 @@ export interface Type<Name extends TypeName, in out Input, in out Output, Error
|
|
|
270
306
|
* // Equivalent because `from.parent` is this Type's deepest `from` operation:
|
|
271
307
|
* const sameValue = getOrNull(NonEmptyString.from.parent("Evolu"));
|
|
272
308
|
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
309
|
+
* assertEqual(value, "Evolu");
|
|
310
|
+
* assertEqual(sameValue, value);
|
|
311
|
+
* assertEqual(NonEmptyString.orNull(""), null);
|
|
276
312
|
* ```
|
|
277
313
|
*/
|
|
278
314
|
readonly orNull: TypeOperationFn<"orNull", Input, Output, never>;
|
|
@@ -344,12 +380,18 @@ export interface TypeNode {
|
|
|
344
380
|
readonly is: (value: unknown) => boolean;
|
|
345
381
|
}
|
|
346
382
|
/**
|
|
347
|
-
* Asserts that a value belongs to a
|
|
383
|
+
* Asserts exact compile-time type equality or that a value belongs to a
|
|
384
|
+
* {@link Type} Output domain.
|
|
348
385
|
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
386
|
+
* - `assertType<Expected, Actual>()` requires compiler-identical types without
|
|
387
|
+
* evaluating a value.
|
|
388
|
+
* - `assertType(type, value)` validates and narrows a runtime value to the Type's
|
|
389
|
+
* Output.
|
|
390
|
+
*
|
|
391
|
+
* Use the runtime form for internal invariants, not external input. Validate
|
|
392
|
+
* external input with `Type.fromUnknown` so validation failures remain typed
|
|
393
|
+
* values. A failed runtime assertion uses the Type name for its message and
|
|
394
|
+
* preserves the exact Output validation error as the thrown Error's cause.
|
|
353
395
|
*
|
|
354
396
|
* ### Example
|
|
355
397
|
*
|
|
@@ -362,14 +404,21 @@ export interface TypeNode {
|
|
|
362
404
|
*
|
|
363
405
|
* const value: unknown = "Evolu";
|
|
364
406
|
* assertType(NonEmptyTrimmedString100, value);
|
|
365
|
-
*
|
|
366
|
-
* string &
|
|
407
|
+
* assertType<
|
|
408
|
+
* string &
|
|
409
|
+
* Brand<"Trimmed"> &
|
|
410
|
+
* Brand<"MinLength1"> &
|
|
411
|
+
* Brand<"MaxLength100">,
|
|
412
|
+
* typeof value
|
|
367
413
|
* >();
|
|
368
414
|
* ```
|
|
369
415
|
*
|
|
370
416
|
* @group Core
|
|
371
417
|
*/
|
|
372
|
-
export declare
|
|
418
|
+
export declare function assertType<Expected, Actual>(...error: IsSameType<Expected, Actual> extends true ? [] : [
|
|
419
|
+
error: CompileTimeError<"assertType", "Expected and actual types must be identical">
|
|
420
|
+
]): void;
|
|
421
|
+
export declare function assertType<T extends TypeNode>(type: T, value: unknown): asserts value is T["Output"];
|
|
373
422
|
/**
|
|
374
423
|
* Creates localized copies of selected {@link Type} declarations.
|
|
375
424
|
*
|
|
@@ -395,13 +444,22 @@ export declare const assertType: <T extends TypeNode>(type: T, value: unknown) =
|
|
|
395
444
|
* every locale an app supports also allows language changes without a network
|
|
396
445
|
* connection.
|
|
397
446
|
*
|
|
398
|
-
* The selected Type map, locale map, and formatter maps must
|
|
399
|
-
*
|
|
447
|
+
* The selected Type map, locale map, and formatter maps must satisfy the
|
|
448
|
+
* realm-neutral structural heuristic described by {@link isPlainObject} and have
|
|
449
|
+
* own enumerable string-keyed data properties.
|
|
400
450
|
*
|
|
401
451
|
* ### Example
|
|
402
452
|
*
|
|
403
453
|
* ```ts
|
|
404
|
-
* import {
|
|
454
|
+
* import {
|
|
455
|
+
* assertEqual,
|
|
456
|
+
* Data,
|
|
457
|
+
* assertErr,
|
|
458
|
+
* assertType,
|
|
459
|
+
* String,
|
|
460
|
+
* localizeTypes,
|
|
461
|
+
* minLength,
|
|
462
|
+
* } from "@evolu/common";
|
|
405
463
|
* import { cs } from "@evolu/common/intl";
|
|
406
464
|
*
|
|
407
465
|
* const Label = minLength(1)(String);
|
|
@@ -416,13 +474,14 @@ export declare const assertType: <T extends TypeNode>(type: T, value: unknown) =
|
|
|
416
474
|
* },
|
|
417
475
|
* );
|
|
418
476
|
*
|
|
419
|
-
*
|
|
420
|
-
* typeof Label
|
|
421
|
-
* >();
|
|
477
|
+
* assertType<typeof Label, typeof typesByLocale.cs.Label>();
|
|
422
478
|
*
|
|
423
479
|
* const result = typesByLocale.cs.Label.fromUnknown("");
|
|
424
|
-
*
|
|
425
|
-
*
|
|
480
|
+
* assertErr(result);
|
|
481
|
+
* assertType(Data, result.error);
|
|
482
|
+
* assertEqual(result.error, { type: "MinLength1", min: 1, value: "" });
|
|
483
|
+
* assertEqual(
|
|
484
|
+
* typesByLocale.cs.Label.formatError(result.error),
|
|
426
485
|
* "Text nesmí být prázdný.",
|
|
427
486
|
* );
|
|
428
487
|
* ```
|
|
@@ -501,7 +560,7 @@ type LocalizedErrorEntry<Error extends TypeError, Seen extends TypeError = never
|
|
|
501
560
|
readonly type: "DiscriminatedUnion";
|
|
502
561
|
readonly reason: unknown;
|
|
503
562
|
} ? LocalizedDiscriminatedUnionErrorEntry<Error, Seen | Error> : Error extends {
|
|
504
|
-
readonly type: infer Name extends "Array" | "Tuple" | "Record" | "Set";
|
|
563
|
+
readonly type: infer Name extends "Array" | "Map" | "Tuple" | "Record" | "Set";
|
|
505
564
|
readonly reason: infer Reason;
|
|
506
565
|
} ? LocalizedErrorEntryValue<Name, Error> | LocalizedIssuesErrorEntry<Reason, Seen | Error> : Error extends {
|
|
507
566
|
readonly type: "Object";
|
|
@@ -549,6 +608,8 @@ declare const identityEncodingSymbol: unique symbol;
|
|
|
549
608
|
*
|
|
550
609
|
* ```ts
|
|
551
610
|
* import {
|
|
611
|
+
* assertEqual,
|
|
612
|
+
* assertType,
|
|
552
613
|
* NonEmptyTrimmedString100,
|
|
553
614
|
* PositiveInt,
|
|
554
615
|
* object,
|
|
@@ -564,8 +625,8 @@ declare const identityEncodingSymbol: unique symbol;
|
|
|
564
625
|
*
|
|
565
626
|
* const user = User.orThrow({ name: "Ada", age: 37 });
|
|
566
627
|
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
628
|
+
* assertType<typeof User.Output, typeof user>();
|
|
629
|
+
* assertEqual(user.name, "Ada");
|
|
569
630
|
* ```
|
|
570
631
|
*
|
|
571
632
|
* @group Core
|
|
@@ -696,7 +757,12 @@ type ConcreteChildTypeNameError = CompileTimeError<"Type", "Name must be one con
|
|
|
696
757
|
*
|
|
697
758
|
* ```ts
|
|
698
759
|
* import {
|
|
760
|
+
* assertEqual,
|
|
761
|
+
* assertErr,
|
|
762
|
+
* assertOk,
|
|
763
|
+
* assertType,
|
|
699
764
|
* createType,
|
|
765
|
+
* Data,
|
|
700
766
|
* err,
|
|
701
767
|
* ok,
|
|
702
768
|
* type Result,
|
|
@@ -714,8 +780,11 @@ type ConcreteChildTypeNameError = CompileTimeError<"Type", "Name must be one con
|
|
|
714
780
|
* () => "Expected text.",
|
|
715
781
|
* );
|
|
716
782
|
*
|
|
717
|
-
*
|
|
718
|
-
*
|
|
783
|
+
* assertOk(Text.fromUnknown("Evolu"), "Evolu");
|
|
784
|
+
* const invalid = Text.fromUnknown(42);
|
|
785
|
+
* assertErr(invalid);
|
|
786
|
+
* assertType(Data, invalid.error);
|
|
787
|
+
* assertEqual(invalid.error, { type: "Text", value: 42 });
|
|
719
788
|
* ```
|
|
720
789
|
*
|
|
721
790
|
* @group Construction
|
|
@@ -756,7 +825,15 @@ export declare function createType<Name extends TypeName, ParentType extends Con
|
|
|
756
825
|
* ### Example
|
|
757
826
|
*
|
|
758
827
|
* ```ts
|
|
759
|
-
* import {
|
|
828
|
+
* import {
|
|
829
|
+
* assertEqual,
|
|
830
|
+
* assertOk,
|
|
831
|
+
* Boolean,
|
|
832
|
+
* literal,
|
|
833
|
+
* ok,
|
|
834
|
+
* transform,
|
|
835
|
+
* union,
|
|
836
|
+
* } from "@evolu/common";
|
|
760
837
|
*
|
|
761
838
|
* const BooleanString = union(literal("false"), literal("true"));
|
|
762
839
|
* const BooleanFromString = transform(
|
|
@@ -769,8 +846,8 @@ export declare function createType<Name extends TypeName, ParentType extends Con
|
|
|
769
846
|
* },
|
|
770
847
|
* );
|
|
771
848
|
*
|
|
772
|
-
*
|
|
773
|
-
*
|
|
849
|
+
* assertOk(BooleanFromString.from.parent("true"), true);
|
|
850
|
+
* assertEqual(BooleanFromString.to(false), "false");
|
|
774
851
|
* ```
|
|
775
852
|
*
|
|
776
853
|
* @group Construction
|
|
@@ -779,7 +856,60 @@ export declare function transform<Name extends TypeName, ParentType extends Conc
|
|
|
779
856
|
readonly from: (value: ParentType["Output"]) => Result<OutputType["Input"], never>;
|
|
780
857
|
readonly to: (value: CanonicalInputOf<OutputType>) => ToOutput;
|
|
781
858
|
}): TransformType<ParentType, OutputType, Name, never, ToOutput>;
|
|
782
|
-
/**
|
|
859
|
+
/**
|
|
860
|
+
* Creates a fallible transformed Type with its own error formatter.
|
|
861
|
+
*
|
|
862
|
+
* ### Example
|
|
863
|
+
*
|
|
864
|
+
* ```ts
|
|
865
|
+
* import {
|
|
866
|
+
* assertEqual,
|
|
867
|
+
* assertType,
|
|
868
|
+
* Data,
|
|
869
|
+
* assertErr,
|
|
870
|
+
* assertOk,
|
|
871
|
+
* Boolean,
|
|
872
|
+
* String,
|
|
873
|
+
* err,
|
|
874
|
+
* ok,
|
|
875
|
+
* transform,
|
|
876
|
+
* type Result,
|
|
877
|
+
* type TypeError,
|
|
878
|
+
* } from "@evolu/common";
|
|
879
|
+
*
|
|
880
|
+
* interface BooleanFromStringError extends TypeError<"BooleanFromString"> {
|
|
881
|
+
* readonly value: string;
|
|
882
|
+
* }
|
|
883
|
+
*
|
|
884
|
+
* const BooleanFromString = transform(
|
|
885
|
+
* "BooleanFromString",
|
|
886
|
+
* String,
|
|
887
|
+
* Boolean,
|
|
888
|
+
* {
|
|
889
|
+
* from: (value): Result<boolean, BooleanFromStringError> =>
|
|
890
|
+
* value === "true"
|
|
891
|
+
* ? ok(true)
|
|
892
|
+
* : value === "false"
|
|
893
|
+
* ? ok(false)
|
|
894
|
+
* : err({ type: "BooleanFromString", value }),
|
|
895
|
+
* to: (value) => (value ? "true" : "false"),
|
|
896
|
+
* },
|
|
897
|
+
* () => 'Expected "true" or "false".',
|
|
898
|
+
* );
|
|
899
|
+
*
|
|
900
|
+
* assertOk(BooleanFromString.fromUnknown("true"), true);
|
|
901
|
+
* assertEqual(BooleanFromString.to(false), "false");
|
|
902
|
+
*
|
|
903
|
+
* const invalid = BooleanFromString.fromUnknown("yes");
|
|
904
|
+
* assertErr(invalid);
|
|
905
|
+
* assertType(Data, invalid.error);
|
|
906
|
+
* assertEqual(invalid.error, { type: "BooleanFromString", value: "yes" });
|
|
907
|
+
* assertEqual(
|
|
908
|
+
* BooleanFromString.formatError(invalid.error),
|
|
909
|
+
* 'Expected "true" or "false".',
|
|
910
|
+
* );
|
|
911
|
+
* ```
|
|
912
|
+
*/
|
|
783
913
|
export declare function transform<Name extends TypeName, ParentType extends ConcreteTypeNode, OutputType extends ConcreteTypeNode, ToOutput extends ParentType["Output"], FromError extends {
|
|
784
914
|
readonly type: Name;
|
|
785
915
|
readonly outputError?: never;
|
|
@@ -871,16 +1001,20 @@ export interface TypeOfError<Name extends keyof TypeOfOutputByName> extends Type
|
|
|
871
1001
|
* and significant whitespace:
|
|
872
1002
|
*
|
|
873
1003
|
* ```ts
|
|
874
|
-
* import {
|
|
1004
|
+
* import {
|
|
1005
|
+
* assertOk,
|
|
1006
|
+
* assertType,
|
|
1007
|
+
* String,
|
|
1008
|
+
* maxLength,
|
|
1009
|
+
* type Brand,
|
|
1010
|
+
* } from "@evolu/common";
|
|
875
1011
|
*
|
|
876
1012
|
* const WireValue100 = maxLength(100)(String);
|
|
877
1013
|
* type WireValue100 = typeof WireValue100.Output;
|
|
878
1014
|
*
|
|
879
|
-
*
|
|
880
|
-
*
|
|
881
|
-
*
|
|
882
|
-
* expectOk(WireValue100.fromUnknown(""), "");
|
|
883
|
-
* expectOk(WireValue100.fromUnknown(" value "), " value ");
|
|
1015
|
+
* assertType<string & Brand<"MaxLength100">, WireValue100>();
|
|
1016
|
+
* assertOk(WireValue100.fromUnknown(""), "");
|
|
1017
|
+
* assertOk(WireValue100.fromUnknown(" value "), " value ");
|
|
884
1018
|
* ```
|
|
885
1019
|
*
|
|
886
1020
|
* @group String
|
|
@@ -906,7 +1040,12 @@ export declare const String: Type<"String", string, string, TypeOfError<"String"
|
|
|
906
1040
|
*
|
|
907
1041
|
* ```ts
|
|
908
1042
|
* import {
|
|
1043
|
+
* assertEqual,
|
|
1044
|
+
* assertErr,
|
|
1045
|
+
* assertOk,
|
|
1046
|
+
* assertType,
|
|
909
1047
|
* Age,
|
|
1048
|
+
* Data,
|
|
910
1049
|
* FiniteNumber,
|
|
911
1050
|
* Int,
|
|
912
1051
|
* NonNaNNumber,
|
|
@@ -916,36 +1055,41 @@ export declare const String: Type<"String", string, string, TypeOfError<"String"
|
|
|
916
1055
|
* } from "@evolu/common";
|
|
917
1056
|
*
|
|
918
1057
|
* // Note how every additional constraint accumulates its Brand.
|
|
919
|
-
*
|
|
920
|
-
*
|
|
921
|
-
*
|
|
922
|
-
* >
|
|
923
|
-
*
|
|
924
|
-
* number & Brand<"NonNaN"> & Brand<"Finite">
|
|
1058
|
+
* assertType<number, typeof Number.Output>();
|
|
1059
|
+
* assertType<number & Brand<"NonNaN">, typeof NonNaNNumber.Output>();
|
|
1060
|
+
* assertType<
|
|
1061
|
+
* number & Brand<"NonNaN"> & Brand<"Finite">,
|
|
1062
|
+
* typeof FiniteNumber.Output
|
|
925
1063
|
* >();
|
|
926
|
-
*
|
|
927
|
-
* number & Brand<"NonNaN"> & Brand<"Finite"> & Brand<"Int"
|
|
1064
|
+
* assertType<
|
|
1065
|
+
* number & Brand<"NonNaN"> & Brand<"Finite"> & Brand<"Int">,
|
|
1066
|
+
* typeof Int.Output
|
|
928
1067
|
* >();
|
|
929
|
-
*
|
|
1068
|
+
* assertType<
|
|
930
1069
|
* number &
|
|
931
1070
|
* Brand<"NonNaN"> &
|
|
932
1071
|
* Brand<"Finite"> &
|
|
933
1072
|
* Brand<"Int"> &
|
|
934
|
-
* Brand<"NonNegative"
|
|
1073
|
+
* Brand<"NonNegative">,
|
|
1074
|
+
* typeof NonNegativeInt.Output
|
|
935
1075
|
* >();
|
|
936
1076
|
*
|
|
937
|
-
*
|
|
1077
|
+
* assertType<
|
|
938
1078
|
* number &
|
|
939
1079
|
* Brand<"NonNaN"> &
|
|
940
1080
|
* Brand<"Finite"> &
|
|
941
1081
|
* Brand<"Int"> &
|
|
942
1082
|
* Brand<"NonNegative"> &
|
|
943
1083
|
* Brand<"LessThan200"> &
|
|
944
|
-
* Brand<"Age"
|
|
1084
|
+
* Brand<"Age">,
|
|
1085
|
+
* typeof Age.Output
|
|
945
1086
|
* >();
|
|
946
1087
|
*
|
|
947
|
-
*
|
|
948
|
-
*
|
|
1088
|
+
* assertOk(Age.fromUnknown(122), 122);
|
|
1089
|
+
* const invalid = Age.fromUnknown(200);
|
|
1090
|
+
* assertErr(invalid);
|
|
1091
|
+
* assertType(Data, invalid.error);
|
|
1092
|
+
* assertEqual(invalid.error, {
|
|
949
1093
|
* type: "LessThan200",
|
|
950
1094
|
* value: 200,
|
|
951
1095
|
* max: 200,
|
|
@@ -1062,18 +1206,52 @@ interface ObjectTagOutputByName {
|
|
|
1062
1206
|
* ### Example
|
|
1063
1207
|
*
|
|
1064
1208
|
* ```ts
|
|
1065
|
-
* import { objectTag } from "@evolu/common";
|
|
1209
|
+
* import { assertOk, objectTag } from "@evolu/common";
|
|
1066
1210
|
*
|
|
1067
1211
|
* const DateType = objectTag("Date");
|
|
1068
|
-
* const date = new
|
|
1212
|
+
* const date = new Date("2025-01-01T00:00:00.000Z");
|
|
1069
1213
|
*
|
|
1070
|
-
*
|
|
1214
|
+
* assertOk(DateType.fromUnknown(date), date);
|
|
1071
1215
|
* ```
|
|
1072
1216
|
*
|
|
1073
1217
|
* @group Base
|
|
1074
1218
|
*/
|
|
1075
1219
|
export declare function objectTag<Name extends keyof ObjectTagOutputByName>(name: ValidateConcreteTypeName<Name>): Type<Name, ObjectTagOutputByName[Name], ObjectTagOutputByName[Name], ObjectTagError<Name>, null, ObjectTagError<Name>, never, ObjectTagOutputByName[Name]>;
|
|
1076
|
-
/**
|
|
1220
|
+
/**
|
|
1221
|
+
* Creates an object-tag Type by refining an existing object Type.
|
|
1222
|
+
*
|
|
1223
|
+
* ### Example
|
|
1224
|
+
*
|
|
1225
|
+
* ```ts
|
|
1226
|
+
* import {
|
|
1227
|
+
* assertEqual,
|
|
1228
|
+
* assertOk,
|
|
1229
|
+
* assertSame,
|
|
1230
|
+
* assertType,
|
|
1231
|
+
* instanceOf,
|
|
1232
|
+
* objectTag,
|
|
1233
|
+
* } from "@evolu/common";
|
|
1234
|
+
*
|
|
1235
|
+
* class TaggedValue {
|
|
1236
|
+
* readonly [Symbol.toStringTag] = "TaggedValue";
|
|
1237
|
+
* }
|
|
1238
|
+
*
|
|
1239
|
+
* const TaggedValueType = objectTag(
|
|
1240
|
+
* "TaggedValue",
|
|
1241
|
+
* instanceOf(TaggedValue),
|
|
1242
|
+
* );
|
|
1243
|
+
* const value = new TaggedValue();
|
|
1244
|
+
* const result = TaggedValueType.fromUnknown(value);
|
|
1245
|
+
*
|
|
1246
|
+
* assertOk(result);
|
|
1247
|
+
* assertSame(result.value, value);
|
|
1248
|
+
* assertType<
|
|
1249
|
+
* true,
|
|
1250
|
+
* typeof result.value extends TaggedValue ? true : false
|
|
1251
|
+
* >();
|
|
1252
|
+
* assertEqual(TaggedValueType.expected, "TaggedValue");
|
|
1253
|
+
* ```
|
|
1254
|
+
*/
|
|
1077
1255
|
export declare function objectTag<Name extends TypeName, OutputType extends ConcreteTypeNode & {
|
|
1078
1256
|
readonly Output: object;
|
|
1079
1257
|
}>(name: ValidateConcreteTypeName<Name>, outputType: ValidateOutput<OutputType> & ([ChildTypeNameValidationError<"ObjectTag", OutputType>] extends [never] ? unknown : ChildTypeNameValidationError<"ObjectTag", OutputType>)): ObjectTagType<Name, OutputType>;
|
|
@@ -1116,7 +1294,7 @@ export declare const ArrayBuffer: Type<"ArrayBuffer", ArrayBuffer, ArrayBuffer,
|
|
|
1116
1294
|
* ### Example
|
|
1117
1295
|
*
|
|
1118
1296
|
* ```ts
|
|
1119
|
-
* import { instanceOf } from "@evolu/common";
|
|
1297
|
+
* import { assertFalse, assertTrue, instanceOf } from "@evolu/common";
|
|
1120
1298
|
*
|
|
1121
1299
|
* class User {
|
|
1122
1300
|
* readonly name: string;
|
|
@@ -1128,8 +1306,8 @@ export declare const ArrayBuffer: Type<"ArrayBuffer", ArrayBuffer, ArrayBuffer,
|
|
|
1128
1306
|
*
|
|
1129
1307
|
* const UserInstance = instanceOf(User);
|
|
1130
1308
|
*
|
|
1131
|
-
*
|
|
1132
|
-
*
|
|
1309
|
+
* assertTrue(UserInstance.is(new User("Ada")));
|
|
1310
|
+
* assertFalse(UserInstance.is({ name: "Ada" }));
|
|
1133
1311
|
* ```
|
|
1134
1312
|
*
|
|
1135
1313
|
* @group Base
|
|
@@ -1179,13 +1357,23 @@ type InstanceConstructorCompileTimeError = CompileTimeError<"Type", "Constructor
|
|
|
1179
1357
|
* ### Example
|
|
1180
1358
|
*
|
|
1181
1359
|
* ```ts
|
|
1182
|
-
* import {
|
|
1360
|
+
* import {
|
|
1361
|
+
* assertEqual,
|
|
1362
|
+
* assertErr,
|
|
1363
|
+
* assertOk,
|
|
1364
|
+
* assertType,
|
|
1365
|
+
* Data,
|
|
1366
|
+
* literal,
|
|
1367
|
+
* } from "@evolu/common";
|
|
1183
1368
|
*
|
|
1184
1369
|
* const Ready = literal("ready");
|
|
1185
1370
|
*
|
|
1186
|
-
*
|
|
1187
|
-
*
|
|
1188
|
-
*
|
|
1371
|
+
* assertType<"ready", typeof Ready.Output>();
|
|
1372
|
+
* assertOk(Ready.fromUnknown("ready"), "ready");
|
|
1373
|
+
* const invalid = Ready.fromUnknown("pending");
|
|
1374
|
+
* assertErr(invalid);
|
|
1375
|
+
* assertType(Data, invalid.error);
|
|
1376
|
+
* assertEqual(invalid.error, {
|
|
1189
1377
|
* type: "Literal",
|
|
1190
1378
|
* expected: "ready",
|
|
1191
1379
|
* value: "pending",
|
|
@@ -1260,17 +1448,29 @@ export declare const Null: LiteralType<null>;
|
|
|
1260
1448
|
* ### Example
|
|
1261
1449
|
*
|
|
1262
1450
|
* ```ts
|
|
1263
|
-
* import {
|
|
1451
|
+
* import {
|
|
1452
|
+
* assertEqual,
|
|
1453
|
+
* assertErr,
|
|
1454
|
+
* assertOk,
|
|
1455
|
+
* assertType,
|
|
1456
|
+
* Data,
|
|
1457
|
+
* Number,
|
|
1458
|
+
* String,
|
|
1459
|
+
* union,
|
|
1460
|
+
* } from "@evolu/common";
|
|
1264
1461
|
*
|
|
1265
1462
|
* const Status = union("draft", "published");
|
|
1266
1463
|
* const StatusOrCode = union("draft", "published", Number);
|
|
1267
1464
|
*
|
|
1268
|
-
*
|
|
1269
|
-
*
|
|
1465
|
+
* assertOk(Status.fromUnknown("draft"), "draft");
|
|
1466
|
+
* assertOk(StatusOrCode.fromUnknown(42), 42);
|
|
1270
1467
|
*
|
|
1271
1468
|
* const TextOrNumber = union(String, Number);
|
|
1272
1469
|
*
|
|
1273
|
-
*
|
|
1470
|
+
* const invalid = TextOrNumber.fromUnknown(true, { errors: "all" });
|
|
1471
|
+
* assertErr(invalid);
|
|
1472
|
+
* assertType(Data, invalid.error);
|
|
1473
|
+
* assertEqual(invalid.error, {
|
|
1274
1474
|
* type: "Union",
|
|
1275
1475
|
* errors: [
|
|
1276
1476
|
* {
|
|
@@ -1309,11 +1509,11 @@ export declare function union<const Members extends AtLeastTwoReadonlyArray<Type
|
|
|
1309
1509
|
* ### Example
|
|
1310
1510
|
*
|
|
1311
1511
|
* ```ts
|
|
1312
|
-
* import { String, undefinedOr } from "@evolu/common";
|
|
1512
|
+
* import { assertOk, String, undefinedOr } from "@evolu/common";
|
|
1313
1513
|
*
|
|
1314
1514
|
* const StringOrUndefined = undefinedOr(String);
|
|
1315
1515
|
*
|
|
1316
|
-
*
|
|
1516
|
+
* assertOk(StringOrUndefined.fromUnknown(undefined), undefined);
|
|
1317
1517
|
* ```
|
|
1318
1518
|
*
|
|
1319
1519
|
* @group Unions
|
|
@@ -1325,11 +1525,11 @@ export declare const undefinedOr: <ValueType extends TypeNode>(type: ValidateUni
|
|
|
1325
1525
|
* ### Example
|
|
1326
1526
|
*
|
|
1327
1527
|
* ```ts
|
|
1328
|
-
* import { String, nullOr } from "@evolu/common";
|
|
1528
|
+
* import { assertOk, String, nullOr } from "@evolu/common";
|
|
1329
1529
|
*
|
|
1330
1530
|
* const NullableString = nullOr(String);
|
|
1331
1531
|
*
|
|
1332
|
-
*
|
|
1532
|
+
* assertOk(NullableString.fromUnknown(null), null);
|
|
1333
1533
|
* ```
|
|
1334
1534
|
*
|
|
1335
1535
|
* @group Unions
|
|
@@ -1341,12 +1541,12 @@ export declare const nullOr: <ValueType extends TypeNode>(type: ValidateUnionTyp
|
|
|
1341
1541
|
* ### Example
|
|
1342
1542
|
*
|
|
1343
1543
|
* ```ts
|
|
1344
|
-
* import { String, nullishOr } from "@evolu/common";
|
|
1544
|
+
* import { assertOk, String, nullishOr } from "@evolu/common";
|
|
1345
1545
|
*
|
|
1346
1546
|
* const NullishString = nullishOr(String);
|
|
1347
1547
|
*
|
|
1348
|
-
*
|
|
1349
|
-
*
|
|
1548
|
+
* assertOk(NullishString.fromUnknown(undefined), undefined);
|
|
1549
|
+
* assertOk(NullishString.fromUnknown(null), null);
|
|
1350
1550
|
* ```
|
|
1351
1551
|
*
|
|
1352
1552
|
* @group Unions
|
|
@@ -1454,7 +1654,16 @@ interface UnionErrorValue<Error extends TypeError, MemberError extends UnionMemb
|
|
|
1454
1654
|
* the structured data decoded from it:
|
|
1455
1655
|
*
|
|
1456
1656
|
* ```ts
|
|
1457
|
-
* import {
|
|
1657
|
+
* import {
|
|
1658
|
+
* assertFalse,
|
|
1659
|
+
* assertEqual,
|
|
1660
|
+
* assertErr,
|
|
1661
|
+
* assertOk,
|
|
1662
|
+
* assertType,
|
|
1663
|
+
* Data,
|
|
1664
|
+
* templateLiteralParser,
|
|
1665
|
+
* union,
|
|
1666
|
+
* } from "@evolu/common";
|
|
1458
1667
|
*
|
|
1459
1668
|
* const Language = union("en", "cs");
|
|
1460
1669
|
* const Region = union("US", "CZ");
|
|
@@ -1464,36 +1673,39 @@ interface UnionErrorValue<Error extends TypeError, MemberError extends UnionMemb
|
|
|
1464
1673
|
*
|
|
1465
1674
|
* // Output is the decoded language and region.
|
|
1466
1675
|
* type SupportedLocale = typeof SupportedLocale.Output;
|
|
1467
|
-
*
|
|
1468
|
-
* readonly ["en" | "cs", "US" | "CZ"]
|
|
1469
|
-
* >();
|
|
1676
|
+
* assertType<readonly ["en" | "cs", "US" | "CZ"], SupportedLocale>();
|
|
1470
1677
|
*
|
|
1471
1678
|
* // The parent Output is the canonical locale string.
|
|
1472
1679
|
* type SupportedLocaleLiteral = typeof SupportedLocale.parent.Output;
|
|
1473
|
-
*
|
|
1474
|
-
* "en-US" | "en-CZ" | "cs-US" | "cs-CZ"
|
|
1680
|
+
* assertType<
|
|
1681
|
+
* "en-US" | "en-CZ" | "cs-US" | "cs-CZ",
|
|
1682
|
+
* SupportedLocaleLiteral
|
|
1475
1683
|
* >();
|
|
1476
1684
|
*
|
|
1477
1685
|
* // Parse an unknown string into structured data.
|
|
1478
1686
|
* const result = SupportedLocale.fromUnknown("cs-CZ");
|
|
1479
|
-
*
|
|
1687
|
+
* assertOk(result, ["cs", "CZ"]);
|
|
1480
1688
|
* const locale = result.value;
|
|
1481
|
-
*
|
|
1482
|
-
*
|
|
1689
|
+
* assertType<SupportedLocale, typeof locale>();
|
|
1690
|
+
* const invalid = SupportedLocale.fromUnknown("cs/CZ");
|
|
1691
|
+
* assertErr(invalid);
|
|
1692
|
+
* assertType(Data, invalid.error);
|
|
1693
|
+
* const error: Data = invalid.error;
|
|
1694
|
+
* assertEqual(error, {
|
|
1483
1695
|
* type: "TemplateLiteral",
|
|
1484
1696
|
* value: "cs/CZ",
|
|
1485
1697
|
* });
|
|
1486
1698
|
*
|
|
1487
1699
|
* // Encode structured data into its canonical string.
|
|
1488
1700
|
* const localeLiteral = SupportedLocale.to(locale);
|
|
1489
|
-
*
|
|
1490
|
-
*
|
|
1701
|
+
* assertType<SupportedLocaleLiteral, typeof localeLiteral>();
|
|
1702
|
+
* assertEqual(localeLiteral, "cs-CZ");
|
|
1491
1703
|
*
|
|
1492
1704
|
* // Validate a string configuration value.
|
|
1493
1705
|
* const configValue: unknown = "cs-CZ";
|
|
1494
|
-
*
|
|
1495
|
-
*
|
|
1496
|
-
*
|
|
1706
|
+
* assertType(SupportedLocale.parent, configValue);
|
|
1707
|
+
* assertType<SupportedLocaleLiteral, typeof configValue>();
|
|
1708
|
+
* assertFalse(SupportedLocale.parent.is("fr-CZ"));
|
|
1497
1709
|
* ```
|
|
1498
1710
|
*
|
|
1499
1711
|
* `SupportedLocale` is structured data for application code.
|
|
@@ -1506,6 +1718,8 @@ interface UnionErrorValue<Error extends TypeError, MemberError extends UnionMemb
|
|
|
1506
1718
|
*
|
|
1507
1719
|
* ```ts
|
|
1508
1720
|
* import {
|
|
1721
|
+
* assertEqual,
|
|
1722
|
+
* assertOk,
|
|
1509
1723
|
* NonNegativeDecimalString,
|
|
1510
1724
|
* templateLiteralParser,
|
|
1511
1725
|
* } from "@evolu/common";
|
|
@@ -1518,8 +1732,8 @@ interface UnionErrorValue<Error extends TypeError, MemberError extends UnionMemb
|
|
|
1518
1732
|
* // DecimalText.to requires a validated NonNegativeDecimalString.
|
|
1519
1733
|
* const zero = NonNegativeDecimalString.orThrow("0");
|
|
1520
1734
|
*
|
|
1521
|
-
*
|
|
1522
|
-
*
|
|
1735
|
+
* assertOk(DecimalText.fromUnknown("decimal:0"), [zero]);
|
|
1736
|
+
* assertEqual(DecimalText.to([zero]), "decimal:0");
|
|
1523
1737
|
* ```
|
|
1524
1738
|
*
|
|
1525
1739
|
* Capture Types (the Type arguments passed to `templateLiteralParser`) can use
|
|
@@ -1527,6 +1741,9 @@ interface UnionErrorValue<Error extends TypeError, MemberError extends UnionMemb
|
|
|
1527
1741
|
*
|
|
1528
1742
|
* ```ts
|
|
1529
1743
|
* import {
|
|
1744
|
+
* assertEqual,
|
|
1745
|
+
* assertOk,
|
|
1746
|
+
* assertType,
|
|
1530
1747
|
* Int64FromInt64String,
|
|
1531
1748
|
* templateLiteralParser,
|
|
1532
1749
|
* } from "@evolu/common";
|
|
@@ -1537,24 +1754,29 @@ interface UnionErrorValue<Error extends TypeError, MemberError extends UnionMemb
|
|
|
1537
1754
|
*
|
|
1538
1755
|
* // Decode the string into structured data.
|
|
1539
1756
|
* const result = ItemId.fromUnknown("item-42");
|
|
1540
|
-
*
|
|
1757
|
+
* assertOk(result, [42n]);
|
|
1541
1758
|
* const itemId = result.value;
|
|
1542
|
-
*
|
|
1759
|
+
* assertType<ItemId, typeof itemId>();
|
|
1543
1760
|
*
|
|
1544
1761
|
* // Encode the structured data into its canonical string.
|
|
1545
1762
|
* const itemIdLiteral = ItemId.to(itemId);
|
|
1546
|
-
*
|
|
1547
|
-
*
|
|
1763
|
+
* assertType<ItemIdLiteral, typeof itemIdLiteral>();
|
|
1764
|
+
* assertEqual(itemIdLiteral, "item-42");
|
|
1548
1765
|
*
|
|
1549
1766
|
* // TypeScript cannot prove from the literal alone that "42" is a valid Int64 encoding.
|
|
1550
1767
|
* // @ts-expect-error Validate it with ItemId.parent or create it with ItemId.to.
|
|
1551
|
-
* const
|
|
1768
|
+
* const _invalidItemIdLiteral: ItemIdLiteral = "item-42";
|
|
1552
1769
|
* ```
|
|
1553
1770
|
*
|
|
1554
1771
|
* Fixed-width captures can be adjacent:
|
|
1555
1772
|
*
|
|
1556
1773
|
* ```ts
|
|
1557
|
-
* import {
|
|
1774
|
+
* import {
|
|
1775
|
+
* assertEqual,
|
|
1776
|
+
* assertOk,
|
|
1777
|
+
* templateLiteralParser,
|
|
1778
|
+
* union,
|
|
1779
|
+
* } from "@evolu/common";
|
|
1558
1780
|
*
|
|
1559
1781
|
* const Digit = union("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
|
|
1560
1782
|
* const TwoDigits = templateLiteralParser(Digit, Digit);
|
|
@@ -1564,10 +1786,10 @@ interface UnionErrorValue<Error extends TypeError, MemberError extends UnionMemb
|
|
|
1564
1786
|
* const twoDigits: TwoDigits = ["4", "2"];
|
|
1565
1787
|
* const twoDigitsLiteral: TwoDigitsLiteral = "42";
|
|
1566
1788
|
* // @ts-expect-error TwoDigitsLiteral requires exactly two digits.
|
|
1567
|
-
* const
|
|
1789
|
+
* const _threeDigitsLiteral: TwoDigitsLiteral = "123";
|
|
1568
1790
|
*
|
|
1569
|
-
*
|
|
1570
|
-
*
|
|
1791
|
+
* assertOk(TwoDigits.from.parent(twoDigitsLiteral), twoDigits);
|
|
1792
|
+
* assertEqual(TwoDigits.to(twoDigits), twoDigitsLiteral);
|
|
1571
1793
|
* ```
|
|
1572
1794
|
*
|
|
1573
1795
|
* TypeScript rejects multiple variable-width captures because their encoded
|
|
@@ -1623,17 +1845,24 @@ export interface TemplateLiteralType<Parts extends TemplateLiteralParts> extends
|
|
|
1623
1845
|
* ### Example
|
|
1624
1846
|
*
|
|
1625
1847
|
* ```ts
|
|
1626
|
-
* import {
|
|
1848
|
+
* import {
|
|
1849
|
+
* assertFalse,
|
|
1850
|
+
* assertOk,
|
|
1851
|
+
* assertType,
|
|
1852
|
+
* templateLiteral,
|
|
1853
|
+
* union,
|
|
1854
|
+
* } from "@evolu/common";
|
|
1627
1855
|
*
|
|
1628
1856
|
* const Language = union("en", "cs");
|
|
1629
1857
|
* const Region = union("US", "CZ");
|
|
1630
1858
|
* const Locale = templateLiteral(Language, "-", Region);
|
|
1631
1859
|
*
|
|
1632
|
-
*
|
|
1633
|
-
* "en-US" | "en-CZ" | "cs-US" | "cs-CZ"
|
|
1860
|
+
* assertType<
|
|
1861
|
+
* "en-US" | "en-CZ" | "cs-US" | "cs-CZ",
|
|
1862
|
+
* typeof Locale.Output
|
|
1634
1863
|
* >();
|
|
1635
|
-
*
|
|
1636
|
-
*
|
|
1864
|
+
* assertOk(Locale.fromUnknown("cs-CZ"), "cs-CZ");
|
|
1865
|
+
* assertFalse(Locale.is("fr-CZ"));
|
|
1637
1866
|
* ```
|
|
1638
1867
|
*
|
|
1639
1868
|
* @group Template literals
|
|
@@ -1703,8 +1932,13 @@ type TemplateLiteralStringWidth<Value extends string, Width extends ReadonlyArra
|
|
|
1703
1932
|
*
|
|
1704
1933
|
* ```ts
|
|
1705
1934
|
* import {
|
|
1935
|
+
* assertEqual,
|
|
1936
|
+
* assertErr,
|
|
1937
|
+
* assertOk,
|
|
1938
|
+
* assertType,
|
|
1706
1939
|
* BigInt,
|
|
1707
1940
|
* brand,
|
|
1941
|
+
* Data,
|
|
1708
1942
|
* err,
|
|
1709
1943
|
* ok,
|
|
1710
1944
|
* type Brand,
|
|
@@ -1723,14 +1957,17 @@ type TemplateLiteralStringWidth<Value extends string, Width extends ReadonlyArra
|
|
|
1723
1957
|
* type Int64 = typeof Int64.Output;
|
|
1724
1958
|
*
|
|
1725
1959
|
* // Note the Brand.
|
|
1726
|
-
*
|
|
1960
|
+
* assertType<bigint & Brand<"Int64">, Int64>();
|
|
1727
1961
|
*
|
|
1728
1962
|
* interface Int64Error extends TypeError<"Int64"> {
|
|
1729
1963
|
* readonly value: bigint;
|
|
1730
1964
|
* }
|
|
1731
1965
|
*
|
|
1732
|
-
*
|
|
1733
|
-
*
|
|
1966
|
+
* assertOk(Int64.fromUnknown(42n), 42n);
|
|
1967
|
+
* const invalid = Int64.fromUnknown(2n ** 63n);
|
|
1968
|
+
* assertErr(invalid);
|
|
1969
|
+
* assertType(Data, invalid.error);
|
|
1970
|
+
* assertEqual(invalid.error, {
|
|
1734
1971
|
* type: "Int64",
|
|
1735
1972
|
* value: 2n ** 63n,
|
|
1736
1973
|
* });
|
|
@@ -1765,13 +2002,21 @@ export interface BrandType<ParentType extends TypeNode, Name extends TypeName, E
|
|
|
1765
2002
|
* ### Example
|
|
1766
2003
|
*
|
|
1767
2004
|
* ```ts
|
|
1768
|
-
* import {
|
|
2005
|
+
* import {
|
|
2006
|
+
* assertEqual,
|
|
2007
|
+
* assertErr,
|
|
2008
|
+
* assertOk,
|
|
2009
|
+
* assertType,
|
|
2010
|
+
* Data,
|
|
2011
|
+
* DateIso,
|
|
2012
|
+
* } from "@evolu/common";
|
|
1769
2013
|
*
|
|
1770
|
-
*
|
|
1771
|
-
*
|
|
1772
|
-
*
|
|
1773
|
-
* );
|
|
1774
|
-
*
|
|
2014
|
+
* const value = "2023-01-01T12:00:00.000Z";
|
|
2015
|
+
* assertOk(DateIso.fromUnknown(value), value);
|
|
2016
|
+
* const invalid = DateIso.fromUnknown("2023-01-01");
|
|
2017
|
+
* assertErr(invalid);
|
|
2018
|
+
* assertType(Data, invalid.error);
|
|
2019
|
+
* assertEqual(invalid.error, {
|
|
1775
2020
|
* type: "DateIso",
|
|
1776
2021
|
* value: "2023-01-01",
|
|
1777
2022
|
* });
|
|
@@ -1795,13 +2040,13 @@ export interface DateIsoError extends TypeError<"DateIso"> {
|
|
|
1795
2040
|
* ### Example
|
|
1796
2041
|
*
|
|
1797
2042
|
* ```ts
|
|
1798
|
-
* import { DateIsoFromDate } from "@evolu/common";
|
|
2043
|
+
* import { assertEqual, assertOk, DateIsoFromDate } from "@evolu/common";
|
|
1799
2044
|
*
|
|
1800
|
-
* const date = new
|
|
2045
|
+
* const date = new Date("2025-01-01T12:00:00.000Z");
|
|
1801
2046
|
* const result = DateIsoFromDate.fromUnknown(date);
|
|
1802
2047
|
*
|
|
1803
|
-
*
|
|
1804
|
-
*
|
|
2048
|
+
* assertOk(result, "2025-01-01T12:00:00.000Z");
|
|
2049
|
+
* assertEqual(DateIsoFromDate.to(result.value), date);
|
|
1805
2050
|
* ```
|
|
1806
2051
|
*
|
|
1807
2052
|
* @group String
|
|
@@ -1857,6 +2102,11 @@ export interface UInt64Error extends TypeError<"UInt64"> {
|
|
|
1857
2102
|
*
|
|
1858
2103
|
* ```ts
|
|
1859
2104
|
* import {
|
|
2105
|
+
* assertEqual,
|
|
2106
|
+
* assertErr,
|
|
2107
|
+
* assertOk,
|
|
2108
|
+
* assertType,
|
|
2109
|
+
* Data,
|
|
1860
2110
|
* String,
|
|
1861
2111
|
* brand,
|
|
1862
2112
|
* err,
|
|
@@ -1882,14 +2132,17 @@ export interface UInt64Error extends TypeError<"UInt64"> {
|
|
|
1882
2132
|
* const TrimmedString = trimmed(String);
|
|
1883
2133
|
* type TrimmedString = typeof TrimmedString.Output;
|
|
1884
2134
|
*
|
|
1885
|
-
*
|
|
2135
|
+
* assertType<string & Brand<"Trimmed">, TrimmedString>();
|
|
1886
2136
|
*
|
|
1887
2137
|
* interface TrimmedError extends TypeError<"Trimmed"> {
|
|
1888
2138
|
* readonly value: string;
|
|
1889
2139
|
* }
|
|
1890
2140
|
*
|
|
1891
|
-
*
|
|
1892
|
-
*
|
|
2141
|
+
* assertOk(TrimmedString.fromUnknown("Evolu"), "Evolu");
|
|
2142
|
+
* const invalid = TrimmedString.fromUnknown(" Evolu");
|
|
2143
|
+
* assertErr(invalid);
|
|
2144
|
+
* assertType(Data, invalid.error);
|
|
2145
|
+
* assertEqual(invalid.error, {
|
|
1893
2146
|
* type: "Trimmed",
|
|
1894
2147
|
* value: " Evolu",
|
|
1895
2148
|
* });
|
|
@@ -1916,6 +2169,7 @@ export type BrandFactory<Name extends TypeName, Value, Error extends TypeError<N
|
|
|
1916
2169
|
*
|
|
1917
2170
|
* ```ts
|
|
1918
2171
|
* import {
|
|
2172
|
+
* assertType,
|
|
1919
2173
|
* Number,
|
|
1920
2174
|
* brand,
|
|
1921
2175
|
* err,
|
|
@@ -1947,10 +2201,8 @@ export type BrandFactory<Name extends TypeName, Value, Error extends TypeError<N
|
|
|
1947
2201
|
* const LessThan100 = lessThan(100)(Number);
|
|
1948
2202
|
* type LessThan100 = typeof LessThan100.Output;
|
|
1949
2203
|
*
|
|
1950
|
-
*
|
|
1951
|
-
*
|
|
1952
|
-
* number & Brand<"LessThan100">
|
|
1953
|
-
* >();
|
|
2204
|
+
* assertType<"LessThan100", typeof LessThan100.name>();
|
|
2205
|
+
* assertType<number & Brand<"LessThan100">, LessThan100>();
|
|
1954
2206
|
*
|
|
1955
2207
|
* interface LessThanError<
|
|
1956
2208
|
* Max extends number,
|
|
@@ -1975,17 +2227,27 @@ type BrandFactoryNumberError = CompileTimeError<"Brand Factory", "Parameter must
|
|
|
1975
2227
|
* ### Example
|
|
1976
2228
|
*
|
|
1977
2229
|
* ```ts
|
|
1978
|
-
* import {
|
|
2230
|
+
* import {
|
|
2231
|
+
* assertEqual,
|
|
2232
|
+
* assertErr,
|
|
2233
|
+
* assertOk,
|
|
2234
|
+
* assertType,
|
|
2235
|
+
* Data,
|
|
2236
|
+
* String,
|
|
2237
|
+
* capitalized,
|
|
2238
|
+
* type Brand,
|
|
2239
|
+
* } from "@evolu/common";
|
|
1979
2240
|
*
|
|
1980
2241
|
* const CapitalizedString = capitalized(String);
|
|
1981
2242
|
* type CapitalizedString = typeof CapitalizedString.Output;
|
|
1982
2243
|
*
|
|
1983
|
-
*
|
|
1984
|
-
* string & Brand<"Capitalized">
|
|
1985
|
-
* >();
|
|
2244
|
+
* assertType<string & Brand<"Capitalized">, CapitalizedString>();
|
|
1986
2245
|
*
|
|
1987
|
-
*
|
|
1988
|
-
*
|
|
2246
|
+
* assertOk(CapitalizedString.fromUnknown("Evolu"), "Evolu");
|
|
2247
|
+
* const invalid = CapitalizedString.fromUnknown("evolu");
|
|
2248
|
+
* assertErr(invalid);
|
|
2249
|
+
* assertType(Data, invalid.error);
|
|
2250
|
+
* assertEqual(invalid.error, {
|
|
1989
2251
|
* type: "Capitalized",
|
|
1990
2252
|
* value: "evolu",
|
|
1991
2253
|
* });
|
|
@@ -2015,11 +2277,11 @@ export type CapitalizedString = typeof CapitalizedString.Output;
|
|
|
2015
2277
|
* ### Example
|
|
2016
2278
|
*
|
|
2017
2279
|
* ```ts
|
|
2018
|
-
* import { String, trimmed } from "@evolu/common";
|
|
2280
|
+
* import { assertOk, String, trimmed } from "@evolu/common";
|
|
2019
2281
|
*
|
|
2020
2282
|
* const Trimmed = trimmed(String);
|
|
2021
2283
|
*
|
|
2022
|
-
*
|
|
2284
|
+
* assertOk(Trimmed.fromUnknown("Evolu"), "Evolu");
|
|
2023
2285
|
* ```
|
|
2024
2286
|
*
|
|
2025
2287
|
* @group String
|
|
@@ -2052,9 +2314,9 @@ export type TrimmedString = typeof TrimmedString.Output;
|
|
|
2052
2314
|
* ### Example
|
|
2053
2315
|
*
|
|
2054
2316
|
* ```ts
|
|
2055
|
-
* import { trim } from "@evolu/common";
|
|
2317
|
+
* import { assertEqual, trim } from "@evolu/common";
|
|
2056
2318
|
*
|
|
2057
|
-
*
|
|
2319
|
+
* assertEqual(trim(" Evolu "), "Evolu");
|
|
2058
2320
|
* ```
|
|
2059
2321
|
*
|
|
2060
2322
|
* @group String
|
|
@@ -2066,13 +2328,13 @@ export declare const trim: (value: string) => TrimmedString;
|
|
|
2066
2328
|
* ### Example
|
|
2067
2329
|
*
|
|
2068
2330
|
* ```ts
|
|
2069
|
-
* import { String, array, minLength } from "@evolu/common";
|
|
2331
|
+
* import { assertOk, String, array, minLength } from "@evolu/common";
|
|
2070
2332
|
*
|
|
2071
2333
|
* const AtLeastThreeCharacters = minLength(3)(String);
|
|
2072
2334
|
* const AtLeastTwoItems = minLength(2)(array(String));
|
|
2073
2335
|
*
|
|
2074
|
-
*
|
|
2075
|
-
*
|
|
2336
|
+
* assertOk(AtLeastThreeCharacters.fromUnknown("abc"), "abc");
|
|
2337
|
+
* assertOk(AtLeastTwoItems.fromUnknown(["a", "b"]), ["a", "b"]);
|
|
2076
2338
|
* ```
|
|
2077
2339
|
*
|
|
2078
2340
|
* @group String
|
|
@@ -2110,13 +2372,13 @@ export type NonEmptyTrimmedString = typeof NonEmptyTrimmedString.Output;
|
|
|
2110
2372
|
* ### Example
|
|
2111
2373
|
*
|
|
2112
2374
|
* ```ts
|
|
2113
|
-
* import { String, array, maxLength } from "@evolu/common";
|
|
2375
|
+
* import { assertOk, String, array, maxLength } from "@evolu/common";
|
|
2114
2376
|
*
|
|
2115
2377
|
* const AtMostThreeCharacters = maxLength(3)(String);
|
|
2116
2378
|
* const AtMostTwoItems = maxLength(2)(array(String));
|
|
2117
2379
|
*
|
|
2118
|
-
*
|
|
2119
|
-
*
|
|
2380
|
+
* assertOk(AtMostThreeCharacters.fromUnknown("abc"), "abc");
|
|
2381
|
+
* assertOk(AtMostTwoItems.fromUnknown(["a", "b"]), ["a", "b"]);
|
|
2120
2382
|
* ```
|
|
2121
2383
|
*
|
|
2122
2384
|
* @group String
|
|
@@ -2152,13 +2414,13 @@ export type NonEmptyTrimmedString1000 = typeof NonEmptyTrimmedString1000.Output;
|
|
|
2152
2414
|
* ### Example
|
|
2153
2415
|
*
|
|
2154
2416
|
* ```ts
|
|
2155
|
-
* import { String, array, length } from "@evolu/common";
|
|
2417
|
+
* import { assertOk, String, array, length } from "@evolu/common";
|
|
2156
2418
|
*
|
|
2157
2419
|
* const ThreeCharacters = length(3)(String);
|
|
2158
2420
|
* const TwoItems = length(2)(array(String));
|
|
2159
2421
|
*
|
|
2160
|
-
*
|
|
2161
|
-
*
|
|
2422
|
+
* assertOk(ThreeCharacters.fromUnknown("abc"), "abc");
|
|
2423
|
+
* assertOk(TwoItems.fromUnknown(["a", "b"]), ["a", "b"]);
|
|
2162
2424
|
* ```
|
|
2163
2425
|
*
|
|
2164
2426
|
* @group String
|
|
@@ -2182,21 +2444,34 @@ export interface LengthError<Exact extends number = number> extends TypeError<`L
|
|
|
2182
2444
|
* A non-empty string using the URL-safe alphabet:
|
|
2183
2445
|
*
|
|
2184
2446
|
* ```ts
|
|
2185
|
-
* import {
|
|
2447
|
+
* import {
|
|
2448
|
+
* assertEqual,
|
|
2449
|
+
* assertErr,
|
|
2450
|
+
* assertOk,
|
|
2451
|
+
* assertType,
|
|
2452
|
+
* Data,
|
|
2453
|
+
* String,
|
|
2454
|
+
* regex,
|
|
2455
|
+
* type Brand,
|
|
2456
|
+
* } from "@evolu/common";
|
|
2186
2457
|
*
|
|
2187
|
-
* const UrlSafeString = regex(
|
|
2458
|
+
* const UrlSafeString = regex(
|
|
2459
|
+
* "UrlSafeString",
|
|
2460
|
+
* /^[A-Za-z0-9_-]+$/u,
|
|
2461
|
+
* )(String);
|
|
2188
2462
|
* type UrlSafeString = typeof UrlSafeString.Output;
|
|
2189
2463
|
*
|
|
2190
|
-
*
|
|
2191
|
-
* string & Brand<"UrlSafeString">
|
|
2192
|
-
* >();
|
|
2464
|
+
* assertType<string & Brand<"UrlSafeString">, UrlSafeString>();
|
|
2193
2465
|
*
|
|
2194
|
-
*
|
|
2195
|
-
*
|
|
2466
|
+
* assertOk(UrlSafeString.fromUnknown("abc-123_DEF"), "abc-123_DEF");
|
|
2467
|
+
* const invalid = UrlSafeString.fromUnknown("not safe");
|
|
2468
|
+
* assertErr(invalid);
|
|
2469
|
+
* assertType(Data, invalid.error);
|
|
2470
|
+
* assertEqual(invalid.error, {
|
|
2196
2471
|
* type: "UrlSafeString",
|
|
2197
2472
|
* value: "not safe",
|
|
2198
2473
|
* source: "^[A-Za-z0-9_-]+$",
|
|
2199
|
-
* flags: "",
|
|
2474
|
+
* flags: "u",
|
|
2200
2475
|
* });
|
|
2201
2476
|
* ```
|
|
2202
2477
|
*
|
|
@@ -2249,9 +2524,10 @@ export interface Base64UrlError extends TypeError<"Base64Url"> {
|
|
|
2249
2524
|
* ### Example
|
|
2250
2525
|
*
|
|
2251
2526
|
* ```ts
|
|
2252
|
-
* import { uint8ArrayToBase64Url } from "@evolu/common";
|
|
2527
|
+
* import { assertEqual, uint8ArrayToBase64Url } from "@evolu/common";
|
|
2253
2528
|
*
|
|
2254
|
-
*
|
|
2529
|
+
* assertEqual(
|
|
2530
|
+
* uint8ArrayToBase64Url(new Uint8Array([0, 1, 2, 255])),
|
|
2255
2531
|
* "AAEC_w",
|
|
2256
2532
|
* );
|
|
2257
2533
|
* ```
|
|
@@ -2265,11 +2541,16 @@ export declare const uint8ArrayToBase64Url: (bytes: Uint8Array) => Base64Url;
|
|
|
2265
2541
|
* ### Example
|
|
2266
2542
|
*
|
|
2267
2543
|
* ```ts
|
|
2268
|
-
* import {
|
|
2544
|
+
* import {
|
|
2545
|
+
* assertEqual,
|
|
2546
|
+
* Base64Url,
|
|
2547
|
+
* base64UrlToUint8Array,
|
|
2548
|
+
* } from "@evolu/common";
|
|
2269
2549
|
*
|
|
2270
2550
|
* const value = Base64Url.orThrow("AAEC_w");
|
|
2271
2551
|
*
|
|
2272
|
-
*
|
|
2552
|
+
* assertEqual(
|
|
2553
|
+
* base64UrlToUint8Array(value),
|
|
2273
2554
|
* new Uint8Array([0, 1, 2, 255]),
|
|
2274
2555
|
* );
|
|
2275
2556
|
* ```
|
|
@@ -2350,6 +2631,8 @@ export interface IdError extends TypeError<"Id"> {
|
|
|
2350
2631
|
*
|
|
2351
2632
|
* ```ts
|
|
2352
2633
|
* import {
|
|
2634
|
+
* assertTrue,
|
|
2635
|
+
* assertType,
|
|
2353
2636
|
* Id,
|
|
2354
2637
|
* createId,
|
|
2355
2638
|
* createRandomBytes,
|
|
@@ -2358,8 +2641,8 @@ export interface IdError extends TypeError<"Id"> {
|
|
|
2358
2641
|
*
|
|
2359
2642
|
* const userId = createId<"User">({ randomBytes: createRandomBytes() });
|
|
2360
2643
|
*
|
|
2361
|
-
*
|
|
2362
|
-
*
|
|
2644
|
+
* assertTrue(Id.is(userId));
|
|
2645
|
+
* assertType<Id & Brand<"User">, typeof userId>();
|
|
2363
2646
|
* ```
|
|
2364
2647
|
*
|
|
2365
2648
|
* @group String
|
|
@@ -2375,14 +2658,20 @@ export declare const createId: <B extends string = never>(deps: RandomBytesDep,
|
|
|
2375
2658
|
* ### Example
|
|
2376
2659
|
*
|
|
2377
2660
|
* ```ts
|
|
2378
|
-
* import {
|
|
2661
|
+
* import {
|
|
2662
|
+
* assertEqual,
|
|
2663
|
+
* assertType,
|
|
2664
|
+
* createIdFromString,
|
|
2665
|
+
* type Brand,
|
|
2666
|
+
* type Id,
|
|
2667
|
+
* } from "@evolu/common";
|
|
2379
2668
|
*
|
|
2380
2669
|
* const first = createIdFromString("external-user-123");
|
|
2381
2670
|
* const second = createIdFromString("external-user-123");
|
|
2382
2671
|
* const todoId = createIdFromString<"Todo">("external-todo-456");
|
|
2383
2672
|
*
|
|
2384
|
-
*
|
|
2385
|
-
*
|
|
2673
|
+
* assertEqual(first, second);
|
|
2674
|
+
* assertType<Id & Brand<"Todo">, typeof todoId>();
|
|
2386
2675
|
* ```
|
|
2387
2676
|
*
|
|
2388
2677
|
* @group String
|
|
@@ -2400,6 +2689,7 @@ export declare const createIdFromString: <B extends string = never>(value: strin
|
|
|
2400
2689
|
*
|
|
2401
2690
|
* ```ts
|
|
2402
2691
|
* import {
|
|
2692
|
+
* assertEqual,
|
|
2403
2693
|
* createIdAsUuidv7,
|
|
2404
2694
|
* createRandomBytes,
|
|
2405
2695
|
* createTime,
|
|
@@ -2412,8 +2702,8 @@ export declare const createIdFromString: <B extends string = never>(value: strin
|
|
|
2412
2702
|
* });
|
|
2413
2703
|
* const bytes = idToIdBytes(value);
|
|
2414
2704
|
*
|
|
2415
|
-
*
|
|
2416
|
-
*
|
|
2705
|
+
* assertEqual(bytes[6] >> 4, 0x7);
|
|
2706
|
+
* assertEqual(bytes[8] & 0xc0, 0x80);
|
|
2417
2707
|
* ```
|
|
2418
2708
|
*
|
|
2419
2709
|
* @group String
|
|
@@ -2426,6 +2716,7 @@ export declare const createIdAsUuidv7: <B extends string = never>(deps: RandomBy
|
|
|
2426
2716
|
*
|
|
2427
2717
|
* ```ts
|
|
2428
2718
|
* import {
|
|
2719
|
+
* assertType,
|
|
2429
2720
|
* createIdFromString,
|
|
2430
2721
|
* id,
|
|
2431
2722
|
* type Brand,
|
|
@@ -2435,7 +2726,7 @@ export declare const createIdAsUuidv7: <B extends string = never>(deps: RandomBy
|
|
|
2435
2726
|
* const TodoId = id("Todo");
|
|
2436
2727
|
* const todoId = TodoId.orThrow(createIdFromString("todo"));
|
|
2437
2728
|
*
|
|
2438
|
-
*
|
|
2729
|
+
* assertType<Id & Brand<"Todo">, typeof todoId>();
|
|
2439
2730
|
* ```
|
|
2440
2731
|
*
|
|
2441
2732
|
* @group String
|
|
@@ -2485,11 +2776,15 @@ export declare const idBytesTypeValueLength: NonNegativeInt;
|
|
|
2485
2776
|
* ### Example
|
|
2486
2777
|
*
|
|
2487
2778
|
* ```ts
|
|
2488
|
-
* import {
|
|
2779
|
+
* import {
|
|
2780
|
+
* assertEqual,
|
|
2781
|
+
* createIdFromString,
|
|
2782
|
+
* idToIdBytes,
|
|
2783
|
+
* } from "@evolu/common";
|
|
2489
2784
|
*
|
|
2490
2785
|
* const bytes = idToIdBytes(createIdFromString("todo"));
|
|
2491
2786
|
*
|
|
2492
|
-
*
|
|
2787
|
+
* assertEqual(bytes.length, 16);
|
|
2493
2788
|
* ```
|
|
2494
2789
|
*
|
|
2495
2790
|
* @group String
|
|
@@ -2502,6 +2797,7 @@ export declare const idToIdBytes: (value: Id) => IdBytes;
|
|
|
2502
2797
|
*
|
|
2503
2798
|
* ```ts
|
|
2504
2799
|
* import {
|
|
2800
|
+
* assertEqual,
|
|
2505
2801
|
* createIdFromString,
|
|
2506
2802
|
* idBytesToId,
|
|
2507
2803
|
* idToIdBytes,
|
|
@@ -2509,7 +2805,7 @@ export declare const idToIdBytes: (value: Id) => IdBytes;
|
|
|
2509
2805
|
*
|
|
2510
2806
|
* const value = createIdFromString("todo");
|
|
2511
2807
|
*
|
|
2512
|
-
*
|
|
2808
|
+
* assertEqual(idBytesToId(idToIdBytes(value)), value);
|
|
2513
2809
|
* ```
|
|
2514
2810
|
*
|
|
2515
2811
|
* @group String
|
|
@@ -2540,12 +2836,17 @@ export interface Int64StringError extends TypeError<"Int64String"> {
|
|
|
2540
2836
|
* ### Example
|
|
2541
2837
|
*
|
|
2542
2838
|
* ```ts
|
|
2543
|
-
* import {
|
|
2839
|
+
* import {
|
|
2840
|
+
* assertEqual,
|
|
2841
|
+
* assertOk,
|
|
2842
|
+
* Int64FromInt64String,
|
|
2843
|
+
* } from "@evolu/common";
|
|
2544
2844
|
*
|
|
2545
2845
|
* const result = Int64FromInt64String.fromUnknown("9223372036854775807");
|
|
2546
2846
|
*
|
|
2547
|
-
*
|
|
2548
|
-
*
|
|
2847
|
+
* assertOk(result, 9223372036854775807n);
|
|
2848
|
+
* assertEqual(
|
|
2849
|
+
* Int64FromInt64String.to(result.value),
|
|
2549
2850
|
* "9223372036854775807",
|
|
2550
2851
|
* );
|
|
2551
2852
|
* ```
|
|
@@ -2559,11 +2860,11 @@ export declare const Int64FromInt64String: TransformType<BrandType<BrandType<Bra
|
|
|
2559
2860
|
* ### Example
|
|
2560
2861
|
*
|
|
2561
2862
|
* ```ts
|
|
2562
|
-
* import { Number, nonNegative } from "@evolu/common";
|
|
2863
|
+
* import { assertOk, Number, nonNegative } from "@evolu/common";
|
|
2563
2864
|
*
|
|
2564
2865
|
* const NonNegative = nonNegative(Number);
|
|
2565
2866
|
*
|
|
2566
|
-
*
|
|
2867
|
+
* assertOk(NonNegative.fromUnknown(0), 0);
|
|
2567
2868
|
* ```
|
|
2568
2869
|
*
|
|
2569
2870
|
* @group Number
|
|
@@ -2590,11 +2891,11 @@ export type NonNegativeNumber = typeof NonNegativeNumber.Output;
|
|
|
2590
2891
|
* ### Example
|
|
2591
2892
|
*
|
|
2592
2893
|
* ```ts
|
|
2593
|
-
* import { Number, positive } from "@evolu/common";
|
|
2894
|
+
* import { assertOk, Number, positive } from "@evolu/common";
|
|
2594
2895
|
*
|
|
2595
2896
|
* const Positive = positive(Number);
|
|
2596
2897
|
*
|
|
2597
|
-
*
|
|
2898
|
+
* assertOk(Positive.fromUnknown(1), 1);
|
|
2598
2899
|
* ```
|
|
2599
2900
|
*
|
|
2600
2901
|
* @group Number
|
|
@@ -2624,11 +2925,11 @@ export type PositiveNumber = typeof PositiveNumber.Output;
|
|
|
2624
2925
|
* ### Example
|
|
2625
2926
|
*
|
|
2626
2927
|
* ```ts
|
|
2627
|
-
* import { Number, nonPositive } from "@evolu/common";
|
|
2928
|
+
* import { assertOk, Number, nonPositive } from "@evolu/common";
|
|
2628
2929
|
*
|
|
2629
2930
|
* const NonPositive = nonPositive(Number);
|
|
2630
2931
|
*
|
|
2631
|
-
*
|
|
2932
|
+
* assertOk(NonPositive.fromUnknown(0), 0);
|
|
2632
2933
|
* ```
|
|
2633
2934
|
*
|
|
2634
2935
|
* @group Number
|
|
@@ -2655,11 +2956,11 @@ export type NonPositiveNumber = typeof NonPositiveNumber.Output;
|
|
|
2655
2956
|
* ### Example
|
|
2656
2957
|
*
|
|
2657
2958
|
* ```ts
|
|
2658
|
-
* import { Number, negative } from "@evolu/common";
|
|
2959
|
+
* import { assertOk, Number, negative } from "@evolu/common";
|
|
2659
2960
|
*
|
|
2660
2961
|
* const Negative = negative(Number);
|
|
2661
2962
|
*
|
|
2662
|
-
*
|
|
2963
|
+
* assertOk(Negative.fromUnknown(-1), -1);
|
|
2663
2964
|
* ```
|
|
2664
2965
|
*
|
|
2665
2966
|
* @group Number
|
|
@@ -2689,11 +2990,11 @@ export type NegativeNumber = typeof NegativeNumber.Output;
|
|
|
2689
2990
|
* ### Example
|
|
2690
2991
|
*
|
|
2691
2992
|
* ```ts
|
|
2692
|
-
* import { Number, nonNaN } from "@evolu/common";
|
|
2993
|
+
* import { assertOk, Number, nonNaN } from "@evolu/common";
|
|
2693
2994
|
*
|
|
2694
2995
|
* const NonNaN = nonNaN(Number);
|
|
2695
2996
|
*
|
|
2696
|
-
*
|
|
2997
|
+
* assertOk(NonNaN.fromUnknown(Infinity), Infinity);
|
|
2697
2998
|
* ```
|
|
2698
2999
|
*
|
|
2699
3000
|
* @group Number
|
|
@@ -2725,11 +3026,11 @@ export type NonNaNNumber = typeof NonNaNNumber.Output;
|
|
|
2725
3026
|
* ### Example
|
|
2726
3027
|
*
|
|
2727
3028
|
* ```ts
|
|
2728
|
-
* import { Number, finite } from "@evolu/common";
|
|
3029
|
+
* import { assertOk, Number, finite } from "@evolu/common";
|
|
2729
3030
|
*
|
|
2730
3031
|
* const Finite = finite(Number);
|
|
2731
3032
|
*
|
|
2732
|
-
*
|
|
3033
|
+
* assertOk(Finite.fromUnknown(42), 42);
|
|
2733
3034
|
* ```
|
|
2734
3035
|
*
|
|
2735
3036
|
* @group Number
|
|
@@ -2773,15 +3074,28 @@ export type PositiveFiniteNumber = typeof PositiveFiniteNumber.Output;
|
|
|
2773
3074
|
* ### Example
|
|
2774
3075
|
*
|
|
2775
3076
|
* ```ts
|
|
2776
|
-
* import {
|
|
3077
|
+
* import {
|
|
3078
|
+
* assertEqual,
|
|
3079
|
+
* assertErr,
|
|
3080
|
+
* assertOk,
|
|
3081
|
+
* assertType,
|
|
3082
|
+
* Data,
|
|
3083
|
+
* Number,
|
|
3084
|
+
* int,
|
|
3085
|
+
* type Brand,
|
|
3086
|
+
* } from "@evolu/common";
|
|
2777
3087
|
*
|
|
2778
3088
|
* const Int = int(Number);
|
|
2779
3089
|
* type Int = typeof Int.Output;
|
|
2780
3090
|
*
|
|
2781
|
-
*
|
|
3091
|
+
* assertType<number & Brand<"Int">, Int>();
|
|
2782
3092
|
*
|
|
2783
|
-
*
|
|
2784
|
-
*
|
|
3093
|
+
* assertOk(Int.fromUnknown(42), 42);
|
|
3094
|
+
* const invalid = Int.fromUnknown(1.5);
|
|
3095
|
+
* assertErr(invalid);
|
|
3096
|
+
* assertType(Data, invalid.error);
|
|
3097
|
+
* const error: Data = invalid.error;
|
|
3098
|
+
* assertEqual(error, { type: "Int", value: 1.5 });
|
|
2785
3099
|
* ```
|
|
2786
3100
|
*
|
|
2787
3101
|
* @group Number
|
|
@@ -2860,11 +3174,11 @@ export type NegativeInt = typeof NegativeInt.Output;
|
|
|
2860
3174
|
* ### Example
|
|
2861
3175
|
*
|
|
2862
3176
|
* ```ts
|
|
2863
|
-
* import { Number, greaterThan } from "@evolu/common";
|
|
3177
|
+
* import { assertOk, Number, greaterThan } from "@evolu/common";
|
|
2864
3178
|
*
|
|
2865
3179
|
* const GreaterThanTen = greaterThan(10)(Number);
|
|
2866
3180
|
*
|
|
2867
|
-
*
|
|
3181
|
+
* assertOk(GreaterThanTen.fromUnknown(11), 11);
|
|
2868
3182
|
* ```
|
|
2869
3183
|
*
|
|
2870
3184
|
* @group Number
|
|
@@ -2885,11 +3199,11 @@ export interface GreaterThanError<Min extends number = number> extends TypeError
|
|
|
2885
3199
|
* ### Example
|
|
2886
3200
|
*
|
|
2887
3201
|
* ```ts
|
|
2888
|
-
* import { Number, greaterThanOrEqualTo } from "@evolu/common";
|
|
3202
|
+
* import { assertOk, Number, greaterThanOrEqualTo } from "@evolu/common";
|
|
2889
3203
|
*
|
|
2890
3204
|
* const AtLeastTen = greaterThanOrEqualTo(10)(Number);
|
|
2891
3205
|
*
|
|
2892
|
-
*
|
|
3206
|
+
* assertOk(AtLeastTen.fromUnknown(10), 10);
|
|
2893
3207
|
* ```
|
|
2894
3208
|
*
|
|
2895
3209
|
* @group Number
|
|
@@ -2910,11 +3224,11 @@ export interface GreaterThanOrEqualToError<Min extends number = number> extends
|
|
|
2910
3224
|
* ### Example
|
|
2911
3225
|
*
|
|
2912
3226
|
* ```ts
|
|
2913
|
-
* import { Number, lessThan } from "@evolu/common";
|
|
3227
|
+
* import { assertOk, Number, lessThan } from "@evolu/common";
|
|
2914
3228
|
*
|
|
2915
3229
|
* const LessThanTen = lessThan(10)(Number);
|
|
2916
3230
|
*
|
|
2917
|
-
*
|
|
3231
|
+
* assertOk(LessThanTen.fromUnknown(9), 9);
|
|
2918
3232
|
* ```
|
|
2919
3233
|
*
|
|
2920
3234
|
* @group Number
|
|
@@ -2942,11 +3256,11 @@ export type Age = typeof Age.Output;
|
|
|
2942
3256
|
* ### Example
|
|
2943
3257
|
*
|
|
2944
3258
|
* ```ts
|
|
2945
|
-
* import { Number, lessThanOrEqualTo } from "@evolu/common";
|
|
3259
|
+
* import { assertOk, Number, lessThanOrEqualTo } from "@evolu/common";
|
|
2946
3260
|
*
|
|
2947
3261
|
* const AtMostTen = lessThanOrEqualTo(10)(Number);
|
|
2948
3262
|
*
|
|
2949
|
-
*
|
|
3263
|
+
* assertOk(AtMostTen.fromUnknown(10), 10);
|
|
2950
3264
|
* ```
|
|
2951
3265
|
*
|
|
2952
3266
|
* @group Number
|
|
@@ -2997,13 +3311,23 @@ export type Ratio = typeof Ratio.Output;
|
|
|
2997
3311
|
* ### Example
|
|
2998
3312
|
*
|
|
2999
3313
|
* ```ts
|
|
3000
|
-
* import {
|
|
3314
|
+
* import {
|
|
3315
|
+
* assertEqual,
|
|
3316
|
+
* assertErr,
|
|
3317
|
+
* assertOk,
|
|
3318
|
+
* assertType,
|
|
3319
|
+
* Data,
|
|
3320
|
+
* DecimalString,
|
|
3321
|
+
* } from "@evolu/common";
|
|
3001
3322
|
*
|
|
3002
|
-
*
|
|
3003
|
-
*
|
|
3004
|
-
*
|
|
3323
|
+
* assertOk(DecimalString.fromUnknown("-10.25"), "-10.25");
|
|
3324
|
+
* assertOk(DecimalString.fromUnknown("0"), "0");
|
|
3325
|
+
* assertOk(DecimalString.fromUnknown("10.25"), "10.25");
|
|
3005
3326
|
*
|
|
3006
|
-
*
|
|
3327
|
+
* const invalid = DecimalString.fromUnknown("10.250");
|
|
3328
|
+
* assertErr(invalid);
|
|
3329
|
+
* assertType(Data, invalid.error);
|
|
3330
|
+
* assertEqual(invalid.error, {
|
|
3007
3331
|
* type: "DecimalString",
|
|
3008
3332
|
* value: "10.250",
|
|
3009
3333
|
* });
|
|
@@ -3027,11 +3351,15 @@ export interface DecimalStringError extends TypeError<"DecimalString"> {
|
|
|
3027
3351
|
* ### Example
|
|
3028
3352
|
*
|
|
3029
3353
|
* ```ts
|
|
3030
|
-
* import {
|
|
3354
|
+
* import {
|
|
3355
|
+
* assertOk,
|
|
3356
|
+
* DecimalString,
|
|
3357
|
+
* nonNegativeDecimalString,
|
|
3358
|
+
* } from "@evolu/common";
|
|
3031
3359
|
*
|
|
3032
3360
|
* const NonNegative = nonNegativeDecimalString(DecimalString);
|
|
3033
3361
|
*
|
|
3034
|
-
*
|
|
3362
|
+
* assertOk(NonNegative.fromUnknown("0.5"), "0.5");
|
|
3035
3363
|
* ```
|
|
3036
3364
|
*
|
|
3037
3365
|
* @group Number
|
|
@@ -3058,11 +3386,15 @@ export type NonNegativeDecimalString = typeof NonNegativeDecimalString.Output;
|
|
|
3058
3386
|
* ### Example
|
|
3059
3387
|
*
|
|
3060
3388
|
* ```ts
|
|
3061
|
-
* import {
|
|
3389
|
+
* import {
|
|
3390
|
+
* assertOk,
|
|
3391
|
+
* DecimalString,
|
|
3392
|
+
* positiveDecimalString,
|
|
3393
|
+
* } from "@evolu/common";
|
|
3062
3394
|
*
|
|
3063
3395
|
* const Positive = positiveDecimalString(DecimalString);
|
|
3064
3396
|
*
|
|
3065
|
-
*
|
|
3397
|
+
* assertOk(Positive.fromUnknown("0.5"), "0.5");
|
|
3066
3398
|
* ```
|
|
3067
3399
|
*
|
|
3068
3400
|
* @group Number
|
|
@@ -3092,11 +3424,15 @@ export type PositiveDecimalString = typeof PositiveDecimalString.Output;
|
|
|
3092
3424
|
* ### Example
|
|
3093
3425
|
*
|
|
3094
3426
|
* ```ts
|
|
3095
|
-
* import {
|
|
3427
|
+
* import {
|
|
3428
|
+
* assertOk,
|
|
3429
|
+
* DecimalString,
|
|
3430
|
+
* nonPositiveDecimalString,
|
|
3431
|
+
* } from "@evolu/common";
|
|
3096
3432
|
*
|
|
3097
3433
|
* const NonPositive = nonPositiveDecimalString(DecimalString);
|
|
3098
3434
|
*
|
|
3099
|
-
*
|
|
3435
|
+
* assertOk(NonPositive.fromUnknown("-0.5"), "-0.5");
|
|
3100
3436
|
* ```
|
|
3101
3437
|
*
|
|
3102
3438
|
* @group Number
|
|
@@ -3123,11 +3459,15 @@ export type NonPositiveDecimalString = typeof NonPositiveDecimalString.Output;
|
|
|
3123
3459
|
* ### Example
|
|
3124
3460
|
*
|
|
3125
3461
|
* ```ts
|
|
3126
|
-
* import {
|
|
3462
|
+
* import {
|
|
3463
|
+
* assertOk,
|
|
3464
|
+
* DecimalString,
|
|
3465
|
+
* negativeDecimalString,
|
|
3466
|
+
* } from "@evolu/common";
|
|
3127
3467
|
*
|
|
3128
3468
|
* const Negative = negativeDecimalString(DecimalString);
|
|
3129
3469
|
*
|
|
3130
|
-
*
|
|
3470
|
+
* assertOk(Negative.fromUnknown("-0.5"), "-0.5");
|
|
3131
3471
|
* ```
|
|
3132
3472
|
*
|
|
3133
3473
|
* @group Number
|
|
@@ -3165,16 +3505,29 @@ export type NegativeDecimalString = typeof NegativeDecimalString.Output;
|
|
|
3165
3505
|
* ### Example
|
|
3166
3506
|
*
|
|
3167
3507
|
* ```ts
|
|
3168
|
-
* import {
|
|
3508
|
+
* import {
|
|
3509
|
+
* assertEqual,
|
|
3510
|
+
* assertErr,
|
|
3511
|
+
* assertOk,
|
|
3512
|
+
* assertType,
|
|
3513
|
+
* Data,
|
|
3514
|
+
* FiniteNumber,
|
|
3515
|
+
* multipleOf,
|
|
3516
|
+
* type Brand,
|
|
3517
|
+
* } from "@evolu/common";
|
|
3169
3518
|
*
|
|
3170
3519
|
* const Tenths = multipleOf("0.1")(FiniteNumber);
|
|
3171
3520
|
*
|
|
3172
|
-
*
|
|
3173
|
-
* FiniteNumber & Brand<"MultipleOf0.1"
|
|
3521
|
+
* assertType<
|
|
3522
|
+
* FiniteNumber & Brand<"MultipleOf0.1">,
|
|
3523
|
+
* typeof Tenths.Output
|
|
3174
3524
|
* >();
|
|
3175
3525
|
*
|
|
3176
|
-
*
|
|
3177
|
-
*
|
|
3526
|
+
* assertOk(Tenths.fromUnknown(0.3), 0.3);
|
|
3527
|
+
* const invalid = Tenths.fromUnknown(0.31);
|
|
3528
|
+
* assertErr(invalid);
|
|
3529
|
+
* assertType(Data, invalid.error);
|
|
3530
|
+
* assertEqual(invalid.error, {
|
|
3178
3531
|
* type: "MultipleOf0.1",
|
|
3179
3532
|
* value: 0.31,
|
|
3180
3533
|
* divisor: "0.1",
|
|
@@ -3207,11 +3560,11 @@ type MultipleOfDivisorError = CompileTimeError<"MultipleOf", 'Divisor must be on
|
|
|
3207
3560
|
* ### Example
|
|
3208
3561
|
*
|
|
3209
3562
|
* ```ts
|
|
3210
|
-
* import { Number, between } from "@evolu/common";
|
|
3563
|
+
* import { assertOk, Number, between } from "@evolu/common";
|
|
3211
3564
|
*
|
|
3212
3565
|
* const Percentage = between(0, 100)(Number);
|
|
3213
3566
|
*
|
|
3214
|
-
*
|
|
3567
|
+
* assertOk(Percentage.fromUnknown(75), 75);
|
|
3215
3568
|
* ```
|
|
3216
3569
|
*
|
|
3217
3570
|
* @group Number
|
|
@@ -3253,6 +3606,11 @@ export interface BetweenError<Min extends number = number, Max extends number =
|
|
|
3253
3606
|
*
|
|
3254
3607
|
* ```ts
|
|
3255
3608
|
* import {
|
|
3609
|
+
* assertEqual,
|
|
3610
|
+
* assertErr,
|
|
3611
|
+
* assertOk,
|
|
3612
|
+
* assertType,
|
|
3613
|
+
* Data,
|
|
3256
3614
|
* String,
|
|
3257
3615
|
* array,
|
|
3258
3616
|
* brand,
|
|
@@ -3264,12 +3622,16 @@ export interface BetweenError<Min extends number = number, Max extends number =
|
|
|
3264
3622
|
* const UserIds = array(UserId);
|
|
3265
3623
|
* const result = UserIds.from.parent(["ada", "grace"]);
|
|
3266
3624
|
*
|
|
3267
|
-
*
|
|
3268
|
-
* Result<ReadonlyArray<string & Brand<"UserId"
|
|
3625
|
+
* assertType<
|
|
3626
|
+
* Result<ReadonlyArray<string & Brand<"UserId">>>,
|
|
3627
|
+
* typeof result
|
|
3269
3628
|
* >();
|
|
3270
|
-
*
|
|
3271
|
-
*
|
|
3272
|
-
*
|
|
3629
|
+
* assertOk(result, ["ada", "grace"]);
|
|
3630
|
+
* assertOk(UserIds.fromUnknown(["ada", "grace"]), ["ada", "grace"]);
|
|
3631
|
+
* const invalid = UserIds.fromUnknown("ada");
|
|
3632
|
+
* assertErr(invalid);
|
|
3633
|
+
* assertType(Data, invalid.error);
|
|
3634
|
+
* assertEqual(invalid.error, {
|
|
3273
3635
|
* type: "Array",
|
|
3274
3636
|
* reason: { kind: "NotArray", value: "ada" },
|
|
3275
3637
|
* });
|
|
@@ -3387,20 +3749,20 @@ interface ArrayItemsErrorValue<Error extends TypeError, IncludeStructuralIssues
|
|
|
3387
3749
|
/**
|
|
3388
3750
|
* Set {@link Type} whose every element must match one Type.
|
|
3389
3751
|
*
|
|
3390
|
-
*
|
|
3391
|
-
*
|
|
3392
|
-
*
|
|
3393
|
-
*
|
|
3752
|
+
* Sets from this or another realm are accepted. A Set must have no own
|
|
3753
|
+
* properties; its elements are validated in iteration order. Classification
|
|
3754
|
+
* uses the realm-neutral object tag under Evolu Type's trusted JavaScript
|
|
3755
|
+
* policy.
|
|
3394
3756
|
*
|
|
3395
3757
|
* ### Example
|
|
3396
3758
|
*
|
|
3397
3759
|
* ```ts
|
|
3398
|
-
* import { String, set } from "@evolu/common";
|
|
3760
|
+
* import { assertOk, String, set } from "@evolu/common";
|
|
3399
3761
|
*
|
|
3400
3762
|
* const Tags = set(String);
|
|
3401
3763
|
* const tags = new Set(["local-first", "offline"]);
|
|
3402
3764
|
*
|
|
3403
|
-
*
|
|
3765
|
+
* assertOk(Tags.fromUnknown(tags), tags);
|
|
3404
3766
|
* ```
|
|
3405
3767
|
*
|
|
3406
3768
|
* @group Collection
|
|
@@ -3431,12 +3793,11 @@ type SetNodeError<ElementType extends TypeNode> = [
|
|
|
3431
3793
|
ElementType["parent"]
|
|
3432
3794
|
] extends [TypeNode] ? SetElementsError<ElementType["Error"]> : SetError<ElementType["Error"]>;
|
|
3433
3795
|
/**
|
|
3434
|
-
* Error returned by {@link set} for a non-Set value
|
|
3435
|
-
* or invalid Set items.
|
|
3796
|
+
* Error returned by {@link set} for a non-Set value or invalid Set items.
|
|
3436
3797
|
*
|
|
3437
3798
|
* @group Collection
|
|
3438
3799
|
*/
|
|
3439
|
-
export type SetError<Error extends TypeError = TypeError> = SetNotSetError |
|
|
3800
|
+
export type SetError<Error extends TypeError = TypeError> = SetNotSetError | SetItemsErrorValue<Error, true>;
|
|
3440
3801
|
/**
|
|
3441
3802
|
* Error returned when a {@link set} input is not a Set.
|
|
3442
3803
|
*
|
|
@@ -3448,17 +3809,6 @@ export interface SetNotSetError extends TypeError<"Set"> {
|
|
|
3448
3809
|
readonly value: unknown;
|
|
3449
3810
|
};
|
|
3450
3811
|
}
|
|
3451
|
-
/**
|
|
3452
|
-
* An error returned when a {@link set} input is a Set subclass.
|
|
3453
|
-
*
|
|
3454
|
-
* @group Collection
|
|
3455
|
-
*/
|
|
3456
|
-
export interface SetUnexpectedPrototypeError extends TypeError<"Set"> {
|
|
3457
|
-
readonly reason: {
|
|
3458
|
-
readonly kind: "UnexpectedPrototype";
|
|
3459
|
-
readonly value: ReadonlySet<unknown>;
|
|
3460
|
-
};
|
|
3461
|
-
}
|
|
3462
3812
|
/**
|
|
3463
3813
|
* An own property found on a Set value.
|
|
3464
3814
|
*
|
|
@@ -3497,6 +3847,133 @@ interface SetItemsErrorValue<Error extends TypeError, IncludeStructuralIssues ex
|
|
|
3497
3847
|
readonly issues: NonEmptyReadonlyArray<(true extends IncludeStructuralIssues ? SetStructuralIssue : never) | SetElementIssue<Error>>;
|
|
3498
3848
|
};
|
|
3499
3849
|
}
|
|
3850
|
+
/**
|
|
3851
|
+
* Map {@link Type} whose keys and values must match their respective Types.
|
|
3852
|
+
*
|
|
3853
|
+
* Maps from this or another realm are accepted. A Map must have no own
|
|
3854
|
+
* properties; its entries are validated in iteration order. When distinct input
|
|
3855
|
+
* keys decode to the same output key, validation fails instead of discarding
|
|
3856
|
+
* one associated value. Classification uses the realm-neutral object tag under
|
|
3857
|
+
* Evolu Type's trusted JavaScript policy.
|
|
3858
|
+
*
|
|
3859
|
+
* ### Example
|
|
3860
|
+
*
|
|
3861
|
+
* ```ts
|
|
3862
|
+
* import { assertOk, PositiveInt, String, map } from "@evolu/common";
|
|
3863
|
+
*
|
|
3864
|
+
* const Scores = map(String, PositiveInt);
|
|
3865
|
+
* const scores = new Map([
|
|
3866
|
+
* ["Ada", 10],
|
|
3867
|
+
* ["Grace", 20],
|
|
3868
|
+
* ]);
|
|
3869
|
+
*
|
|
3870
|
+
* assertOk(Scores.fromUnknown(scores), scores);
|
|
3871
|
+
* ```
|
|
3872
|
+
*
|
|
3873
|
+
* @group Collection
|
|
3874
|
+
*/
|
|
3875
|
+
export declare const map: <KeyType extends ConcreteTypeNode, ValueType extends ConcreteTypeNode>(key: ValidateMapKeyType<KeyType>, value: ValidateMapValueType<ValueType>) => MapType<KeyType, ValueType>;
|
|
3876
|
+
/**
|
|
3877
|
+
* The readonly-map {@link Type} returned by {@link map}.
|
|
3878
|
+
*
|
|
3879
|
+
* @group Collection
|
|
3880
|
+
*/
|
|
3881
|
+
export interface MapType<KeyType extends TypeNode, ValueType extends TypeNode> extends Type<"Map", ReadonlyMap<KeyType["Input"], ValueType["Input"]>, ReadonlyMap<KeyType["Output"], ValueType["Output"]>, MapNodeError<KeyType, ValueType>, MapParent<KeyType, ValueType>, MapError<InferErrors<KeyType>, InferErrors<ValueType>, MapCollisionFor<KeyType>>, never, CanonicalInputSubset<ReadonlyMap<KeyType["Input"], ValueType["Input"]>, ReadonlyMap<CanonicalInputOf<KeyType>, CanonicalInputOf<ValueType>>>, AllTypesUseIdentityEncoding<KeyType | ValueType>> {
|
|
3882
|
+
readonly [reflectedTypesSymbol]?: KeyType | ValueType;
|
|
3883
|
+
readonly key: KeyType;
|
|
3884
|
+
readonly value: ValueType;
|
|
3885
|
+
}
|
|
3886
|
+
type MapParent<KeyType extends TypeNode, ValueType extends TypeNode> = [
|
|
3887
|
+
KeyType["parent"] | ValueType["parent"]
|
|
3888
|
+
] extends [null] ? null : MapType<RootType<KeyType>, RootType<ValueType>>;
|
|
3889
|
+
type MapNodeError<KeyType extends TypeNode, ValueType extends TypeNode> = [
|
|
3890
|
+
KeyType["parent"] | ValueType["parent"]
|
|
3891
|
+
] extends [null] ? MapError<InferErrors<KeyType>, InferErrors<ValueType>, never> : MapEntriesError<TypeFromError<KeyType>, TypeFromError<ValueType>, MapCollisionFor<KeyType>>;
|
|
3892
|
+
type MapCollisionFor<KeyType extends TypeNode> = [KeyType["parent"]] extends [
|
|
3893
|
+
TypeNode
|
|
3894
|
+
] ? MapKeyCollisionIssue : never;
|
|
3895
|
+
type ValidateMapKeyType<T extends ConcreteTypeNode> = IsUnion<T> extends false ? T : CompileTimeError<"Type", "Map key must use one concrete Type node. Pass a Union Type node instead of a union of Type nodes.">;
|
|
3896
|
+
type ValidateMapValueType<T extends ConcreteTypeNode> = IsUnion<T> extends false ? T : CompileTimeError<"Type", "Map value must use one concrete Type node. Pass a Union Type node instead of a union of Type nodes.">;
|
|
3897
|
+
/**
|
|
3898
|
+
* Error returned while validating a {@link map} and its entries.
|
|
3899
|
+
*
|
|
3900
|
+
* @group Collection
|
|
3901
|
+
*/
|
|
3902
|
+
export type MapError<KeyError extends TypeError = TypeError, ValueError extends TypeError = TypeError, Collision extends MapKeyCollisionIssue = MapKeyCollisionIssue> = MapNotMapError | MapEntriesErrorValue<KeyError, ValueError, Collision | MapExcessPropertyIssue>;
|
|
3903
|
+
/**
|
|
3904
|
+
* Error returned when a {@link map} input is not a Map.
|
|
3905
|
+
*
|
|
3906
|
+
* @group Collection
|
|
3907
|
+
*/
|
|
3908
|
+
export interface MapNotMapError extends TypeError<"Map"> {
|
|
3909
|
+
readonly reason: {
|
|
3910
|
+
readonly kind: "NotMap";
|
|
3911
|
+
readonly value: unknown;
|
|
3912
|
+
};
|
|
3913
|
+
}
|
|
3914
|
+
/**
|
|
3915
|
+
* An own property found on a Map value.
|
|
3916
|
+
*
|
|
3917
|
+
* @group Collection
|
|
3918
|
+
*/
|
|
3919
|
+
export interface MapExcessPropertyIssue {
|
|
3920
|
+
readonly kind: "ExcessProperty";
|
|
3921
|
+
readonly key: string | symbol;
|
|
3922
|
+
}
|
|
3923
|
+
/**
|
|
3924
|
+
* An invalid key and its entry index in a {@link map}.
|
|
3925
|
+
*
|
|
3926
|
+
* @group Collection
|
|
3927
|
+
*/
|
|
3928
|
+
export type MapKeyIssue<Error extends TypeError> = Error extends TypeError ? {
|
|
3929
|
+
readonly kind: "Key";
|
|
3930
|
+
readonly index: number;
|
|
3931
|
+
readonly key: unknown;
|
|
3932
|
+
readonly error: Error;
|
|
3933
|
+
} : never;
|
|
3934
|
+
/**
|
|
3935
|
+
* An invalid value and its entry index in a {@link map}.
|
|
3936
|
+
*
|
|
3937
|
+
* @group Collection
|
|
3938
|
+
*/
|
|
3939
|
+
export type MapValueIssue<Error extends TypeError> = Error extends TypeError ? {
|
|
3940
|
+
readonly kind: "Value";
|
|
3941
|
+
readonly index: number;
|
|
3942
|
+
readonly key: unknown;
|
|
3943
|
+
readonly error: Error;
|
|
3944
|
+
} : never;
|
|
3945
|
+
/**
|
|
3946
|
+
* Two {@link map} keys that decode to the same output key.
|
|
3947
|
+
*
|
|
3948
|
+
* @group Collection
|
|
3949
|
+
*/
|
|
3950
|
+
export interface MapKeyCollisionIssue {
|
|
3951
|
+
readonly kind: "Collision";
|
|
3952
|
+
readonly index: number;
|
|
3953
|
+
readonly key: unknown;
|
|
3954
|
+
readonly previousIndex: number;
|
|
3955
|
+
readonly previousKey: unknown;
|
|
3956
|
+
readonly outputKey: unknown;
|
|
3957
|
+
}
|
|
3958
|
+
type MapStructuralIssue = MapExcessPropertyIssue | MapKeyCollisionIssue;
|
|
3959
|
+
/**
|
|
3960
|
+
* An invalid key, value, or structure in a {@link map}.
|
|
3961
|
+
*
|
|
3962
|
+
* @group Collection
|
|
3963
|
+
*/
|
|
3964
|
+
export type MapIssue<KeyError extends TypeError, ValueError extends TypeError, StructuralIssue extends MapStructuralIssue = MapKeyCollisionIssue> = MapKeyIssue<KeyError> | MapValueIssue<ValueError> | StructuralIssue;
|
|
3965
|
+
/**
|
|
3966
|
+
* Entry errors returned by a {@link map} operation.
|
|
3967
|
+
*
|
|
3968
|
+
* @group Collection
|
|
3969
|
+
*/
|
|
3970
|
+
export type MapEntriesError<KeyError extends TypeError, ValueError extends TypeError, StructuralIssue extends MapStructuralIssue = MapKeyCollisionIssue> = [KeyError | ValueError | StructuralIssue] extends [never] ? never : MapEntriesErrorValue<KeyError, ValueError, StructuralIssue>;
|
|
3971
|
+
interface MapEntriesErrorValue<KeyError extends TypeError, ValueError extends TypeError, StructuralIssue extends MapStructuralIssue> extends TypeError<"Map"> {
|
|
3972
|
+
readonly reason: {
|
|
3973
|
+
readonly kind: "Entries";
|
|
3974
|
+
readonly issues: NonEmptyReadonlyArray<MapKeyIssue<KeyError> | MapValueIssue<ValueError> | StructuralIssue>;
|
|
3975
|
+
};
|
|
3976
|
+
}
|
|
3500
3977
|
/**
|
|
3501
3978
|
* Tuple {@link Type}.
|
|
3502
3979
|
*
|
|
@@ -3514,20 +3991,24 @@ interface SetItemsErrorValue<Error extends TypeError, IncludeStructuralIssues ex
|
|
|
3514
3991
|
*
|
|
3515
3992
|
* A Tuple must be recognized by `Array.isArray`, have exactly the declared
|
|
3516
3993
|
* length, be dense, and have no own properties other than `length` and the
|
|
3517
|
-
* indexed data properties for its elements.
|
|
3518
|
-
*
|
|
3519
|
-
*
|
|
3520
|
-
* properties are rejected.
|
|
3994
|
+
* indexed data properties for its elements. Foreign-realm arrays are accepted
|
|
3995
|
+
* when their own data representation is valid. Sparse arrays, accessor
|
|
3996
|
+
* elements, and excess properties are rejected.
|
|
3521
3997
|
*
|
|
3522
3998
|
* ### Example
|
|
3523
3999
|
*
|
|
3524
4000
|
* ```ts
|
|
3525
|
-
* import {
|
|
4001
|
+
* import {
|
|
4002
|
+
* assertOk,
|
|
4003
|
+
* Int64FromInt64String,
|
|
4004
|
+
* String,
|
|
4005
|
+
* tuple,
|
|
4006
|
+
* } from "@evolu/common";
|
|
3526
4007
|
*
|
|
3527
4008
|
* const Entry = tuple(String, Int64FromInt64String);
|
|
3528
4009
|
*
|
|
3529
|
-
*
|
|
3530
|
-
*
|
|
4010
|
+
* assertOk(Entry.fromUnknown(["count", "1"]), ["count", 1n]);
|
|
4011
|
+
* assertOk(Entry.from.parent(["count", "1"]), ["count", 1n]);
|
|
3531
4012
|
* ```
|
|
3532
4013
|
*
|
|
3533
4014
|
* @group Collection
|
|
@@ -3716,11 +4197,12 @@ type PlainObjectError = ObjectError<Readonly<Record<never, never>>, ObjectProper
|
|
|
3716
4197
|
* A {@link Type} for readonly plain objects with unknown property values.
|
|
3717
4198
|
*
|
|
3718
4199
|
* `Object` is the runtime counterpart of a `Readonly<Record<string, unknown>>`
|
|
3719
|
-
* data boundary. Its
|
|
3720
|
-
*
|
|
3721
|
-
*
|
|
3722
|
-
*
|
|
3723
|
-
* properties, and symbol properties
|
|
4200
|
+
* data boundary. Its prototype rule uses the realm-neutral structural heuristic
|
|
4201
|
+
* described by {@link isPlainObject}. A matching custom root prototype can be
|
|
4202
|
+
* classified as plain; other custom prototypes and class instances are
|
|
4203
|
+
* rejected. Every own property must have a string key and be an enumerable data
|
|
4204
|
+
* property. Accessors, non-enumerable properties, and symbol properties are
|
|
4205
|
+
* rejected without reading their values.
|
|
3724
4206
|
*
|
|
3725
4207
|
* Use {@link object} when property names are fixed, {@link record} when keys and
|
|
3726
4208
|
* values have their own Types, and {@link instanceOf} when an instance belongs
|
|
@@ -3746,12 +4228,13 @@ export { _Object as Object };
|
|
|
3746
4228
|
* By default, validation returns the first issue. Pass `{ errors: "all" }` to
|
|
3747
4229
|
* collect issues across the whole Record.
|
|
3748
4230
|
*
|
|
3749
|
-
* A Record must
|
|
3750
|
-
*
|
|
3751
|
-
*
|
|
3752
|
-
*
|
|
3753
|
-
*
|
|
3754
|
-
* `__proto__` remain ordinary
|
|
4231
|
+
* A Record must satisfy the realm-neutral structural heuristic described by
|
|
4232
|
+
* {@link isPlainObject}. A matching custom root prototype can be classified as
|
|
4233
|
+
* plain; other custom prototypes and class instances are rejected. Every own
|
|
4234
|
+
* property must be an enumerable data property whose key and value satisfy
|
|
4235
|
+
* their Types. When decoding or encoding changes an entry, the constructed
|
|
4236
|
+
* Record uses a `null` prototype so keys such as `__proto__` remain ordinary
|
|
4237
|
+
* data.
|
|
3755
4238
|
*
|
|
3756
4239
|
* If transformed keys collide, validation fails instead of overwriting an
|
|
3757
4240
|
* entry.
|
|
@@ -3760,6 +4243,8 @@ export { _Object as Object };
|
|
|
3760
4243
|
*
|
|
3761
4244
|
* ```ts
|
|
3762
4245
|
* import {
|
|
4246
|
+
* assertOk,
|
|
4247
|
+
* assertType,
|
|
3763
4248
|
* Int64FromInt64String,
|
|
3764
4249
|
* String,
|
|
3765
4250
|
* record,
|
|
@@ -3775,21 +4260,22 @@ export { _Object as Object };
|
|
|
3775
4260
|
* grace: "20",
|
|
3776
4261
|
* });
|
|
3777
4262
|
*
|
|
3778
|
-
*
|
|
4263
|
+
* assertOk(scoresFromUnknown, { ada: 10n, grace: 20n });
|
|
3779
4264
|
*
|
|
3780
4265
|
* // Validate keys and values with their root Types.
|
|
3781
4266
|
* const scoresInput = ScoresByUser.parent.fromUnknown({
|
|
3782
4267
|
* ada: "10",
|
|
3783
4268
|
* grace: "20",
|
|
3784
4269
|
* });
|
|
3785
|
-
*
|
|
4270
|
+
* assertOk(scoresInput, { ada: "10", grace: "20" });
|
|
3786
4271
|
*
|
|
3787
4272
|
* // Run the remaining key and value stages.
|
|
3788
4273
|
* const scoresFromInput = ScoresByUser.from.parent(scoresInput.value);
|
|
3789
4274
|
*
|
|
3790
|
-
*
|
|
3791
|
-
*
|
|
3792
|
-
* Readonly<Partial<Record<string, Int64
|
|
4275
|
+
* assertOk(scoresFromInput, { ada: 10n, grace: 20n });
|
|
4276
|
+
* assertType<
|
|
4277
|
+
* Readonly<Partial<Record<string, Int64>>>,
|
|
4278
|
+
* typeof scoresFromInput.value
|
|
3793
4279
|
* >();
|
|
3794
4280
|
* ```
|
|
3795
4281
|
*
|
|
@@ -3798,34 +4284,64 @@ export { _Object as Object };
|
|
|
3798
4284
|
* as a Record entry:
|
|
3799
4285
|
*
|
|
3800
4286
|
* ```ts
|
|
4287
|
+
* import {
|
|
4288
|
+
* assertEqual,
|
|
4289
|
+
* assertErr,
|
|
4290
|
+
* assertTrue,
|
|
4291
|
+
* trySync,
|
|
4292
|
+
* } from "@evolu/common";
|
|
4293
|
+
*
|
|
3801
4294
|
* type Values = Partial<Record<"toString", number>>;
|
|
3802
4295
|
* const values: Values = {};
|
|
3803
4296
|
*
|
|
3804
4297
|
* // TypeScript treats the inherited function as `number | undefined`.
|
|
3805
4298
|
* const value: number | undefined = values.toString;
|
|
4299
|
+
* const valueType = typeof value;
|
|
3806
4300
|
*
|
|
3807
|
-
*
|
|
3808
|
-
*
|
|
3809
|
-
*
|
|
3810
|
-
*
|
|
4301
|
+
* assertEqual(valueType, "function");
|
|
4302
|
+
* const called = trySync(
|
|
4303
|
+
* () => {
|
|
4304
|
+
* if (value !== undefined) value.toFixed(0);
|
|
4305
|
+
* },
|
|
4306
|
+
* (error) => error,
|
|
4307
|
+
* );
|
|
4308
|
+
* assertErr(called);
|
|
4309
|
+
* assertTrue(called.error instanceof TypeError);
|
|
3811
4310
|
* ```
|
|
3812
4311
|
*
|
|
3813
4312
|
* Evolu Record Outputs use the same TypeScript Record representation.
|
|
3814
4313
|
*
|
|
3815
4314
|
* ```ts
|
|
3816
|
-
* import {
|
|
4315
|
+
* import {
|
|
4316
|
+
* assertEqual,
|
|
4317
|
+
* assertErr,
|
|
4318
|
+
* assertOk,
|
|
4319
|
+
* assertTrue,
|
|
4320
|
+
* trySync,
|
|
4321
|
+
* Number,
|
|
4322
|
+
* literal,
|
|
4323
|
+
* record,
|
|
4324
|
+
* type Data,
|
|
4325
|
+
* } from "@evolu/common";
|
|
3817
4326
|
*
|
|
3818
4327
|
* const Values = record(literal("toString"), Number);
|
|
3819
4328
|
* const result = Values.fromUnknown({});
|
|
4329
|
+
* const emptyValues: Data = {};
|
|
3820
4330
|
*
|
|
3821
|
-
*
|
|
4331
|
+
* assertOk(result, emptyValues);
|
|
3822
4332
|
*
|
|
3823
4333
|
* const value: number | undefined = result.value.toString;
|
|
4334
|
+
* const valueType = typeof value;
|
|
3824
4335
|
*
|
|
3825
|
-
*
|
|
3826
|
-
*
|
|
3827
|
-
*
|
|
3828
|
-
*
|
|
4336
|
+
* assertEqual(valueType, "function");
|
|
4337
|
+
* const called = trySync(
|
|
4338
|
+
* () => {
|
|
4339
|
+
* if (value !== undefined) value.toFixed(0);
|
|
4340
|
+
* },
|
|
4341
|
+
* (error) => error,
|
|
4342
|
+
* );
|
|
4343
|
+
* assertErr(called);
|
|
4344
|
+
* assertTrue(called.error instanceof TypeError);
|
|
3829
4345
|
* ```
|
|
3830
4346
|
*
|
|
3831
4347
|
* In other words, treat Record Outputs as string-keyed data rather than calling
|
|
@@ -3992,7 +4508,13 @@ export interface OptionalProperty<T extends TypeNode> {
|
|
|
3992
4508
|
* ### Example
|
|
3993
4509
|
*
|
|
3994
4510
|
* ```ts
|
|
3995
|
-
* import {
|
|
4511
|
+
* import {
|
|
4512
|
+
* assertOk,
|
|
4513
|
+
* String,
|
|
4514
|
+
* object,
|
|
4515
|
+
* optional,
|
|
4516
|
+
* undefinedOr,
|
|
4517
|
+
* } from "@evolu/common";
|
|
3996
4518
|
*
|
|
3997
4519
|
* const User = object({
|
|
3998
4520
|
* name: String,
|
|
@@ -4000,8 +4522,8 @@ export interface OptionalProperty<T extends TypeNode> {
|
|
|
4000
4522
|
* preferredName: optional(undefinedOr(String)),
|
|
4001
4523
|
* });
|
|
4002
4524
|
*
|
|
4003
|
-
*
|
|
4004
|
-
*
|
|
4525
|
+
* assertOk(User.fromUnknown({ name: "Ada" }), { name: "Ada" });
|
|
4526
|
+
* assertOk(User.fromUnknown({ name: "Ada", preferredName: undefined }), {
|
|
4005
4527
|
* name: "Ada",
|
|
4006
4528
|
* preferredName: undefined,
|
|
4007
4529
|
* });
|
|
@@ -4035,10 +4557,11 @@ type ObjectProperty = ObjectProps[string];
|
|
|
4035
4557
|
* required properties nor make optional properties present. This keeps Outputs
|
|
4036
4558
|
* valid after ordinary object spread restores `Object.prototype`.
|
|
4037
4559
|
*
|
|
4038
|
-
*
|
|
4039
|
-
*
|
|
4040
|
-
*
|
|
4041
|
-
*
|
|
4560
|
+
* The prototype must satisfy the realm-neutral structural heuristic described
|
|
4561
|
+
* by {@link isPlainObject}. A matching custom root prototype can be classified
|
|
4562
|
+
* as plain; other custom prototypes, class instances, accessors, and
|
|
4563
|
+
* non-enumerable properties are rejected. Use {@link instanceOf} for class
|
|
4564
|
+
* Outputs or {@link transform} to decode instances into plain data.
|
|
4042
4565
|
*
|
|
4043
4566
|
* When decoding changes no property, it preserves the input. When decoding or
|
|
4044
4567
|
* encoding changes a property, it constructs an object with a `null`
|
|
@@ -4051,6 +4574,8 @@ type ObjectProperty = ObjectProps[string];
|
|
|
4051
4574
|
*
|
|
4052
4575
|
* ```ts
|
|
4053
4576
|
* import {
|
|
4577
|
+
* assertOk,
|
|
4578
|
+
* assertType,
|
|
4054
4579
|
* Int64FromInt64String,
|
|
4055
4580
|
* String,
|
|
4056
4581
|
* object,
|
|
@@ -4069,20 +4594,20 @@ type ObjectProperty = ObjectProps[string];
|
|
|
4069
4594
|
* loginCount: "42",
|
|
4070
4595
|
* });
|
|
4071
4596
|
*
|
|
4072
|
-
*
|
|
4597
|
+
* assertOk(userFromUnknown, { name: "Ada", loginCount: 42n });
|
|
4073
4598
|
*
|
|
4074
4599
|
* // Validate the object and root property Types.
|
|
4075
4600
|
* const userInput = User.parent.fromUnknown({
|
|
4076
4601
|
* name: "Ada",
|
|
4077
4602
|
* loginCount: "42",
|
|
4078
4603
|
* });
|
|
4079
|
-
*
|
|
4604
|
+
* assertOk(userInput, { name: "Ada", loginCount: "42" });
|
|
4080
4605
|
*
|
|
4081
4606
|
* // Run the remaining property stages.
|
|
4082
4607
|
* const userFromInput = User.from.parent(userInput.value);
|
|
4083
4608
|
*
|
|
4084
|
-
*
|
|
4085
|
-
*
|
|
4609
|
+
* assertOk(userFromInput, { name: "Ada", loginCount: 42n });
|
|
4610
|
+
* assertType<typeof User.Output, typeof userFromInput.value>();
|
|
4086
4611
|
* ```
|
|
4087
4612
|
*
|
|
4088
4613
|
* Note that TypeScript does not model an object's runtime prototype. This can
|
|
@@ -4090,38 +4615,68 @@ type ObjectProperty = ObjectProps[string];
|
|
|
4090
4615
|
* as an object property:
|
|
4091
4616
|
*
|
|
4092
4617
|
* ```ts
|
|
4618
|
+
* import {
|
|
4619
|
+
* assertEqual,
|
|
4620
|
+
* assertErr,
|
|
4621
|
+
* assertTrue,
|
|
4622
|
+
* trySync,
|
|
4623
|
+
* } from "@evolu/common";
|
|
4624
|
+
*
|
|
4093
4625
|
* interface Values {
|
|
4094
4626
|
* readonly toString?: number;
|
|
4095
4627
|
* }
|
|
4096
4628
|
*
|
|
4097
|
-
* const nullPrototypeValues =
|
|
4629
|
+
* const nullPrototypeValues = Object.create(null) as Values;
|
|
4098
4630
|
* const values = { ...nullPrototypeValues };
|
|
4099
4631
|
*
|
|
4100
4632
|
* // TypeScript treats the inherited function as `number | undefined`.
|
|
4101
4633
|
* const value: number | undefined = values.toString;
|
|
4634
|
+
* const valueType = typeof value;
|
|
4102
4635
|
*
|
|
4103
|
-
*
|
|
4104
|
-
*
|
|
4105
|
-
*
|
|
4106
|
-
*
|
|
4636
|
+
* assertEqual(valueType, "function");
|
|
4637
|
+
* const called = trySync(
|
|
4638
|
+
* () => {
|
|
4639
|
+
* if (value !== undefined) value.toFixed(0);
|
|
4640
|
+
* },
|
|
4641
|
+
* (error) => error,
|
|
4642
|
+
* );
|
|
4643
|
+
* assertErr(called);
|
|
4644
|
+
* assertTrue(called.error instanceof TypeError);
|
|
4107
4645
|
* ```
|
|
4108
4646
|
*
|
|
4109
4647
|
* Evolu Object Outputs use the same TypeScript object representation.
|
|
4110
4648
|
*
|
|
4111
4649
|
* ```ts
|
|
4112
|
-
* import {
|
|
4650
|
+
* import {
|
|
4651
|
+
* assertEqual,
|
|
4652
|
+
* assertErr,
|
|
4653
|
+
* assertOk,
|
|
4654
|
+
* assertTrue,
|
|
4655
|
+
* trySync,
|
|
4656
|
+
* Number,
|
|
4657
|
+
* object,
|
|
4658
|
+
* optional,
|
|
4659
|
+
* type Data,
|
|
4660
|
+
* } from "@evolu/common";
|
|
4113
4661
|
*
|
|
4114
4662
|
* const Values = object({ toString: optional(Number) });
|
|
4115
4663
|
* const result = Values.fromUnknown({});
|
|
4664
|
+
* const emptyValues: Data = {};
|
|
4116
4665
|
*
|
|
4117
|
-
*
|
|
4666
|
+
* assertOk(result, emptyValues);
|
|
4118
4667
|
*
|
|
4119
4668
|
* const value: number | undefined = result.value.toString;
|
|
4669
|
+
* const valueType = typeof value;
|
|
4120
4670
|
*
|
|
4121
|
-
*
|
|
4122
|
-
*
|
|
4123
|
-
*
|
|
4124
|
-
*
|
|
4671
|
+
* assertEqual(valueType, "function");
|
|
4672
|
+
* const called = trySync(
|
|
4673
|
+
* () => {
|
|
4674
|
+
* if (value !== undefined) value.toFixed(0);
|
|
4675
|
+
* },
|
|
4676
|
+
* (error) => error,
|
|
4677
|
+
* );
|
|
4678
|
+
* assertErr(called);
|
|
4679
|
+
* assertTrue(called.error instanceof TypeError);
|
|
4125
4680
|
* ```
|
|
4126
4681
|
*
|
|
4127
4682
|
* In other words, treat Object Outputs as data rather than calling inherited
|
|
@@ -4130,7 +4685,36 @@ type ObjectProperty = ObjectProps[string];
|
|
|
4130
4685
|
* @group Objects
|
|
4131
4686
|
*/
|
|
4132
4687
|
export declare function object<const Props extends ObjectProps>(props: Props, ...validation: [ObjectValidationError<Props>] extends [never] ? [] : [ValidationFailure<ObjectValidationError<Props>>]): StrictObjectType<Props>;
|
|
4133
|
-
/**
|
|
4688
|
+
/**
|
|
4689
|
+
* Creates an Object Type with additional record properties.
|
|
4690
|
+
*
|
|
4691
|
+
* ### Example
|
|
4692
|
+
*
|
|
4693
|
+
* ```ts
|
|
4694
|
+
* import {
|
|
4695
|
+
* assertOk,
|
|
4696
|
+
* assertType,
|
|
4697
|
+
* String,
|
|
4698
|
+
* object,
|
|
4699
|
+
* record,
|
|
4700
|
+
* } from "@evolu/common";
|
|
4701
|
+
*
|
|
4702
|
+
* const RequestHeaders = object(
|
|
4703
|
+
* { authorization: String },
|
|
4704
|
+
* record(String, String),
|
|
4705
|
+
* );
|
|
4706
|
+
* const result = RequestHeaders.fromUnknown({
|
|
4707
|
+
* authorization: "Bearer token",
|
|
4708
|
+
* "x-request-id": "request-1",
|
|
4709
|
+
* });
|
|
4710
|
+
*
|
|
4711
|
+
* assertOk(result, {
|
|
4712
|
+
* authorization: "Bearer token",
|
|
4713
|
+
* "x-request-id": "request-1",
|
|
4714
|
+
* });
|
|
4715
|
+
* assertType<string | undefined, (typeof result.value)["x-request-id"]>();
|
|
4716
|
+
* ```
|
|
4717
|
+
*/
|
|
4134
4718
|
export declare function object<const Props extends ObjectProps, const Rest extends RecordTypeNode & ConcreteTypeNode>(props: Props, record: Rest, ...validation: [
|
|
4135
4719
|
ObjectValidationError<Props> | ObjectRecordValidationError<Props, Rest>
|
|
4136
4720
|
] extends [never] ? [] : [
|
|
@@ -4272,12 +4856,10 @@ export interface ObjectNotObjectError extends TypeError<"Object"> {
|
|
|
4272
4856
|
* An error returned when an {@link object} input falls outside its supported
|
|
4273
4857
|
* plain-object prototype boundary.
|
|
4274
4858
|
*
|
|
4275
|
-
* Object Types
|
|
4276
|
-
*
|
|
4277
|
-
*
|
|
4278
|
-
*
|
|
4279
|
-
* return this error instead of having their prototype or inherited state
|
|
4280
|
-
* discarded. `reason.value` is the rejected object.
|
|
4859
|
+
* Object Types use the realm-neutral structural heuristic described by
|
|
4860
|
+
* {@link isPlainObject}. Values that do not satisfy it return this error instead
|
|
4861
|
+
* of having their prototype or inherited state discarded. `reason.value` is the
|
|
4862
|
+
* rejected object.
|
|
4281
4863
|
*
|
|
4282
4864
|
* @group Objects
|
|
4283
4865
|
*/
|
|
@@ -4354,13 +4936,20 @@ type ObjectRestFromParentError<Rest extends ObjectRecordTypeNode | undefined> =
|
|
|
4354
4936
|
* ### Example
|
|
4355
4937
|
*
|
|
4356
4938
|
* ```ts
|
|
4357
|
-
* import {
|
|
4939
|
+
* import {
|
|
4940
|
+
* assertFalse,
|
|
4941
|
+
* assertOk,
|
|
4942
|
+
* PositiveInt,
|
|
4943
|
+
* String,
|
|
4944
|
+
* partial,
|
|
4945
|
+
* } from "@evolu/common";
|
|
4358
4946
|
*
|
|
4359
4947
|
* const PartialUser = partial({ name: String, age: PositiveInt });
|
|
4948
|
+
* const emptyPartialUser: typeof PartialUser.Output = {};
|
|
4360
4949
|
*
|
|
4361
|
-
*
|
|
4362
|
-
*
|
|
4363
|
-
*
|
|
4950
|
+
* assertOk(PartialUser.fromUnknown({}), emptyPartialUser);
|
|
4951
|
+
* assertOk(PartialUser.fromUnknown({ name: "Ada" }), { name: "Ada" });
|
|
4952
|
+
* assertFalse(PartialUser.fromUnknown({ age: -1 }).ok);
|
|
4364
4953
|
* ```
|
|
4365
4954
|
*
|
|
4366
4955
|
* @group Objects
|
|
@@ -4385,15 +4974,20 @@ export type PartialObjectProps<Props extends ObjectProps> = {
|
|
|
4385
4974
|
* ### Example
|
|
4386
4975
|
*
|
|
4387
4976
|
* ```ts
|
|
4388
|
-
* import {
|
|
4977
|
+
* import {
|
|
4978
|
+
* assertOk,
|
|
4979
|
+
* String,
|
|
4980
|
+
* nullOr,
|
|
4981
|
+
* nullableToOptional,
|
|
4982
|
+
* } from "@evolu/common";
|
|
4389
4983
|
*
|
|
4390
4984
|
* const User = nullableToOptional({
|
|
4391
4985
|
* name: String,
|
|
4392
4986
|
* nickname: nullOr(String),
|
|
4393
4987
|
* });
|
|
4394
4988
|
*
|
|
4395
|
-
*
|
|
4396
|
-
*
|
|
4989
|
+
* assertOk(User.fromUnknown({ name: "Ada" }), { name: "Ada" });
|
|
4990
|
+
* assertOk(User.fromUnknown({ name: "Ada", nickname: null }), {
|
|
4397
4991
|
* name: "Ada",
|
|
4398
4992
|
* nickname: null,
|
|
4399
4993
|
* });
|
|
@@ -4417,12 +5011,12 @@ export type NullableToOptionalProps<Props extends ObjectProps> = {
|
|
|
4417
5011
|
* ### Example
|
|
4418
5012
|
*
|
|
4419
5013
|
* ```ts
|
|
4420
|
-
* import { String, object, omit } from "@evolu/common";
|
|
5014
|
+
* import { assertOk, String, object, omit } from "@evolu/common";
|
|
4421
5015
|
*
|
|
4422
5016
|
* const User = object({ name: String, password: String });
|
|
4423
5017
|
* const PublicUser = omit(User, "password");
|
|
4424
5018
|
*
|
|
4425
|
-
*
|
|
5019
|
+
* assertOk(PublicUser.fromUnknown({ name: "Ada" }), { name: "Ada" });
|
|
4426
5020
|
* ```
|
|
4427
5021
|
*
|
|
4428
5022
|
* @group Objects
|
|
@@ -4445,6 +5039,7 @@ type OmitKeyConcreteTypeError = CompileTimeError<"Type", "Each omitted key must
|
|
|
4445
5039
|
*
|
|
4446
5040
|
* ```ts
|
|
4447
5041
|
* import {
|
|
5042
|
+
* assertOk,
|
|
4448
5043
|
* NonNegativeInt,
|
|
4449
5044
|
* String,
|
|
4450
5045
|
* object,
|
|
@@ -4462,8 +5057,8 @@ type OmitKeyConcreteTypeError = CompileTimeError<"Type", "Each omitted key must
|
|
|
4462
5057
|
* value: { timestamp: 42 },
|
|
4463
5058
|
* });
|
|
4464
5059
|
*
|
|
4465
|
-
*
|
|
4466
|
-
*
|
|
5060
|
+
* assertOk(validated, { ok: true, value: { timestamp: 42 } });
|
|
5061
|
+
* assertOk(validated.value, { timestamp: 42 });
|
|
4467
5062
|
* ```
|
|
4468
5063
|
*
|
|
4469
5064
|
* @group Results
|
|
@@ -4507,24 +5102,84 @@ export type UnknownResult = typeof UnknownResult.Output;
|
|
|
4507
5102
|
* ### Example
|
|
4508
5103
|
*
|
|
4509
5104
|
* ```ts
|
|
4510
|
-
* import {
|
|
5105
|
+
* import {
|
|
5106
|
+
* assertFalse,
|
|
5107
|
+
* assertOk,
|
|
5108
|
+
* assertType,
|
|
5109
|
+
* String,
|
|
5110
|
+
* discriminatedUnion,
|
|
5111
|
+
* typed,
|
|
5112
|
+
* } from "@evolu/common";
|
|
5113
|
+
*
|
|
5114
|
+
* const Loading = typed("Loading");
|
|
5115
|
+
* const Loaded = typed("Loaded", { value: String });
|
|
5116
|
+
* const State = discriminatedUnion(Loading, Loaded);
|
|
5117
|
+
*
|
|
5118
|
+
* assertOk(State.fromUnknown({ type: "Loading" }), { type: "Loading" });
|
|
5119
|
+
* assertOk(State.fromUnknown({ type: "Loaded", value: "Evolu" }), {
|
|
5120
|
+
* type: "Loaded",
|
|
5121
|
+
* value: "Evolu",
|
|
5122
|
+
* });
|
|
5123
|
+
* assertFalse(Loading.is({ type: "Loading", progress: 1 }));
|
|
5124
|
+
* assertType<
|
|
5125
|
+
* true,
|
|
5126
|
+
* typeof Loading.Output extends { readonly type: "Loading" }
|
|
5127
|
+
* ? true
|
|
5128
|
+
* : false
|
|
5129
|
+
* >();
|
|
5130
|
+
* ```
|
|
5131
|
+
*
|
|
5132
|
+
* @group Discriminated unions
|
|
5133
|
+
*/
|
|
5134
|
+
export declare function typed<const Tag extends TypeName>(tag: ValidateTypedTag<Tag>): TypedType<Tag>;
|
|
5135
|
+
/**
|
|
5136
|
+
* Creates a Tagged Object Type with declared properties.
|
|
5137
|
+
*
|
|
5138
|
+
* ### Example
|
|
5139
|
+
*
|
|
5140
|
+
* ```ts
|
|
5141
|
+
* import { assertOk, String, typed } from "@evolu/common";
|
|
4511
5142
|
*
|
|
4512
5143
|
* const Pending = typed("Pending", {
|
|
4513
5144
|
* label: String,
|
|
4514
5145
|
* });
|
|
4515
5146
|
*
|
|
4516
|
-
*
|
|
5147
|
+
* assertOk(Pending.fromUnknown({ type: "Pending", label: "Waiting" }), {
|
|
4517
5148
|
* type: "Pending",
|
|
4518
5149
|
* label: "Waiting",
|
|
4519
5150
|
* });
|
|
4520
5151
|
* ```
|
|
4521
|
-
*
|
|
4522
|
-
* @group Discriminated unions
|
|
4523
5152
|
*/
|
|
4524
|
-
export declare function typed<const Tag extends TypeName>(tag: ValidateTypedTag<Tag>): TypedType<Tag>;
|
|
4525
|
-
/** Creates a Tagged Object Type with declared properties. */
|
|
4526
5153
|
export declare function typed<const Tag extends TypeName, const Props extends ObjectProps>(tag: ValidateTypedTag<Tag>, props: Props, ...validation: [TypedValidationError<Props>] extends [never] ? [] : [ValidationFailure<TypedValidationError<Props>>]): TypedType<Tag, Props>;
|
|
4527
|
-
/**
|
|
5154
|
+
/**
|
|
5155
|
+
* Creates a Tagged Object Type with additional record properties.
|
|
5156
|
+
*
|
|
5157
|
+
* ### Example
|
|
5158
|
+
*
|
|
5159
|
+
* ```ts
|
|
5160
|
+
* import {
|
|
5161
|
+
* assertOk,
|
|
5162
|
+
* assertType,
|
|
5163
|
+
* String,
|
|
5164
|
+
* record,
|
|
5165
|
+
* typed,
|
|
5166
|
+
* } from "@evolu/common";
|
|
5167
|
+
*
|
|
5168
|
+
* const Open = typed("Open", { label: String }, record(String, String));
|
|
5169
|
+
* const result = Open.fromUnknown({
|
|
5170
|
+
* type: "Open",
|
|
5171
|
+
* label: "Ready",
|
|
5172
|
+
* note: "Connected",
|
|
5173
|
+
* });
|
|
5174
|
+
*
|
|
5175
|
+
* assertOk(result, {
|
|
5176
|
+
* type: "Open",
|
|
5177
|
+
* label: "Ready",
|
|
5178
|
+
* note: "Connected",
|
|
5179
|
+
* });
|
|
5180
|
+
* assertType<string | undefined, typeof result.value.note>();
|
|
5181
|
+
* ```
|
|
5182
|
+
*/
|
|
4528
5183
|
export declare function typed<const Tag extends TypeName, const Props extends ObjectProps, const Rest extends RecordTypeNode & ConcreteTypeNode>(tag: ValidateTypedTag<Tag>, props: Props, record: Rest, ...validation: [
|
|
4529
5184
|
TypedValidationError<Props> | ObjectRecordValidationError<TypedProps<Tag, Props>, Rest>
|
|
4530
5185
|
] extends [never] ? [] : [
|
|
@@ -4549,7 +5204,14 @@ export declare function typed<const Tag extends TypeName, const Props extends Ob
|
|
|
4549
5204
|
* ### Example
|
|
4550
5205
|
*
|
|
4551
5206
|
* ```ts
|
|
4552
|
-
* import {
|
|
5207
|
+
* import {
|
|
5208
|
+
* assertErr,
|
|
5209
|
+
* assertOk,
|
|
5210
|
+
* err,
|
|
5211
|
+
* ok,
|
|
5212
|
+
* type Result,
|
|
5213
|
+
* type Typed,
|
|
5214
|
+
* } from "@evolu/common";
|
|
4553
5215
|
*
|
|
4554
5216
|
* interface User extends Typed<"User"> {
|
|
4555
5217
|
* readonly id: string;
|
|
@@ -4564,8 +5226,8 @@ export declare function typed<const Tag extends TypeName, const Props extends Ob
|
|
|
4564
5226
|
* readonly id: string;
|
|
4565
5227
|
* }
|
|
4566
5228
|
*
|
|
4567
|
-
*
|
|
4568
|
-
*
|
|
5229
|
+
* assertOk(getUser("user-1"), { type: "User", id: "user-1" });
|
|
5230
|
+
* assertErr(getUser("missing"), { type: "UserNotFound", id: "missing" });
|
|
4569
5231
|
* ```
|
|
4570
5232
|
*
|
|
4571
5233
|
* @group Discriminated unions
|
|
@@ -4584,6 +5246,7 @@ export interface Typed<Tag extends TypeName> {
|
|
|
4584
5246
|
*
|
|
4585
5247
|
* ```ts
|
|
4586
5248
|
* import {
|
|
5249
|
+
* assertType,
|
|
4587
5250
|
* String,
|
|
4588
5251
|
* discriminatedUnion,
|
|
4589
5252
|
* typed,
|
|
@@ -4597,10 +5260,10 @@ export interface Typed<Tag extends TypeName> {
|
|
|
4597
5260
|
*
|
|
4598
5261
|
* type CreateMessage = ExtractTyped<Message, "Create">;
|
|
4599
5262
|
*
|
|
4600
|
-
*
|
|
5263
|
+
* assertType<typeof Create.Output, CreateMessage>();
|
|
4601
5264
|
*
|
|
4602
5265
|
* // @ts-expect-error "Cretae" is not a Message type.
|
|
4603
|
-
* type
|
|
5266
|
+
* type _Typo = ExtractTyped<Message, "Cretae">;
|
|
4604
5267
|
* ```
|
|
4605
5268
|
*
|
|
4606
5269
|
* @group Discriminated unions
|
|
@@ -4632,7 +5295,7 @@ type TypedTypePropertyError = CompileTimeError<"Type", 'Additional properties mu
|
|
|
4632
5295
|
* ### Example
|
|
4633
5296
|
*
|
|
4634
5297
|
* ```ts
|
|
4635
|
-
* import { String, nextResult, typed } from "@evolu/common";
|
|
5298
|
+
* import { assertEqual, String, nextResult, typed } from "@evolu/common";
|
|
4636
5299
|
*
|
|
4637
5300
|
* const StringNextResult = nextResult(
|
|
4638
5301
|
* String,
|
|
@@ -4650,19 +5313,21 @@ type TypedTypePropertyError = CompileTimeError<"Type", 'Additional properties mu
|
|
|
4650
5313
|
* return `Error: ${result.error.message}`;
|
|
4651
5314
|
* };
|
|
4652
5315
|
*
|
|
4653
|
-
*
|
|
4654
|
-
*
|
|
5316
|
+
* assertEqual(describeNext({ ok: true, value: "item" }), "Value: item");
|
|
5317
|
+
* assertEqual(
|
|
4655
5318
|
* describeNext({
|
|
4656
5319
|
* ok: false,
|
|
4657
5320
|
* error: { type: "Done", done: "complete" },
|
|
4658
5321
|
* }),
|
|
4659
|
-
*
|
|
4660
|
-
*
|
|
5322
|
+
* "Done: complete",
|
|
5323
|
+
* );
|
|
5324
|
+
* assertEqual(
|
|
4661
5325
|
* describeNext({
|
|
4662
5326
|
* ok: false,
|
|
4663
5327
|
* error: { type: "ReadFailed", message: "Offline" },
|
|
4664
5328
|
* }),
|
|
4665
|
-
*
|
|
5329
|
+
* "Error: Offline",
|
|
5330
|
+
* );
|
|
4666
5331
|
* ```
|
|
4667
5332
|
*
|
|
4668
5333
|
* @group Results
|
|
@@ -4708,13 +5373,18 @@ export type UnknownNextResult = typeof UnknownNextResult.Output;
|
|
|
4708
5373
|
* ### Example
|
|
4709
5374
|
*
|
|
4710
5375
|
* ```ts
|
|
4711
|
-
* import {
|
|
5376
|
+
* import {
|
|
5377
|
+
* assertOk,
|
|
5378
|
+
* String,
|
|
5379
|
+
* discriminatedUnion,
|
|
5380
|
+
* typed,
|
|
5381
|
+
* } from "@evolu/common";
|
|
4712
5382
|
*
|
|
4713
5383
|
* const Created = typed("Created", { id: String });
|
|
4714
5384
|
* const Deleted = typed("Deleted", { id: String });
|
|
4715
5385
|
* const Event = discriminatedUnion(Created, Deleted);
|
|
4716
5386
|
*
|
|
4717
|
-
*
|
|
5387
|
+
* assertOk(Event.fromUnknown({ type: "Created", id: "id" }), {
|
|
4718
5388
|
* type: "Created",
|
|
4719
5389
|
* id: "id",
|
|
4720
5390
|
* });
|
|
@@ -4730,6 +5400,7 @@ export declare function discriminatedUnion<const Members extends DiscriminatedUn
|
|
|
4730
5400
|
*
|
|
4731
5401
|
* ```ts
|
|
4732
5402
|
* import {
|
|
5403
|
+
* assertOk,
|
|
4733
5404
|
* Number,
|
|
4734
5405
|
* String,
|
|
4735
5406
|
* discriminatedUnion,
|
|
@@ -4741,11 +5412,11 @@ export declare function discriminatedUnion<const Members extends DiscriminatedUn
|
|
|
4741
5412
|
* const Removed = object({ kind: literal("removed"), id: Number });
|
|
4742
5413
|
* const Event = discriminatedUnion("kind", Added, Removed);
|
|
4743
5414
|
*
|
|
4744
|
-
*
|
|
5415
|
+
* assertOk(Event.fromUnknown({ kind: "added", value: "Evolu" }), {
|
|
4745
5416
|
* kind: "added",
|
|
4746
5417
|
* value: "Evolu",
|
|
4747
5418
|
* });
|
|
4748
|
-
*
|
|
5419
|
+
* assertOk(Event.fromUnknown({ kind: "removed", id: 1 }), {
|
|
4749
5420
|
* kind: "removed",
|
|
4750
5421
|
* id: 1,
|
|
4751
5422
|
* });
|
|
@@ -4887,15 +5558,18 @@ type DiscriminatedUnionDuplicateValueError<Key extends string, Expected extends
|
|
|
4887
5558
|
*
|
|
4888
5559
|
* The definition must return one concrete non-Lazy Type. Use {@link union} for
|
|
4889
5560
|
* alternatives. Every recursive Lazy reference must be nested behind an
|
|
4890
|
-
* {@link object}, {@link array}, {@link tuple}, {@link record},
|
|
4891
|
-
* structural boundary. Union does not guard recursion because it
|
|
4892
|
-
* same value to every member. Lazy defers schema construction; it
|
|
4893
|
-
* cyclic runtime object graphs or arbitrarily deep values
|
|
5561
|
+
* {@link object}, {@link array}, {@link tuple}, {@link record}, {@link set}, or
|
|
5562
|
+
* {@link map} structural boundary. Union does not guard recursion because it
|
|
5563
|
+
* passes the same value to every member. Lazy defers schema construction; it
|
|
5564
|
+
* does not make cyclic runtime object graphs or arbitrarily deep values
|
|
5565
|
+
* stack-safe.
|
|
4894
5566
|
*
|
|
4895
5567
|
* ### Example
|
|
4896
5568
|
*
|
|
4897
5569
|
* ```ts
|
|
4898
5570
|
* import {
|
|
5571
|
+
* assertOk,
|
|
5572
|
+
* assertType,
|
|
4899
5573
|
* String,
|
|
4900
5574
|
* array,
|
|
4901
5575
|
* lazy,
|
|
@@ -4925,11 +5599,11 @@ type DiscriminatedUnionDuplicateValueError<Key extends string, Expected extends
|
|
|
4925
5599
|
* children: [{ value: "leaf", children: [] }],
|
|
4926
5600
|
* });
|
|
4927
5601
|
*
|
|
4928
|
-
*
|
|
5602
|
+
* assertOk(result, {
|
|
4929
5603
|
* value: "root",
|
|
4930
5604
|
* children: [{ value: "leaf", children: [] }],
|
|
4931
5605
|
* });
|
|
4932
|
-
*
|
|
5606
|
+
* assertType<Tree, typeof result.value>();
|
|
4933
5607
|
* ```
|
|
4934
5608
|
*
|
|
4935
5609
|
* @group Recursive
|
|
@@ -4959,6 +5633,166 @@ export interface LazyType<in out Input, in out Output, in out FromError extends
|
|
|
4959
5633
|
}
|
|
4960
5634
|
type ValidateLazyTarget<Target extends ConcreteTypeNode> = IsUnion<Target> extends false ? Target : LazyTargetConcreteTypeError;
|
|
4961
5635
|
type LazyTargetConcreteTypeError = CompileTimeError<"Type", "Lazy Type definition must return one concrete Type node. Pass a Union Type node instead of a union of Type nodes.">;
|
|
5636
|
+
/**
|
|
5637
|
+
* Evolu's recursive platform-independent structured-cloneable data domain.
|
|
5638
|
+
*
|
|
5639
|
+
* Data is intentionally limited to values supported by the structured clone
|
|
5640
|
+
* algorithm, so it can be sent through APIs such as worker `postMessage`. It
|
|
5641
|
+
* includes supported JavaScript primitives and the runtime representations
|
|
5642
|
+
* defined by {@link array}, {@link Object}, {@link set}, {@link map}, {@link Date},
|
|
5643
|
+
* and {@link Uint8Array}. Array elements, Object properties, Set elements, and
|
|
5644
|
+
* Map keys and values must also be Data. Cyclic and shared data graphs are
|
|
5645
|
+
* supported. Raw {@link ArrayBuffer} values are excluded; represent bytes with a
|
|
5646
|
+
* Uint8Array.
|
|
5647
|
+
*
|
|
5648
|
+
* Functions, arbitrary class instances, and other behavioral objects are not
|
|
5649
|
+
* Data. The structural representations follow the corresponding Evolu Type
|
|
5650
|
+
* rules. As with every Type operation, classification assumes trusted
|
|
5651
|
+
* application code or audited dependencies; it is not a security boundary for
|
|
5652
|
+
* adversarial Proxies or forged built-in object tags.
|
|
5653
|
+
*
|
|
5654
|
+
* TypeScript cannot express dense Arrays, exact property descriptors, object
|
|
5655
|
+
* prototypes, or the absence of custom properties on built-ins. Use the runtime
|
|
5656
|
+
* {@link Data} Type when a value crosses an unknown boundary.
|
|
5657
|
+
*
|
|
5658
|
+
* ### Example
|
|
5659
|
+
*
|
|
5660
|
+
* ```ts
|
|
5661
|
+
* import { assertOk, assertSame, assertType, Data } from "@evolu/common";
|
|
5662
|
+
*
|
|
5663
|
+
* const value: unknown = {
|
|
5664
|
+
* user: { name: "Ada" },
|
|
5665
|
+
* scores: new Map([["logic", 100]]),
|
|
5666
|
+
* roles: new Set(["admin"]),
|
|
5667
|
+
* };
|
|
5668
|
+
* const result = Data.fromUnknown(value);
|
|
5669
|
+
*
|
|
5670
|
+
* assertOk(result);
|
|
5671
|
+
* assertSame(result.value, value);
|
|
5672
|
+
* assertType<Data, typeof result.value>();
|
|
5673
|
+
* ```
|
|
5674
|
+
*
|
|
5675
|
+
* @group Base
|
|
5676
|
+
*/
|
|
5677
|
+
export type Data = undefined | null | string | number | bigint | boolean | ReadonlyArray<Data> | {
|
|
5678
|
+
readonly [key: string]: Data;
|
|
5679
|
+
} | ReadonlySet<Data> | ReadonlyMap<Data, Data> | globalThis.Date | globalThis.Uint8Array;
|
|
5680
|
+
/**
|
|
5681
|
+
* Returns whether a TypeScript type consists only of {@link Data}.
|
|
5682
|
+
*
|
|
5683
|
+
* Unlike `Value extends Data`, this recursively checks the declared properties
|
|
5684
|
+
* of object types, so ordinary interfaces do not need a string index signature.
|
|
5685
|
+
* This is a compile-time approximation of the Data domain; representation
|
|
5686
|
+
* details such as prototypes and property descriptors still require the runtime
|
|
5687
|
+
* {@link Data} Type.
|
|
5688
|
+
*
|
|
5689
|
+
* Recursive object types are supported.
|
|
5690
|
+
*
|
|
5691
|
+
* ### Example
|
|
5692
|
+
*
|
|
5693
|
+
* ```ts
|
|
5694
|
+
* import { assertType, type IsData } from "@evolu/common";
|
|
5695
|
+
*
|
|
5696
|
+
* interface User {
|
|
5697
|
+
* readonly name: string;
|
|
5698
|
+
* readonly roles: ReadonlySet<string>;
|
|
5699
|
+
* }
|
|
5700
|
+
*
|
|
5701
|
+
* interface Service {
|
|
5702
|
+
* readonly run: () => void;
|
|
5703
|
+
* }
|
|
5704
|
+
*
|
|
5705
|
+
* assertType<true, IsData<User>>();
|
|
5706
|
+
* assertType<false, IsData<Service>>();
|
|
5707
|
+
* ```
|
|
5708
|
+
*
|
|
5709
|
+
* @group Base
|
|
5710
|
+
*/
|
|
5711
|
+
export type IsData<Value> = IsDataValue<Value, readonly []>;
|
|
5712
|
+
type IsDataValue<Value, Seen extends ReadonlyArray<unknown>> = IsAny<Value> extends true ? false : unknown extends Value ? false : [Value] extends [never] ? true : false extends (Value extends unknown ? IsDataMember<Value, Seen> : never) ? false : true;
|
|
5713
|
+
type IsAny<Value> = 0 extends 1 & Value ? true : false;
|
|
5714
|
+
type IsDataMember<Value, Seen extends ReadonlyArray<unknown>> = IsSameType<Value, object> extends true ? false : IncludesSameType<Seen, Value> extends true ? true : Value extends void | null | string | number | bigint | boolean ? true : Value extends globalThis.Function ? false : Value extends globalThis.Date | globalThis.Uint8Array ? true : Value extends ReadonlyArray<infer Element> ? IsDataValue<Element, readonly [...Seen, Value]> : Value extends ReadonlySet<infer Element> ? IsDataValue<Element, readonly [...Seen, Value]> : Value extends ReadonlyMap<infer Key, infer MapValue> ? IsDataValue<Key | MapValue, readonly [...Seen, Value]> : Value extends object ? Extract<keyof Value, symbol> extends never ? IsDataObject<Value, readonly [...Seen, Value]> : false : false;
|
|
5715
|
+
type IsDataObject<Value extends object, Seen extends ReadonlyArray<unknown>> = [
|
|
5716
|
+
keyof Value
|
|
5717
|
+
] extends [never] ? false : false extends {
|
|
5718
|
+
[Key in keyof Value]-?: IsDataValue<Value[Key], Seen>;
|
|
5719
|
+
}[keyof Value] ? false : true;
|
|
5720
|
+
type IncludesSameType<Values extends ReadonlyArray<unknown>, Value> = Values extends readonly [infer First, ...infer Rest] ? IsSameType<First, Value> extends true ? true : IncludesSameType<Rest, Value> : false;
|
|
5721
|
+
/**
|
|
5722
|
+
* One issue found while validating a candidate as {@link Data}.
|
|
5723
|
+
*
|
|
5724
|
+
* @group Base
|
|
5725
|
+
*/
|
|
5726
|
+
export type DataIssue = {
|
|
5727
|
+
readonly kind: "InvalidType";
|
|
5728
|
+
readonly path: ReadonlyArray<PropertyKey>;
|
|
5729
|
+
readonly value: unknown;
|
|
5730
|
+
} | {
|
|
5731
|
+
readonly kind: "UnexpectedPrototype";
|
|
5732
|
+
readonly path: ReadonlyArray<PropertyKey>;
|
|
5733
|
+
readonly container: "Object";
|
|
5734
|
+
readonly value: object;
|
|
5735
|
+
} | {
|
|
5736
|
+
readonly kind: "Accessor";
|
|
5737
|
+
readonly path: ReadonlyArray<PropertyKey>;
|
|
5738
|
+
} | {
|
|
5739
|
+
readonly kind: "NonEnumerable";
|
|
5740
|
+
readonly path: ReadonlyArray<PropertyKey>;
|
|
5741
|
+
} | {
|
|
5742
|
+
readonly kind: "SymbolProperty";
|
|
5743
|
+
readonly path: ReadonlyArray<PropertyKey>;
|
|
5744
|
+
} | {
|
|
5745
|
+
readonly kind: "Hole";
|
|
5746
|
+
readonly path: ReadonlyArray<PropertyKey>;
|
|
5747
|
+
} | {
|
|
5748
|
+
readonly kind: "InvalidUint8Array";
|
|
5749
|
+
readonly path: ReadonlyArray<PropertyKey>;
|
|
5750
|
+
readonly value: globalThis.Uint8Array;
|
|
5751
|
+
} | {
|
|
5752
|
+
readonly kind: "ExcessProperty";
|
|
5753
|
+
readonly path: ReadonlyArray<PropertyKey>;
|
|
5754
|
+
readonly container: "Array" | "Set" | "Map";
|
|
5755
|
+
};
|
|
5756
|
+
/**
|
|
5757
|
+
* An error containing one or more issues found while validating a candidate as
|
|
5758
|
+
* {@link Data}.
|
|
5759
|
+
*
|
|
5760
|
+
* @group Base
|
|
5761
|
+
*/
|
|
5762
|
+
export interface DataError extends TypeError<"Data"> {
|
|
5763
|
+
readonly reason: {
|
|
5764
|
+
readonly kind: "Issues";
|
|
5765
|
+
readonly issues: NonEmptyReadonlyArray<DataIssue>;
|
|
5766
|
+
};
|
|
5767
|
+
}
|
|
5768
|
+
/**
|
|
5769
|
+
* The root {@link Type} for Evolu {@link Data}.
|
|
5770
|
+
*
|
|
5771
|
+
* @group Base
|
|
5772
|
+
*/
|
|
5773
|
+
export interface DataType extends Type<"Data", Data, Data, DataError, null, DataError, never, Data> {
|
|
5774
|
+
}
|
|
5775
|
+
/**
|
|
5776
|
+
* Root Type for {@link Data} values.
|
|
5777
|
+
*
|
|
5778
|
+
* Validation is iterative and preserves the input identity. Cyclic and shared
|
|
5779
|
+
* data graphs are valid.
|
|
5780
|
+
*
|
|
5781
|
+
* ### Example
|
|
5782
|
+
*
|
|
5783
|
+
* ```ts
|
|
5784
|
+
* import { assertOk, assertTrue, Data } from "@evolu/common";
|
|
5785
|
+
*
|
|
5786
|
+
* const value = new Map([["count", 1]]);
|
|
5787
|
+
* const result = Data.fromUnknown(value);
|
|
5788
|
+
*
|
|
5789
|
+
* assertOk(result, value);
|
|
5790
|
+
* assertTrue(Data.is(result.value));
|
|
5791
|
+
* ```
|
|
5792
|
+
*
|
|
5793
|
+
* @group Base
|
|
5794
|
+
*/
|
|
5795
|
+
export declare const Data: DataType;
|
|
4962
5796
|
/**
|
|
4963
5797
|
* A candidate JSON value before exact runtime validation.
|
|
4964
5798
|
*
|
|
@@ -5086,7 +5920,12 @@ export interface JsonError extends TypeError<"Json"> {
|
|
|
5086
5920
|
* ### Example
|
|
5087
5921
|
*
|
|
5088
5922
|
* ```ts
|
|
5089
|
-
* import {
|
|
5923
|
+
* import {
|
|
5924
|
+
* assertOk,
|
|
5925
|
+
* assertType,
|
|
5926
|
+
* JsonValue,
|
|
5927
|
+
* type JsonValueInput,
|
|
5928
|
+
* } from "@evolu/common";
|
|
5090
5929
|
*
|
|
5091
5930
|
* const input: JsonValueInput = {
|
|
5092
5931
|
* name: "Ada",
|
|
@@ -5094,8 +5933,8 @@ export interface JsonError extends TypeError<"Json"> {
|
|
|
5094
5933
|
* };
|
|
5095
5934
|
* const result = JsonValue.fromUnknown(input);
|
|
5096
5935
|
*
|
|
5097
|
-
*
|
|
5098
|
-
*
|
|
5936
|
+
* assertOk(result, input);
|
|
5937
|
+
* assertType<JsonValue, typeof result.value>();
|
|
5099
5938
|
* ```
|
|
5100
5939
|
*
|
|
5101
5940
|
* @group JSON
|
|
@@ -5130,11 +5969,11 @@ export type Json = typeof Json.Output;
|
|
|
5130
5969
|
* ### Example
|
|
5131
5970
|
*
|
|
5132
5971
|
* ```ts
|
|
5133
|
-
* import { Json, jsonToJsonValue } from "@evolu/common";
|
|
5972
|
+
* import { assertEqual, Json, jsonToJsonValue } from "@evolu/common";
|
|
5134
5973
|
*
|
|
5135
5974
|
* const value = jsonToJsonValue(Json.orThrow('{"name":"Ada"}'));
|
|
5136
5975
|
*
|
|
5137
|
-
*
|
|
5976
|
+
* assertEqual(value, { name: "Ada" });
|
|
5138
5977
|
* ```
|
|
5139
5978
|
*
|
|
5140
5979
|
* @group JSON
|
|
@@ -5146,11 +5985,15 @@ export declare const jsonToJsonValue: (value: Json) => JsonValue;
|
|
|
5146
5985
|
* ### Example
|
|
5147
5986
|
*
|
|
5148
5987
|
* ```ts
|
|
5149
|
-
* import {
|
|
5988
|
+
* import {
|
|
5989
|
+
* assertEqual,
|
|
5990
|
+
* jsonValueToJson,
|
|
5991
|
+
* type JsonValue,
|
|
5992
|
+
* } from "@evolu/common";
|
|
5150
5993
|
*
|
|
5151
5994
|
* const value: JsonValue = { name: "Ada" };
|
|
5152
5995
|
*
|
|
5153
|
-
*
|
|
5996
|
+
* assertEqual(jsonValueToJson(value), '{"name":"Ada"}');
|
|
5154
5997
|
* ```
|
|
5155
5998
|
*
|
|
5156
5999
|
* @group JSON
|
|
@@ -5165,12 +6008,12 @@ export declare const jsonValueToJson: (value: JsonValue) => Json;
|
|
|
5165
6008
|
* ### Example
|
|
5166
6009
|
*
|
|
5167
6010
|
* ```ts
|
|
5168
|
-
* import { JsonValueFromJson } from "@evolu/common";
|
|
6011
|
+
* import { assertEqual, assertOk, JsonValueFromJson } from "@evolu/common";
|
|
5169
6012
|
*
|
|
5170
6013
|
* const result = JsonValueFromJson.fromUnknown('{ "name": "Ada" }');
|
|
5171
6014
|
*
|
|
5172
|
-
*
|
|
5173
|
-
*
|
|
6015
|
+
* assertOk(result, { name: "Ada" });
|
|
6016
|
+
* assertEqual(JsonValueFromJson.to(result.value), '{"name":"Ada"}');
|
|
5174
6017
|
* ```
|
|
5175
6018
|
*
|
|
5176
6019
|
* @group JSON
|
|
@@ -5188,6 +6031,8 @@ export declare const JsonValueFromJson: TransformType<BrandType<Type<"String", s
|
|
|
5188
6031
|
*
|
|
5189
6032
|
* ```ts
|
|
5190
6033
|
* import {
|
|
6034
|
+
* assertEqual,
|
|
6035
|
+
* assertType,
|
|
5191
6036
|
* Age,
|
|
5192
6037
|
* NonEmptyTrimmedString100,
|
|
5193
6038
|
* json,
|
|
@@ -5208,11 +6053,13 @@ export declare const JsonValueFromJson: TransformType<BrandType<Type<"String", s
|
|
|
5208
6053
|
* const user = User.orThrow({ name: "Ada", age: 37 });
|
|
5209
6054
|
* const userJson = userToUserJson(user);
|
|
5210
6055
|
*
|
|
5211
|
-
*
|
|
5212
|
-
* string & Brand<"Json"> & Brand<"UserJson"
|
|
6056
|
+
* assertType<
|
|
6057
|
+
* string & Brand<"Json"> & Brand<"UserJson">,
|
|
6058
|
+
* typeof userJson
|
|
5213
6059
|
* >();
|
|
5214
|
-
*
|
|
5215
|
-
*
|
|
6060
|
+
* assertEqual(userJson, '{"name":"Ada","age":37}');
|
|
6061
|
+
* assertEqual(UserJson.orThrow(userJson), userJson);
|
|
6062
|
+
* assertEqual(userJsonToUser(userJson), user);
|
|
5216
6063
|
* ```
|
|
5217
6064
|
*
|
|
5218
6065
|
* The supplied Type must have a JSON-compatible `CanonicalInput`. The branded
|
|
@@ -5229,10 +6076,9 @@ type IsJsonTypeCompatible<T extends TypeNode> = IsJsonCompatible<CanonicalInputO
|
|
|
5229
6076
|
type IsJsonCompatible<Value, Seen extends ReadonlyArray<unknown> = readonly []> = IsExactlyJsonValue<Value> extends true ? true : false extends JsonCompatibleMember<Value, Seen> ? false : true;
|
|
5230
6077
|
type IsExactlyJsonValue<Value> = IsSameType<Value, JsonValue>;
|
|
5231
6078
|
type JsonCompatibleMember<Value, Seen extends ReadonlyArray<unknown>> = Value extends unknown ? IsJsonCompatibilityCycle<Value, Seen> extends true ? true : Value extends string | boolean | null ? true : Value extends number ? JsonNumberCompatible<Value> : Value extends ReadonlyArray<infer Item> ? Exclude<keyof Value, AllowedJsonArrayKeys<Value>> extends never ? IsJsonCompatible<Item, readonly [...Seen, Value]> : false : Value extends globalThis.Function ? false : Value extends object ? JsonObjectCompatible<Value, readonly [...Seen, Value]> : false : never;
|
|
5232
|
-
type AllowedJsonArrayKeys<Value extends ReadonlyArray<unknown>> = keyof ReadonlyArray<unknown> | (Value extends
|
|
5233
|
-
type JsonTupleIndexKeys<Value extends ReadonlyArray<unknown>> = Value extends readonly [...infer Elements] ? Exclude<keyof Elements, keyof
|
|
6079
|
+
type AllowedJsonArrayKeys<Value extends ReadonlyArray<unknown>> = keyof ReadonlyArray<unknown> | (Value extends Array<unknown> ? keyof Array<unknown> : never) | JsonTupleIndexKeys<Value>;
|
|
6080
|
+
type JsonTupleIndexKeys<Value extends ReadonlyArray<unknown>> = Value extends readonly [...infer Elements] ? Exclude<keyof Elements, keyof Array<unknown>> : never;
|
|
5234
6081
|
type IsJsonCompatibilityCycle<Value, Seen extends ReadonlyArray<unknown>> = Seen extends readonly [infer Candidate, ...infer Rest] ? IsSameType<Value, Candidate> extends true ? true : IsJsonCompatibilityCycle<Value, Rest> : false;
|
|
5235
|
-
type IsSameType<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => (T extends B ? 1 : 2) ? (<T>() => T extends B ? 1 : 2) extends <T>() => (T extends A ? 1 : 2) ? true : false : false;
|
|
5236
6082
|
type JsonNumberCompatible<Value extends number> = [Value] extends [FiniteNumber] ? true : [Value] extends [Brand<string>] ? false : number extends Value ? false : true;
|
|
5237
6083
|
type JsonObjectCompatible<Value extends object, Seen extends ReadonlyArray<unknown>> = [keyof Value] extends [never] ? false : string extends keyof Value ? Exclude<keyof Value, string | number> extends never ? Value extends Readonly<Partial<Record<string, infer Item>>> ? IsJsonCompatible<Item, Seen> : false : false : false extends {
|
|
5238
6084
|
readonly [Key in keyof Value]-?: Key extends string ? IsJsonCompatible<{} extends Pick<Value, Key> ? Required<Pick<Value, Key>>[Key] : Value[Key], Seen> : false;
|