@evolu/common 8.9.0 → 8.11.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/Bytes.d.ts +647 -0
- package/dist/src/Bytes.d.ts.map +1 -0
- package/dist/src/{Binary.js → Bytes.js} +266 -16
- package/dist/src/Config.d.ts +142 -0
- package/dist/src/Config.d.ts.map +1 -0
- package/dist/src/Config.js +181 -0
- package/dist/src/Console.d.ts +62 -7
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +20 -4
- package/dist/src/Crypto.d.ts +76 -4
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +55 -4
- package/dist/src/Error.d.ts +45 -0
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +69 -0
- package/dist/src/Fs.d.ts +376 -0
- package/dist/src/Fs.d.ts.map +1 -0
- package/dist/src/Fs.js +113 -0
- package/dist/src/Identicon.d.ts +2 -2
- package/dist/src/Identicon.js +2 -2
- package/dist/src/LeakDetector.d.ts +22 -3
- package/dist/src/LeakDetector.d.ts.map +1 -1
- package/dist/src/LeakDetector.js +12 -2
- package/dist/src/LockManager.d.ts +8 -0
- package/dist/src/LockManager.d.ts.map +1 -1
- package/dist/src/LockManager.js +6 -0
- package/dist/src/Number.d.ts +50 -7
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +47 -8
- package/dist/src/Object.d.ts +32 -0
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +46 -0
- package/dist/src/Platform.d.ts +47 -7
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +24 -5
- package/dist/src/Random.d.ts +25 -2
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +14 -2
- package/dist/src/Resource.d.ts +156 -1
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +201 -72
- package/dist/src/Schedule.d.ts +11 -10
- package/dist/src/Schedule.d.ts.map +1 -1
- package/dist/src/Schedule.js +1 -1
- package/dist/src/Sqlite.d.ts +132 -16
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +64 -10
- package/dist/src/Task.d.ts +15 -4
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +41 -15
- package/dist/src/Test.d.ts +9 -0
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +4 -0
- package/dist/src/Time.d.ts +179 -20
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +95 -6
- package/dist/src/Type.d.ts +3056 -1539
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +2548 -584
- package/dist/src/WebSocket.d.ts +164 -13
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +133 -24
- package/dist/src/Worker.d.ts +90 -8
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +28 -2
- package/dist/src/index.d.ts +9 -8
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -4
- package/dist/src/intl/_en.d.ts +24 -1
- package/dist/src/intl/_en.d.ts.map +1 -1
- package/dist/src/intl/_en.js +20 -0
- package/dist/src/intl/ar.d.ts +24 -1
- package/dist/src/intl/ar.d.ts.map +1 -1
- package/dist/src/intl/ar.js +20 -0
- package/dist/src/intl/bn.d.ts +24 -1
- package/dist/src/intl/bn.d.ts.map +1 -1
- package/dist/src/intl/bn.js +20 -0
- package/dist/src/intl/ca.d.ts +24 -1
- package/dist/src/intl/ca.d.ts.map +1 -1
- package/dist/src/intl/ca.js +20 -0
- package/dist/src/intl/cs.d.ts +24 -1
- package/dist/src/intl/cs.d.ts.map +1 -1
- package/dist/src/intl/cs.js +20 -0
- package/dist/src/intl/da.d.ts +24 -1
- package/dist/src/intl/da.d.ts.map +1 -1
- package/dist/src/intl/da.js +20 -0
- package/dist/src/intl/de.d.ts +24 -1
- package/dist/src/intl/de.d.ts.map +1 -1
- package/dist/src/intl/de.js +20 -0
- package/dist/src/intl/el.d.ts +24 -1
- package/dist/src/intl/el.d.ts.map +1 -1
- package/dist/src/intl/el.js +20 -0
- package/dist/src/intl/es.d.ts +24 -1
- package/dist/src/intl/es.d.ts.map +1 -1
- package/dist/src/intl/es.js +20 -0
- package/dist/src/intl/fa.d.ts +24 -1
- package/dist/src/intl/fa.d.ts.map +1 -1
- package/dist/src/intl/fa.js +20 -0
- package/dist/src/intl/fi.d.ts +24 -1
- package/dist/src/intl/fi.d.ts.map +1 -1
- package/dist/src/intl/fi.js +20 -0
- package/dist/src/intl/fil.d.ts +24 -1
- package/dist/src/intl/fil.d.ts.map +1 -1
- package/dist/src/intl/fil.js +20 -0
- package/dist/src/intl/fr.d.ts +24 -1
- package/dist/src/intl/fr.d.ts.map +1 -1
- package/dist/src/intl/fr.js +20 -0
- package/dist/src/intl/he.d.ts +24 -1
- package/dist/src/intl/he.d.ts.map +1 -1
- package/dist/src/intl/he.js +20 -0
- package/dist/src/intl/hi.d.ts +24 -1
- package/dist/src/intl/hi.d.ts.map +1 -1
- package/dist/src/intl/hi.js +20 -0
- package/dist/src/intl/hr.d.ts +24 -1
- package/dist/src/intl/hr.d.ts.map +1 -1
- package/dist/src/intl/hr.js +20 -0
- package/dist/src/intl/hu.d.ts +22 -1
- package/dist/src/intl/hu.d.ts.map +1 -1
- package/dist/src/intl/hu.js +18 -0
- package/dist/src/intl/id.d.ts +24 -1
- package/dist/src/intl/id.d.ts.map +1 -1
- package/dist/src/intl/id.js +20 -0
- package/dist/src/intl/it.d.ts +24 -1
- package/dist/src/intl/it.d.ts.map +1 -1
- package/dist/src/intl/it.js +20 -0
- package/dist/src/intl/ja.d.ts +24 -1
- package/dist/src/intl/ja.d.ts.map +1 -1
- package/dist/src/intl/ja.js +20 -0
- package/dist/src/intl/ko.d.ts +24 -1
- package/dist/src/intl/ko.d.ts.map +1 -1
- package/dist/src/intl/ko.js +20 -0
- package/dist/src/intl/ml.d.ts +24 -1
- package/dist/src/intl/ml.d.ts.map +1 -1
- package/dist/src/intl/ml.js +20 -0
- package/dist/src/intl/mr.d.ts +24 -1
- package/dist/src/intl/mr.d.ts.map +1 -1
- package/dist/src/intl/mr.js +20 -0
- package/dist/src/intl/ms.d.ts +24 -1
- package/dist/src/intl/ms.d.ts.map +1 -1
- package/dist/src/intl/ms.js +20 -0
- package/dist/src/intl/nb.d.ts +22 -1
- package/dist/src/intl/nb.d.ts.map +1 -1
- package/dist/src/intl/nb.js +18 -0
- package/dist/src/intl/nl.d.ts +24 -1
- package/dist/src/intl/nl.d.ts.map +1 -1
- package/dist/src/intl/nl.js +20 -0
- package/dist/src/intl/pa.d.ts +24 -1
- package/dist/src/intl/pa.d.ts.map +1 -1
- package/dist/src/intl/pa.js +20 -0
- package/dist/src/intl/pl.d.ts +23 -0
- package/dist/src/intl/pl.d.ts.map +1 -1
- package/dist/src/intl/pl.js +20 -0
- package/dist/src/intl/pt-BR.d.ts +24 -1
- package/dist/src/intl/pt-BR.d.ts.map +1 -1
- package/dist/src/intl/pt-BR.js +20 -0
- package/dist/src/intl/pt.d.ts +24 -1
- package/dist/src/intl/pt.d.ts.map +1 -1
- package/dist/src/intl/pt.js +20 -0
- package/dist/src/intl/ro.d.ts +24 -1
- package/dist/src/intl/ro.d.ts.map +1 -1
- package/dist/src/intl/ro.js +20 -0
- package/dist/src/intl/sk.d.ts +24 -1
- package/dist/src/intl/sk.d.ts.map +1 -1
- package/dist/src/intl/sk.js +20 -0
- package/dist/src/intl/sl.d.ts +24 -1
- package/dist/src/intl/sl.d.ts.map +1 -1
- package/dist/src/intl/sl.js +20 -0
- package/dist/src/intl/sv.d.ts +24 -1
- package/dist/src/intl/sv.d.ts.map +1 -1
- package/dist/src/intl/sv.js +20 -0
- package/dist/src/intl/sw.d.ts +21 -0
- package/dist/src/intl/sw.d.ts.map +1 -1
- package/dist/src/intl/sw.js +18 -0
- package/dist/src/intl/ta.d.ts +24 -1
- package/dist/src/intl/ta.d.ts.map +1 -1
- package/dist/src/intl/ta.js +20 -0
- package/dist/src/intl/te.d.ts +24 -1
- package/dist/src/intl/te.d.ts.map +1 -1
- package/dist/src/intl/te.js +20 -0
- package/dist/src/intl/th.d.ts +24 -1
- package/dist/src/intl/th.d.ts.map +1 -1
- package/dist/src/intl/th.js +20 -0
- package/dist/src/intl/tr.d.ts +24 -1
- package/dist/src/intl/tr.d.ts.map +1 -1
- package/dist/src/intl/tr.js +20 -0
- package/dist/src/intl/uk.d.ts +80 -57
- package/dist/src/intl/uk.d.ts.map +1 -1
- package/dist/src/intl/uk.js +174 -149
- package/dist/src/intl/ur.d.ts +24 -1
- package/dist/src/intl/ur.d.ts.map +1 -1
- package/dist/src/intl/ur.js +20 -0
- package/dist/src/intl/vi.d.ts +24 -1
- package/dist/src/intl/vi.d.ts.map +1 -1
- package/dist/src/intl/vi.js +20 -0
- package/dist/src/intl/zh-CN.d.ts +24 -1
- package/dist/src/intl/zh-CN.d.ts.map +1 -1
- package/dist/src/intl/zh-CN.js +20 -0
- package/dist/src/intl/zh-TW.d.ts +24 -1
- package/dist/src/intl/zh-TW.d.ts.map +1 -1
- package/dist/src/intl/zh-TW.js +20 -0
- package/dist/src/local-first/Db.d.ts +52 -3
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +412 -137
- package/dist/src/local-first/Evolu.d.ts +336 -211
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +102 -15
- package/dist/src/local-first/Owner.d.ts +13 -30
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +13 -30
- package/dist/src/local-first/Protocol.d.ts +95 -17
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +119 -39
- package/dist/src/local-first/Query.d.ts +8 -15
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Schema.d.ts +345 -21
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +214 -17
- package/dist/src/local-first/Shared.d.ts +537 -22
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +1437 -234
- package/dist/src/local-first/Storage.d.ts +192 -14
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +82 -21
- package/dist/src/local-first/Timestamp.d.ts +392 -41
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +404 -82
- package/dist/src/local-first/index.d.ts +0 -1
- package/dist/src/local-first/index.d.ts.map +1 -1
- package/dist/src/local-first/index.js +0 -1
- package/package.json +1 -1
- package/src/Assert.test.ts +2 -5
- package/src/{Binary.test.ts → Bytes.test.ts} +286 -1
- package/src/{Binary.ts → Bytes.ts} +652 -21
- package/src/Config.test.ts +668 -0
- package/src/Config.ts +410 -0
- package/src/Console.ts +62 -7
- package/src/Crypto.ts +76 -4
- package/src/Eq.test.ts +2 -3
- package/src/Error.test.ts +76 -3
- package/src/Error.ts +71 -0
- package/src/Fs.test.ts +105 -0
- package/src/Fs.ts +488 -0
- package/src/Identicon.ts +2 -2
- package/src/LeakDetector.ts +22 -3
- package/src/LockManager.ts +8 -0
- package/src/Number.test.ts +82 -18
- package/src/Number.ts +76 -8
- package/src/Object.test.ts +139 -10
- package/src/Object.ts +49 -0
- package/src/Platform.ts +50 -8
- package/src/Random.ts +25 -2
- package/src/Resource.test.ts +837 -0
- package/src/Resource.ts +235 -15
- package/src/Schedule.test.ts +50 -12
- package/src/Schedule.ts +24 -14
- package/src/Sqlite.ts +138 -18
- package/src/Task.test.ts +189 -8
- package/src/Task.ts +56 -17
- package/src/Test.ts +9 -0
- package/src/Time.test.ts +82 -11
- package/src/Time.ts +246 -24
- package/src/Type.test.ts +3994 -1119
- package/src/Type.ts +7258 -3842
- package/src/Types.test.ts +4 -14
- package/src/WebSocket.ts +313 -40
- package/src/Worker.ts +90 -8
- package/src/index.ts +18 -7
- package/src/intl/_en.ts +70 -0
- package/src/intl/ar.ts +71 -0
- package/src/intl/bn.ts +70 -0
- package/src/intl/ca.ts +70 -0
- package/src/intl/cs.ts +70 -0
- package/src/intl/da.ts +70 -0
- package/src/intl/de.ts +70 -0
- package/src/intl/el.ts +70 -0
- package/src/intl/es.ts +70 -0
- package/src/intl/fa.ts +70 -0
- package/src/intl/fi.ts +70 -0
- package/src/intl/fil.ts +70 -0
- package/src/intl/fr.ts +70 -0
- package/src/intl/he.ts +70 -0
- package/src/intl/hi.ts +70 -0
- package/src/intl/hr.ts +70 -0
- package/src/intl/hu.ts +69 -0
- package/src/intl/id.ts +70 -0
- package/src/intl/intl.test.ts +819 -1
- package/src/intl/it.ts +70 -0
- package/src/intl/ja.ts +70 -0
- package/src/intl/ko.ts +68 -0
- package/src/intl/ml.ts +70 -0
- package/src/intl/mr.ts +70 -0
- package/src/intl/ms.ts +71 -0
- package/src/intl/nb.ts +69 -0
- package/src/intl/nl.ts +70 -0
- package/src/intl/pa.ts +70 -0
- package/src/intl/pl.ts +63 -0
- package/src/intl/pt-BR.ts +70 -0
- package/src/intl/pt.ts +71 -0
- package/src/intl/ro.ts +70 -0
- package/src/intl/sk.ts +71 -0
- package/src/intl/sl.ts +70 -0
- package/src/intl/sv.ts +70 -0
- package/src/intl/sw.ts +62 -0
- package/src/intl/ta.ts +70 -0
- package/src/intl/te.ts +70 -0
- package/src/intl/th.ts +68 -0
- package/src/intl/tr.ts +70 -0
- package/src/intl/uk.ts +228 -155
- package/src/intl/ur.ts +70 -0
- package/src/intl/vi.ts +70 -0
- package/src/intl/zh-CN.ts +68 -0
- package/src/intl/zh-TW.ts +68 -0
- package/src/local-first/Db.ts +644 -339
- package/src/local-first/Evolu.test.ts +686 -21
- package/src/local-first/Evolu.ts +450 -228
- package/src/local-first/Owner.ts +13 -30
- package/src/local-first/Protocol.test.ts +618 -11
- package/src/local-first/Protocol.ts +197 -73
- package/src/local-first/Query.ts +8 -15
- package/src/local-first/Schema.test.ts +143 -0
- package/src/local-first/Schema.ts +374 -24
- package/src/local-first/Shared.test.ts +7731 -559
- package/src/local-first/Shared.ts +2036 -267
- package/src/local-first/Storage.ts +219 -33
- package/src/local-first/Timestamp.test.ts +344 -70
- package/src/local-first/Timestamp.ts +435 -119
- package/src/local-first/index.ts +0 -1
- package/dist/src/Binary.d.ts +0 -254
- package/dist/src/Binary.d.ts.map +0 -1
- package/dist/src/local-first/Error.d.ts +0 -12
- package/dist/src/local-first/Error.d.ts.map +0 -1
- package/dist/src/local-first/Error.js +0 -6
- package/dist/src/local-first/LocalAuth.d.ts +0 -150
- package/dist/src/local-first/LocalAuth.d.ts.map +0 -1
- package/dist/src/local-first/LocalAuth.js +0 -179
- package/src/local-first/Error.ts +0 -17
- package/src/local-first/LocalAuth.ts +0 -457
|
@@ -5,29 +5,47 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { type NonEmptyReadonlyArray } from "../Array.ts";
|
|
7
7
|
import type { ConsoleDep } from "../Console.ts";
|
|
8
|
+
import type { DecryptWithXChaCha20Poly1305Error } from "../Crypto.ts";
|
|
9
|
+
import type { UnknownError } from "../Error.ts";
|
|
8
10
|
import { type LockManagerDep } from "../LockManager.ts";
|
|
9
11
|
import type { FlushSyncDep, ReloadAppDep } from "../Platform.ts";
|
|
10
12
|
import type { Listener, ReadonlyStore, Unsubscribe } from "../Store.ts";
|
|
11
13
|
import type { Task } from "../Task.ts";
|
|
12
14
|
import { Name, type TypeError, UrlSafeString } from "../Type.ts";
|
|
13
15
|
import type { CreateBroadcastChannelDep, CreateMessageChannelDep } from "../Worker.ts";
|
|
14
|
-
import type { CreateDbWorkerDep } from "./Db.ts";
|
|
15
|
-
import type {
|
|
16
|
-
import type {
|
|
16
|
+
import type { CreateDbWorkerDep, UnsupportedDbVersionError } from "./Db.ts";
|
|
17
|
+
import type { AppOwner, Owner, OwnerId, OwnerTransport, ReadonlyOwner } from "./Owner.ts";
|
|
18
|
+
import type { ProtocolError } from "./Protocol.ts";
|
|
17
19
|
import type { Queries, QueriesToQueryRowsPromises, Query, QueryRows, Row } from "./Query.ts";
|
|
18
20
|
import type { EvoluSchema, IndexesConfig, Mutation, ValidateSchema } from "./Schema.ts";
|
|
19
|
-
import type { SharedWorkerDep } from "./Shared.ts";
|
|
21
|
+
import type { OtherBuildRunningError, SharedWorkerDep, SyncState } from "./Shared.ts";
|
|
22
|
+
import { type StorageQuotaError } from "./Storage.ts";
|
|
23
|
+
/**
|
|
24
|
+
* Configuration for {@link createEvolu}.
|
|
25
|
+
*
|
|
26
|
+
* @group Configuration
|
|
27
|
+
*/
|
|
20
28
|
export interface EvoluConfig {
|
|
21
29
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
30
|
+
* An application name used in logs and local database names.
|
|
31
|
+
*
|
|
32
|
+
* Evolu combines `appName` with the {@link AppOwner} identity to identify the
|
|
33
|
+
* local database. Changing either opens a different database. Keep `appName`
|
|
34
|
+
* stable across ordinary application updates.
|
|
25
35
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
36
|
+
* Instances that share an `appName` and AppOwner open the same database and
|
|
37
|
+
* must use the same schema. Evolu applies the schema of the first instance
|
|
38
|
+
* and later instances join it.
|
|
39
|
+
*
|
|
40
|
+
* A different app name lets you create a separate local replica for the same
|
|
41
|
+
* AppOwner—for example, to test a different SQLite implementation or index
|
|
42
|
+
* configuration, or rebuild a replica for debugging while preserving the
|
|
43
|
+
* existing database.
|
|
44
|
+
*
|
|
45
|
+
* Evolu supports running these databases concurrently. Their local separation
|
|
46
|
+
* does not isolate synchronization: replicas synchronizing the same owners
|
|
47
|
+
* through the same relay can still exchange changes. Changing `appName`
|
|
48
|
+
* neither migrates existing local data nor isolates incompatible schemas.
|
|
31
49
|
*
|
|
32
50
|
* ### Example
|
|
33
51
|
*
|
|
@@ -61,6 +79,69 @@ export interface EvoluConfig {
|
|
|
61
79
|
* flow).
|
|
62
80
|
*/
|
|
63
81
|
readonly appOwner: AppOwner;
|
|
82
|
+
/**
|
|
83
|
+
* Keep the database in memory instead of persisting it on this device.
|
|
84
|
+
*
|
|
85
|
+
* This option controls device persistence independently of synchronization.
|
|
86
|
+
* When synchronization is enabled, data can still be synchronized and
|
|
87
|
+
* persisted remotely.
|
|
88
|
+
*
|
|
89
|
+
* Useful for testing or temporary sessions. Data that exists only in this
|
|
90
|
+
* database is lost when the database closes.
|
|
91
|
+
*
|
|
92
|
+
* The default value is: `false`.
|
|
93
|
+
*/
|
|
94
|
+
readonly memoryOnly?: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Use the `indexes` option to define SQLite indexes.
|
|
97
|
+
*
|
|
98
|
+
* Table and column names are not typed because Kysely doesn't support it.
|
|
99
|
+
*
|
|
100
|
+
* https://medium.com/@JasonWyatt/squeezing-performance-from-sqlite-indexes-indexes-c4e175f3c346
|
|
101
|
+
*
|
|
102
|
+
* ### Example
|
|
103
|
+
*
|
|
104
|
+
* ```ts
|
|
105
|
+
* import {
|
|
106
|
+
* createEvolu,
|
|
107
|
+
* id,
|
|
108
|
+
* testAppName,
|
|
109
|
+
* testAppOwner,
|
|
110
|
+
* } from "@evolu/common";
|
|
111
|
+
*
|
|
112
|
+
* const Schema = {
|
|
113
|
+
* todo: { id: id("Todo") },
|
|
114
|
+
* todoCategory: { id: id("TodoCategory") },
|
|
115
|
+
* };
|
|
116
|
+
*
|
|
117
|
+
* const _createTodoEvolu = createEvolu(Schema, {
|
|
118
|
+
* appName: testAppName,
|
|
119
|
+
* appOwner: testAppOwner,
|
|
120
|
+
* transports: [],
|
|
121
|
+
* indexes: (create) => [
|
|
122
|
+
* create("todoCreatedAt").on("todo").column("createdAt"),
|
|
123
|
+
* create("todoCategoryCreatedAt")
|
|
124
|
+
* .on("todoCategory")
|
|
125
|
+
* .column("createdAt"),
|
|
126
|
+
* ],
|
|
127
|
+
* });
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
readonly indexes?: IndexesConfig;
|
|
131
|
+
/**
|
|
132
|
+
* Called when this instance's local database is deleted.
|
|
133
|
+
*
|
|
134
|
+
* Apps can use this to update UI immediately because the corresponding
|
|
135
|
+
* {@link Evolu} instance becomes unusable after local database deletion.
|
|
136
|
+
*/
|
|
137
|
+
readonly onDatabaseDeleted?: () => void;
|
|
138
|
+
/**
|
|
139
|
+
* Called when local data for an {@link Owner} is deleted.
|
|
140
|
+
*
|
|
141
|
+
* Apps can use this to update UI immediately because that owner stops being
|
|
142
|
+
* used across tabs and instances.
|
|
143
|
+
*/
|
|
144
|
+
readonly onOwnerDeleted?: (owner: Owner) => void;
|
|
64
145
|
/**
|
|
65
146
|
* Transport configuration for sync and backup.
|
|
66
147
|
*
|
|
@@ -98,18 +179,11 @@ export interface EvoluConfig {
|
|
|
98
179
|
* ```ts
|
|
99
180
|
* import {
|
|
100
181
|
* assertEqual,
|
|
101
|
-
* createAppOwner,
|
|
102
182
|
* createOwnerWebSocketTransport,
|
|
103
|
-
*
|
|
104
|
-
* createRandomBytes,
|
|
183
|
+
* testAppOwner,
|
|
105
184
|
* type OwnerTransport,
|
|
106
185
|
* } from "@evolu/common";
|
|
107
186
|
*
|
|
108
|
-
* // Create once, persist the mnemonic securely, and restore it on later runs.
|
|
109
|
-
* const appOwner = createAppOwner(
|
|
110
|
-
* createOwnerSecret({ randomBytes: createRandomBytes() }),
|
|
111
|
-
* );
|
|
112
|
-
*
|
|
113
187
|
* // Use one relay.
|
|
114
188
|
* const _singleRelay = [
|
|
115
189
|
* { type: "WebSocket", url: "wss://relay1.example.com" },
|
|
@@ -130,87 +204,17 @@ export interface EvoluConfig {
|
|
|
130
204
|
* const authenticatedRelay = [
|
|
131
205
|
* createOwnerWebSocketTransport({
|
|
132
206
|
* url: "wss://relay.example.com",
|
|
133
|
-
* ownerId:
|
|
207
|
+
* ownerId: testAppOwner.id,
|
|
134
208
|
* }),
|
|
135
209
|
* ];
|
|
136
210
|
*
|
|
137
211
|
* assertEqual(
|
|
138
212
|
* authenticatedRelay[0]?.url,
|
|
139
|
-
* `wss://relay.example.com?ownerId=${
|
|
213
|
+
* `wss://relay.example.com?ownerId=${testAppOwner.id}`,
|
|
140
214
|
* );
|
|
141
215
|
* ```
|
|
142
216
|
*/
|
|
143
217
|
readonly transports?: ReadonlyArray<OwnerTransport>;
|
|
144
|
-
/**
|
|
145
|
-
* Keep local data only in memory instead of persisting it on this device.
|
|
146
|
-
* Useful for testing, temporary data, or sensitive data that should not be
|
|
147
|
-
* recoverable from local storage after the process ends.
|
|
148
|
-
*
|
|
149
|
-
* Local data stored in memory is completely destroyed when the process ends.
|
|
150
|
-
* Sync can still persist data remotely when transports are enabled.
|
|
151
|
-
*
|
|
152
|
-
* The default value is: `false`.
|
|
153
|
-
*/
|
|
154
|
-
readonly memoryOnly?: boolean;
|
|
155
|
-
/**
|
|
156
|
-
* Use the `indexes` option to define SQLite indexes.
|
|
157
|
-
*
|
|
158
|
-
* Table and column names are not typed because Kysely doesn't support it.
|
|
159
|
-
*
|
|
160
|
-
* https://medium.com/@JasonWyatt/squeezing-performance-from-sqlite-indexes-indexes-c4e175f3c346
|
|
161
|
-
*
|
|
162
|
-
* ### Example
|
|
163
|
-
*
|
|
164
|
-
* ```ts
|
|
165
|
-
* import {
|
|
166
|
-
* AppName,
|
|
167
|
-
* assertTrue,
|
|
168
|
-
* createAppOwner,
|
|
169
|
-
* createEvolu,
|
|
170
|
-
* createOwnerSecret,
|
|
171
|
-
* createRandomBytes,
|
|
172
|
-
* id,
|
|
173
|
-
* } from "@evolu/common";
|
|
174
|
-
*
|
|
175
|
-
* const Schema = {
|
|
176
|
-
* todo: { id: id("Todo") },
|
|
177
|
-
* todoCategory: { id: id("TodoCategory") },
|
|
178
|
-
* };
|
|
179
|
-
* // Create once, persist the mnemonic securely, and restore it on later runs.
|
|
180
|
-
* const appOwner = createAppOwner(
|
|
181
|
-
* createOwnerSecret({ randomBytes: createRandomBytes() }),
|
|
182
|
-
* );
|
|
183
|
-
*
|
|
184
|
-
* const createTodoEvolu = createEvolu(Schema, {
|
|
185
|
-
* appName: AppName.orThrow("IndexedTodos"),
|
|
186
|
-
* appOwner,
|
|
187
|
-
* transports: [],
|
|
188
|
-
* indexes: (create) => [
|
|
189
|
-
* create("todoCreatedAt").on("todo").column("createdAt"),
|
|
190
|
-
* create("todoCategoryCreatedAt")
|
|
191
|
-
* .on("todoCategory")
|
|
192
|
-
* .column("createdAt"),
|
|
193
|
-
* ],
|
|
194
|
-
* });
|
|
195
|
-
*
|
|
196
|
-
* assertTrue(typeof createTodoEvolu === "function");
|
|
197
|
-
* ```
|
|
198
|
-
*/
|
|
199
|
-
readonly indexes?: IndexesConfig;
|
|
200
|
-
/**
|
|
201
|
-
* Called when this instance's local database is deleted.
|
|
202
|
-
*
|
|
203
|
-
* Apps can use this to update UI immediately because the corresponding
|
|
204
|
-
* {@link Evolu} instance becomes unusable after local database deletion.
|
|
205
|
-
*/
|
|
206
|
-
readonly onDatabaseDeleted?: () => void;
|
|
207
|
-
/**
|
|
208
|
-
* Called when local data for an {@link Owner} is deleted.
|
|
209
|
-
*
|
|
210
|
-
* Apps can use this to update UI immediately because that owner stops being
|
|
211
|
-
* used across tabs and instances.
|
|
212
|
-
*/
|
|
213
|
-
readonly onOwnerDeleted?: (owner: Owner) => void;
|
|
214
218
|
}
|
|
215
219
|
/**
|
|
216
220
|
* Application name.
|
|
@@ -221,17 +225,38 @@ export interface EvoluConfig {
|
|
|
221
225
|
*
|
|
222
226
|
* Uses the same safe alphabet as {@link UrlSafeString} (letters, digits, `-`,
|
|
223
227
|
* `_`) and must be between 1 and 41 characters.
|
|
228
|
+
*
|
|
229
|
+
* @group Configuration
|
|
224
230
|
*/
|
|
225
231
|
export declare const AppName: import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"String", string, string, import("../Type.ts").TypeOfError<"String">, null, import("../Type.ts").TypeOfError<"String">, never, string, true>, "UrlSafeString", import("../Type.ts").RegexError<"UrlSafeString">>, "AppName", AppNameError>;
|
|
226
232
|
export type AppName = typeof AppName.Output;
|
|
233
|
+
/**
|
|
234
|
+
* Error produced when a value is not a valid {@link AppName}.
|
|
235
|
+
*
|
|
236
|
+
* @group Configuration
|
|
237
|
+
*/
|
|
227
238
|
export interface AppNameError extends TypeError<"AppName"> {
|
|
228
239
|
readonly value: UrlSafeString;
|
|
229
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Stable valid {@link AppName} for tests and examples.
|
|
243
|
+
*
|
|
244
|
+
* @group Testing
|
|
245
|
+
*/
|
|
230
246
|
export declare const testAppName: string & import("../Brand.ts").Brand<"UrlSafeString"> & import("../Brand.ts").Brand<"AppName">;
|
|
231
247
|
/**
|
|
232
|
-
*
|
|
248
|
+
* A local-first SQL database.
|
|
249
|
+
*
|
|
250
|
+
* Stores application data in SQLite on the device, so reads and writes work
|
|
251
|
+
* offline. Provides typed queries, mutations, and reactive subscriptions, with
|
|
252
|
+
* synchronization between devices. Persistent SQLite is encrypted with the
|
|
253
|
+
* {@link AppOwner} key, and synchronized data is end-to-end encrypted.
|
|
233
254
|
*
|
|
234
|
-
*
|
|
255
|
+
* Tables whose names start with `_` stay local, even when the instance
|
|
256
|
+
* synchronizes other data. Use them for device-local data such as application
|
|
257
|
+
* settings or an app-owner registry.
|
|
258
|
+
*
|
|
259
|
+
* @group Core
|
|
235
260
|
*/
|
|
236
261
|
export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposable {
|
|
237
262
|
/**
|
|
@@ -249,32 +274,29 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
249
274
|
* every row has a globally unique, conflict-free identifier without
|
|
250
275
|
* coordination.
|
|
251
276
|
*
|
|
252
|
-
* Pass `onComplete` when follow-up work must wait until the mutation
|
|
253
|
-
*
|
|
277
|
+
* Pass `onComplete` when follow-up work must wait until the mutation is
|
|
278
|
+
* stored and subscribed queries reflect it. It never runs when the database
|
|
279
|
+
* is unavailable; see {@link Evolu.loadQuery}. A stored change is not always
|
|
280
|
+
* visible; see {@link MutationOptions.onComplete}.
|
|
254
281
|
*
|
|
255
282
|
* ### Example
|
|
256
283
|
*
|
|
257
284
|
* ```ts
|
|
258
285
|
* import {
|
|
259
286
|
* assertType,
|
|
260
|
-
*
|
|
287
|
+
* type TestEvoluSchema,
|
|
261
288
|
* NonEmptyTrimmedString100,
|
|
262
289
|
* type Evolu,
|
|
290
|
+
* type TestTodoId,
|
|
263
291
|
* } from "@evolu/common";
|
|
264
292
|
*
|
|
265
|
-
* const
|
|
266
|
-
* type TodoId = typeof TodoId.Output;
|
|
267
|
-
* const Schema = {
|
|
268
|
-
* todo: { id: TodoId, title: NonEmptyTrimmedString100 },
|
|
269
|
-
* };
|
|
270
|
-
*
|
|
271
|
-
* const insertTodo = (evolu: Evolu<typeof Schema>) =>
|
|
293
|
+
* const insertTodo = (evolu: Evolu<TestEvoluSchema>) =>
|
|
272
294
|
* evolu.insert("todo", {
|
|
273
295
|
* title: NonEmptyTrimmedString100.orThrow("Learn Evolu"),
|
|
274
296
|
* }).id;
|
|
275
297
|
*
|
|
276
298
|
* const insertTodoAndNotify = (
|
|
277
|
-
* evolu: Evolu<
|
|
299
|
+
* evolu: Evolu<TestEvoluSchema>,
|
|
278
300
|
* onComplete: () => void,
|
|
279
301
|
* ) =>
|
|
280
302
|
* evolu.insert(
|
|
@@ -288,7 +310,7 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
288
310
|
* ReturnType<typeof insertTodo>,
|
|
289
311
|
* ReturnType<typeof insertTodoAndNotify>,
|
|
290
312
|
* ],
|
|
291
|
-
* [
|
|
313
|
+
* [TestTodoId, TestTodoId]
|
|
292
314
|
* >();
|
|
293
315
|
* ```
|
|
294
316
|
*
|
|
@@ -305,30 +327,30 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
305
327
|
* ```ts
|
|
306
328
|
* import {
|
|
307
329
|
* assertType,
|
|
308
|
-
*
|
|
330
|
+
* type TestEvoluSchema,
|
|
309
331
|
* NonEmptyTrimmedString100,
|
|
310
332
|
* sqliteTrue,
|
|
311
333
|
* type Evolu,
|
|
334
|
+
* type TestTodoId,
|
|
312
335
|
* } from "@evolu/common";
|
|
313
336
|
*
|
|
314
|
-
* const
|
|
315
|
-
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
* };
|
|
319
|
-
*
|
|
320
|
-
* const renameTodo = (evolu: Evolu<typeof Schema>, todoId: TodoId) =>
|
|
337
|
+
* const renameTodo = (
|
|
338
|
+
* evolu: Evolu<TestEvoluSchema>,
|
|
339
|
+
* todoId: TestTodoId,
|
|
340
|
+
* ) =>
|
|
321
341
|
* evolu.update("todo", {
|
|
322
342
|
* id: todoId,
|
|
323
343
|
* title: NonEmptyTrimmedString100.orThrow("Updated title"),
|
|
324
344
|
* }).id;
|
|
325
345
|
*
|
|
326
|
-
* const softDeleteTodo = (
|
|
327
|
-
* evolu
|
|
346
|
+
* const softDeleteTodo = (
|
|
347
|
+
* evolu: Evolu<TestEvoluSchema>,
|
|
348
|
+
* todoId: TestTodoId,
|
|
349
|
+
* ) => evolu.update("todo", { id: todoId, isDeleted: sqliteTrue }).id;
|
|
328
350
|
*
|
|
329
351
|
* assertType<
|
|
330
352
|
* [ReturnType<typeof renameTodo>, ReturnType<typeof softDeleteTodo>],
|
|
331
|
-
* [
|
|
353
|
+
* [TestTodoId, TestTodoId]
|
|
332
354
|
* >();
|
|
333
355
|
* ```
|
|
334
356
|
*
|
|
@@ -353,24 +375,20 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
353
375
|
* import {
|
|
354
376
|
* assertType,
|
|
355
377
|
* createIdFromString,
|
|
356
|
-
*
|
|
378
|
+
* type TestEvoluSchema,
|
|
357
379
|
* NonEmptyTrimmedString100,
|
|
358
380
|
* type Evolu,
|
|
381
|
+
* TestTodoId,
|
|
359
382
|
* } from "@evolu/common";
|
|
360
383
|
*
|
|
361
|
-
* const
|
|
362
|
-
*
|
|
363
|
-
* const Schema = {
|
|
364
|
-
* todo: { id: TodoId, title: NonEmptyTrimmedString100 },
|
|
365
|
-
* };
|
|
366
|
-
* const stableId = TodoId.orThrow(createIdFromString("my-todo-1"));
|
|
367
|
-
* const upsertTodo = (evolu: Evolu<typeof Schema>) =>
|
|
384
|
+
* const stableId = TestTodoId.orThrow(createIdFromString("my-todo-1"));
|
|
385
|
+
* const upsertTodo = (evolu: Evolu<TestEvoluSchema>) =>
|
|
368
386
|
* evolu.upsert("todo", {
|
|
369
387
|
* id: stableId,
|
|
370
388
|
* title: NonEmptyTrimmedString100.orThrow("Learn Evolu"),
|
|
371
389
|
* }).id;
|
|
372
390
|
*
|
|
373
|
-
* assertType<ReturnType<typeof upsertTodo>,
|
|
391
|
+
* assertType<ReturnType<typeof upsertTodo>, TestTodoId>();
|
|
374
392
|
* ```
|
|
375
393
|
*
|
|
376
394
|
* @see {@link Mutation}
|
|
@@ -379,14 +397,19 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
379
397
|
/**
|
|
380
398
|
* Load {@link Query} and return a promise with {@link QueryRows}.
|
|
381
399
|
*
|
|
382
|
-
* The returned promise always resolves successfully because
|
|
383
|
-
*
|
|
384
|
-
*
|
|
400
|
+
* The returned promise always resolves successfully because all data are
|
|
401
|
+
* local and the query is typed. If the database refuses startup, unanswered
|
|
402
|
+
* loads stay pending until disposal resolves them with empty rows. Observe
|
|
403
|
+
* {@link EvoluErrorDep.evoluError} to display the refusal independently of
|
|
404
|
+
* query loading.
|
|
385
405
|
*
|
|
386
406
|
* Loading is batched. Returned promises are cached while pending and can be
|
|
387
|
-
* reused after fulfillment
|
|
388
|
-
*
|
|
389
|
-
*
|
|
407
|
+
* reused after fulfillment, which prevents redundant database queries and
|
|
408
|
+
* supports React Suspense (stable references while pending). A mutation or
|
|
409
|
+
* incoming sync invalidates the cache of an unsubscribed query, so its next
|
|
410
|
+
* load reads again. A subscribed query keeps its cached rows and the
|
|
411
|
+
* subscription refreshes them, so a load can return rows that a pending
|
|
412
|
+
* refresh is about to replace.
|
|
390
413
|
*
|
|
391
414
|
* To subscribe a query for automatic updates, use
|
|
392
415
|
* {@link Evolu.subscribeQuery}.
|
|
@@ -397,20 +420,17 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
397
420
|
* import {
|
|
398
421
|
* assertType,
|
|
399
422
|
* createQueryBuilder,
|
|
400
|
-
*
|
|
401
|
-
*
|
|
423
|
+
* testEvoluSchema,
|
|
424
|
+
* type TestEvoluSchema,
|
|
402
425
|
* type Evolu,
|
|
403
426
|
* type QueryRows,
|
|
404
427
|
* } from "@evolu/common";
|
|
405
428
|
*
|
|
406
|
-
* const
|
|
407
|
-
* todo: { id: id("Todo"), title: NonEmptyTrimmedString100 },
|
|
408
|
-
* };
|
|
409
|
-
* const createQuery = createQueryBuilder(Schema);
|
|
429
|
+
* const createQuery = createQueryBuilder(testEvoluSchema);
|
|
410
430
|
* const allTodos = createQuery((db) =>
|
|
411
431
|
* db.selectFrom("todo").selectAll(),
|
|
412
432
|
* );
|
|
413
|
-
* const loadTodos = async (evolu: Evolu<
|
|
433
|
+
* const loadTodos = async (evolu: Evolu<TestEvoluSchema>) => {
|
|
414
434
|
* const rows = await evolu.loadQuery(allTodos);
|
|
415
435
|
* return rows;
|
|
416
436
|
* };
|
|
@@ -432,31 +452,22 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
432
452
|
* ```ts
|
|
433
453
|
* import {
|
|
434
454
|
* assertType,
|
|
435
|
-
* createIdFromString,
|
|
436
455
|
* createQueryBuilder,
|
|
437
|
-
*
|
|
438
|
-
*
|
|
456
|
+
* testEvoluSchema,
|
|
457
|
+
* type TestEvoluSchema,
|
|
458
|
+
* testTodoId,
|
|
439
459
|
* type Evolu,
|
|
440
460
|
* type QueryRows,
|
|
441
461
|
* } from "@evolu/common";
|
|
442
462
|
*
|
|
443
|
-
* const
|
|
444
|
-
* type TodoId = typeof TodoId.Output;
|
|
445
|
-
* const Schema = {
|
|
446
|
-
* todo: { id: TodoId, title: NonEmptyTrimmedString100 },
|
|
447
|
-
* };
|
|
448
|
-
* const createQuery = createQueryBuilder(Schema);
|
|
463
|
+
* const createQuery = createQueryBuilder(testEvoluSchema);
|
|
449
464
|
* const allTodos = createQuery((db) =>
|
|
450
465
|
* db.selectFrom("todo").select(["id", "title"]),
|
|
451
466
|
* );
|
|
452
|
-
* const
|
|
453
|
-
*
|
|
454
|
-
* db.selectFrom("todo").select("title").where("id", "=", todoId),
|
|
455
|
-
* );
|
|
456
|
-
* const firstTodo = todoById(
|
|
457
|
-
* TodoId.orThrow(createIdFromString("first-todo")),
|
|
467
|
+
* const firstTodo = createQuery((db) =>
|
|
468
|
+
* db.selectFrom("todo").select("title").where("id", "=", testTodoId),
|
|
458
469
|
* );
|
|
459
|
-
* const loadTodoQueries = (evolu: Evolu<
|
|
470
|
+
* const loadTodoQueries = (evolu: Evolu<TestEvoluSchema>) =>
|
|
460
471
|
* evolu.loadQueries([allTodos, firstTodo]);
|
|
461
472
|
*
|
|
462
473
|
* assertType<
|
|
@@ -472,28 +483,28 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
472
483
|
/**
|
|
473
484
|
* Subscribe to {@link Query} {@link QueryRows} changes.
|
|
474
485
|
*
|
|
486
|
+
* Cached rows invalidated before subscription are refreshed. Subscribing
|
|
487
|
+
* alone does not load a query that has no cached rows.
|
|
488
|
+
*
|
|
475
489
|
* ### Example
|
|
476
490
|
*
|
|
477
491
|
* ```ts
|
|
478
492
|
* import {
|
|
479
493
|
* assertType,
|
|
480
494
|
* createQueryBuilder,
|
|
481
|
-
*
|
|
482
|
-
*
|
|
495
|
+
* testEvoluSchema,
|
|
496
|
+
* type TestEvoluSchema,
|
|
483
497
|
* type Evolu,
|
|
484
498
|
* type QueryRows,
|
|
485
499
|
* type Unsubscribe,
|
|
486
500
|
* } from "@evolu/common";
|
|
487
501
|
*
|
|
488
|
-
* const
|
|
489
|
-
* todo: { id: id("Todo"), title: NonEmptyTrimmedString100 },
|
|
490
|
-
* };
|
|
491
|
-
* const createQuery = createQueryBuilder(Schema);
|
|
502
|
+
* const createQuery = createQueryBuilder(testEvoluSchema);
|
|
492
503
|
* const allTodos = createQuery((db) =>
|
|
493
504
|
* db.selectFrom("todo").select("title"),
|
|
494
505
|
* );
|
|
495
506
|
* const subscribeToTodos = (
|
|
496
|
-
* evolu: Evolu<
|
|
507
|
+
* evolu: Evolu<TestEvoluSchema>,
|
|
497
508
|
* onRows: (rows: QueryRows<typeof allTodos.Row>) => void,
|
|
498
509
|
* ) =>
|
|
499
510
|
* evolu.subscribeQuery(allTodos)(() => {
|
|
@@ -513,20 +524,17 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
513
524
|
* import {
|
|
514
525
|
* assertType,
|
|
515
526
|
* createQueryBuilder,
|
|
516
|
-
*
|
|
517
|
-
*
|
|
527
|
+
* testEvoluSchema,
|
|
528
|
+
* type TestEvoluSchema,
|
|
518
529
|
* type Evolu,
|
|
519
530
|
* type QueryRows,
|
|
520
531
|
* } from "@evolu/common";
|
|
521
532
|
*
|
|
522
|
-
* const
|
|
523
|
-
* todo: { id: id("Todo"), title: NonEmptyTrimmedString100 },
|
|
524
|
-
* };
|
|
525
|
-
* const createQuery = createQueryBuilder(Schema);
|
|
533
|
+
* const createQuery = createQueryBuilder(testEvoluSchema);
|
|
526
534
|
* const allTodos = createQuery((db) =>
|
|
527
535
|
* db.selectFrom("todo").select("title"),
|
|
528
536
|
* );
|
|
529
|
-
* const getTodos = (evolu: Evolu<
|
|
537
|
+
* const getTodos = (evolu: Evolu<TestEvoluSchema>) =>
|
|
530
538
|
* evolu.getQueryRows(allTodos);
|
|
531
539
|
*
|
|
532
540
|
* assertType<
|
|
@@ -543,7 +551,8 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
543
551
|
* of starting parallel exports.
|
|
544
552
|
*
|
|
545
553
|
* The pending promise rejects if this {@link Evolu} instance is disposed
|
|
546
|
-
* before export completion.
|
|
554
|
+
* before export completion. If the database refuses startup, export stays
|
|
555
|
+
* pending until disposal; see {@link Evolu.loadQuery}.
|
|
547
556
|
*/
|
|
548
557
|
readonly exportDatabase: () => Promise<Uint8Array<ArrayBuffer>>;
|
|
549
558
|
/**
|
|
@@ -594,21 +603,15 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
594
603
|
* ```ts
|
|
595
604
|
* import {
|
|
596
605
|
* assertEqual,
|
|
597
|
-
* createAppOwner,
|
|
598
606
|
* createOwnerWebSocketTransport,
|
|
599
|
-
* createOwnerSecret,
|
|
600
|
-
* createRandomBytes,
|
|
601
607
|
* deriveShardOwner,
|
|
608
|
+
* testAppOwner,
|
|
602
609
|
* type Evolu,
|
|
603
610
|
* type ReadonlyOwner,
|
|
604
611
|
* type UnuseOwner,
|
|
605
612
|
* } from "@evolu/common";
|
|
606
613
|
*
|
|
607
|
-
*
|
|
608
|
-
* const appOwner = createAppOwner(
|
|
609
|
-
* createOwnerSecret({ randomBytes: createRandomBytes() }),
|
|
610
|
-
* );
|
|
611
|
-
* const shardOwner = deriveShardOwner(appOwner, ["todos", 1]);
|
|
614
|
+
* const shardOwner = deriveShardOwner(testAppOwner, ["todos", 1]);
|
|
612
615
|
* const shardTransport = createOwnerWebSocketTransport({
|
|
613
616
|
* url: "wss://relay.example.com",
|
|
614
617
|
* ownerId: shardOwner.id,
|
|
@@ -641,15 +644,80 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
641
644
|
* ```
|
|
642
645
|
*/
|
|
643
646
|
readonly useOwner: (owner: ReadonlyOwner | Owner, transports?: NonEmptyReadonlyArray<OwnerTransport>) => UnuseOwner;
|
|
647
|
+
/**
|
|
648
|
+
* Requests a new synchronization round for an active {@link OwnerId}.
|
|
649
|
+
*
|
|
650
|
+
* Reconciles locally stored changes, including writes previously rejected
|
|
651
|
+
* with {@link ProtocolQuotaError}, through the owner's active transports. Call
|
|
652
|
+
* this after the relay provider confirms additional quota is available.
|
|
653
|
+
* Existing connections and {@link Evolu.useOwner} registrations are retained,
|
|
654
|
+
* including registrations shared by multiple instances or tabs.
|
|
655
|
+
*
|
|
656
|
+
* The owner must have an active writable registration in this database.
|
|
657
|
+
* Unregistered or read-only owners are ignored. Requests are skipped while
|
|
658
|
+
* all of the owner's transports are closed; they synchronize when they
|
|
659
|
+
* reopen. Disposal drops locally buffered requests. Calling a disposed
|
|
660
|
+
* instance throws, like other Evolu operations.
|
|
661
|
+
*
|
|
662
|
+
* Returns immediately, without waiting for synchronization to complete.
|
|
663
|
+
* Errors are reported through {@link EvoluErrorDep.evoluError}.
|
|
664
|
+
*
|
|
665
|
+
* ### Example
|
|
666
|
+
*
|
|
667
|
+
* ```ts
|
|
668
|
+
* import { assertType, type Evolu, type OwnerId } from "@evolu/common";
|
|
669
|
+
*
|
|
670
|
+
* // Call after successfully increasing the affected owner's relay quota.
|
|
671
|
+
* const onQuotaIncreased = (evolu: Evolu, ownerId: OwnerId) => {
|
|
672
|
+
* evolu.requestSync(ownerId);
|
|
673
|
+
* };
|
|
674
|
+
*
|
|
675
|
+
* assertType<
|
|
676
|
+
* typeof onQuotaIncreased,
|
|
677
|
+
* (evolu: Evolu, ownerId: OwnerId) => void
|
|
678
|
+
* >();
|
|
679
|
+
* ```
|
|
680
|
+
*/
|
|
681
|
+
readonly requestSync: (ownerId: OwnerId) => void;
|
|
644
682
|
}
|
|
645
|
-
/**
|
|
683
|
+
/**
|
|
684
|
+
* Function returned by {@link Evolu.useOwner} to stop using an Owner for sync.
|
|
685
|
+
*
|
|
686
|
+
* @group Core
|
|
687
|
+
*/
|
|
646
688
|
export type UnuseOwner = () => void;
|
|
689
|
+
/**
|
|
690
|
+
* Represents errors that can occur in {@link Evolu}.
|
|
691
|
+
*
|
|
692
|
+
* @group Core
|
|
693
|
+
*/
|
|
694
|
+
export type EvoluError = DecryptWithXChaCha20Poly1305Error | OtherBuildRunningError | ProtocolError | StorageQuotaError | UnknownError | UnsupportedDbVersionError;
|
|
695
|
+
/**
|
|
696
|
+
* Dependency wrapper for the shared {@link EvoluError} store.
|
|
697
|
+
*
|
|
698
|
+
* @group Construction
|
|
699
|
+
*/
|
|
647
700
|
export interface EvoluErrorDep {
|
|
648
701
|
/**
|
|
649
702
|
* {@link ReadonlyStore} of {@link EvoluError} shared by all {@link Evolu}
|
|
650
703
|
* instances created from the same {@link createEvoluDeps} result.
|
|
651
704
|
*
|
|
705
|
+
* Starts at `null` and otherwise holds the latest reported error until the
|
|
706
|
+
* first {@link UnsupportedDbVersionError}. That refusal remains for the
|
|
707
|
+
* lifetime of these dependencies, even if a tenant is disposed and recreated.
|
|
708
|
+
* Later errors are still logged but do not replace it or notify this store's
|
|
709
|
+
* subscribers. Fresh dependencies start with a fresh error store. An
|
|
710
|
+
* {@link OtherBuildRunningError} reports a wait, so the store returns to
|
|
711
|
+
* `null` when the wait ends, unless another error replaced it.
|
|
712
|
+
*
|
|
652
713
|
* Subscribe once to show user-facing error messages across all instances.
|
|
714
|
+
* While a refused database's tenant remains alive, the SharedWorker sends the
|
|
715
|
+
* refusal to each tab once, including tabs that connect later, and starts no
|
|
716
|
+
* replacement database workers. After all instances release that tenant and
|
|
717
|
+
* it is disposed when idle, creating another instance retries startup and may
|
|
718
|
+
* send the refusal again. On the web, a refused tab first reloads once
|
|
719
|
+
* instead; see {@link UnsupportedDbVersionError}. Show that blocking message
|
|
720
|
+
* outside any query-loading boundary, so pending queries do not hide it.
|
|
653
721
|
*
|
|
654
722
|
* ### Example
|
|
655
723
|
*
|
|
@@ -657,62 +725,115 @@ export interface EvoluErrorDep {
|
|
|
657
725
|
* import {
|
|
658
726
|
* assertEqual,
|
|
659
727
|
* createStore,
|
|
660
|
-
* Millis,
|
|
661
728
|
* type EvoluError,
|
|
662
729
|
* } from "@evolu/common";
|
|
663
730
|
* import type { EvoluErrorDep } from "@evolu/common/local-first";
|
|
664
731
|
*
|
|
732
|
+
* // The message for the current error, or null for none.
|
|
733
|
+
* const errorMessage = (error: EvoluError | null): string | null => {
|
|
734
|
+
* if (!error) return null;
|
|
735
|
+
* // oxlint-disable-next-line typescript/switch-exhaustiveness-check -- The default handles every other EvoluError.
|
|
736
|
+
* switch (error.type) {
|
|
737
|
+
* case "UnsupportedDbVersionError":
|
|
738
|
+
* return "Your data requires a newer version of this app. Please update it.";
|
|
739
|
+
* case "OtherBuildRunningError":
|
|
740
|
+
* return "This app is open in another tab with a different version. Close that tab to continue.";
|
|
741
|
+
* default:
|
|
742
|
+
* return "Something went wrong. Please try again.";
|
|
743
|
+
* }
|
|
744
|
+
* };
|
|
745
|
+
*
|
|
665
746
|
* // Stand-in for run.deps.evoluError from createEvoluDeps.
|
|
666
747
|
* using evoluError = createStore<EvoluError | null>(null);
|
|
667
748
|
* const deps = { evoluError } satisfies EvoluErrorDep;
|
|
668
|
-
*
|
|
669
|
-
* const
|
|
670
|
-
* displayedMessage = message;
|
|
671
|
-
* };
|
|
749
|
+
* // What the app showed over time; null hides the message.
|
|
750
|
+
* const shown: Array<string | null> = [];
|
|
672
751
|
*
|
|
673
752
|
* deps.evoluError.subscribe(() => {
|
|
674
|
-
*
|
|
675
|
-
* if (!error) return;
|
|
676
|
-
*
|
|
677
|
-
* // oxlint-disable-next-line typescript/switch-exhaustiveness-check -- The default intentionally handles every other EvoluError.
|
|
678
|
-
* switch (error.type) {
|
|
679
|
-
* case "TimestampDriftError":
|
|
680
|
-
* // Show guidance specific to the detected error.
|
|
681
|
-
* showMessage(
|
|
682
|
-
* "Your system clock appears incorrect. Please fix it.",
|
|
683
|
-
* );
|
|
684
|
-
* break;
|
|
685
|
-
* default:
|
|
686
|
-
* // Show a generic user message for other operational errors.
|
|
687
|
-
* showMessage("Something went wrong. Please try again.");
|
|
688
|
-
* }
|
|
753
|
+
* shown.push(errorMessage(deps.evoluError.get()));
|
|
689
754
|
* });
|
|
690
755
|
*
|
|
691
|
-
*
|
|
692
|
-
*
|
|
693
|
-
*
|
|
694
|
-
*
|
|
695
|
-
*
|
|
696
|
-
*
|
|
697
|
-
*
|
|
698
|
-
*
|
|
699
|
-
* );
|
|
756
|
+
* // Another version keeps this tab waiting, then the wait ends.
|
|
757
|
+
* deps.evoluError.set({ type: "OtherBuildRunningError" });
|
|
758
|
+
* deps.evoluError.set(null);
|
|
759
|
+
*
|
|
760
|
+
* assertEqual(shown, [
|
|
761
|
+
* "This app is open in another tab with a different version. Close that tab to continue.",
|
|
762
|
+
* null,
|
|
763
|
+
* ]);
|
|
700
764
|
* ```
|
|
701
765
|
*/
|
|
702
766
|
readonly evoluError: ReadonlyStore<EvoluError | null>;
|
|
703
767
|
}
|
|
768
|
+
/**
|
|
769
|
+
* Dependency wrapper for the shared {@link SyncState} store.
|
|
770
|
+
*
|
|
771
|
+
* @group Construction
|
|
772
|
+
*/
|
|
773
|
+
export interface SyncStateDep {
|
|
774
|
+
/**
|
|
775
|
+
* {@link ReadonlyStore} of the latest {@link SyncState} shared by all
|
|
776
|
+
* {@link Evolu} instances, or null before the shared worker sends its first
|
|
777
|
+
* snapshot. Derive what to show from it, such as one indicator per relay, or
|
|
778
|
+
* use {@link syncStateToOwnerSyncStates} for one state per owner.
|
|
779
|
+
*
|
|
780
|
+
* ### Example
|
|
781
|
+
*
|
|
782
|
+
* ```ts
|
|
783
|
+
* import {
|
|
784
|
+
* assertEqual,
|
|
785
|
+
* createId,
|
|
786
|
+
* createStore,
|
|
787
|
+
* testCreateDeps,
|
|
788
|
+
* } from "@evolu/common";
|
|
789
|
+
* import type {
|
|
790
|
+
* SyncState,
|
|
791
|
+
* SyncStateDep,
|
|
792
|
+
* } from "@evolu/common/local-first";
|
|
793
|
+
*
|
|
794
|
+
* const openRelayLabels = (deps: SyncStateDep): ReadonlyArray<string> =>
|
|
795
|
+
* (deps.syncState.get()?.transports ?? [])
|
|
796
|
+
* .filter(({ readyState }) => readyState === "open")
|
|
797
|
+
* .map(({ label }) => label);
|
|
798
|
+
*
|
|
799
|
+
* using syncState = createStore<SyncState | null>(null);
|
|
800
|
+
* assertEqual(openRelayLabels({ syncState }), []);
|
|
801
|
+
*
|
|
802
|
+
* const deps = testCreateDeps();
|
|
803
|
+
* syncState.set({
|
|
804
|
+
* transports: [
|
|
805
|
+
* {
|
|
806
|
+
* id: createId<"SyncTransport">(deps),
|
|
807
|
+
* label: "wss://relay.example",
|
|
808
|
+
* readyState: "open",
|
|
809
|
+
* openedAt: null,
|
|
810
|
+
* closedAt: null,
|
|
811
|
+
* error: null,
|
|
812
|
+
* },
|
|
813
|
+
* ],
|
|
814
|
+
* tenants: [],
|
|
815
|
+
* });
|
|
816
|
+
* assertEqual(openRelayLabels({ syncState }), ["wss://relay.example"]);
|
|
817
|
+
* ```
|
|
818
|
+
*/
|
|
819
|
+
readonly syncState: ReadonlyStore<SyncState | null>;
|
|
820
|
+
}
|
|
704
821
|
/**
|
|
705
822
|
* Shared platform dependencies for creating {@link Evolu} instances.
|
|
706
823
|
*
|
|
707
824
|
* Includes platform adapters, the shared {@link EvoluErrorDep.evoluError} store,
|
|
708
825
|
* and disposal for owned resources.
|
|
826
|
+
*
|
|
827
|
+
* @group Construction
|
|
709
828
|
*/
|
|
710
|
-
export type EvoluDeps = EvoluPlatformDeps & ConsoleDep & EvoluErrorDep & Disposable;
|
|
829
|
+
export type EvoluDeps = EvoluPlatformDeps & ConsoleDep & EvoluErrorDep & SyncStateDep & Disposable;
|
|
711
830
|
/**
|
|
712
831
|
* Platform-specific dependencies required to create {@link EvoluDeps}.
|
|
713
832
|
*
|
|
714
833
|
* Provides worker and channel adapters plus optional platform integrations for
|
|
715
834
|
* logging and synchronous UI flush.
|
|
835
|
+
*
|
|
836
|
+
* @group Construction
|
|
716
837
|
*/
|
|
717
838
|
export type EvoluPlatformDeps = CreateDbWorkerDep & CreateBroadcastChannelDep & CreateMessageChannelDep & LockManagerDep & ReloadAppDep & SharedWorkerDep & Partial<ConsoleDep> & Partial<FlushSyncDep>;
|
|
718
839
|
/**
|
|
@@ -721,15 +842,19 @@ export type EvoluPlatformDeps = CreateDbWorkerDep & CreateBroadcastChannelDep &
|
|
|
721
842
|
*
|
|
722
843
|
* Call this once per platform and reuse the returned deps when creating
|
|
723
844
|
* multiple Evolu instances. The returned deps object owns long-lived resources
|
|
724
|
-
* such as worker channels and the shared {@link EvoluErrorDep.evoluError}
|
|
725
|
-
*
|
|
845
|
+
* such as worker channels and the shared {@link EvoluErrorDep.evoluError} and
|
|
846
|
+
* {@link SyncStateDep.syncState} stores.
|
|
726
847
|
*
|
|
727
848
|
* Dispose it only during app shutdown.
|
|
849
|
+
*
|
|
850
|
+
* @group Construction
|
|
728
851
|
*/
|
|
729
852
|
export declare const createEvoluDeps: (deps: EvoluPlatformDeps) => EvoluDeps;
|
|
730
853
|
/**
|
|
731
854
|
* Creates an {@link Evolu} instance from {@link EvoluSchema} and
|
|
732
855
|
* {@link EvoluConfig}.
|
|
856
|
+
*
|
|
857
|
+
* @group Construction
|
|
733
858
|
*/
|
|
734
859
|
export declare const createEvolu: <S extends EvoluSchema>(schema: ValidateSchema<S> extends never ? S : ValidateSchema<S>, config: EvoluConfig) => Task<Evolu<S>, never, EvoluPlatformDeps>;
|
|
735
860
|
//# sourceMappingURL=Evolu.d.ts.map
|