@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/src/Assert.ts
CHANGED
|
@@ -4,9 +4,7 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type {
|
|
8
|
-
import type { AbortError } from "./Task.js";
|
|
9
|
-
import type { AnyType, InferType, Type } from "./Type.js";
|
|
7
|
+
import type { Type } from "./Type.ts";
|
|
10
8
|
|
|
11
9
|
/**
|
|
12
10
|
* Ensures a condition is true, throwing an error with the provided message if
|
|
@@ -22,8 +20,12 @@ import type { AnyType, InferType, Type } from "./Type.js";
|
|
|
22
20
|
* ### Example
|
|
23
21
|
*
|
|
24
22
|
* ```ts
|
|
25
|
-
* assert
|
|
26
|
-
*
|
|
23
|
+
* import { assert as assertInvariant } from "@evolu/common";
|
|
24
|
+
*
|
|
25
|
+
* expect(() => assertInvariant(true, "Expected true.")).not.toThrow();
|
|
26
|
+
* expect(() => assertInvariant(false, "Expected true.")).toThrow(
|
|
27
|
+
* "Expected true.",
|
|
28
|
+
* );
|
|
27
29
|
* ```
|
|
28
30
|
*/
|
|
29
31
|
export const assert: (
|
|
@@ -35,6 +37,22 @@ export const assert: (
|
|
|
35
37
|
}
|
|
36
38
|
};
|
|
37
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Asserts that a value is non-nullable.
|
|
42
|
+
*
|
|
43
|
+
* Narrows a nullable value to {@link NonNullable} when null or undefined is
|
|
44
|
+
* logically impossible but TypeScript cannot prove it.
|
|
45
|
+
*/
|
|
46
|
+
export const assertNonNullable: <T>(
|
|
47
|
+
value: T,
|
|
48
|
+
message?: string,
|
|
49
|
+
) => asserts value is NonNullable<T> = (
|
|
50
|
+
value,
|
|
51
|
+
message = "Expected value to be non-nullable.",
|
|
52
|
+
) => {
|
|
53
|
+
assert(value != null, message);
|
|
54
|
+
};
|
|
55
|
+
|
|
38
56
|
/**
|
|
39
57
|
* Asserts that an array is non-empty.
|
|
40
58
|
*
|
|
@@ -45,8 +63,13 @@ export const assert: (
|
|
|
45
63
|
* ### Example
|
|
46
64
|
*
|
|
47
65
|
* ```ts
|
|
48
|
-
* assertNonEmptyArray
|
|
49
|
-
*
|
|
66
|
+
* import { assertNonEmptyArray } from "@evolu/common";
|
|
67
|
+
*
|
|
68
|
+
* const values = [1, 2, 3];
|
|
69
|
+
* assertNonEmptyArray(values);
|
|
70
|
+
* expectTypeOf(values).toEqualTypeOf<[number, ...Array<number>]>();
|
|
71
|
+
* expect(values[0]).toBe(1);
|
|
72
|
+
* expect(() => assertNonEmptyArray([])).toThrow();
|
|
50
73
|
* ```
|
|
51
74
|
*/
|
|
52
75
|
export const assertNonEmptyArray: <T>(
|
|
@@ -69,8 +92,15 @@ export const assertNonEmptyArray: <T>(
|
|
|
69
92
|
* ### Example
|
|
70
93
|
*
|
|
71
94
|
* ```ts
|
|
72
|
-
* assertNonEmptyReadonlyArray
|
|
73
|
-
*
|
|
95
|
+
* import { assertNonEmptyReadonlyArray } from "@evolu/common";
|
|
96
|
+
*
|
|
97
|
+
* const values: ReadonlyArray<number> = [1, 2, 3];
|
|
98
|
+
* assertNonEmptyReadonlyArray(values);
|
|
99
|
+
* expectTypeOf(values).toEqualTypeOf<
|
|
100
|
+
* readonly [number, ...Array<number>]
|
|
101
|
+
* >();
|
|
102
|
+
* expect(values[0]).toBe(1);
|
|
103
|
+
* expect(() => assertNonEmptyReadonlyArray([])).toThrow();
|
|
74
104
|
* ```
|
|
75
105
|
*/
|
|
76
106
|
export const assertNonEmptyReadonlyArray: <T>(
|
|
@@ -83,61 +113,6 @@ export const assertNonEmptyReadonlyArray: <T>(
|
|
|
83
113
|
assert(arr.length > 0, message);
|
|
84
114
|
};
|
|
85
115
|
|
|
86
|
-
/**
|
|
87
|
-
* Ensures a value conforms to a {@link Type}.
|
|
88
|
-
*
|
|
89
|
-
* Uses the Type name for the default error message.
|
|
90
|
-
*
|
|
91
|
-
* ### Example
|
|
92
|
-
*
|
|
93
|
-
* ```ts
|
|
94
|
-
* const length = buffer.getLength();
|
|
95
|
-
*
|
|
96
|
-
* // We know length is logically non-negative, but TypeScript doesn't.
|
|
97
|
-
* assertType(NonNegativeInt, length);
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
|
-
export const assertType: <T extends AnyType>(
|
|
101
|
-
type: T,
|
|
102
|
-
value: unknown,
|
|
103
|
-
message?: string,
|
|
104
|
-
) => asserts value is InferType<T> = (type, value, message) => {
|
|
105
|
-
assert(type.is(value), message ?? `Expected ${type.name}.`);
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Asserts that a {@link Result} did not fail with `AbortError`.
|
|
110
|
-
*
|
|
111
|
-
* Use when abort would indicate a programmer error rather than ordinary control
|
|
112
|
-
* flow.
|
|
113
|
-
*
|
|
114
|
-
* In general, abort is normal control flow. Stopping work and returning
|
|
115
|
-
* `AbortError` is the correct behavior when a `Run` or `Fiber` is cancelled.
|
|
116
|
-
*
|
|
117
|
-
* Use `assertNotAborted` only to protect invariants in code that has already
|
|
118
|
-
* decided abort must not happen, such as resource helpers built on
|
|
119
|
-
* `unabortable`. In those places it helps fail fast on mistakes, because
|
|
120
|
-
* TypeScript cannot fully enforce that lifecycle logic is correct.
|
|
121
|
-
*/
|
|
122
|
-
export function assertNotAborted<T>(
|
|
123
|
-
result: Result<T, AbortError>,
|
|
124
|
-
message?: string,
|
|
125
|
-
): asserts result is Ok<T>;
|
|
126
|
-
export function assertNotAborted<T, E>(
|
|
127
|
-
result: Result<T, E | AbortError>,
|
|
128
|
-
message?: string,
|
|
129
|
-
): asserts result is Result<T, E>;
|
|
130
|
-
export function assertNotAborted<T, E>(
|
|
131
|
-
result: Result<T, E | AbortError>,
|
|
132
|
-
message = "Expected result to not be aborted.",
|
|
133
|
-
): asserts result is Result<T, E> {
|
|
134
|
-
const isAbortError =
|
|
135
|
-
!result.ok &&
|
|
136
|
-
(result.error as { readonly type?: unknown }).type === "AbortError";
|
|
137
|
-
|
|
138
|
-
assert(!isAbortError, message);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
116
|
/**
|
|
142
117
|
* Guards synchronous methods on objects that may be called after disposal.
|
|
143
118
|
*
|
|
@@ -146,14 +121,24 @@ export function assertNotAborted<T, E>(
|
|
|
146
121
|
* ### Example
|
|
147
122
|
*
|
|
148
123
|
* ```ts
|
|
149
|
-
*
|
|
150
|
-
*
|
|
124
|
+
* import { assertNotDisposed } from "@evolu/common";
|
|
125
|
+
*
|
|
126
|
+
* await using disposer = new globalThis.AsyncDisposableStack();
|
|
127
|
+
* expect(() => assertNotDisposed(disposer)).not.toThrow();
|
|
151
128
|
* await disposer.disposeAsync();
|
|
152
|
-
* assertNotDisposed(disposer)
|
|
129
|
+
* expect(() => assertNotDisposed(disposer)).toThrow(
|
|
130
|
+
* "Cannot use a disposed object.",
|
|
131
|
+
* );
|
|
153
132
|
* ```
|
|
133
|
+
*
|
|
134
|
+
* This is the JavaScript equivalent of the .NET `ObjectDisposedException`
|
|
135
|
+
* pattern: once a helper has been disposed, calling its synchronous methods is
|
|
136
|
+
* a programmer error and should throw immediately instead of continuing with
|
|
137
|
+
* invalid state.
|
|
154
138
|
*/
|
|
155
139
|
export const assertNotDisposed = (
|
|
156
|
-
value:
|
|
140
|
+
value:
|
|
141
|
+
DisposableStack | AsyncDisposableStack | { readonly disposed: boolean },
|
|
157
142
|
): void => {
|
|
158
|
-
assert(!value.disposed, "
|
|
143
|
+
assert(!value.disposed, "Cannot use a disposed object.");
|
|
159
144
|
};
|
package/src/BigInt.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { Predicate } from "./Types.
|
|
7
|
+
import type { Predicate } from "./Types.ts";
|
|
8
8
|
|
|
9
9
|
/** Increments a bigint by 1. */
|
|
10
10
|
export const incrementBigInt = (n: bigint): bigint => n + 1n;
|
|
@@ -24,9 +24,12 @@ export const clampBigInt =
|
|
|
24
24
|
* ### Example
|
|
25
25
|
*
|
|
26
26
|
* ```ts
|
|
27
|
+
* import { isBetweenBigInt } from "@evolu/common";
|
|
28
|
+
*
|
|
27
29
|
* const isBetween10And20 = isBetweenBigInt(10n, 20n);
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
+
*
|
|
31
|
+
* expect(isBetween10And20(20n)).toBe(true);
|
|
32
|
+
* expect(isBetween10And20(25n)).toBe(false);
|
|
30
33
|
* ```
|
|
31
34
|
*/
|
|
32
35
|
export const isBetweenBigInt =
|
package/src/Brand.ts
CHANGED
|
@@ -15,57 +15,42 @@
|
|
|
15
15
|
* Avoid primitive types in domain code—brand everything. Evolu Type provides
|
|
16
16
|
* many brand helpers.
|
|
17
17
|
*
|
|
18
|
-
* ### Single
|
|
18
|
+
* ### Single brand
|
|
19
19
|
*
|
|
20
20
|
* ```ts
|
|
21
|
-
*
|
|
22
|
-
* type UserId = number & Brand<"UserId">;
|
|
23
|
-
*
|
|
24
|
-
* // A function that creates `UserId` values.
|
|
25
|
-
* // Casting with `as UserId` is unsafe, so `createUserId` must be unit-tested.
|
|
26
|
-
* const createUserId = (): UserId => {
|
|
27
|
-
* return 123 as UserId; // Unsafe casting
|
|
28
|
-
* };
|
|
21
|
+
* import type { Brand } from "@evolu/common";
|
|
29
22
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* // A function that accepts only `UserId`.
|
|
33
|
-
* const getUser = (id: UserId) => {
|
|
34
|
-
* // Implementation
|
|
35
|
-
* };
|
|
23
|
+
* type UserId = number & Brand<"UserId">;
|
|
36
24
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
25
|
+
* // Branding does not validate at runtime, so isolate the cast in a trusted
|
|
26
|
+
* // factory.
|
|
27
|
+
* const createUserId = (value: number): UserId => value as UserId;
|
|
28
|
+
* const getUser = (id: UserId): number => id;
|
|
29
|
+
* const userId = createUserId(123);
|
|
30
|
+
* expect(getUser(userId)).toBe(123);
|
|
31
|
+
* // @ts-expect-error A plain number is not a UserId.
|
|
32
|
+
* getUser(123);
|
|
40
33
|
* ```
|
|
41
34
|
*
|
|
42
|
-
* ### Multiple
|
|
35
|
+
* ### Multiple brands
|
|
43
36
|
*
|
|
44
37
|
* ```ts
|
|
45
|
-
*
|
|
38
|
+
* import type { Brand } from "@evolu/common";
|
|
39
|
+
*
|
|
46
40
|
* type Min1 = string & Brand<"Min1">;
|
|
47
41
|
* type Max100 = string & Brand<"Max100">;
|
|
48
42
|
* type Min1Max100 = string & Brand<"Min1" | "Max100">;
|
|
49
43
|
*
|
|
50
|
-
*
|
|
51
|
-
* const
|
|
52
|
-
* const requiresMax100 = (value: Max100): void => {};
|
|
53
|
-
*
|
|
54
|
-
* // Values with single brands
|
|
55
|
-
* const min1Value: Min1 = "hello" as Min1;
|
|
56
|
-
* const max100Value: Max100 = "world" as Max100;
|
|
44
|
+
* const requiresMin1 = (value: Min1): string => value;
|
|
45
|
+
* const requiresMax100 = (value: Max100): string => value;
|
|
57
46
|
*
|
|
58
|
-
* // Value with multiple brands
|
|
59
47
|
* const min1Max100Value: Min1Max100 = "typescript" as Min1Max100;
|
|
60
48
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* requiresMax100(max100Value); // Valid
|
|
64
|
-
* requiresMin1(min1Max100Value); // Valid: Min1Max100 satisfies Min1
|
|
65
|
-
* requiresMax100(min1Max100Value); // Valid: Min1Max100 satisfies Max100
|
|
49
|
+
* expect(requiresMin1(min1Max100Value)).toBe("typescript");
|
|
50
|
+
* expect(requiresMax100(min1Max100Value)).toBe("typescript");
|
|
66
51
|
* ```
|
|
67
52
|
*
|
|
68
|
-
* ### Standalone
|
|
53
|
+
* ### Standalone brand
|
|
69
54
|
*
|
|
70
55
|
* Brand can be used alone without a base type for purely nominal typing. This
|
|
71
56
|
* is useful for opaque values where the internal structure is hidden and type
|
|
@@ -74,15 +59,17 @@
|
|
|
74
59
|
* code platform-agnostic.
|
|
75
60
|
*
|
|
76
61
|
* ```ts
|
|
77
|
-
*
|
|
62
|
+
* import type { Brand } from "@evolu/common";
|
|
63
|
+
*
|
|
78
64
|
* type NativePort = Brand<"NativePort">;
|
|
79
65
|
*
|
|
80
|
-
*
|
|
81
|
-
* const requiresNativePort = (port: NativePort): void => {};
|
|
66
|
+
* const requiresNativePort = (port: NativePort): NativePort => port;
|
|
82
67
|
*
|
|
83
|
-
* const
|
|
84
|
-
*
|
|
85
|
-
* requiresNativePort(nativeValue);
|
|
68
|
+
* const nativeValue: unknown = { id: 1 };
|
|
69
|
+
* const port = nativeValue as NativePort;
|
|
70
|
+
* expect(requiresNativePort(port)).toBe(nativeValue);
|
|
71
|
+
* // @ts-expect-error An unknown value is not a NativePort.
|
|
72
|
+
* requiresNativePort(nativeValue);
|
|
86
73
|
* ```
|
|
87
74
|
*/
|
|
88
75
|
export interface Brand<B extends string> {
|
package/src/Buffer.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { Result } from "./Result.
|
|
8
|
-
import { NonNegativeInt, zeroNonNegativeInt } from "./Type.
|
|
7
|
+
import type { Result } from "./Result.ts";
|
|
8
|
+
import { NonNegativeInt, zeroNonNegativeInt } from "./Type.ts";
|
|
9
9
|
export {
|
|
10
10
|
bytesToHex,
|
|
11
11
|
bytesToUtf8,
|
|
@@ -51,18 +51,34 @@ export class BufferError extends Error {
|
|
|
51
51
|
* ### Example
|
|
52
52
|
*
|
|
53
53
|
* ```ts
|
|
54
|
+
* import {
|
|
55
|
+
* createBuffer,
|
|
56
|
+
* createIdFromString,
|
|
57
|
+
* IdBytes,
|
|
58
|
+
* idBytesToId,
|
|
59
|
+
* idBytesTypeValueLength,
|
|
60
|
+
* idToIdBytes,
|
|
61
|
+
* NonNegativeInt,
|
|
62
|
+
* } from "@evolu/common";
|
|
63
|
+
* import {
|
|
64
|
+
* decodeNonNegativeInt,
|
|
65
|
+
* encodeNonNegativeInt,
|
|
66
|
+
* } from "@evolu/common/local-first";
|
|
67
|
+
*
|
|
54
68
|
* const buffer = createBuffer();
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
69
|
+
* const id = createIdFromString("buffer-example");
|
|
70
|
+
* encodeNonNegativeInt(buffer, NonNegativeInt.orThrow(300));
|
|
71
|
+
* buffer.extend(idToIdBytes(id));
|
|
58
72
|
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
73
|
+
* const decoder = createBuffer(buffer.unwrap());
|
|
74
|
+
* expect(decodeNonNegativeInt(decoder)).toBe(300);
|
|
75
|
+
* const decodedId = idBytesToId(
|
|
76
|
+
* IdBytes.orThrow(decoder.shiftN(idBytesTypeValueLength)),
|
|
77
|
+
* );
|
|
78
|
+
* expect(decodedId).toBe(id);
|
|
79
|
+
* expect(() => decodeNonNegativeInt(decoder)).toThrow(
|
|
80
|
+
* "Buffer parse ended prematurely",
|
|
81
|
+
* );
|
|
66
82
|
* ```
|
|
67
83
|
*
|
|
68
84
|
* For more on exponential growth, see:
|
package/src/Cache.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { PositiveInt } from "./Type.
|
|
7
|
+
import { PositiveInt } from "./Type.ts";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Generic cache interface providing basic key-value storage operations.
|
|
@@ -43,11 +43,16 @@ export interface Cache<K, V> {
|
|
|
43
43
|
* ### Example
|
|
44
44
|
*
|
|
45
45
|
* ```ts
|
|
46
|
-
*
|
|
46
|
+
* import { createLruCache, PositiveInt } from "@evolu/common";
|
|
47
|
+
*
|
|
48
|
+
* const cache = createLruCache<string, number>(PositiveInt.orThrow(2));
|
|
47
49
|
* cache.set("a", 1);
|
|
48
50
|
* cache.set("b", 2);
|
|
49
|
-
*
|
|
50
|
-
* cache.
|
|
51
|
+
* // Reading "a" makes "b" the least recently used entry.
|
|
52
|
+
* expect(cache.get("a")).toBe(1);
|
|
53
|
+
* cache.set("c", 3);
|
|
54
|
+
*
|
|
55
|
+
* expect(cache.has("b")).toBe(false);
|
|
51
56
|
* ```
|
|
52
57
|
*/
|
|
53
58
|
export const createLruCache = <K, V>(capacity: PositiveInt): Cache<K, V> => {
|
package/src/Callbacks.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { RandomBytesDep } from "./Crypto.
|
|
8
|
-
import type { Result } from "./Result.
|
|
9
|
-
import { createId, Id } from "./Type.
|
|
10
|
-
import type { Callback } from "./Types.
|
|
7
|
+
import type { RandomBytesDep } from "./Crypto.ts";
|
|
8
|
+
import type { Result } from "./Result.ts";
|
|
9
|
+
import { createId, Id } from "./Type.ts";
|
|
10
|
+
import type { Callback } from "./Types.ts";
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Request-response correlation for callbacks across boundaries.
|
|
@@ -22,27 +22,38 @@ import type { Callback } from "./Types.js";
|
|
|
22
22
|
* The `execute` method intentionally does not use try-catch or {@link Result}
|
|
23
23
|
* because it's the callback's responsibility to handle its own errors.
|
|
24
24
|
*
|
|
25
|
-
* ###
|
|
25
|
+
* ### Correlating callback responses
|
|
26
26
|
*
|
|
27
27
|
* ```ts
|
|
28
|
-
*
|
|
29
|
-
* const callbacks = createCallbacks(deps);
|
|
30
|
-
* const id = callbacks.register(() => console.log("called"));
|
|
31
|
-
* callbacks.execute(id);
|
|
28
|
+
* import { createCallbacks, testCreateDeps } from "@evolu/common";
|
|
32
29
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
30
|
+
* const deps = testCreateDeps();
|
|
31
|
+
*
|
|
32
|
+
* // No-argument callback
|
|
33
|
+
* using callbacks = createCallbacks(deps);
|
|
34
|
+
* let noArgumentCalls = 0;
|
|
35
|
+
* const noArgumentId = callbacks.register(() => {
|
|
36
|
+
* noArgumentCalls++;
|
|
37
|
+
* });
|
|
38
|
+
* callbacks.execute(noArgumentId);
|
|
39
|
+
* callbacks.execute(noArgumentId);
|
|
40
|
+
* expect(noArgumentCalls).toBe(1);
|
|
41
|
+
*
|
|
42
|
+
* // Typed callback
|
|
43
|
+
* using stringCallbacks = createCallbacks<string>(deps);
|
|
44
|
+
* let received = "";
|
|
45
|
+
* const stringCallbackId = stringCallbacks.register((value) => {
|
|
46
|
+
* received = value;
|
|
37
47
|
* });
|
|
38
|
-
* stringCallbacks.execute(
|
|
48
|
+
* stringCallbacks.execute(stringCallbackId, "hello");
|
|
49
|
+
* expect(received).toBe("hello");
|
|
39
50
|
*
|
|
40
|
-
* // Promise.withResolvers
|
|
41
|
-
*
|
|
51
|
+
* // Promise.withResolvers
|
|
52
|
+
* using promiseCallbacks = createCallbacks<string>(deps);
|
|
42
53
|
* const { promise, resolve } = Promise.withResolvers<string>();
|
|
43
|
-
* const
|
|
44
|
-
* promiseCallbacks.execute(
|
|
45
|
-
* await promise
|
|
54
|
+
* const promiseCallbackId = promiseCallbacks.register(resolve);
|
|
55
|
+
* promiseCallbacks.execute(promiseCallbackId, "resolved value");
|
|
56
|
+
* expect(await promise).toBe("resolved value");
|
|
46
57
|
* ```
|
|
47
58
|
*
|
|
48
59
|
* @template T - The type of argument passed to callbacks (defaults to undefined
|