@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/src/local-first/Owner.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ## Intro
|
|
3
|
-
*
|
|
4
2
|
* Cryptographic identities that define ownership, encryption, sync, and
|
|
5
3
|
* deletion boundaries for Evolu data.
|
|
6
4
|
*
|
|
@@ -11,15 +9,15 @@
|
|
|
11
9
|
*
|
|
12
10
|
* Individual changes in an append-only local-first history can only be marked
|
|
13
11
|
* as deleted. An entire owner, however, can be removed from devices and relays
|
|
14
|
-
* together with all of its data. The AppOwner must remain because it
|
|
15
|
-
* the deletion of other owners across devices.
|
|
12
|
+
* together with all of its data. The AppOwner must remain because it
|
|
13
|
+
* coordinates the deletion of other owners across devices.
|
|
16
14
|
*
|
|
17
15
|
* Choose an owner by how its data should live and be shared:
|
|
18
16
|
*
|
|
19
17
|
* - {@link AppOwner} coordinates sync and persists for the lifetime of the app
|
|
20
18
|
* identity.
|
|
21
|
-
* - {@link ShardOwner} partitions application data so it can be synced and
|
|
22
|
-
*
|
|
19
|
+
* - {@link ShardOwner} partitions application data so it can be synced and deleted
|
|
20
|
+
* independently.
|
|
23
21
|
* - {@link SharedOwner} grants collaborative read and write access.
|
|
24
22
|
* - {@link SharedReadonlyOwner} grants read-only access to shared data.
|
|
25
23
|
*
|
|
@@ -62,8 +60,8 @@ import { TimestampBytes } from "./Timestamp.ts";
|
|
|
62
60
|
/**
|
|
63
61
|
* {@link Owner} without a {@link OwnerWriteKey}.
|
|
64
62
|
*
|
|
65
|
-
* @see {@link createSharedReadonlyOwner}
|
|
66
63
|
* @group Core
|
|
64
|
+
* @see {@link createSharedReadonlyOwner}
|
|
67
65
|
*/
|
|
68
66
|
export interface ReadonlyOwner {
|
|
69
67
|
readonly id: OwnerId;
|
|
@@ -427,9 +425,9 @@ export type OwnerTransport = OwnerWebSocketTransport;
|
|
|
427
425
|
* Legitimate clients will be properly configured with valid credentials, so
|
|
428
426
|
* automatic retry is OK.
|
|
429
427
|
*
|
|
428
|
+
* @group Transport
|
|
430
429
|
* @see {@link createOwnerWebSocketTransport}
|
|
431
430
|
* @see {@link parseOwnerIdFromOwnerWebSocketTransportUrl}
|
|
432
|
-
* @group Transport
|
|
433
431
|
*/
|
|
434
432
|
export interface OwnerWebSocketTransport extends Typed<"WebSocket"> {
|
|
435
433
|
readonly url: string;
|
|
@@ -448,6 +446,8 @@ export interface OwnerWebSocketTransport extends Typed<"WebSocket"> {
|
|
|
448
446
|
* ```ts
|
|
449
447
|
* import {
|
|
450
448
|
* AppName,
|
|
449
|
+
* assertEqual,
|
|
450
|
+
* assertTrue,
|
|
451
451
|
* createAppOwner,
|
|
452
452
|
* createEvolu,
|
|
453
453
|
* createOwnerWebSocketTransport,
|
|
@@ -473,8 +473,8 @@ export interface OwnerWebSocketTransport extends Typed<"WebSocket"> {
|
|
|
473
473
|
* },
|
|
474
474
|
* );
|
|
475
475
|
*
|
|
476
|
-
*
|
|
477
|
-
*
|
|
476
|
+
* assertTrue(typeof createTodoEvolu === "function");
|
|
477
|
+
* assertEqual(transport, {
|
|
478
478
|
* type: "WebSocket",
|
|
479
479
|
* url: `wss://relay.evolu.dev?ownerId=${appOwner.id}`,
|
|
480
480
|
* });
|
|
@@ -501,6 +501,7 @@ export const createOwnerWebSocketTransport = (config: {
|
|
|
501
501
|
*
|
|
502
502
|
* ```ts
|
|
503
503
|
* import {
|
|
504
|
+
* assertEqual,
|
|
504
505
|
* createAppOwner,
|
|
505
506
|
* createOwnerSecret,
|
|
506
507
|
* createRandomBytes,
|
|
@@ -513,12 +514,14 @@ export const createOwnerWebSocketTransport = (config: {
|
|
|
513
514
|
* );
|
|
514
515
|
* const url = `/sync?ownerId=${appOwner.id}`;
|
|
515
516
|
*
|
|
516
|
-
*
|
|
517
|
+
* assertEqual(
|
|
518
|
+
* parseOwnerIdFromOwnerWebSocketTransportUrl(url),
|
|
517
519
|
* appOwner.id,
|
|
518
520
|
* );
|
|
519
|
-
*
|
|
521
|
+
* assertEqual(
|
|
520
522
|
* parseOwnerIdFromOwnerWebSocketTransportUrl("/sync?ownerId=invalid"),
|
|
521
|
-
*
|
|
523
|
+
* null,
|
|
524
|
+
* );
|
|
522
525
|
* ```
|
|
523
526
|
*
|
|
524
527
|
* @group Transport
|
|
@@ -553,7 +556,8 @@ export interface OwnerUsage {
|
|
|
553
556
|
*
|
|
554
557
|
* Measures only {@link EncryptedDbChange} data and excludes {@link Storage}
|
|
555
558
|
* implementation overhead such as indexes and skip-list columns. This makes
|
|
556
|
-
* the measurement consistent across storage implementations and suitable
|
|
559
|
+
* the measurement consistent across storage implementations and suitable
|
|
560
|
+
* for:
|
|
557
561
|
*
|
|
558
562
|
* - **Predictable measurement** - same data = same byte count across all
|
|
559
563
|
* instances
|
|
@@ -178,7 +178,11 @@
|
|
|
178
178
|
*/
|
|
179
179
|
|
|
180
180
|
import { Packr } from "msgpackr";
|
|
181
|
-
import {
|
|
181
|
+
import {
|
|
182
|
+
createMutableArray,
|
|
183
|
+
isNonEmptyArray,
|
|
184
|
+
type NonEmptyReadonlyArray,
|
|
185
|
+
} from "../Array.ts";
|
|
182
186
|
import { assert, assertNonNullable } from "../Assert.ts";
|
|
183
187
|
import type { Brand } from "../Brand.ts";
|
|
184
188
|
import {
|
|
@@ -692,11 +696,16 @@ export const createProtocolMessageBuffer = (
|
|
|
692
696
|
* approach, contributions are welcome.
|
|
693
697
|
*/
|
|
694
698
|
const safeMargins = {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
699
|
+
// bytes: range type + possible increased count varint
|
|
700
|
+
remainingRange: fingerprintSize + 10,
|
|
701
|
+
// bytes: max millis + max count + NodeId
|
|
702
|
+
timestamp: 30,
|
|
703
|
+
// bytes: maximum encoded DbChange length varint
|
|
704
|
+
dbChangeLength: 8,
|
|
705
|
+
// bytes: worst case is around 650 bytes
|
|
706
|
+
splitRange: 800,
|
|
707
|
+
// bytes: range type + its upperBound + possible increased count varint
|
|
708
|
+
timestampsRange: 50,
|
|
700
709
|
};
|
|
701
710
|
|
|
702
711
|
const addMessageSafeMargin =
|
|
@@ -972,7 +981,7 @@ export const applyProtocolMessageAsClient =
|
|
|
972
981
|
);
|
|
973
982
|
|
|
974
983
|
if (messageType === MessageType.Response) {
|
|
975
|
-
const errorCode = input.shift()
|
|
984
|
+
const errorCode = input.shift();
|
|
976
985
|
if (errorCode !== ProtocolErrorCode.NoError) {
|
|
977
986
|
switch (errorCode) {
|
|
978
987
|
case ProtocolErrorCode.WriteKeyError:
|
|
@@ -1318,7 +1327,7 @@ const decodeMessages = (
|
|
|
1318
1327
|
): ReadonlyArray<EncryptedCrdtMessage> => {
|
|
1319
1328
|
const timestamps = decodeTimestamps(buffer);
|
|
1320
1329
|
|
|
1321
|
-
const messages =
|
|
1330
|
+
const messages = createMutableArray<EncryptedCrdtMessage>(timestamps.length);
|
|
1322
1331
|
for (let i = 0; i < timestamps.length; i++) {
|
|
1323
1332
|
const timestamp = timestamps[i];
|
|
1324
1333
|
const changeLength = decodeLength(buffer);
|
|
@@ -1441,21 +1450,19 @@ const sync =
|
|
|
1441
1450
|
|
|
1442
1451
|
if (eqArrayNumber(range.fingerprint, ourFingerprint)) {
|
|
1443
1452
|
skipRange(range);
|
|
1453
|
+
} else if (output.canSplitRange()) {
|
|
1454
|
+
coalesceSkipsBeforeAdd();
|
|
1455
|
+
splitRange(deps)(
|
|
1456
|
+
ownerIdBytes,
|
|
1457
|
+
lower,
|
|
1458
|
+
upper,
|
|
1459
|
+
currentUpperBound,
|
|
1460
|
+
output,
|
|
1461
|
+
);
|
|
1444
1462
|
} else {
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
ownerIdBytes,
|
|
1449
|
-
lower,
|
|
1450
|
-
upper,
|
|
1451
|
-
currentUpperBound,
|
|
1452
|
-
output,
|
|
1453
|
-
);
|
|
1454
|
-
} else {
|
|
1455
|
-
return addFingerprintForRemainingRange(upper)
|
|
1456
|
-
? ok(true)
|
|
1457
|
-
: err(ProtocolErrorCode.SyncError);
|
|
1458
|
-
}
|
|
1463
|
+
return addFingerprintForRemainingRange(upper)
|
|
1464
|
+
? ok(true)
|
|
1465
|
+
: err(ProtocolErrorCode.SyncError);
|
|
1459
1466
|
}
|
|
1460
1467
|
break;
|
|
1461
1468
|
}
|
|
@@ -1635,7 +1642,7 @@ const decodeRanges = (buffer: Buffer): ReadonlyArray<Range> => {
|
|
|
1635
1642
|
const timestampsCount = NonNegativeInt.orThrow(rangesCount - 1);
|
|
1636
1643
|
const timestamps = decodeTimestamps(buffer, timestampsCount);
|
|
1637
1644
|
|
|
1638
|
-
const rangeTypes =
|
|
1645
|
+
const rangeTypes = createMutableArray<RangeType>(rangesCount);
|
|
1639
1646
|
|
|
1640
1647
|
for (let i = 0; i < rangesCount; i++) {
|
|
1641
1648
|
const rangeType = decodeNonNegativeInt(buffer);
|
|
@@ -1650,7 +1657,7 @@ const decodeRanges = (buffer: Buffer): ReadonlyArray<Range> => {
|
|
|
1650
1657
|
}
|
|
1651
1658
|
}
|
|
1652
1659
|
|
|
1653
|
-
const ranges =
|
|
1660
|
+
const ranges = createMutableArray<Range>(rangesCount);
|
|
1654
1661
|
|
|
1655
1662
|
for (let i = 0; i < rangesCount; i++) {
|
|
1656
1663
|
const upperBound =
|
|
@@ -1700,7 +1707,7 @@ const decodeTimestamps = (
|
|
|
1700
1707
|
|
|
1701
1708
|
let previousMillis = 0 as Millis;
|
|
1702
1709
|
|
|
1703
|
-
const millises =
|
|
1710
|
+
const millises = createMutableArray<Millis>(length);
|
|
1704
1711
|
for (let i = 0; i < length; i++) {
|
|
1705
1712
|
const deltaMillis = decodeNonNegativeInt(buffer);
|
|
1706
1713
|
const millis = Millis.fromUnknown(previousMillis + deltaMillis);
|
|
@@ -1717,7 +1724,7 @@ const decodeTimestamps = (
|
|
|
1717
1724
|
|
|
1718
1725
|
const nodeIds = decodeRle(buffer, length, (): NodeId => decodeNodeId(buffer));
|
|
1719
1726
|
|
|
1720
|
-
const timestamps =
|
|
1727
|
+
const timestamps = createMutableArray<Timestamp>(length);
|
|
1721
1728
|
for (let i = 0; i < length; i++) {
|
|
1722
1729
|
timestamps[i] = {
|
|
1723
1730
|
millis: millises[i],
|
|
@@ -1734,7 +1741,7 @@ export const decodeRle = <T>(
|
|
|
1734
1741
|
length: NonNegativeInt,
|
|
1735
1742
|
decodeValue: () => T,
|
|
1736
1743
|
): ReadonlyArray<T> => {
|
|
1737
|
-
const values =
|
|
1744
|
+
const values = createMutableArray<T>(length);
|
|
1738
1745
|
let index = 0;
|
|
1739
1746
|
while (index < length) {
|
|
1740
1747
|
const value = decodeValue();
|
|
@@ -1807,13 +1814,13 @@ export const decodeNumber = (buffer: Buffer): number => {
|
|
|
1807
1814
|
* ### Example
|
|
1808
1815
|
*
|
|
1809
1816
|
* ```ts
|
|
1810
|
-
* import { createBuffer } from "@evolu/common";
|
|
1817
|
+
* import { assertEqual, createBuffer } from "@evolu/common";
|
|
1811
1818
|
* import { encodeFlags } from "@evolu/common/local-first";
|
|
1812
1819
|
*
|
|
1813
1820
|
* const buffer = createBuffer();
|
|
1814
1821
|
* encodeFlags(buffer, [true, false, true]);
|
|
1815
1822
|
*
|
|
1816
|
-
*
|
|
1823
|
+
* assertEqual(buffer.unwrap(), new Uint8Array([0b101]));
|
|
1817
1824
|
* ```
|
|
1818
1825
|
*/
|
|
1819
1826
|
export const encodeFlags = (
|
|
@@ -1835,14 +1842,14 @@ export const encodeFlags = (
|
|
|
1835
1842
|
* ### Example
|
|
1836
1843
|
*
|
|
1837
1844
|
* ```ts
|
|
1838
|
-
* import { createBuffer, PositiveInt } from "@evolu/common";
|
|
1845
|
+
* import { assertEqual, createBuffer, PositiveInt } from "@evolu/common";
|
|
1839
1846
|
* import { decodeFlags } from "@evolu/common/local-first";
|
|
1840
1847
|
*
|
|
1841
1848
|
* const buffer = createBuffer([0b101]);
|
|
1842
1849
|
* const flags = decodeFlags(buffer, PositiveInt.orThrow(3));
|
|
1843
1850
|
*
|
|
1844
|
-
*
|
|
1845
|
-
*
|
|
1851
|
+
* assertEqual(flags, [true, false, true]);
|
|
1852
|
+
* assertEqual(buffer.getLength(), 0);
|
|
1846
1853
|
* ```
|
|
1847
1854
|
*/
|
|
1848
1855
|
export const decodeFlags = (
|
|
@@ -1851,7 +1858,7 @@ export const decodeFlags = (
|
|
|
1851
1858
|
): ReadonlyArray<boolean> => {
|
|
1852
1859
|
const byte = buffer.shift();
|
|
1853
1860
|
const length = globalThis.Math.min(count, 8);
|
|
1854
|
-
const flags =
|
|
1861
|
+
const flags = createMutableArray<boolean>(length);
|
|
1855
1862
|
for (let i = 0; i < length; i++) {
|
|
1856
1863
|
flags[i] = (byte & (1 << i)) !== 0;
|
|
1857
1864
|
}
|
|
@@ -2088,7 +2095,8 @@ export const ProtocolValueType = {
|
|
|
2088
2095
|
NonNegativeInt: /*#__PURE__*/ NonNegativeInt.orThrow(30),
|
|
2089
2096
|
|
|
2090
2097
|
// String optimizations
|
|
2091
|
-
|
|
2098
|
+
// 1 byte vs 2 bytes (50% reduction)
|
|
2099
|
+
EmptyString: /*#__PURE__*/ NonNegativeInt.orThrow(31),
|
|
2092
2100
|
Base64Url: /*#__PURE__*/ NonNegativeInt.orThrow(32),
|
|
2093
2101
|
Id: /*#__PURE__*/ NonNegativeInt.orThrow(33),
|
|
2094
2102
|
Json: /*#__PURE__*/ NonNegativeInt.orThrow(34),
|
|
@@ -2097,7 +2105,8 @@ export const ProtocolValueType = {
|
|
|
2097
2105
|
// encoded with fixed length - 8 bytes
|
|
2098
2106
|
// encode as NonNegativeInt - 6 bytes (additional 25% reduction)
|
|
2099
2107
|
DateIsoWithNonNegativeTime: /*#__PURE__*/ NonNegativeInt.orThrow(35),
|
|
2100
|
-
|
|
2108
|
+
// 9 bytes
|
|
2109
|
+
DateIsoWithNegativeTime: /*#__PURE__*/ NonNegativeInt.orThrow(36),
|
|
2101
2110
|
|
|
2102
2111
|
// TODO: Operations (from 40)
|
|
2103
2112
|
// Increment, Decrement, Patch, whatever.
|
|
@@ -2109,6 +2118,7 @@ export const encodeSqliteValue = (buffer: Buffer, value: SqliteValue): void => {
|
|
|
2109
2118
|
return;
|
|
2110
2119
|
}
|
|
2111
2120
|
|
|
2121
|
+
// oxlint-disable-next-line typescript/switch-exhaustiveness-check -- The remaining SqliteValue is Uint8Array and is encoded after the switch.
|
|
2112
2122
|
switch (typeof value) {
|
|
2113
2123
|
case "string": {
|
|
2114
2124
|
if (value === "") {
|
package/src/local-first/Query.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
TableNode,
|
|
22
22
|
ValueNode,
|
|
23
23
|
} from "kysely";
|
|
24
|
+
import { createMutableArray } from "../Array.ts";
|
|
24
25
|
import type { Brand } from "../Brand.ts";
|
|
25
26
|
import { createRandomBytes } from "../Crypto.ts";
|
|
26
27
|
import type { ReadonlyRecord } from "../Object.ts";
|
|
@@ -40,6 +41,7 @@ export type { NotNull as KyselyNotNull } from "kysely";
|
|
|
40
41
|
*
|
|
41
42
|
* ```ts
|
|
42
43
|
* import {
|
|
44
|
+
* assertType,
|
|
43
45
|
* createQueryBuilder,
|
|
44
46
|
* id,
|
|
45
47
|
* NonEmptyTrimmedString100,
|
|
@@ -55,11 +57,12 @@ export type { NotNull as KyselyNotNull } from "kysely";
|
|
|
55
57
|
* const allTodos = createQuery((db) => db.selectFrom("todo").selectAll());
|
|
56
58
|
*
|
|
57
59
|
* type AllTodosRow = typeof allTodos.Row;
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
60
|
+
* assertType<
|
|
61
|
+
* true,
|
|
62
|
+
* typeof allTodos extends Query<typeof Schema> ? true : false
|
|
63
|
+
* >();
|
|
64
|
+
* assertType<TodoId, AllTodosRow["id"]>();
|
|
65
|
+
* assertType<NonEmptyTrimmedString100 | null, AllTodosRow["title"]>();
|
|
63
66
|
* ```
|
|
64
67
|
*/
|
|
65
68
|
export type Query<
|
|
@@ -77,6 +80,7 @@ export type Query<
|
|
|
77
80
|
*
|
|
78
81
|
* ```ts
|
|
79
82
|
* import {
|
|
83
|
+
* assertType,
|
|
80
84
|
* createQueryBuilder,
|
|
81
85
|
* id,
|
|
82
86
|
* type InferRow,
|
|
@@ -92,9 +96,7 @@ export type Query<
|
|
|
92
96
|
* );
|
|
93
97
|
*
|
|
94
98
|
* type AllTodosRow = typeof allTodos.Row;
|
|
95
|
-
*
|
|
96
|
-
* InferRow<typeof allTodos>
|
|
97
|
-
* >();
|
|
99
|
+
* assertType<InferRow<typeof allTodos>, AllTodosRow>();
|
|
98
100
|
* ```
|
|
99
101
|
*/
|
|
100
102
|
Row: R;
|
|
@@ -106,8 +108,10 @@ export type InferRow<T extends Query> =
|
|
|
106
108
|
export interface Row {
|
|
107
109
|
readonly [key: string]:
|
|
108
110
|
| SqliteValue
|
|
109
|
-
|
|
110
|
-
|
|
|
111
|
+
// for evoluJsonObjectFrom
|
|
112
|
+
| Row
|
|
113
|
+
// for evoluJsonArrayFrom
|
|
114
|
+
| ReadonlyArray<Row>;
|
|
111
115
|
}
|
|
112
116
|
|
|
113
117
|
/**
|
|
@@ -123,6 +127,7 @@ export interface Row {
|
|
|
123
127
|
*
|
|
124
128
|
* ```ts
|
|
125
129
|
* import {
|
|
130
|
+
* assertType,
|
|
126
131
|
* createQueryBuilder,
|
|
127
132
|
* evoluJsonArrayFrom,
|
|
128
133
|
* id,
|
|
@@ -154,10 +159,13 @@ export interface Row {
|
|
|
154
159
|
* ]),
|
|
155
160
|
* );
|
|
156
161
|
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
162
|
+
* assertType<
|
|
163
|
+
* {
|
|
164
|
+
* petId: typeof Schema.pet.id.Output;
|
|
165
|
+
* name: NonEmptyTrimmedString100 | null;
|
|
166
|
+
* },
|
|
167
|
+
* (typeof people.Row.pets)[number]
|
|
168
|
+
* >();
|
|
161
169
|
* ```
|
|
162
170
|
*/
|
|
163
171
|
export const evoluJsonArrayFrom = <O>(
|
|
@@ -182,6 +190,7 @@ export const evoluJsonArrayFrom = <O>(
|
|
|
182
190
|
*
|
|
183
191
|
* ```ts
|
|
184
192
|
* import {
|
|
193
|
+
* assertType,
|
|
185
194
|
* createQueryBuilder,
|
|
186
195
|
* evoluJsonObjectFrom,
|
|
187
196
|
* id,
|
|
@@ -215,10 +224,13 @@ export const evoluJsonArrayFrom = <O>(
|
|
|
215
224
|
* ]),
|
|
216
225
|
* );
|
|
217
226
|
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
227
|
+
* assertType<
|
|
228
|
+
* {
|
|
229
|
+
* petId: typeof Schema.pet.id.Output;
|
|
230
|
+
* name: NonEmptyTrimmedString100 | null;
|
|
231
|
+
* } | null,
|
|
232
|
+
* typeof people.Row.favoritePet
|
|
233
|
+
* >();
|
|
222
234
|
* ```
|
|
223
235
|
*/
|
|
224
236
|
export const evoluJsonObjectFrom = <O>(
|
|
@@ -241,6 +253,7 @@ export const evoluJsonObjectFrom = <O>(
|
|
|
241
253
|
*
|
|
242
254
|
* ```ts
|
|
243
255
|
* import {
|
|
256
|
+
* assertType,
|
|
244
257
|
* createQueryBuilder,
|
|
245
258
|
* evoluJsonBuildObject,
|
|
246
259
|
* id,
|
|
@@ -271,11 +284,14 @@ export const evoluJsonObjectFrom = <O>(
|
|
|
271
284
|
* ]),
|
|
272
285
|
* );
|
|
273
286
|
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
287
|
+
* assertType<
|
|
288
|
+
* {
|
|
289
|
+
* first: NonEmptyTrimmedString100 | null;
|
|
290
|
+
* last: NonEmptyTrimmedString100 | null;
|
|
291
|
+
* full: string;
|
|
292
|
+
* },
|
|
293
|
+
* typeof people.Row.name
|
|
294
|
+
* >();
|
|
279
295
|
* ```
|
|
280
296
|
*/
|
|
281
297
|
export const evoluJsonBuildObject = <
|
|
@@ -455,7 +471,7 @@ const getSqliteJsonObjectArgs = (
|
|
|
455
471
|
export const parseSqliteJsonArray = <T>(
|
|
456
472
|
arr: ReadonlyArray<T>,
|
|
457
473
|
): ReadonlyArray<T> => {
|
|
458
|
-
const result =
|
|
474
|
+
const result = createMutableArray<T>(arr.length);
|
|
459
475
|
for (let i = 0; i < arr.length; ++i) {
|
|
460
476
|
result[i] = parse(arr[i]) as T;
|
|
461
477
|
}
|
package/src/local-first/Relay.ts
CHANGED
|
@@ -79,6 +79,9 @@ export interface RelayConfig extends StorageConfig {
|
|
|
79
79
|
* ```ts
|
|
80
80
|
* import {
|
|
81
81
|
* AppName,
|
|
82
|
+
* assertEqual,
|
|
83
|
+
* assertTrue,
|
|
84
|
+
* assertType,
|
|
82
85
|
* createAppOwner,
|
|
83
86
|
* createEvolu,
|
|
84
87
|
* createOwnerWebSocketTransport,
|
|
@@ -107,7 +110,10 @@ export interface RelayConfig extends StorageConfig {
|
|
|
107
110
|
* transports: [transport],
|
|
108
111
|
* },
|
|
109
112
|
* );
|
|
110
|
-
*
|
|
113
|
+
* assertType<
|
|
114
|
+
* true,
|
|
115
|
+
* typeof createTodoEvolu extends AnyTask ? true : false
|
|
116
|
+
* >();
|
|
111
117
|
*
|
|
112
118
|
* // Relay: accept owners allowed by the app's access policy.
|
|
113
119
|
* type IsOwnerAllowed = NonNullable<RelayConfig["isOwnerAllowed"]>;
|
|
@@ -115,12 +121,13 @@ export interface RelayConfig extends StorageConfig {
|
|
|
115
121
|
* const isOwnerAllowed: IsOwnerAllowed = (ownerId, { signal }) =>
|
|
116
122
|
* !signal.aborted && allowedOwnerIds.has(ownerId);
|
|
117
123
|
*
|
|
118
|
-
*
|
|
119
|
-
* isOwnerAllowed(appOwner.id, {
|
|
124
|
+
* assertEqual(
|
|
125
|
+
* await isOwnerAllowed(appOwner.id, {
|
|
120
126
|
* signal: new AbortController().signal,
|
|
121
127
|
* }),
|
|
122
|
-
*
|
|
123
|
-
*
|
|
128
|
+
* true,
|
|
129
|
+
* );
|
|
130
|
+
* assertTrue(transport.url.includes(`ownerId=${appOwner.id}`));
|
|
124
131
|
* ```
|
|
125
132
|
*/
|
|
126
133
|
readonly isOwnerAllowed?: (
|
|
@@ -305,7 +312,7 @@ export const createRelaySqliteStorage =
|
|
|
305
312
|
where "ownerId" = ${ownerId} and "timestamp" = ${timestamp};
|
|
306
313
|
`);
|
|
307
314
|
|
|
308
|
-
const row = result.rows
|
|
315
|
+
const row = result.rows.at(0);
|
|
309
316
|
assert(row, "Every timestamp must have a change");
|
|
310
317
|
return row.change;
|
|
311
318
|
},
|
|
@@ -62,6 +62,8 @@ export type AnyStandardSchemaV1 = StandardSchemaV1<any, any>;
|
|
|
62
62
|
* ```ts
|
|
63
63
|
* import * as z from "zod";
|
|
64
64
|
* import {
|
|
65
|
+
* assertOk,
|
|
66
|
+
* assertTrue,
|
|
65
67
|
* id,
|
|
66
68
|
* NonEmptyTrimmedString100,
|
|
67
69
|
* nullOr,
|
|
@@ -79,7 +81,7 @@ export type AnyStandardSchemaV1 = StandardSchemaV1<any, any>;
|
|
|
79
81
|
* isCompleted: nullOr(SqliteBoolean),
|
|
80
82
|
* },
|
|
81
83
|
* };
|
|
82
|
-
*
|
|
84
|
+
* assertOk(Schema.todo.title.fromUnknown("Write docs"), "Write docs");
|
|
83
85
|
*
|
|
84
86
|
* // Zod, or another Standard Schema library
|
|
85
87
|
* const ZodSchema = {
|
|
@@ -89,7 +91,7 @@ export type AnyStandardSchemaV1 = StandardSchemaV1<any, any>;
|
|
|
89
91
|
* isCompleted: z.union([z.literal(0), z.literal(1)]).nullable(),
|
|
90
92
|
* },
|
|
91
93
|
* };
|
|
92
|
-
*
|
|
94
|
+
* assertTrue(ZodSchema.todo.title.safeParse("Write docs").success);
|
|
93
95
|
* ```
|
|
94
96
|
*/
|
|
95
97
|
export type EvoluSchema = ReadonlyRecord<
|
|
@@ -238,6 +240,7 @@ export interface MutationOptions {
|
|
|
238
240
|
*
|
|
239
241
|
* ```ts
|
|
240
242
|
* import {
|
|
243
|
+
* assertEqual,
|
|
241
244
|
* createAppOwner,
|
|
242
245
|
* createOwnerSecret,
|
|
243
246
|
* createRandomBytes,
|
|
@@ -263,7 +266,7 @@ export interface MutationOptions {
|
|
|
263
266
|
* createOwnerSecret({ randomBytes }),
|
|
264
267
|
* );
|
|
265
268
|
*
|
|
266
|
-
* const
|
|
269
|
+
* const _insertOwnedRows = (evolu: Evolu<typeof Schema>): void => {
|
|
267
270
|
* // Partition app data by project.
|
|
268
271
|
* evolu.insert(
|
|
269
272
|
* "task",
|
|
@@ -279,8 +282,8 @@ export interface MutationOptions {
|
|
|
279
282
|
* );
|
|
280
283
|
* };
|
|
281
284
|
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
285
|
+
* assertEqual(projectOwner.type, "ShardOwner");
|
|
286
|
+
* assertEqual(sharedOwner.type, "SharedOwner");
|
|
284
287
|
* ```
|
|
285
288
|
*/
|
|
286
289
|
readonly ownerId?: OwnerId;
|
|
@@ -448,6 +451,8 @@ export const evoluSchemaToSqliteSchema = <S extends EvoluSchema>(
|
|
|
448
451
|
*
|
|
449
452
|
* ```ts
|
|
450
453
|
* import {
|
|
454
|
+
* assertTrue,
|
|
455
|
+
* assertType,
|
|
451
456
|
* createQueryBuilder,
|
|
452
457
|
* id,
|
|
453
458
|
* NonEmptyTrimmedString100,
|
|
@@ -471,12 +476,15 @@ export const evoluSchemaToSqliteSchema = <S extends EvoluSchema>(
|
|
|
471
476
|
* db.selectFrom("todo").select(["id", "title", "isCompleted"]),
|
|
472
477
|
* );
|
|
473
478
|
*
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
*
|
|
479
|
-
*
|
|
479
|
+
* assertType<
|
|
480
|
+
* {
|
|
481
|
+
* id: TodoId;
|
|
482
|
+
* title: NonEmptyTrimmedString100 | null;
|
|
483
|
+
* isCompleted: SqliteBoolean | null;
|
|
484
|
+
* },
|
|
485
|
+
* typeof todosQuery.Row
|
|
486
|
+
* >();
|
|
487
|
+
* assertTrue(typeof todosQuery === "string");
|
|
480
488
|
* ```
|
|
481
489
|
*/
|
|
482
490
|
export const createQueryBuilder = <S extends EvoluSchema>(
|
|
@@ -324,7 +324,9 @@ export const initSharedWorker =
|
|
|
324
324
|
const tenantLease = await run.ok(
|
|
325
325
|
unabortable(tenantsByName.acquire(message)),
|
|
326
326
|
);
|
|
327
|
-
tenantLease.resource.addInstance(message,
|
|
327
|
+
tenantLease.resource.addInstance(message, () => {
|
|
328
|
+
tenantLease.release();
|
|
329
|
+
});
|
|
328
330
|
return ok();
|
|
329
331
|
});
|
|
330
332
|
break;
|
|
@@ -479,7 +481,7 @@ const createEvoluTenant =
|
|
|
479
481
|
new Map<EvoluInstanceId, EvoluInstance>(),
|
|
480
482
|
async (instancesById) => {
|
|
481
483
|
await using disposer = new AsyncDisposableStack();
|
|
482
|
-
for (const instance of
|
|
484
|
+
for (const instance of instancesById.values()) {
|
|
483
485
|
disposer.use(instance);
|
|
484
486
|
}
|
|
485
487
|
},
|
|
@@ -70,6 +70,7 @@ export interface StorageConfig {
|
|
|
70
70
|
*
|
|
71
71
|
* ```ts
|
|
72
72
|
* import {
|
|
73
|
+
* assertEqual,
|
|
73
74
|
* createAppOwner,
|
|
74
75
|
* createOwnerSecret,
|
|
75
76
|
* createRandomBytes,
|
|
@@ -87,12 +88,13 @@ export interface StorageConfig {
|
|
|
87
88
|
* ownerId === appOwner.id && requiredBytes <= maxBytes,
|
|
88
89
|
* };
|
|
89
90
|
*
|
|
90
|
-
*
|
|
91
|
+
* assertEqual(
|
|
91
92
|
* await relayStorageConfig.isOwnerWithinQuota(
|
|
92
93
|
* appOwner.id,
|
|
93
94
|
* PositiveInt.orThrow(2048),
|
|
94
95
|
* ),
|
|
95
|
-
*
|
|
96
|
+
* false,
|
|
97
|
+
* );
|
|
96
98
|
* ```
|
|
97
99
|
*/
|
|
98
100
|
readonly isOwnerWithinQuota: (
|
|
@@ -93,7 +93,7 @@ export const maxCounter = 65535 as Counter;
|
|
|
93
93
|
* yet they will think they are synced. This is extremely rare and can be
|
|
94
94
|
* resolved by resetting one device to generate a new NodeId.
|
|
95
95
|
*/
|
|
96
|
-
export const NodeId = /*#__PURE__*/ regex("NodeId", /^[a-f0-9]{16}$/)(String);
|
|
96
|
+
export const NodeId = /*#__PURE__*/ regex("NodeId", /^[a-f0-9]{16}$/u)(String);
|
|
97
97
|
export type NodeId = typeof NodeId.Output;
|
|
98
98
|
|
|
99
99
|
export const minNodeId = "0000000000000000" as NodeId;
|