@evolu/common 8.0.0-next.4 → 8.0.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 +279 -173
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +105 -101
- package/dist/src/Assert.d.ts +44 -44
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +44 -32
- package/dist/src/BigInt.d.ts +6 -3
- package/dist/src/BigInt.d.ts.map +1 -1
- package/dist/src/BigInt.js +5 -2
- package/dist/src/Brand.d.ts +27 -40
- package/dist/src/Brand.d.ts.map +1 -1
- package/dist/src/Buffer.d.ts +27 -11
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Cache.d.ts +9 -4
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +8 -3
- package/dist/src/Callbacks.d.ts +30 -19
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Console.d.ts +145 -66
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +91 -43
- package/dist/src/Crypto.d.ts +85 -42
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +44 -20
- package/dist/src/Eq.d.ts +87 -21
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +67 -19
- package/dist/src/Error.d.ts +5 -3
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +16 -0
- package/dist/src/Function.d.ts +119 -58
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +86 -43
- package/dist/src/Http.d.ts +394 -0
- package/dist/src/Http.d.ts.map +1 -0
- package/dist/src/Http.js +102 -0
- package/dist/src/Identicon.d.ts +16 -7
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +14 -5
- package/dist/src/LeakDetector.d.ts +88 -0
- package/dist/src/LeakDetector.d.ts.map +1 -0
- package/dist/src/LeakDetector.js +86 -0
- package/dist/src/LockManager.d.ts +18 -9
- package/dist/src/LockManager.d.ts.map +1 -1
- package/dist/src/LockManager.js +7 -8
- package/dist/src/Lookup.d.ts +43 -13
- package/dist/src/Lookup.d.ts.map +1 -1
- package/dist/src/Lookup.js +28 -8
- package/dist/src/Microtask.d.ts +1 -1
- package/dist/src/Microtask.d.ts.map +1 -1
- package/dist/src/Microtask.js +3 -7
- package/dist/src/Number.d.ts +49 -13
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +34 -5
- package/dist/src/Object.d.ts +160 -40
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +92 -46
- package/dist/src/Option.d.ts +10 -7
- package/dist/src/Option.d.ts.map +1 -1
- package/dist/src/Option.js +9 -6
- package/dist/src/Order.d.ts +21 -21
- package/dist/src/Order.d.ts.map +1 -1
- package/dist/src/Order.js +18 -21
- package/dist/src/Platform.d.ts +31 -0
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +98 -0
- package/dist/src/Random.d.ts +32 -17
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +12 -8
- package/dist/src/Redacted.d.ts +43 -29
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +14 -3
- package/dist/src/Ref.d.ts +11 -3
- package/dist/src/Ref.d.ts.map +1 -1
- package/dist/src/Ref.js +2 -2
- package/dist/src/RefCount.d.ts +2 -6
- package/dist/src/RefCount.d.ts.map +1 -1
- package/dist/src/RefCount.js +33 -90
- package/dist/src/Relation.d.ts +70 -5
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Relation.js +77 -2
- package/dist/src/Resource.d.ts +590 -155
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +592 -343
- package/dist/src/Result.d.ts +838 -191
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +163 -102
- package/dist/src/Schedule.d.ts +684 -231
- package/dist/src/Schedule.d.ts.map +1 -1
- package/dist/src/Schedule.js +766 -295
- package/dist/src/Set.d.ts +89 -40
- package/dist/src/Set.d.ts.map +1 -1
- package/dist/src/Set.js +50 -29
- package/dist/src/Sqlite.d.ts +29 -72
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +41 -46
- package/dist/src/StackTrace.d.ts +40 -0
- package/dist/src/StackTrace.d.ts.map +1 -0
- package/dist/src/StackTrace.js +140 -0
- package/dist/src/Store.d.ts +5 -4
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +5 -4
- package/dist/src/String.d.ts +7 -1
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +20 -7
- package/dist/src/Task.d.ts +3572 -1770
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +1879 -1274
- package/dist/src/Test.d.ts +17 -125
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +17 -68
- package/dist/src/Time.d.ts +108 -49
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +172 -73
- package/dist/src/Type.d.ts +3542 -1926
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +3070 -1784
- package/dist/src/Types.d.ts +200 -108
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +39 -8
- package/dist/src/WebSocket.d.ts +48 -23
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +15 -6
- package/dist/src/Worker.d.ts +94 -36
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +58 -24
- package/dist/src/index.d.ts +55 -52
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/intl/cs.d.ts +94 -0
- package/dist/src/intl/cs.d.ts.map +1 -0
- package/dist/src/intl/cs.js +220 -0
- package/dist/src/intl/index.d.ts +7 -0
- package/dist/src/intl/index.d.ts.map +1 -0
- package/dist/src/intl/index.js +6 -0
- package/dist/src/local-first/Db.d.ts +12 -8
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +109 -132
- package/dist/src/local-first/Error.d.ts +4 -4
- package/dist/src/local-first/Evolu.d.ts +338 -92
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +47 -55
- package/dist/src/local-first/LocalAuth.d.ts +4 -4
- package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
- package/dist/src/local-first/Owner.d.ts +61 -24
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +45 -8
- package/dist/src/local-first/Protocol.d.ts +44 -31
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +36 -13
- package/dist/src/local-first/Query.d.ts +147 -62
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +112 -58
- package/dist/src/local-first/Relay.d.ts +44 -14
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Schema.d.ts +92 -41
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +25 -8
- package/dist/src/local-first/Shared.d.ts +23 -21
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +100 -57
- package/dist/src/local-first/Storage.d.ts +53 -32
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +194 -234
- package/dist/src/local-first/Timestamp.d.ts +21 -21
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +2 -2
- package/dist/src/local-first/index.d.ts +11 -11
- package/package.json +14 -13
- package/src/Array.ts +306 -205
- package/src/Assert.ts +54 -69
- package/src/BigInt.ts +6 -3
- package/src/Brand.ts +27 -40
- package/src/Buffer.ts +28 -12
- package/src/Cache.ts +9 -4
- package/src/Callbacks.ts +30 -19
- package/src/Console.ts +156 -84
- package/src/Crypto.ts +83 -41
- package/src/Eq.ts +95 -22
- package/src/Error.ts +8 -4
- package/src/Function.ts +167 -59
- package/src/Http.ts +549 -0
- package/src/Identicon.ts +16 -7
- package/src/LeakDetector.ts +182 -0
- package/src/LockManager.ts +43 -39
- package/src/Lookup.ts +62 -28
- package/src/Microtask.ts +19 -23
- package/src/Number.ts +64 -12
- package/src/Object.ts +173 -49
- package/src/Option.ts +10 -7
- package/src/Order.ts +23 -21
- package/src/Platform.ts +136 -0
- package/src/Polyfills.ts +6 -12
- package/src/Random.ts +32 -19
- package/src/Redacted.ts +44 -30
- package/src/Ref.ts +14 -6
- package/src/RefCount.ts +38 -80
- package/src/Relation.ts +202 -10
- package/src/Resource.ts +1199 -591
- package/src/Result.ts +930 -271
- package/src/Schedule.ts +859 -343
- package/src/Set.ts +89 -40
- package/src/Sqlite.ts +144 -138
- package/src/StackTrace.ts +230 -0
- package/src/Store.ts +8 -7
- package/src/String.ts +22 -5
- package/src/Task.ts +5101 -2832
- package/src/Test.ts +20 -168
- package/src/Time.ts +293 -90
- package/src/Type.ts +10034 -4117
- package/src/Types.ts +227 -110
- package/src/WebSocket.ts +64 -36
- package/src/Worker.ts +180 -72
- package/src/index.ts +55 -52
- package/src/intl/cs.ts +388 -0
- package/src/intl/index.ts +7 -0
- package/src/local-first/Db.ts +152 -179
- package/src/local-first/Error.ts +4 -4
- package/src/local-first/Evolu.ts +495 -250
- package/src/local-first/LocalAuth.ts +6 -12
- package/src/local-first/Owner.ts +58 -21
- package/src/local-first/Protocol.ts +49 -31
- package/src/local-first/Query.ts +146 -61
- package/src/local-first/Relay.ts +51 -21
- package/src/local-first/Schema.ts +109 -51
- package/src/local-first/Shared.ts +266 -226
- package/src/local-first/Storage.ts +266 -264
- package/src/local-first/Timestamp.ts +25 -18
- package/src/local-first/index.ts +11 -11
- package/dist/src/Skiplist.d.ts +0 -28
- package/dist/src/Skiplist.d.ts.map +0 -1
- package/dist/src/Skiplist.js +0 -64
- package/dist/src/Tracer.d.ts +0 -48
- package/dist/src/Tracer.d.ts.map +0 -1
- package/dist/src/Tracer.js +0 -6
- package/src/Skiplist.ts +0 -108
- package/src/Tracer.ts +0 -54
package/dist/src/Types.d.ts
CHANGED
|
@@ -3,18 +3,29 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
import * as Kysely from "kysely";
|
|
7
|
-
import type { TypeName } from "./Type.js";
|
|
8
6
|
/**
|
|
9
7
|
* A function that receives a value and returns nothing.
|
|
10
8
|
*
|
|
11
9
|
* Use for event handlers, observers, and async completion handlers.
|
|
12
10
|
*
|
|
13
|
-
* ###
|
|
11
|
+
* ### Completion callbacks
|
|
14
12
|
*
|
|
15
13
|
* ```ts
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
* import { ok, type Callback, type Result } from "@evolu/common";
|
|
15
|
+
*
|
|
16
|
+
* const completedValues: Array<string> = [];
|
|
17
|
+
* const onComplete: Callback<string> = (value) => {
|
|
18
|
+
* completedValues.push(value);
|
|
19
|
+
* };
|
|
20
|
+
* const queue = new Set<Callback<Result<string, Error>>>();
|
|
21
|
+
* queue.add((result) => {
|
|
22
|
+
* if (result.ok) completedValues.push(result.value);
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* onComplete("direct");
|
|
26
|
+
* for (const callback of queue) callback(ok("queued"));
|
|
27
|
+
*
|
|
28
|
+
* expect(completedValues).toEqual(["direct", "queued"]);
|
|
18
29
|
* ```
|
|
19
30
|
*/
|
|
20
31
|
export type Callback<T> = (value: T) => void;
|
|
@@ -23,13 +34,29 @@ export type Callback<T> = (value: T) => void;
|
|
|
23
34
|
*
|
|
24
35
|
* Use for subscriptions or callbacks that need abort-time teardown.
|
|
25
36
|
*
|
|
26
|
-
* ###
|
|
37
|
+
* ### Subscription teardown
|
|
27
38
|
*
|
|
28
39
|
* ```ts
|
|
40
|
+
* import type { CallbackWithTeardown } from "@evolu/common";
|
|
41
|
+
*
|
|
42
|
+
* interface EventSource {
|
|
43
|
+
* readonly start: () => void;
|
|
44
|
+
* readonly stop: () => void;
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* const events: Array<string> = [];
|
|
48
|
+
* const source: EventSource = {
|
|
49
|
+
* start: () => events.push("started"),
|
|
50
|
+
* stop: () => events.push("stopped"),
|
|
51
|
+
* };
|
|
29
52
|
* const subscribe: CallbackWithTeardown<EventSource> = (source) => {
|
|
30
53
|
* source.start();
|
|
31
|
-
* return
|
|
54
|
+
* return source.stop;
|
|
32
55
|
* };
|
|
56
|
+
* const teardown = subscribe(source);
|
|
57
|
+
* if (teardown) teardown();
|
|
58
|
+
*
|
|
59
|
+
* expect(events).toEqual(["started", "stopped"]);
|
|
33
60
|
* ```
|
|
34
61
|
*/
|
|
35
62
|
export type CallbackWithTeardown<T> = (value: T) => void | (() => void);
|
|
@@ -38,13 +65,14 @@ export type CallbackWithTeardown<T> = (value: T) => void | (() => void);
|
|
|
38
65
|
*
|
|
39
66
|
* A predicate starts with an 'is' prefix, e.g., `isEven`.
|
|
40
67
|
*
|
|
41
|
-
* ###
|
|
68
|
+
* ### Filtering values
|
|
42
69
|
*
|
|
43
70
|
* ```ts
|
|
71
|
+
* import type { Predicate } from "@evolu/common";
|
|
72
|
+
*
|
|
44
73
|
* const isEven: Predicate<number> = (n) => n % 2 === 0;
|
|
45
74
|
*
|
|
46
|
-
*
|
|
47
|
-
* const evenNumbers = numbers.filter(isEven); // [2, 4]
|
|
75
|
+
* expect([1, 2, 3, 4].filter(isEven)).toEqual([2, 4]);
|
|
48
76
|
* ```
|
|
49
77
|
*/
|
|
50
78
|
export type Predicate<T> = (value: T) => boolean;
|
|
@@ -53,33 +81,40 @@ export type Predicate<T> = (value: T) => boolean;
|
|
|
53
81
|
*
|
|
54
82
|
* Useful for callbacks that need both the element and its position.
|
|
55
83
|
*
|
|
56
|
-
* ###
|
|
84
|
+
* ### Filtering by position
|
|
57
85
|
*
|
|
58
86
|
* ```ts
|
|
87
|
+
* import type { PredicateWithIndex } from "@evolu/common";
|
|
88
|
+
*
|
|
59
89
|
* const isEvenIndex: PredicateWithIndex<string> = (value, index) =>
|
|
60
90
|
* index % 2 === 0;
|
|
61
91
|
*
|
|
62
|
-
*
|
|
63
|
-
* const evenIndexItems = items.filter(isEvenIndex); // ["a", "c"]
|
|
92
|
+
* expect(["a", "b", "c", "d"].filter(isEvenIndex)).toEqual(["a", "c"]);
|
|
64
93
|
* ```
|
|
65
94
|
*/
|
|
66
95
|
export type PredicateWithIndex<T> = (value: T, index: number) => boolean;
|
|
67
96
|
/**
|
|
68
97
|
* A type guard function that refines type `A` to a narrower type `B`.
|
|
69
98
|
*
|
|
70
|
-
* ###
|
|
99
|
+
* ### Narrowing a value
|
|
71
100
|
*
|
|
72
101
|
* ```ts
|
|
73
|
-
* type
|
|
74
|
-
*
|
|
102
|
+
* import type { Refinement } from "@evolu/common";
|
|
103
|
+
*
|
|
104
|
+
* interface Animal {
|
|
105
|
+
* readonly name: string;
|
|
106
|
+
* }
|
|
107
|
+
* interface Dog extends Animal {
|
|
108
|
+
* readonly breed: string;
|
|
109
|
+
* }
|
|
75
110
|
*
|
|
76
111
|
* const isDog: Refinement<Animal, Dog> = (animal): animal is Dog =>
|
|
77
112
|
* "breed" in animal;
|
|
113
|
+
* const dog: Dog = { name: "Dog", breed: "Beagle" };
|
|
114
|
+
* const animal: Animal = dog;
|
|
115
|
+
* if (!isDog(animal)) throw new Error("Expected a dog");
|
|
78
116
|
*
|
|
79
|
-
*
|
|
80
|
-
* if (isDog(animal)) {
|
|
81
|
-
* console.log(animal.breed); // Safe access to `breed`
|
|
82
|
-
* }
|
|
117
|
+
* expect(animal.breed).toBe("Beagle");
|
|
83
118
|
* ```
|
|
84
119
|
*/
|
|
85
120
|
export type Refinement<in A, out B extends A> = (a: A) => a is B;
|
|
@@ -90,40 +125,112 @@ export type Refinement<in A, out B extends A> = (a: A) => a is B;
|
|
|
90
125
|
* Useful for callbacks that need both the element and its position while
|
|
91
126
|
* maintaining type narrowing.
|
|
92
127
|
*
|
|
93
|
-
* ###
|
|
128
|
+
* ### Indexed refinement
|
|
94
129
|
*
|
|
95
130
|
* ```ts
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* const isNumberItem: RefinementWithIndex<Item, Item & { type: "number" }> =
|
|
99
|
-
* (item, index): item is Item & { type: "number" } =>
|
|
100
|
-
* index > 0 && item.type === "number";
|
|
131
|
+
* import { partitionArray, type RefinementWithIndex } from "@evolu/common";
|
|
101
132
|
*
|
|
102
|
-
*
|
|
133
|
+
* type Item = {
|
|
134
|
+
* readonly type: "number" | "string";
|
|
135
|
+
* readonly value: unknown;
|
|
136
|
+
* };
|
|
137
|
+
* type NumberItem = Item & { readonly type: "number" };
|
|
138
|
+
*
|
|
139
|
+
* const isNumberItem: RefinementWithIndex<Item, NumberItem> = (
|
|
140
|
+
* item,
|
|
141
|
+
* index,
|
|
142
|
+
* ): item is NumberItem => index > 0 && item.type === "number";
|
|
143
|
+
* const items: ReadonlyArray<Item> = [
|
|
144
|
+
* { type: "number", value: 1 },
|
|
145
|
+
* { type: "number", value: 2 },
|
|
146
|
+
* ];
|
|
103
147
|
* const [numbers, others] = partitionArray(items, isNumberItem);
|
|
148
|
+
*
|
|
149
|
+
* expectTypeOf(numbers).toEqualTypeOf<ReadonlyArray<NumberItem>>();
|
|
150
|
+
* expect(numbers[0]?.value).toBe(2);
|
|
151
|
+
* expect(others[0]?.value).toBe(1);
|
|
104
152
|
* ```
|
|
105
153
|
*/
|
|
106
154
|
export type RefinementWithIndex<in A, out B extends A> = (a: A, index: number) => a is B;
|
|
155
|
+
/**
|
|
156
|
+
* Realm-neutral runtime identity for a TypeScript interface.
|
|
157
|
+
*
|
|
158
|
+
* Extend this interface and add its runtime evidence with {@link instance} when
|
|
159
|
+
* constructing a value. Unlike JavaScript `instanceof`, the identity does not
|
|
160
|
+
* depend on a constructor or prototype and therefore survives realms, package
|
|
161
|
+
* duplication, object spreading, and structured cloning.
|
|
162
|
+
*
|
|
163
|
+
* The marker is intentionally forgeable. It identifies values created by
|
|
164
|
+
* trusted constructors; it is not structural validation or a security
|
|
165
|
+
* boundary.
|
|
166
|
+
*
|
|
167
|
+
* ### Adding runtime identity
|
|
168
|
+
*
|
|
169
|
+
* ```ts
|
|
170
|
+
* import { instance, type Instance } from "@evolu/common";
|
|
171
|
+
*
|
|
172
|
+
* interface Foo extends Instance<"Foo"> {
|
|
173
|
+
* readonly value: string;
|
|
174
|
+
* }
|
|
175
|
+
*
|
|
176
|
+
* const foo: Foo = {
|
|
177
|
+
* ...instance("Foo"),
|
|
178
|
+
* value: "value",
|
|
179
|
+
* };
|
|
180
|
+
*
|
|
181
|
+
* expect(foo["~evolu/instance"]).toBe("Foo");
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
export interface Instance<Name extends string> {
|
|
185
|
+
readonly "~evolu/instance": Name;
|
|
186
|
+
}
|
|
187
|
+
/** Creates the runtime identity property required by {@link Instance}. */
|
|
188
|
+
export declare const instance: <const Name extends string>(name: Name) => Instance<Name>;
|
|
189
|
+
/**
|
|
190
|
+
* Creates a realm-neutral predicate for one {@link Instance} name.
|
|
191
|
+
*
|
|
192
|
+
* The identity must be stored directly on the value; inherited markers are
|
|
193
|
+
* ignored.
|
|
194
|
+
*
|
|
195
|
+
* The explicit value type can include the rest of an interface whose trusted
|
|
196
|
+
* constructors attach the matching identity.
|
|
197
|
+
*
|
|
198
|
+
* ### Checking runtime identity
|
|
199
|
+
*
|
|
200
|
+
* ```ts
|
|
201
|
+
* import { instance, isInstance, type Instance } from "@evolu/common";
|
|
202
|
+
*
|
|
203
|
+
* interface Foo extends Instance<"Foo"> {
|
|
204
|
+
* readonly value: string;
|
|
205
|
+
* }
|
|
206
|
+
*
|
|
207
|
+
* const isFoo = isInstance<Foo>("Foo");
|
|
208
|
+
* const value: unknown = { ...instance("Foo"), value: "value" };
|
|
209
|
+
*
|
|
210
|
+
* expect(isFoo(value)).toBe(true);
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
export declare const isInstance: <Value extends Instance<string>>(name: Value["~evolu/instance"]) => (value: unknown) => value is Value;
|
|
107
214
|
/**
|
|
108
215
|
* Makes properties optional if they accept `null` as a value.
|
|
109
216
|
*
|
|
110
217
|
* For each property in `T`, if `null` is a valid value for that property, the
|
|
111
218
|
* property will be made optional in the resulting type.
|
|
112
219
|
*
|
|
113
|
-
* ###
|
|
220
|
+
* ### Optional nullable properties
|
|
114
221
|
*
|
|
115
222
|
* ```ts
|
|
223
|
+
* import type { NullablePartial } from "@evolu/common";
|
|
224
|
+
*
|
|
116
225
|
* type Example = {
|
|
117
226
|
* required: string;
|
|
118
227
|
* optionalWithNull: string | null;
|
|
119
228
|
* };
|
|
120
229
|
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* // optionalWithNull?: string | null;
|
|
126
|
-
* // }
|
|
230
|
+
* expectTypeOf<NullablePartial<Example>>().toEqualTypeOf<{
|
|
231
|
+
* required: string;
|
|
232
|
+
* optionalWithNull?: string | null;
|
|
233
|
+
* }>();
|
|
127
234
|
* ```
|
|
128
235
|
*/
|
|
129
236
|
export type NullablePartial<T, NK extends keyof T = {
|
|
@@ -131,6 +238,10 @@ export type NullablePartial<T, NK extends keyof T = {
|
|
|
131
238
|
}[keyof T], NP = Pick<T, Exclude<keyof T, NK>> & Partial<Pick<T, NK>>> = {
|
|
132
239
|
[K in keyof NP]: NP[K];
|
|
133
240
|
};
|
|
241
|
+
/** A value with a numeric length. */
|
|
242
|
+
export interface ValueWithLength {
|
|
243
|
+
readonly length: number;
|
|
244
|
+
}
|
|
134
245
|
/**
|
|
135
246
|
* String, number, bigint, boolean, undefined, null
|
|
136
247
|
*
|
|
@@ -148,13 +259,8 @@ export type Literal = string | number | bigint | boolean | undefined | null;
|
|
|
148
259
|
* - True -> boolean
|
|
149
260
|
*/
|
|
150
261
|
export type WidenLiteral<T extends Literal> = T extends string ? string : T extends number ? number : T extends boolean ? boolean : T extends bigint ? bigint : T;
|
|
151
|
-
/**
|
|
152
|
-
|
|
153
|
-
*
|
|
154
|
-
* Useful for constructing immutable objects step-by-step (e.g. builder pattern)
|
|
155
|
-
* before casting them back to the readonly type.
|
|
156
|
-
*/
|
|
157
|
-
export type Mutable<T> = {
|
|
262
|
+
/** Removes `readonly` modifier from all properties of a type. */
|
|
263
|
+
export type Writable<T> = {
|
|
158
264
|
-readonly [P in keyof T]: T[P];
|
|
159
265
|
};
|
|
160
266
|
/**
|
|
@@ -163,19 +269,23 @@ export type Mutable<T> = {
|
|
|
163
269
|
* This utility forces TypeScript to "flatten" an intersection type into a
|
|
164
270
|
* single object type so that tooltips and error messages are easier to read.
|
|
165
271
|
*
|
|
166
|
-
* ###
|
|
272
|
+
* ### Flattening an intersection
|
|
167
273
|
*
|
|
168
274
|
* ```ts
|
|
169
|
-
* type
|
|
170
|
-
* // Without Simplify, TypeScript may display A as:
|
|
171
|
-
* // { a: string } & { b: number }
|
|
275
|
+
* import type { Simplify } from "@evolu/common";
|
|
172
276
|
*
|
|
277
|
+
* type A = { a: string } & { b: number };
|
|
173
278
|
* type B = Simplify<A>;
|
|
174
|
-
*
|
|
175
|
-
*
|
|
279
|
+
*
|
|
280
|
+
* expectTypeOf<B>().toEqualTypeOf<{
|
|
281
|
+
* a: string;
|
|
282
|
+
* b: number;
|
|
283
|
+
* }>();
|
|
176
284
|
* ```
|
|
177
285
|
*/
|
|
178
|
-
export type Simplify<T> =
|
|
286
|
+
export type Simplify<T> = {
|
|
287
|
+
[K in keyof T]: T[K];
|
|
288
|
+
} & {};
|
|
179
289
|
/**
|
|
180
290
|
* Makes a specific property of an object optional while keeping others
|
|
181
291
|
* unchanged.
|
|
@@ -187,21 +297,21 @@ export type PartialProp<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
|
|
|
187
297
|
* Use when a function may complete synchronously or asynchronously depending on
|
|
188
298
|
* runtime conditions (e.g., cache hit vs network fetch).
|
|
189
299
|
*
|
|
190
|
-
* ###
|
|
300
|
+
* ### Sync and async completion
|
|
191
301
|
*
|
|
192
302
|
* ```ts
|
|
193
|
-
*
|
|
194
|
-
* const cached = cache.get(id);
|
|
195
|
-
* if (cached) return cached; // Sync path
|
|
196
|
-
* return fetchData(id); // Async path
|
|
197
|
-
* };
|
|
303
|
+
* import { isPromiseLike, type Awaitable } from "@evolu/common";
|
|
198
304
|
*
|
|
199
|
-
*
|
|
200
|
-
* const
|
|
305
|
+
* const cache = new Map([["cached", "from cache"]]);
|
|
306
|
+
* const getData = (id: string): Awaitable<string> =>
|
|
307
|
+
* cache.get(id) ?? Promise.resolve(`fetched ${id}`);
|
|
201
308
|
*
|
|
202
|
-
*
|
|
203
|
-
* const result = getData(
|
|
204
|
-
* const
|
|
309
|
+
* const fetched = await getData("missing");
|
|
310
|
+
* const result = getData("cached");
|
|
311
|
+
* const cached = isPromiseLike(result) ? await result : result;
|
|
312
|
+
*
|
|
313
|
+
* expect(fetched).toBe("fetched missing");
|
|
314
|
+
* expect(cached).toBe("from cache");
|
|
205
315
|
* ```
|
|
206
316
|
*/
|
|
207
317
|
export type Awaitable<T> = T | PromiseLike<T>;
|
|
@@ -211,33 +321,35 @@ export type Awaitable<T> = T | PromiseLike<T>;
|
|
|
211
321
|
* Use with {@link Awaitable} to conditionally `await` only when necessary,
|
|
212
322
|
* avoiding microtask overhead for synchronous values.
|
|
213
323
|
*
|
|
214
|
-
* ###
|
|
324
|
+
* ### Conditional awaiting
|
|
215
325
|
*
|
|
216
326
|
* ```ts
|
|
217
|
-
*
|
|
218
|
-
* const cached = cache.get(id);
|
|
219
|
-
* if (cached !== undefined) return cached; // Sync path
|
|
220
|
-
* return fetchValidation(id); // Async path
|
|
221
|
-
* };
|
|
327
|
+
* import { isPromiseLike, type Awaitable } from "@evolu/common";
|
|
222
328
|
*
|
|
223
|
-
* const
|
|
329
|
+
* const cache = new Map([["cached", true]]);
|
|
330
|
+
* const validate = (id: string): Awaitable<boolean> =>
|
|
331
|
+
* cache.get(id) ?? Promise.resolve(false);
|
|
332
|
+
*
|
|
333
|
+
* const result = validate("cached");
|
|
224
334
|
* const isValid = isPromiseLike(result) ? await result : result;
|
|
335
|
+
*
|
|
336
|
+
* expect(isValid).toBe(true);
|
|
225
337
|
* ```
|
|
226
338
|
*/
|
|
227
339
|
export declare const isPromiseLike: <T>(value: Awaitable<T>) => value is PromiseLike<T>;
|
|
228
|
-
/**
|
|
340
|
+
/** Decimal digit from `"0"` to `"9"`. */
|
|
229
341
|
export type Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
|
|
230
|
-
/**
|
|
342
|
+
/** Decimal digit from `"1"` to `"9"`. */
|
|
231
343
|
export type Digit1To9 = Exclude<Digit, "0">;
|
|
232
|
-
/**
|
|
344
|
+
/** Decimal string from `"1"` to `"6"`. */
|
|
233
345
|
export type Digit1To6 = "1" | "2" | "3" | "4" | "5" | "6";
|
|
234
|
-
/**
|
|
346
|
+
/** Decimal string from `"1"` to `"23"`. */
|
|
235
347
|
export type Digit1To23 = Digit1To9 | `1${Digit}` | `2${"0" | "1" | "2" | "3"}`;
|
|
236
|
-
/**
|
|
348
|
+
/** Decimal string from `"1"` to `"51"`. */
|
|
237
349
|
export type Digit1To51 = Digit1To9 | `${"1" | "2" | "3" | "4"}${Digit}` | `5${"0" | "1"}`;
|
|
238
|
-
/**
|
|
350
|
+
/** Decimal string from `"1"` to `"99"`. */
|
|
239
351
|
export type Digit1To99 = Digit1To9 | `${Digit1To9}${Digit}`;
|
|
240
|
-
/**
|
|
352
|
+
/** Decimal string from `"1"` to `"59"`. */
|
|
241
353
|
export type Digit1To59 = Digit1To9 | `1${Digit}` | `2${Digit}` | `3${Digit}` | `4${Digit}` | `5${Digit}`;
|
|
242
354
|
/** Numeric literal 1-99. */
|
|
243
355
|
export type Int1To99 = NumberFromString<Digit1To99>;
|
|
@@ -249,57 +361,37 @@ export type Int1To100 = Int1To99 | 100;
|
|
|
249
361
|
* Used by {@link Int1To99}.
|
|
250
362
|
*/
|
|
251
363
|
export type NumberFromString<T extends string> = T extends `${infer N extends number}` ? N : never;
|
|
364
|
+
/** Creates a readable compiler-facing error message. */
|
|
365
|
+
export type CompileTimeError<Context extends string, Message extends string> = `⛔ ${Context} error: ${Message}`;
|
|
366
|
+
/** Returns whether a type is a union. */
|
|
367
|
+
export type IsUnion<T, Whole = T> = [T] extends [never] ? false : T extends Whole ? [Whole] extends [T] ? false : true : never;
|
|
368
|
+
/** Returns every property key present in any member of a union. */
|
|
369
|
+
export type KeysOfUnion<T> = T extends T ? keyof T : never;
|
|
252
370
|
/** Converts a union to an intersection. */
|
|
253
371
|
export type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
372
|
+
/** Intersects the parameter types of a union of unary functions. */
|
|
373
|
+
export type ParameterIntersection<T> = [T] extends [(value: infer I) => void] ? I : unknown;
|
|
254
374
|
/**
|
|
255
375
|
* Removes keys from each member of a union.
|
|
256
376
|
*
|
|
257
377
|
* Use when {@link Omit} would collapse a discriminated union into a single
|
|
258
378
|
* shared shape.
|
|
259
379
|
*
|
|
260
|
-
* ###
|
|
380
|
+
* ### Preserving discriminated unions
|
|
261
381
|
*
|
|
262
382
|
* ```ts
|
|
383
|
+
* import type { DistributiveOmit } from "@evolu/common";
|
|
384
|
+
*
|
|
263
385
|
* type Event =
|
|
264
386
|
* | { type: "a"; a: string; shared: number }
|
|
265
387
|
* | { type: "b"; b: number; shared: number };
|
|
266
388
|
*
|
|
267
389
|
* type Payload = DistributiveOmit<Event, "shared">;
|
|
268
|
-
* // { type: "a"; a: string } | { type: "b"; b: number }
|
|
269
|
-
* ```
|
|
270
|
-
*/
|
|
271
|
-
export type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
|
|
272
|
-
/**
|
|
273
|
-
* Extracts members of a discriminated union by their `type` literal.
|
|
274
|
-
*
|
|
275
|
-
* Constrains `TType` to valid `type` values, so typos fail at the type argument
|
|
276
|
-
* instead of silently producing `never`.
|
|
277
|
-
*
|
|
278
|
-
* ### Example
|
|
279
390
|
*
|
|
280
|
-
*
|
|
281
|
-
* type
|
|
282
|
-
*
|
|
283
|
-
* | { readonly type: "Delete"; readonly id: string };
|
|
284
|
-
*
|
|
285
|
-
* type CreateMessage = ExtractType<Message, "Create">;
|
|
286
|
-
* // { readonly type: "Create"; readonly id: string }
|
|
287
|
-
*
|
|
288
|
-
* // Type error: "Cretae" is not a valid Message type
|
|
289
|
-
* type _Typo = ExtractType<Message, "Cretae">;
|
|
391
|
+
* expectTypeOf<Payload>().toEqualTypeOf<
|
|
392
|
+
* { type: "a"; a: string } | { type: "b"; b: number }
|
|
393
|
+
* >();
|
|
290
394
|
* ```
|
|
291
395
|
*/
|
|
292
|
-
export type
|
|
293
|
-
readonly type: TypeName;
|
|
294
|
-
}, TType extends TUnion["type"]> = Extract<TUnion, {
|
|
295
|
-
readonly type: TType;
|
|
296
|
-
}>;
|
|
297
|
-
/**
|
|
298
|
-
* Constrains `T` to only contain keys not present in `Existing`.
|
|
299
|
-
*
|
|
300
|
-
* Use as a generic constraint to prevent overriding existing properties.
|
|
301
|
-
*/
|
|
302
|
-
export type NewKeys<T, Existing> = {
|
|
303
|
-
[K in keyof T]: K extends keyof Existing ? never : T[K];
|
|
304
|
-
};
|
|
396
|
+
export type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
|
|
305
397
|
//# sourceMappingURL=Types.d.ts.map
|
package/dist/src/Types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Types.d.ts","sourceRoot":"","sources":["../../src/Types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH
|
|
1
|
+
{"version":3,"file":"Types.d.ts","sourceRoot":"","sources":["../../src/Types.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Types.js
CHANGED
|
@@ -3,24 +3,55 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
/** Creates the runtime identity property required by {@link Instance}. */
|
|
7
|
+
export const instance = (name) => ({ "~evolu/instance": name });
|
|
8
|
+
/**
|
|
9
|
+
* Creates a realm-neutral predicate for one {@link Instance} name.
|
|
10
|
+
*
|
|
11
|
+
* The identity must be stored directly on the value; inherited markers are
|
|
12
|
+
* ignored.
|
|
13
|
+
*
|
|
14
|
+
* The explicit value type can include the rest of an interface whose trusted
|
|
15
|
+
* constructors attach the matching identity.
|
|
16
|
+
*
|
|
17
|
+
* ### Checking runtime identity
|
|
18
|
+
*
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { instance, isInstance, type Instance } from "@evolu/common";
|
|
21
|
+
*
|
|
22
|
+
* interface Foo extends Instance<"Foo"> {
|
|
23
|
+
* readonly value: string;
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* const isFoo = isInstance<Foo>("Foo");
|
|
27
|
+
* const value: unknown = { ...instance("Foo"), value: "value" };
|
|
28
|
+
*
|
|
29
|
+
* expect(isFoo(value)).toBe(true);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export const isInstance = (name) => (value) => value !== null &&
|
|
33
|
+
typeof value === "object" &&
|
|
34
|
+
globalThis.Object.hasOwn(value, "~evolu/instance") &&
|
|
35
|
+
value["~evolu/instance"] === name;
|
|
7
36
|
/**
|
|
8
37
|
* Type guard to check if a value is a {@link PromiseLike}.
|
|
9
38
|
*
|
|
10
39
|
* Use with {@link Awaitable} to conditionally `await` only when necessary,
|
|
11
40
|
* avoiding microtask overhead for synchronous values.
|
|
12
41
|
*
|
|
13
|
-
* ###
|
|
42
|
+
* ### Conditional awaiting
|
|
14
43
|
*
|
|
15
44
|
* ```ts
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
45
|
+
* import { isPromiseLike, type Awaitable } from "@evolu/common";
|
|
46
|
+
*
|
|
47
|
+
* const cache = new Map([["cached", true]]);
|
|
48
|
+
* const validate = (id: string): Awaitable<boolean> =>
|
|
49
|
+
* cache.get(id) ?? Promise.resolve(false);
|
|
21
50
|
*
|
|
22
|
-
* const result = validate(
|
|
51
|
+
* const result = validate("cached");
|
|
23
52
|
* const isValid = isPromiseLike(result) ? await result : result;
|
|
53
|
+
*
|
|
54
|
+
* expect(isValid).toBe(true);
|
|
24
55
|
* ```
|
|
25
56
|
*/
|
|
26
57
|
export const isPromiseLike = (value) => typeof value?.then === "function";
|
package/dist/src/WebSocket.d.ts
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
import type { Result } from "./Result.
|
|
7
|
-
import type { Schedule } from "./Schedule.
|
|
8
|
-
import type { RetryError, Task } from "./Task.
|
|
9
|
-
import type { Millis } from "./Time.
|
|
10
|
-
import { type Typed } from "./Type.
|
|
6
|
+
import type { Result } from "./Result.ts";
|
|
7
|
+
import type { Schedule } from "./Schedule.ts";
|
|
8
|
+
import type { RetryError, Task } from "./Task.ts";
|
|
9
|
+
import type { Millis } from "./Time.ts";
|
|
10
|
+
import { type Typed } from "./Type.ts";
|
|
11
11
|
/**
|
|
12
12
|
* WebSocket with auto-reconnect.
|
|
13
13
|
*
|
|
@@ -42,20 +42,42 @@ import { type Typed } from "./Type.js";
|
|
|
42
42
|
* - A Blob (default: "blob")
|
|
43
43
|
* - An ArrayBuffer ("arraybuffer")
|
|
44
44
|
*
|
|
45
|
-
* ###
|
|
45
|
+
* ### Connecting and sending
|
|
46
46
|
*
|
|
47
47
|
* ```ts
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
48
|
+
* import {
|
|
49
|
+
* createRun,
|
|
50
|
+
* createWebSocket,
|
|
51
|
+
* testCreateWebSocket,
|
|
52
|
+
* type CreateWebSocket,
|
|
53
|
+
* type Task,
|
|
54
|
+
* type WebSocketSendError,
|
|
55
|
+
* } from "@evolu/common";
|
|
56
|
+
*
|
|
57
|
+
* const connectAndSend =
|
|
58
|
+
* (
|
|
59
|
+
* createSocket: CreateWebSocket = createWebSocket,
|
|
60
|
+
* ): Task<void, WebSocketSendError> =>
|
|
61
|
+
* async (run) => {
|
|
62
|
+
* await using socket = await run.ok(
|
|
63
|
+
* createSocket("wss://example.com", {
|
|
64
|
+
* protocols: ["evolu"],
|
|
65
|
+
* binaryType: "arraybuffer",
|
|
66
|
+
* onOpen: () => console.log("Connected"),
|
|
67
|
+
* onMessage: (data) => console.log("Received:", data),
|
|
68
|
+
* onClose: () => console.log("Disconnected"),
|
|
69
|
+
* }),
|
|
70
|
+
* );
|
|
71
|
+
* return socket.send("Hello");
|
|
72
|
+
* };
|
|
73
|
+
*
|
|
74
|
+
* const socketFactory = testCreateWebSocket();
|
|
75
|
+
* await using run = createRun();
|
|
76
|
+
*
|
|
77
|
+
* expectOk(await run(connectAndSend(socketFactory)), undefined);
|
|
78
|
+
* expect(socketFactory.sentMessages).toEqual([
|
|
79
|
+
* { url: "wss://example.com", data: "Hello" },
|
|
80
|
+
* ]);
|
|
59
81
|
* ```
|
|
60
82
|
*/
|
|
61
83
|
export interface WebSocket extends AsyncDisposable {
|
|
@@ -104,12 +126,8 @@ export interface WebSocketOptions {
|
|
|
104
126
|
/** Callback when message data is received. */
|
|
105
127
|
readonly onMessage?: (data: string | ArrayBuffer | Blob) => void;
|
|
106
128
|
/**
|
|
107
|
-
* Retry schedule for reconnection. Defaults to
|
|
108
|
-
*
|
|
109
|
-
* ```ts
|
|
110
|
-
* // A jittered, capped, unlimited exponential backoff.
|
|
111
|
-
* jitter(1)(maxDelay("30s")(exponential("100ms")));
|
|
112
|
-
* ```
|
|
129
|
+
* Retry schedule for reconnection. Defaults to
|
|
130
|
+
* {@link webSocketReconnectSchedule}.
|
|
113
131
|
*/
|
|
114
132
|
readonly schedule?: Schedule<Millis, WebSocketRetryError>;
|
|
115
133
|
/**
|
|
@@ -146,6 +164,13 @@ export type WebSocketRetryError = WebSocketConnectError | WebSocketConnectionClo
|
|
|
146
164
|
export interface WebSocketConnectionCloseError extends Typed<"WebSocketConnectionCloseError"> {
|
|
147
165
|
readonly event: CloseEvent;
|
|
148
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Default WebSocket reconnect schedule.
|
|
169
|
+
*
|
|
170
|
+
* Uses unlimited exponential backoff with a 100ms base, 30s cap, and full
|
|
171
|
+
* jitter.
|
|
172
|
+
*/
|
|
173
|
+
export declare const webSocketReconnectSchedule: Schedule<Millis, WebSocketRetryError>;
|
|
149
174
|
/** Create a new {@link WebSocket}. */
|
|
150
175
|
export declare const createWebSocket: CreateWebSocket;
|
|
151
176
|
/**
|