@evolu/common 7.4.1 → 8.0.0-next.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/README.md +4 -61
- package/dist/src/Array.d.ts +343 -102
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +181 -85
- package/dist/src/Assert.d.ts +57 -11
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +47 -11
- package/dist/src/BigInt.d.ts +6 -1
- package/dist/src/BigInt.d.ts.map +1 -1
- package/dist/src/BigInt.js +5 -0
- package/dist/src/Brand.d.ts +40 -12
- package/dist/src/Brand.d.ts.map +1 -1
- package/dist/src/Brand.js +5 -0
- package/dist/src/Buffer.d.ts +6 -1
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Buffer.js +7 -2
- package/dist/src/Cache.d.ts +10 -2
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +6 -0
- package/dist/src/Callbacks.d.ts +10 -7
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Callbacks.js +23 -13
- package/dist/src/Console.d.ts +361 -69
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +217 -117
- package/dist/src/Crypto.d.ts +70 -21
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +72 -27
- package/dist/src/Eq.d.ts +22 -2
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +21 -1
- package/dist/src/Error.d.ts +23 -12
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +27 -11
- package/dist/src/Function.d.ts +128 -56
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +118 -14
- package/dist/src/Identicon.d.ts +5 -0
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +6 -1
- package/dist/src/Lookup.d.ts +160 -0
- package/dist/src/Lookup.d.ts.map +1 -0
- package/dist/src/Lookup.js +192 -0
- package/dist/src/Microtask.d.ts +21 -0
- package/dist/src/Microtask.d.ts.map +1 -0
- package/dist/src/Microtask.js +37 -0
- package/dist/src/Number.d.ts +18 -4
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +23 -1
- package/dist/src/Object.d.ts +110 -5
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +108 -5
- package/dist/src/Option.d.ts +58 -0
- package/dist/src/Option.d.ts.map +1 -0
- package/dist/src/Option.js +43 -0
- package/dist/src/Order.d.ts +5 -0
- package/dist/src/Order.d.ts.map +1 -1
- package/dist/src/Order.js +8 -3
- package/dist/src/Platform.d.ts +36 -2
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +10 -6
- package/dist/src/Polyfills.d.ts +27 -0
- package/dist/src/Polyfills.d.ts.map +1 -0
- package/dist/src/Polyfills.js +299 -0
- package/dist/src/Random.d.ts +18 -7
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +9 -7
- package/dist/src/Redacted.d.ts +7 -4
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +5 -0
- package/dist/src/Ref.d.ts +31 -16
- package/dist/src/Ref.d.ts.map +1 -1
- package/dist/src/Ref.js +35 -7
- package/dist/src/RefCount.d.ts +62 -0
- package/dist/src/RefCount.d.ts.map +1 -0
- package/dist/src/RefCount.js +83 -0
- package/dist/src/Relation.d.ts +84 -29
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Relation.js +83 -105
- package/dist/src/Resource.d.ts +263 -0
- package/dist/src/Resource.d.ts.map +1 -0
- package/dist/src/Resource.js +389 -0
- package/dist/src/Result.d.ts +390 -374
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +142 -70
- package/dist/src/Schedule.d.ts +953 -0
- package/dist/src/Schedule.d.ts.map +1 -0
- package/dist/src/Schedule.js +1199 -0
- package/dist/src/Set.d.ts +181 -0
- package/dist/src/Set.d.ts.map +1 -0
- package/dist/src/Set.js +137 -0
- package/dist/src/Skiplist.d.ts +6 -1
- package/dist/src/Skiplist.d.ts.map +1 -1
- package/dist/src/Skiplist.js +5 -0
- package/dist/src/Sqlite.d.ts +160 -60
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +290 -190
- package/dist/src/Store.d.ts +36 -28
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +55 -15
- package/dist/src/String.d.ts +5 -0
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +5 -0
- package/dist/src/Task.d.ts +2263 -423
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +1488 -348
- package/dist/src/Test.d.ts +122 -0
- package/dist/src/Test.d.ts.map +1 -0
- package/dist/src/Test.js +66 -0
- package/dist/src/Time.d.ts +201 -48
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +190 -86
- package/dist/src/Tracer.d.ts +48 -0
- package/dist/src/Tracer.d.ts.map +1 -0
- package/dist/src/Tracer.js +6 -0
- package/dist/src/Type.d.ts +582 -209
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +362 -240
- package/dist/src/Types.d.ts +160 -6
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +22 -2
- package/dist/src/WebSocket.d.ts +113 -58
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +210 -118
- package/dist/src/Worker.d.ts +245 -60
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +220 -64
- package/dist/src/index.d.ts +25 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +19 -3
- package/dist/src/local-first/Db.d.ts +24 -213
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +622 -293
- package/dist/src/local-first/Error.d.ts +12 -0
- package/dist/src/local-first/Error.d.ts.map +1 -0
- package/dist/src/local-first/Error.js +6 -0
- package/dist/src/local-first/Evolu.d.ts +330 -285
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +472 -402
- package/dist/src/local-first/LocalAuth.d.ts +10 -10
- package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
- package/dist/src/local-first/LocalAuth.js +6 -1
- package/dist/src/local-first/Owner.d.ts +70 -27
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +27 -14
- package/dist/src/local-first/Protocol.d.ts +58 -50
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +253 -155
- package/dist/src/local-first/Query.d.ts +133 -43
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +139 -90
- package/dist/src/local-first/Relay.d.ts +18 -38
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Relay.js +59 -171
- package/dist/src/local-first/Schema.d.ts +139 -144
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +78 -163
- package/dist/src/local-first/Shared.d.ts +125 -0
- package/dist/src/local-first/Shared.d.ts.map +1 -0
- package/dist/src/local-first/Shared.js +569 -0
- package/dist/src/local-first/Storage.d.ts +50 -53
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +121 -173
- package/dist/src/local-first/Timestamp.d.ts +28 -35
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +24 -25
- package/dist/src/local-first/index.d.ts +2 -15
- package/dist/src/local-first/index.d.ts.map +1 -1
- package/dist/src/local-first/index.js +2 -15
- package/package.json +36 -26
- package/src/Array.ts +467 -106
- package/src/Assert.ts +87 -12
- package/src/BigInt.ts +7 -1
- package/src/Brand.ts +41 -12
- package/src/Buffer.ts +10 -4
- package/src/Cache.ts +11 -2
- package/src/Callbacks.ts +33 -23
- package/src/Console.ts +567 -178
- package/src/Crypto.ts +111 -62
- package/src/Eq.ts +30 -3
- package/src/Error.ts +50 -34
- package/src/Function.ts +140 -68
- package/src/Identicon.ts +7 -1
- package/src/Lookup.ts +415 -0
- package/src/Microtask.ts +58 -0
- package/src/Number.ts +40 -7
- package/src/Object.ts +155 -16
- package/src/Option.ts +74 -0
- package/src/Order.ts +11 -3
- package/src/Platform.ts +43 -7
- package/src/Polyfills.ts +465 -0
- package/src/Random.ts +25 -11
- package/src/Redacted.ts +8 -4
- package/src/Ref.ts +72 -21
- package/src/RefCount.ts +170 -0
- package/src/Relation.ts +188 -136
- package/src/Resource.ts +864 -0
- package/src/Result.ts +548 -381
- package/src/Schedule.ts +1471 -0
- package/src/Set.ts +247 -0
- package/src/Skiplist.ts +7 -1
- package/src/Sqlite.ts +409 -304
- package/src/Store.ts +94 -48
- package/src/String.ts +6 -0
- package/src/Task.ts +3685 -740
- package/src/Test.ts +162 -0
- package/src/Time.ts +348 -145
- package/src/Tracer.ts +54 -0
- package/src/Type.ts +851 -430
- package/src/Types.ts +202 -7
- package/src/WebSocket.ts +311 -178
- package/src/Worker.ts +527 -147
- package/src/index.ts +74 -3
- package/src/local-first/Db.ts +871 -597
- package/src/local-first/Error.ts +17 -0
- package/src/local-first/Evolu.ts +884 -824
- package/src/local-first/LocalAuth.ts +10 -10
- package/src/local-first/Owner.ts +94 -42
- package/src/local-first/Protocol.ts +440 -303
- package/src/local-first/Query.ts +243 -194
- package/src/local-first/Relay.ts +91 -252
- package/src/local-first/Schema.ts +284 -394
- package/src/local-first/Shared.ts +932 -0
- package/src/local-first/Storage.ts +206 -277
- package/src/local-first/Timestamp.ts +38 -45
- package/src/local-first/index.ts +2 -16
- package/LICENSE +0 -21
- package/dist/src/Instances.d.ts +0 -34
- package/dist/src/Instances.d.ts.map +0 -1
- package/dist/src/Instances.js +0 -44
- package/dist/src/Resources.d.ts +0 -118
- package/dist/src/Resources.d.ts.map +0 -1
- package/dist/src/Resources.js +0 -197
- package/dist/src/local-first/Platform.d.ts +0 -25
- package/dist/src/local-first/Platform.d.ts.map +0 -1
- package/dist/src/local-first/Platform.js +0 -1
- package/dist/src/local-first/Public.d.ts +0 -22
- package/dist/src/local-first/Public.d.ts.map +0 -1
- package/dist/src/local-first/Public.js +0 -15
- package/dist/src/local-first/PublicKysely.d.ts +0 -148
- package/dist/src/local-first/PublicKysely.d.ts.map +0 -1
- package/dist/src/local-first/PublicKysely.js +0 -184
- package/dist/src/local-first/Sync.d.ts +0 -112
- package/dist/src/local-first/Sync.d.ts.map +0 -1
- package/dist/src/local-first/Sync.js +0 -526
- package/src/Instances.ts +0 -92
- package/src/Resources.ts +0 -367
- package/src/local-first/Platform.ts +0 -27
- package/src/local-first/Public.ts +0 -42
- package/src/local-first/PublicKysely.ts +0 -239
- package/src/local-first/Sync.ts +0 -949
package/src/Object.ts
CHANGED
|
@@ -1,28 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object utilities.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A read-only `Record<K, V>` with `K extends keyof any` to preserve branded key
|
|
9
|
+
* types (e.g., in {@link mapObject}).
|
|
10
|
+
*/
|
|
11
|
+
export type ReadonlyRecord<K extends keyof any, V> = Readonly<Record<K, V>>;
|
|
12
|
+
|
|
1
13
|
/**
|
|
2
14
|
* Checks if a value is a plain object (e.g., created with `{}` or `Object`).
|
|
3
15
|
*
|
|
16
|
+
* Accepts objects with `Object.prototype` and objects with a `null` prototype
|
|
17
|
+
* created via `Object.create(null)`. Rejects class instances and other built-in
|
|
18
|
+
* objects because their prototype chain includes an application-specific or
|
|
19
|
+
* built-in prototype before `Object.prototype`.
|
|
20
|
+
*
|
|
21
|
+
* The prototype-chain check uses structure instead of `prototype ===
|
|
22
|
+
* Object.prototype` so it also works for plain objects coming from another
|
|
23
|
+
* JavaScript realm.
|
|
24
|
+
*
|
|
4
25
|
* ### Example
|
|
5
26
|
*
|
|
6
27
|
* ```ts
|
|
7
28
|
* isPlainObject({}); // true
|
|
29
|
+
* isPlainObject(Object.create(null)); // true
|
|
8
30
|
* isPlainObject(new Date()); // false
|
|
31
|
+
* isPlainObject(new (class Example {})()); // false
|
|
9
32
|
* isPlainObject([]); // false
|
|
10
33
|
* isPlainObject(null); // false
|
|
11
34
|
* ```
|
|
12
35
|
*/
|
|
13
36
|
export const isPlainObject = (
|
|
14
37
|
value: unknown,
|
|
15
|
-
): value is Record<string, unknown> =>
|
|
16
|
-
Object.prototype.toString.call(value)
|
|
38
|
+
): value is Record<string, unknown> => {
|
|
39
|
+
if (Object.prototype.toString.call(value) !== "[object Object]") {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const prototype = Object.getPrototypeOf(value) as object | null;
|
|
44
|
+
return prototype === null || Object.getPrototypeOf(prototype) === null;
|
|
45
|
+
};
|
|
17
46
|
|
|
18
47
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
48
|
+
* Checks if a value is a function.
|
|
49
|
+
*
|
|
50
|
+
* ### Example
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* isFunction(() => {}); // true
|
|
54
|
+
* isFunction(function () {}); // true
|
|
55
|
+
* isFunction({}); // false
|
|
56
|
+
* ```
|
|
21
57
|
*/
|
|
22
|
-
export
|
|
58
|
+
export const isFunction = (value: unknown): value is globalThis.Function =>
|
|
59
|
+
typeof value === "function";
|
|
23
60
|
|
|
24
|
-
|
|
25
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Checks if a value is {@link Iterable}.
|
|
63
|
+
*
|
|
64
|
+
* ### Example
|
|
65
|
+
*
|
|
66
|
+
* ```ts
|
|
67
|
+
* isIterable([1, 2, 3]); // true
|
|
68
|
+
* isIterable("abc"); // true
|
|
69
|
+
* isIterable({}); // false
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export const isIterable = (value: unknown): value is Iterable<unknown> =>
|
|
73
|
+
value != null &&
|
|
74
|
+
typeof (value as Iterable<unknown>)[Symbol.iterator] === "function";
|
|
26
75
|
|
|
27
76
|
/**
|
|
28
77
|
* Like `Object.entries` but preserves branded keys.
|
|
@@ -42,6 +91,51 @@ export const objectToEntries = <T extends Record<string, any>>(
|
|
|
42
91
|
[StringKeyOf<T>, T[StringKeyOf<T>]]
|
|
43
92
|
> as ReadonlyArray<[StringKeyOf<T>, T[StringKeyOf<T>]]>;
|
|
44
93
|
|
|
94
|
+
// A helper type to remove symbol keys (e.g for branded objects).
|
|
95
|
+
type StringKeyOf<T> = Extract<keyof T, string>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Creates an object from key-value pairs, preserving branded key types.
|
|
99
|
+
*
|
|
100
|
+
* The inverse of {@link objectToEntries}. Use when you need type-safe
|
|
101
|
+
* reconstruction of objects with branded keys.
|
|
102
|
+
*
|
|
103
|
+
* ### Example
|
|
104
|
+
*
|
|
105
|
+
* ```ts
|
|
106
|
+
* type UserId = string & { readonly __brand: "UserId" };
|
|
107
|
+
* const entries: ReadonlyArray<[UserId, string]> = [
|
|
108
|
+
* ["u1" as UserId, "Alice"],
|
|
109
|
+
* ];
|
|
110
|
+
* const users = objectFromEntries(entries); // ReadonlyRecord<UserId, string>
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export const objectFromEntries = <K extends string, V>(
|
|
114
|
+
entries: Iterable<readonly [K, V]>,
|
|
115
|
+
): ReadonlyRecord<K, V> => Object.fromEntries(entries) as ReadonlyRecord<K, V>;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Creates an object by mapping keys to values.
|
|
119
|
+
*
|
|
120
|
+
* The inverse of `Object.keys` — instead of extracting keys from an object,
|
|
121
|
+
* builds an object from keys with a mapper function.
|
|
122
|
+
*
|
|
123
|
+
* ### Example
|
|
124
|
+
*
|
|
125
|
+
* ```ts
|
|
126
|
+
* objectFrom(["en", "fr", "de"], loadTranslations);
|
|
127
|
+
* // { en: Translations, fr: Translations, de: Translations }
|
|
128
|
+
*
|
|
129
|
+
* objectFrom(["trace", "debug", "log"], (level) => createHandler(level));
|
|
130
|
+
* // { trace: Handler, debug: Handler, log: Handler }
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
export const objectFrom = <K extends string, V>(
|
|
134
|
+
keys: ReadonlyArray<K>,
|
|
135
|
+
getValue: (key: K) => V,
|
|
136
|
+
): ReadonlyRecord<K, V> =>
|
|
137
|
+
Object.fromEntries(keys.map((k) => [k, getValue(k)])) as ReadonlyRecord<K, V>;
|
|
138
|
+
|
|
45
139
|
/**
|
|
46
140
|
* Maps a `ReadonlyRecord<K, V>` to a new `ReadonlyRecord<K, U>`, preserving
|
|
47
141
|
* branded key types (e.g., `type Id = 'id' & string`) lost by `Object.entries`.
|
|
@@ -50,13 +144,15 @@ export const objectToEntries = <T extends Record<string, any>>(
|
|
|
50
144
|
export const mapObject = <K extends string, V, U>(
|
|
51
145
|
record: ReadonlyRecord<K, V>,
|
|
52
146
|
fn: (value: V, key: K) => U,
|
|
53
|
-
): ReadonlyRecord<K, U> =>
|
|
54
|
-
Object.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
147
|
+
): ReadonlyRecord<K, U> => {
|
|
148
|
+
const out = Object.create(null) as Record<K, U>;
|
|
149
|
+
|
|
150
|
+
for (const key in record) {
|
|
151
|
+
out[key as K] = fn(record[key as K], key as K);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return out as ReadonlyRecord<K, U>;
|
|
155
|
+
};
|
|
60
156
|
|
|
61
157
|
/** Conditionally excludes a property from an object. */
|
|
62
158
|
export const excludeProp = <T extends object, K extends keyof T>(
|
|
@@ -90,6 +186,16 @@ export const createRecord = <K extends string = string, V = unknown>(): Record<
|
|
|
90
186
|
V
|
|
91
187
|
> => Object.create(null) as Record<K, V>;
|
|
92
188
|
|
|
189
|
+
/**
|
|
190
|
+
* An empty readonly record.
|
|
191
|
+
*
|
|
192
|
+
* Use as a default or initial value to avoid allocating new empty records.
|
|
193
|
+
*
|
|
194
|
+
* @group Constants
|
|
195
|
+
*/
|
|
196
|
+
export const emptyRecord: Readonly<Record<string, never>> =
|
|
197
|
+
/*#__PURE__*/ createRecord();
|
|
198
|
+
|
|
93
199
|
/**
|
|
94
200
|
* Safely gets a property from a record, returning `undefined` if the key
|
|
95
201
|
* doesn't exist.
|
|
@@ -107,5 +213,38 @@ export const createRecord = <K extends string = string, V = unknown>(): Record<
|
|
|
107
213
|
*/
|
|
108
214
|
export const getProperty = <K extends string, V>(
|
|
109
215
|
record: ReadonlyRecord<K, V>,
|
|
110
|
-
key:
|
|
111
|
-
): V | undefined => (key in record ? record[key
|
|
216
|
+
key: K,
|
|
217
|
+
): V | undefined => (key in record ? record[key] : undefined);
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* A disposable wrapper around `URL.createObjectURL` that automatically revokes
|
|
221
|
+
* the URL when disposed. Use with the `using` declaration for automatic
|
|
222
|
+
* cleanup.
|
|
223
|
+
*
|
|
224
|
+
* ### Example
|
|
225
|
+
*
|
|
226
|
+
* ```ts
|
|
227
|
+
* const blob = new Blob(["hello"], { type: "text/plain" });
|
|
228
|
+
* using objectUrl = createObjectURL(blob);
|
|
229
|
+
* console.log(objectUrl.url); // blob:...
|
|
230
|
+
* // URL.revokeObjectURL is automatically called when the scope ends
|
|
231
|
+
* ```
|
|
232
|
+
*
|
|
233
|
+
* This ensures the URL is always revoked when the scope ends, even if an error
|
|
234
|
+
* occurs, preventing memory leaks from unreleased blob URLs.
|
|
235
|
+
*/
|
|
236
|
+
export interface ObjectURL extends Disposable {
|
|
237
|
+
/** The object URL string created by `URL.createObjectURL`. */
|
|
238
|
+
readonly url: string;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Creates a disposable {@link ObjectURL} for the given blob. */
|
|
242
|
+
export const createObjectURL = (blob: Blob): ObjectURL => {
|
|
243
|
+
const url = URL.createObjectURL(blob);
|
|
244
|
+
return {
|
|
245
|
+
url,
|
|
246
|
+
[Symbol.dispose]: () => {
|
|
247
|
+
URL.revokeObjectURL(url);
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
};
|
package/src/Option.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional value container.
|
|
3
|
+
*
|
|
4
|
+
* Distinguishes absence from values like `null` or `undefined`.
|
|
5
|
+
*
|
|
6
|
+
* Use Option when the value itself can be `null` or `undefined`. For APIs where
|
|
7
|
+
* `null` means "not found", just use `T | null` directly.
|
|
8
|
+
*
|
|
9
|
+
* ### Example
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* // A cache that can store any value, including null and undefined
|
|
13
|
+
* const cache = new Map<string, Option<unknown>>();
|
|
14
|
+
*
|
|
15
|
+
* const get = (key: string): Option<unknown> => cache.get(key) ?? none;
|
|
16
|
+
*
|
|
17
|
+
* cache.set("a", some(null)); // Stored null
|
|
18
|
+
* cache.set("b", some(undefined)); // Stored undefined
|
|
19
|
+
*
|
|
20
|
+
* isSome(get("a")); // true — value is null
|
|
21
|
+
* isSome(get("b")); // true — value is undefined
|
|
22
|
+
* isNone(get("c")); // true — key doesn't exist
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @module
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/** Optional value. */
|
|
29
|
+
import type { Typed } from "./Type.js";
|
|
30
|
+
|
|
31
|
+
/** Optional value. */
|
|
32
|
+
export type Option<T> = Some<T> | None;
|
|
33
|
+
|
|
34
|
+
/** Present value in an {@link Option}. */
|
|
35
|
+
export interface Some<out T> extends Typed<"Some"> {
|
|
36
|
+
readonly value: T;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Absent value in an {@link Option}. */
|
|
40
|
+
export interface None extends Typed<"None"> {}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Extracts the value type from an {@link Option} or {@link Some}.
|
|
44
|
+
*
|
|
45
|
+
* @group Utilities
|
|
46
|
+
*/
|
|
47
|
+
export type InferOption<O extends Option<any>> =
|
|
48
|
+
O extends Some<infer T> ? T : never;
|
|
49
|
+
|
|
50
|
+
/** Creates a {@link Some}. */
|
|
51
|
+
export const some = <T>(value: T): Option<T> => ({
|
|
52
|
+
type: "Some",
|
|
53
|
+
value,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
/** Shared {@link None} instance. */
|
|
57
|
+
export const none: None = { type: "None" };
|
|
58
|
+
|
|
59
|
+
/** Type guard for {@link Some}. */
|
|
60
|
+
export const isSome = <T>(option: Option<T>): option is Some<T> =>
|
|
61
|
+
option.type === "Some";
|
|
62
|
+
|
|
63
|
+
/** Type guard for {@link None}. */
|
|
64
|
+
export const isNone = <T>(option: Option<T>): option is None =>
|
|
65
|
+
option.type === "None";
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Converts a nullable value to an {@link Option}.
|
|
69
|
+
*
|
|
70
|
+
* `null` and `undefined` become {@link none}.
|
|
71
|
+
*/
|
|
72
|
+
export const fromNullable = <T>(
|
|
73
|
+
value: T | null | undefined,
|
|
74
|
+
): Option<NonNullable<T>> => (value == null ? none : some(value));
|
package/src/Order.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ordering and comparison utilities.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
/**
|
|
2
8
|
* Compares two values of type `A` and returns their ordering.
|
|
3
9
|
*
|
|
@@ -61,7 +67,9 @@ export const reverseOrder =
|
|
|
61
67
|
* ["c", "b", "a"].toSorted(orderString); // ["a", "b", "c"]
|
|
62
68
|
* ```
|
|
63
69
|
*/
|
|
64
|
-
export const orderString: Order<string> = createOrder(
|
|
70
|
+
export const orderString: Order<string> = /*#__PURE__*/ createOrder(
|
|
71
|
+
(a, b) => a < b,
|
|
72
|
+
);
|
|
65
73
|
|
|
66
74
|
/**
|
|
67
75
|
* An order for numbers in ascending order.
|
|
@@ -78,7 +86,7 @@ export const orderString: Order<string> = createOrder((a, b) => a < b);
|
|
|
78
86
|
* reverseOrder(orderNumber)(1, 1); // 0
|
|
79
87
|
* ```
|
|
80
88
|
*/
|
|
81
|
-
export const orderNumber = createOrder<number>((a, b) => a < b);
|
|
89
|
+
export const orderNumber = /*#__PURE__*/ createOrder<number>((a, b) => a < b);
|
|
82
90
|
|
|
83
91
|
/**
|
|
84
92
|
* An order for bigints in ascending order.
|
|
@@ -92,7 +100,7 @@ export const orderNumber = createOrder<number>((a, b) => a < b);
|
|
|
92
100
|
* [2n, 1n, 3n].toSorted(orderBigInt); // [1n, 2n, 3n]
|
|
93
101
|
* ```
|
|
94
102
|
*/
|
|
95
|
-
export const orderBigInt = createOrder<bigint>((a, b) => a < b);
|
|
103
|
+
export const orderBigInt = /*#__PURE__*/ createOrder<bigint>((a, b) => a < b);
|
|
96
104
|
|
|
97
105
|
/** An {@link Order} for Uint8Array. */
|
|
98
106
|
export const orderUint8Array: Order<Uint8Array> = (a, b) => {
|
package/src/Platform.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Platform runtime utilities and capability abstractions.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** Returns true if running in React Native with Hermes engine. */
|
|
8
|
+
export const isHermes = "HermesInternal" in globalThis;
|
|
9
|
+
|
|
10
|
+
/** Returns true if running in a server environment (no DOM). */
|
|
11
|
+
export const isServer = typeof document === "undefined";
|
|
7
12
|
|
|
8
13
|
/**
|
|
9
14
|
* Detects if Node.js Buffer is available and should be used.
|
|
@@ -17,4 +22,35 @@ export const isReactNative =
|
|
|
17
22
|
* @see https://github.com/craftzdog/react-native-quick-base64#installation
|
|
18
23
|
*/
|
|
19
24
|
export const hasNodeBuffer =
|
|
20
|
-
!
|
|
25
|
+
!isHermes && typeof globalThis.Buffer !== "undefined";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* FlushSync is for libraries like React to flush updates synchronously inside
|
|
29
|
+
* the provided callback to ensure the DOM is updated immediately.
|
|
30
|
+
*
|
|
31
|
+
* For example, with React, when we want to focus on an element rendered as a
|
|
32
|
+
* result of a mutation, Evolu ensures all DOM changes are flushed synchronously
|
|
33
|
+
* if an onComplete callback is used.
|
|
34
|
+
*
|
|
35
|
+
* https://react.dev/reference/react-dom/flushSync
|
|
36
|
+
*/
|
|
37
|
+
export type FlushSync = (callback: () => void) => void;
|
|
38
|
+
|
|
39
|
+
export interface FlushSyncDep {
|
|
40
|
+
readonly flushSync: FlushSync;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Reload the app in a platform-specific way.
|
|
45
|
+
*
|
|
46
|
+
* Use this after purging persistent storage to clear in-memory state and ensure
|
|
47
|
+
* the app starts fresh. It does not purge storage itself.
|
|
48
|
+
*
|
|
49
|
+
* - Web: Redirects to the specified URL (defaults to `/`)
|
|
50
|
+
* - React Native: Restarts the app (URL ignored)
|
|
51
|
+
*/
|
|
52
|
+
export type ReloadApp = (url?: string) => void;
|
|
53
|
+
|
|
54
|
+
export interface ReloadAppDep {
|
|
55
|
+
readonly reloadApp: ReloadApp;
|
|
56
|
+
}
|