@evolu/common 8.11.0 → 8.13.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 +39 -2
- package/dist/src/Bytes.d.ts.map +1 -1
- package/dist/src/Bytes.js +50 -2
- package/dist/src/Callbacks.d.ts +12 -1
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Callbacks.js +3 -0
- package/dist/src/Error.d.ts +10 -4
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +10 -4
- package/dist/src/Object.d.ts +65 -0
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +142 -0
- package/dist/src/Resource.d.ts +0 -5
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +6 -13
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +7 -0
- package/dist/src/Task.d.ts +10 -8
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +41 -5
- package/dist/src/Worker.d.ts +3 -3
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/local-first/Db.d.ts +8 -3
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +56 -19
- package/dist/src/local-first/Evolu.d.ts +142 -24
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +109 -8
- package/dist/src/local-first/Owner.d.ts +9 -0
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +9 -0
- package/dist/src/local-first/Protocol.d.ts +18 -7
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +45 -28
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Relay.js +4 -2
- package/dist/src/local-first/Schema.d.ts +18 -3
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Shared.d.ts +523 -133
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +696 -256
- package/dist/src/local-first/Storage.d.ts +19 -15
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +4 -2
- package/package.json +1 -1
- package/src/Bytes.test.ts +27 -0
- package/src/Bytes.ts +58 -2
- package/src/Callbacks.test.ts +20 -0
- package/src/Callbacks.ts +17 -1
- package/src/Error.ts +10 -4
- package/src/Object.test.ts +296 -0
- package/src/Object.ts +163 -0
- package/src/Resource.test.ts +20 -16
- package/src/Resource.ts +6 -20
- package/src/Sqlite.ts +7 -0
- package/src/Task.test.ts +233 -62
- package/src/Task.ts +47 -13
- package/src/Worker.ts +3 -3
- package/src/index.ts +6 -1
- package/src/local-first/Db.ts +88 -18
- package/src/local-first/Evolu.test.ts +589 -2
- package/src/local-first/Evolu.ts +285 -36
- package/src/local-first/Owner.ts +9 -0
- package/src/local-first/Protocol.test.ts +59 -60
- package/src/local-first/Protocol.ts +67 -47
- package/src/local-first/Relay.ts +4 -2
- package/src/local-first/Schema.ts +20 -3
- package/src/local-first/Shared.test.ts +2633 -646
- package/src/local-first/Shared.ts +1192 -364
- package/src/local-first/Storage.ts +24 -23
|
@@ -5,21 +5,18 @@
|
|
|
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
8
|
import type { UnknownError } from "../Error.ts";
|
|
10
9
|
import { type LockManagerDep } from "../LockManager.ts";
|
|
11
10
|
import type { FlushSyncDep, ReloadAppDep } from "../Platform.ts";
|
|
12
11
|
import type { Listener, ReadonlyStore, Unsubscribe } from "../Store.ts";
|
|
13
12
|
import type { Task } from "../Task.ts";
|
|
14
|
-
import { Name, type TypeError, UrlSafeString } from "../Type.ts";
|
|
13
|
+
import { Name, PositiveInt, type TypeError, UrlSafeString } from "../Type.ts";
|
|
15
14
|
import type { CreateBroadcastChannelDep, CreateMessageChannelDep } from "../Worker.ts";
|
|
16
15
|
import type { CreateDbWorkerDep, UnsupportedDbVersionError } from "./Db.ts";
|
|
17
16
|
import type { AppOwner, Owner, OwnerId, OwnerTransport, ReadonlyOwner } from "./Owner.ts";
|
|
18
|
-
import type { ProtocolError } from "./Protocol.ts";
|
|
19
17
|
import type { Queries, QueriesToQueryRowsPromises, Query, QueryRows, Row } from "./Query.ts";
|
|
20
|
-
import type { EvoluSchema, IndexesConfig, Mutation, ValidateSchema } from "./Schema.ts";
|
|
18
|
+
import type { EvoluSchema, IndexesConfig, Mutation, MutationValues, ValidateSchema } from "./Schema.ts";
|
|
21
19
|
import type { OtherBuildRunningError, SharedWorkerDep, SyncState } from "./Shared.ts";
|
|
22
|
-
import { type StorageQuotaError } from "./Storage.ts";
|
|
23
20
|
/**
|
|
24
21
|
* Configuration for {@link createEvolu}.
|
|
25
22
|
*
|
|
@@ -276,8 +273,10 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
276
273
|
*
|
|
277
274
|
* Pass `onComplete` when follow-up work must wait until the mutation is
|
|
278
275
|
* stored and subscribed queries reflect it. It never runs when the database
|
|
279
|
-
* is unavailable; see {@link Evolu.loadQuery}.
|
|
280
|
-
*
|
|
276
|
+
* is unavailable; see {@link Evolu.loadQuery}. It also never runs when the
|
|
277
|
+
* mutation could not be stored, which {@link EvoluErrorDep.evoluError}
|
|
278
|
+
* reports. A stored change is not always visible; see
|
|
279
|
+
* {@link MutationOptions.onComplete}.
|
|
281
280
|
*
|
|
282
281
|
* ### Example
|
|
283
282
|
*
|
|
@@ -394,6 +393,37 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
394
393
|
* @see {@link Mutation}
|
|
395
394
|
*/
|
|
396
395
|
readonly upsert: Mutation<S, "upsert">;
|
|
396
|
+
/**
|
|
397
|
+
* Returns the size of a mutation of `table` with `values`, measured as
|
|
398
|
+
* {@link maxMutationSize} describes.
|
|
399
|
+
*
|
|
400
|
+
* Use it to check values that column Types do not bound before mutating, or
|
|
401
|
+
* to show how much of the limit a mutation uses. It accepts any of the
|
|
402
|
+
* table's columns, so the values of an insert, update, or upsert fit, and it
|
|
403
|
+
* ignores `id` and `isDeleted`, which are not columns. Mutations of
|
|
404
|
+
* local-only tables are measured too, although they are exempt from the
|
|
405
|
+
* limit.
|
|
406
|
+
*
|
|
407
|
+
* ### Example
|
|
408
|
+
*
|
|
409
|
+
* ```ts
|
|
410
|
+
* import {
|
|
411
|
+
* assertType,
|
|
412
|
+
* type Evolu,
|
|
413
|
+
* maxMutationSize,
|
|
414
|
+
* type NonEmptyTrimmedString100,
|
|
415
|
+
* type TestEvoluSchema,
|
|
416
|
+
* } from "@evolu/common";
|
|
417
|
+
*
|
|
418
|
+
* const fitsTodo = (
|
|
419
|
+
* evolu: Evolu<TestEvoluSchema>,
|
|
420
|
+
* title: NonEmptyTrimmedString100,
|
|
421
|
+
* ) => evolu.getMutationSize("todo", { title }) <= maxMutationSize;
|
|
422
|
+
*
|
|
423
|
+
* assertType<ReturnType<typeof fitsTodo>, boolean>();
|
|
424
|
+
* ```
|
|
425
|
+
*/
|
|
426
|
+
readonly getMutationSize: <TableName extends keyof S>(table: TableName, values: Partial<MutationValues<S[TableName], "update">>) => PositiveInt;
|
|
397
427
|
/**
|
|
398
428
|
* Load {@link Query} and return a promise with {@link QueryRows}.
|
|
399
429
|
*
|
|
@@ -547,6 +577,9 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
547
577
|
/**
|
|
548
578
|
* Exports the SQLite database file.
|
|
549
579
|
*
|
|
580
|
+
* The exported file is not encrypted, even when the local database is. Any
|
|
581
|
+
* SQLite tool can read all local data from it, so treat it as plaintext.
|
|
582
|
+
*
|
|
550
583
|
* Exports are sequential: concurrent calls share one pending export instead
|
|
551
584
|
* of starting parallel exports.
|
|
552
585
|
*
|
|
@@ -649,9 +682,12 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
649
682
|
*
|
|
650
683
|
* Reconciles locally stored changes, including writes previously rejected
|
|
651
684
|
* with {@link ProtocolQuotaError}, through the owner's active transports. Call
|
|
652
|
-
* this after the relay provider confirms additional quota is available.
|
|
653
|
-
*
|
|
654
|
-
*
|
|
685
|
+
* this after the relay provider confirms additional quota is available. It
|
|
686
|
+
* also checks again the changes this database skipped from the owner's
|
|
687
|
+
* relays, and sends such a relay the changes received from other relays,
|
|
688
|
+
* which otherwise wait for its next sync, such as after a reconnect. Existing
|
|
689
|
+
* connections and {@link Evolu.useOwner} registrations are retained, including
|
|
690
|
+
* registrations shared by multiple instances or tabs.
|
|
655
691
|
*
|
|
656
692
|
* The owner must have an active writable registration in this database.
|
|
657
693
|
* Unregistered or read-only owners are ignored. Requests are skipped while
|
|
@@ -659,8 +695,9 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
659
695
|
* reopen. Disposal drops locally buffered requests. Calling a disposed
|
|
660
696
|
* instance throws, like other Evolu operations.
|
|
661
697
|
*
|
|
662
|
-
* Returns immediately, without waiting for synchronization to complete.
|
|
663
|
-
*
|
|
698
|
+
* Returns immediately, without waiting for synchronization to complete. The
|
|
699
|
+
* owner's routes in sync state show a failure, such as a quota rejection, as
|
|
700
|
+
* `failure`, and a skipped change as `skippedError`.
|
|
664
701
|
*
|
|
665
702
|
* ### Example
|
|
666
703
|
*
|
|
@@ -687,11 +724,76 @@ export interface Evolu<S extends EvoluSchema = EvoluSchema> extends AsyncDisposa
|
|
|
687
724
|
*/
|
|
688
725
|
export type UnuseOwner = () => void;
|
|
689
726
|
/**
|
|
690
|
-
* Represents errors that can occur in {@link Evolu}.
|
|
727
|
+
* Represents app-level errors that can occur in {@link Evolu}.
|
|
728
|
+
*
|
|
729
|
+
* Apps show them from {@link EvoluErrorDep.evoluError}. Problems a relay causes
|
|
730
|
+
* while syncing an owner are not EvoluErrors; see below. An unexpected failure
|
|
731
|
+
* while syncing is an {@link UnknownError}.
|
|
732
|
+
*
|
|
733
|
+
* An error that leaves the app unusable deserves a modal dialog, which moves
|
|
734
|
+
* focus into itself and restores it when closed. Any other error is a status
|
|
735
|
+
* message: show it in a region with `role="alert"`, which screen readers
|
|
736
|
+
* announce without moving focus, so the user keeps working and a background tab
|
|
737
|
+
* shows it when the user returns. Avoid `alert()`, which blocks the page, once
|
|
738
|
+
* in every open tab.
|
|
739
|
+
*
|
|
740
|
+
* - {@link UnsupportedDbVersionError} blocks the app: the local data needs a newer
|
|
741
|
+
* version of it. Ask the user to update the app or close all its tabs.
|
|
742
|
+
* - {@link OtherBuildRunningError} blocks the app while it lasts: another version
|
|
743
|
+
* of the app holds the local data. Ask the user to close the app's other
|
|
744
|
+
* tabs. It clears when the wait ends.
|
|
745
|
+
* - {@link UnknownError} does not block the app: Evolu logged an unexpected
|
|
746
|
+
* failure, such as a mutation that could not be stored. Show a generic
|
|
747
|
+
* message.
|
|
748
|
+
*
|
|
749
|
+
* A problem syncing an owner through a relay belongs to that relay and often
|
|
750
|
+
* repeats in every round, so sync state shows it on the relay's route, as its
|
|
751
|
+
* {@link PendingSyncRoute.failure} with its details, and apps show it as the
|
|
752
|
+
* owner's `Error` {@link OwnerSyncStatus}. When the relay rejected or failed a
|
|
753
|
+
* request, or sent a frame that could not be decoded, the route shows a
|
|
754
|
+
* {@link ProtocolError}. A {@link ProtocolQuotaError} needs more relay quota,
|
|
755
|
+
* then {@link Evolu.requestSync}, and a {@link ProtocolVersionError} needs an app
|
|
756
|
+
* or relay update.
|
|
757
|
+
*
|
|
758
|
+
* A received change that was not created with the owner's encryption key, was
|
|
759
|
+
* altered afterwards, or cannot be decoded by this app version is skipped,
|
|
760
|
+
* while everything else still syncs. The relay offers it again in every round,
|
|
761
|
+
* so the route shows it as its `skippedError`: the
|
|
762
|
+
* {@link DecryptWithXChaCha20Poly1305Error},
|
|
763
|
+
* {@link ProtocolTimestampMismatchError}, or {@link ProtocolInvalidDataError} of
|
|
764
|
+
* the first change skipped in a reply, with its details. The owner's status is
|
|
765
|
+
* `Error` with it too, unless a relay has a failure. Once this database stores
|
|
766
|
+
* a valid change with that timestamp, for example from another relay, the relay
|
|
767
|
+
* no longer offers its copy, and the route completes with its next sync, such
|
|
768
|
+
* as after a reconnect or {@link Evolu.requestSync}, during which no changes
|
|
769
|
+
* arrive from other relays. If you don't trust that relay, stop using it for
|
|
770
|
+
* the owner. For owners that use the default transports, such as
|
|
771
|
+
* {@link Evolu.appOwner} when {@link EvoluConfig.transports} is not empty,
|
|
772
|
+
* replace the relay there; an empty list stops syncing the app owner and makes
|
|
773
|
+
* {@link Evolu.useOwner} require explicit transports. For an owner you passed
|
|
774
|
+
* explicit transports to {@link Evolu.useOwner}, call its {@link UnuseOwner} and
|
|
775
|
+
* use it again without that relay. Do this wherever the owner is used, such as
|
|
776
|
+
* in every tab, because the owner syncs through every transport any of its uses
|
|
777
|
+
* claims. If every route of the owner shows
|
|
778
|
+
* {@link DecryptWithXChaCha20Poly1305Error} and your code creates or shares the
|
|
779
|
+
* owner, check the owner's keys.
|
|
780
|
+
*
|
|
781
|
+
* @group Core
|
|
782
|
+
*/
|
|
783
|
+
export type EvoluError = OtherBuildRunningError | UnknownError | UnsupportedDbVersionError;
|
|
784
|
+
/**
|
|
785
|
+
* The largest {@link Mutation}, in bytes.
|
|
786
|
+
*
|
|
787
|
+
* A mutation's size is its change as encoded for sync: the table name, the ID,
|
|
788
|
+
* and every column name and value, with a few bytes of overhead. A string takes
|
|
789
|
+
* at most three bytes per UTF-16 code unit. Every mutation within the limit
|
|
790
|
+
* fits one protocol message, so it can always sync. A larger mutation throws
|
|
791
|
+
* and is not saved. Mutations of local-only tables are exempt, because they
|
|
792
|
+
* never sync. Measure a mutation in advance with {@link Evolu.getMutationSize}.
|
|
691
793
|
*
|
|
692
794
|
* @group Core
|
|
693
795
|
*/
|
|
694
|
-
export
|
|
796
|
+
export declare const maxMutationSize: PositiveInt;
|
|
695
797
|
/**
|
|
696
798
|
* Dependency wrapper for the shared {@link EvoluError} store.
|
|
697
799
|
*
|
|
@@ -719,6 +821,13 @@ export interface EvoluErrorDep {
|
|
|
719
821
|
* instead; see {@link UnsupportedDbVersionError}. Show that blocking message
|
|
720
822
|
* outside any query-loading boundary, so pending queries do not hide it.
|
|
721
823
|
*
|
|
824
|
+
* An {@link UnknownError} leaves Evolu in an unknown state, so the app can
|
|
825
|
+
* only ask the user to close the tab. A failed shared worker closes itself,
|
|
826
|
+
* so the app opened again starts a new one. Some errors reach every tab, such
|
|
827
|
+
* as an unexpected failure of the shared worker. An app that forwards this
|
|
828
|
+
* store to an error tracker from each tab then reports such an error once per
|
|
829
|
+
* tab.
|
|
830
|
+
*
|
|
722
831
|
* ### Example
|
|
723
832
|
*
|
|
724
833
|
* ```ts
|
|
@@ -732,14 +841,13 @@ export interface EvoluErrorDep {
|
|
|
732
841
|
* // The message for the current error, or null for none.
|
|
733
842
|
* const errorMessage = (error: EvoluError | null): string | null => {
|
|
734
843
|
* if (!error) return null;
|
|
735
|
-
* // oxlint-disable-next-line typescript/switch-exhaustiveness-check -- The default handles every other EvoluError.
|
|
736
844
|
* switch (error.type) {
|
|
737
845
|
* case "UnsupportedDbVersionError":
|
|
738
846
|
* return "Your data requires a newer version of this app. Please update it.";
|
|
739
847
|
* case "OtherBuildRunningError":
|
|
740
848
|
* return "This app is open in another tab with a different version. Close that tab to continue.";
|
|
741
|
-
*
|
|
742
|
-
* return "Something went wrong. Please
|
|
849
|
+
* case "UnknownError":
|
|
850
|
+
* return "Something went wrong. Please close this tab and open the app again.";
|
|
743
851
|
* }
|
|
744
852
|
* };
|
|
745
853
|
*
|
|
@@ -774,8 +882,15 @@ export interface SyncStateDep {
|
|
|
774
882
|
/**
|
|
775
883
|
* {@link ReadonlyStore} of the latest {@link SyncState} shared by all
|
|
776
884
|
* {@link Evolu} instances, or null before the shared worker sends its first
|
|
777
|
-
* snapshot.
|
|
778
|
-
*
|
|
885
|
+
* snapshot. It lists every database the shared worker serves, including other
|
|
886
|
+
* tabs', so an app finds its own by {@link Evolu.name}. Apps show users an
|
|
887
|
+
* owner's {@link OwnerSyncStatus}, from {@link syncStateToOwnerSyncStatus} or a
|
|
888
|
+
* framework binding's `useOwnerSyncStatus`; views of each relay use
|
|
889
|
+
* {@link syncStateToRelaySyncStates}.
|
|
890
|
+
*
|
|
891
|
+
* Each snapshot keeps the previous snapshot's object for every part that did
|
|
892
|
+
* not change, and a snapshot equal to the previous one leaves the store
|
|
893
|
+
* unchanged, so parts and derived statuses can be compared with `===`.
|
|
779
894
|
*
|
|
780
895
|
* ### Example
|
|
781
896
|
*
|
|
@@ -784,6 +899,7 @@ export interface SyncStateDep {
|
|
|
784
899
|
* assertEqual,
|
|
785
900
|
* createId,
|
|
786
901
|
* createStore,
|
|
902
|
+
* Millis,
|
|
787
903
|
* testCreateDeps,
|
|
788
904
|
* } from "@evolu/common";
|
|
789
905
|
* import type {
|
|
@@ -793,7 +909,7 @@ export interface SyncStateDep {
|
|
|
793
909
|
*
|
|
794
910
|
* const openRelayLabels = (deps: SyncStateDep): ReadonlyArray<string> =>
|
|
795
911
|
* (deps.syncState.get()?.transports ?? [])
|
|
796
|
-
* .filter(({
|
|
912
|
+
* .filter(({ connection }) => connection.type === "Open")
|
|
797
913
|
* .map(({ label }) => label);
|
|
798
914
|
*
|
|
799
915
|
* using syncState = createStore<SyncState | null>(null);
|
|
@@ -803,12 +919,14 @@ export interface SyncStateDep {
|
|
|
803
919
|
* syncState.set({
|
|
804
920
|
* transports: [
|
|
805
921
|
* {
|
|
922
|
+
* type: "WebSocket",
|
|
806
923
|
* id: createId<"SyncTransport">(deps),
|
|
807
924
|
* label: "wss://relay.example",
|
|
808
|
-
*
|
|
809
|
-
*
|
|
810
|
-
*
|
|
811
|
-
*
|
|
925
|
+
* connection: {
|
|
926
|
+
* type: "Open",
|
|
927
|
+
* openedAt: Millis.orThrow(1000),
|
|
928
|
+
* error: null,
|
|
929
|
+
* },
|
|
812
930
|
* },
|
|
813
931
|
* ],
|
|
814
932
|
* tenants: [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../../src/local-first/Evolu.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAIL,KAAK,qBAAqB,EAC3B,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"Evolu.d.ts","sourceRoot":"","sources":["../../../src/local-first/Evolu.ts"],"names":[],"mappings":"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"}
|
|
@@ -57,23 +57,27 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
57
57
|
});
|
|
58
58
|
import { emptyArray, isNonEmptyArray, mapArray, } from "../Array.js";
|
|
59
59
|
import { assert, assertNonEmptyReadonlyArray, assertNotUndefined, } from "../Assert.js";
|
|
60
|
+
import { createBuffer } from "../Bytes.js";
|
|
60
61
|
import { createCallbacks } from "../Callbacks.js";
|
|
61
62
|
import { createConsole } from "../Console.js";
|
|
62
63
|
import { createUnknownError } from "../Error.js";
|
|
63
64
|
import { disposable, exhaustiveCheck, todo } from "../Function.js";
|
|
64
65
|
import { acquireLeaderLock, acquireLeaderLockCallback, } from "../LockManager.js";
|
|
65
66
|
import { createMicrotaskBatch } from "../Microtask.js";
|
|
67
|
+
import { createMutableRecord, isPlainObject, objectToEntries, shareStructure, } from "../Object.js";
|
|
66
68
|
import { createRefCountByKey } from "../RefCount.js";
|
|
67
69
|
import { err, ok } from "../Result.js";
|
|
68
70
|
import { isNonEmptySet } from "../Set.js";
|
|
69
|
-
import { SqliteBoolean, sqliteBooleanToBoolean } from "../Sqlite.js";
|
|
71
|
+
import { SqliteBoolean, sqliteBooleanToBoolean, } from "../Sqlite.js";
|
|
70
72
|
import { createStore } from "../Store.js";
|
|
71
|
-
import { brand, createId, createIdFromString, Name, UrlSafeString, } from "../Type.js";
|
|
73
|
+
import { brand, createId, createIdFromString, Id, Name, PositiveInt, UrlSafeString, } from "../Type.js";
|
|
72
74
|
import { createOwnerWebSocketTransport } from "./Owner.js";
|
|
75
|
+
import { encodeDbChange, } from "./Protocol.js";
|
|
73
76
|
import { applyPatches } from "./Query.js";
|
|
74
|
-
import { evoluSchemaToSqliteSchema } from "./Schema.js";
|
|
77
|
+
import { evoluSchemaToSqliteSchema, isLocalOnlyTable } from "./Schema.js";
|
|
75
78
|
import { consoleEntryOrErrorBroadcastChannelName } from "./Shared.js";
|
|
76
79
|
import { DbChange } from "./Storage.js";
|
|
80
|
+
import { createTimestamp } from "./Timestamp.js";
|
|
77
81
|
/**
|
|
78
82
|
* Application name.
|
|
79
83
|
*
|
|
@@ -95,6 +99,47 @@ export const AppName = /*#__PURE__*/ brand("AppName", UrlSafeString, (value) =>
|
|
|
95
99
|
* @group Testing
|
|
96
100
|
*/
|
|
97
101
|
export const testAppName = /*#__PURE__*/ AppName.orThrow("AppName");
|
|
102
|
+
/**
|
|
103
|
+
* The largest {@link Mutation}, in bytes.
|
|
104
|
+
*
|
|
105
|
+
* A mutation's size is its change as encoded for sync: the table name, the ID,
|
|
106
|
+
* and every column name and value, with a few bytes of overhead. A string takes
|
|
107
|
+
* at most three bytes per UTF-16 code unit. Every mutation within the limit
|
|
108
|
+
* fits one protocol message, so it can always sync. A larger mutation throws
|
|
109
|
+
* and is not saved. Mutations of local-only tables are exempt, because they
|
|
110
|
+
* never sync. Measure a mutation in advance with {@link Evolu.getMutationSize}.
|
|
111
|
+
*
|
|
112
|
+
* @group Core
|
|
113
|
+
*/
|
|
114
|
+
export const maxMutationSize =
|
|
115
|
+
/*#__PURE__*/ PositiveInt.orThrow(640_000);
|
|
116
|
+
/** Measures a mutation as {@link maxMutationSize} describes. */
|
|
117
|
+
const measureMutation = (table, values) => {
|
|
118
|
+
const columns = createMutableRecord();
|
|
119
|
+
for (const [column, value] of objectToEntries(values)) {
|
|
120
|
+
if (value !== undefined && column !== "id" && column !== "isDeleted") {
|
|
121
|
+
columns[column] = value;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Measuring with the protocol's encoding keeps the limit and the message size
|
|
125
|
+
// from disagreeing. A separate formula would save the tab about 3 KB
|
|
126
|
+
// compressed, but it would be a second encoding to keep in sync, and it
|
|
127
|
+
// would have to overcount.
|
|
128
|
+
const buffer = createBuffer();
|
|
129
|
+
encodeDbChange(buffer, {
|
|
130
|
+
// Every timestamp and ID takes 16 bytes, and the flags always take one.
|
|
131
|
+
timestamp: createTimestamp(),
|
|
132
|
+
change: DbChange.orThrow({
|
|
133
|
+
table,
|
|
134
|
+
id: mutationSizeId,
|
|
135
|
+
values: columns,
|
|
136
|
+
isInsert: true,
|
|
137
|
+
isDelete: null,
|
|
138
|
+
}),
|
|
139
|
+
});
|
|
140
|
+
return buffer.getLength();
|
|
141
|
+
};
|
|
142
|
+
const mutationSizeId = /*#__PURE__*/ Id.orThrow("A".repeat(22));
|
|
98
143
|
/**
|
|
99
144
|
* Creates shared dependencies used by all {@link createEvolu} instances on a
|
|
100
145
|
* platform.
|
|
@@ -138,11 +183,16 @@ export const createEvoluDeps = (deps) => {
|
|
|
138
183
|
setEvoluError(createUnknownError(message.entry.args));
|
|
139
184
|
}
|
|
140
185
|
break;
|
|
141
|
-
case "Error":
|
|
142
|
-
|
|
186
|
+
case "Error": {
|
|
187
|
+
// Every build shares this channel, so another build's worker can post
|
|
188
|
+
// an error type this build does not post, such as an older build's
|
|
189
|
+
// sync error. That build's own tabs show it, so this tab only logs it.
|
|
190
|
+
if (message.error.type === "UnknownError")
|
|
191
|
+
setEvoluError(message.error);
|
|
143
192
|
// Keep typed errors visible in logs as operational failures.
|
|
144
193
|
console.error(message.error);
|
|
145
194
|
break;
|
|
195
|
+
}
|
|
146
196
|
default:
|
|
147
197
|
exhaustiveCheck(message);
|
|
148
198
|
}
|
|
@@ -153,8 +203,9 @@ export const createEvoluDeps = (deps) => {
|
|
|
153
203
|
deps.createDbWorker().postMessage(message, [message.port]);
|
|
154
204
|
break;
|
|
155
205
|
case "Error":
|
|
156
|
-
// Sent to this tab only: its database refused startup,
|
|
157
|
-
// still waits for another
|
|
206
|
+
// Sent to this tab only: its database refused startup, a mutation it
|
|
207
|
+
// made could not be stored, or its worker still waits for another
|
|
208
|
+
// build.
|
|
158
209
|
setEvoluError(message.error);
|
|
159
210
|
console.error(message.error);
|
|
160
211
|
break;
|
|
@@ -173,7 +224,13 @@ export const createEvoluDeps = (deps) => {
|
|
|
173
224
|
// arrive in order, so the last one is current.
|
|
174
225
|
syncStateBroadcastChannel = createBroadcastChannel(message.syncStateChannelName);
|
|
175
226
|
syncStateBroadcastChannel.onMessage = (state) => {
|
|
176
|
-
|
|
227
|
+
// Every snapshot arrives as a new structured clone, so its unchanged
|
|
228
|
+
// parts get the previous snapshot's objects back, and an unchanged
|
|
229
|
+
// snapshot leaves the store as it is.
|
|
230
|
+
const previous = syncState.get();
|
|
231
|
+
syncState.set(previous
|
|
232
|
+
? shareStructure(previous, state, syncStateItemToKey)
|
|
233
|
+
: state);
|
|
177
234
|
};
|
|
178
235
|
// Asking only after listening misses no snapshot.
|
|
179
236
|
sharedWorker.port.postMessage({ type: "RequestSyncState" });
|
|
@@ -209,6 +266,12 @@ export const createEvoluDeps = (deps) => {
|
|
|
209
266
|
__disposeResources(env_1);
|
|
210
267
|
}
|
|
211
268
|
};
|
|
269
|
+
// Transports, tenants, owners, and routes come and go, so each is compared
|
|
270
|
+
// with its previous self by its ID: a transport's id, a tenant's name, an
|
|
271
|
+
// owner's ownerId, or a route's transportId. A wrong key only loses sharing.
|
|
272
|
+
const syncStateItemToKey = (item) => isPlainObject(item)
|
|
273
|
+
? (item.id ?? item.name ?? item.ownerId ?? item.transportId)
|
|
274
|
+
: undefined;
|
|
212
275
|
/**
|
|
213
276
|
* Creates an {@link Evolu} instance from {@link EvoluSchema} and
|
|
214
277
|
* {@link EvoluConfig}.
|
|
@@ -342,6 +405,13 @@ export const createEvolu = (schema, config) => async (run) => {
|
|
|
342
405
|
exportDatabasePending = null;
|
|
343
406
|
break;
|
|
344
407
|
}
|
|
408
|
+
case "OnMutateFailed": {
|
|
409
|
+
// The tab reports the failure, and these callbacks never run.
|
|
410
|
+
for (const onCompleteId of message.onCompleteIds) {
|
|
411
|
+
onMutateCompleteCallbacks.unregister(onCompleteId);
|
|
412
|
+
}
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
345
415
|
default:
|
|
346
416
|
exhaustiveCheck(message);
|
|
347
417
|
}
|
|
@@ -397,6 +467,36 @@ export const createEvolu = (schema, config) => async (run) => {
|
|
|
397
467
|
: null,
|
|
398
468
|
};
|
|
399
469
|
assert(DbChange.is(dbChange), `Invalid DbChange for table '${String(table)}'.`);
|
|
470
|
+
// Copy binary values, so what is saved is what was passed: the caller
|
|
471
|
+
// can change a Uint8Array before the batch is sent, a view of a
|
|
472
|
+
// resizable buffer can grow, and a view of a shared buffer cannot be
|
|
473
|
+
// sent to a SharedWorker at all. Node's Buffer passes validation and
|
|
474
|
+
// its slice shares memory, so only the constructor copies reliably.
|
|
475
|
+
for (const [column, value] of objectToEntries(dbChange.values)) {
|
|
476
|
+
if (typeof value === "object" && value !== null) {
|
|
477
|
+
changeValues[column] = new Uint8Array(value);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
// A change over maxMutationSize could never sync, and a shared worker
|
|
481
|
+
// hosting two databases would stop all work of that database. Correct
|
|
482
|
+
// apps bound column Types, so it is a programmer error and throws like
|
|
483
|
+
// the DbChange check above, before batching: it gets no timestamp, the
|
|
484
|
+
// database worker never sees it, and the code after the call does not
|
|
485
|
+
// run, so a form keeps its input and no row refers to the missing one.
|
|
486
|
+
//
|
|
487
|
+
// Rejected: reporting it through evoluError, which lets that code run
|
|
488
|
+
// as if the mutation was saved; checking in the database worker, which
|
|
489
|
+
// gets it already batched and cannot reach the call site; quarantine,
|
|
490
|
+
// which holds changes stored for sync; and skipping it in sync, which
|
|
491
|
+
// keeps range fingerprints disagreeing. Received changes are not
|
|
492
|
+
// checked, and oversized changes stored before this limit are not
|
|
493
|
+
// recovered, which needs a history-aware design.
|
|
494
|
+
//
|
|
495
|
+
// Local-only tables never sync, so they have no limit.
|
|
496
|
+
if (!isLocalOnlyTable(dbChange.table)) {
|
|
497
|
+
const size = measureMutation(dbChange.table, dbChange.values);
|
|
498
|
+
assert(size <= maxMutationSize, `The mutation of table '${dbChange.table}' is ${size} bytes, over maxMutationSize (${maxMutationSize}). Bound the Types of its columns or check it with evolu.getMutationSize.`);
|
|
499
|
+
}
|
|
400
500
|
mutateBatch.push({
|
|
401
501
|
change: { ...dbChange, ownerId: options?.ownerId ?? appOwner.id },
|
|
402
502
|
onComplete: options?.onComplete,
|
|
@@ -458,6 +558,7 @@ export const createEvolu = (schema, config) => async (run) => {
|
|
|
458
558
|
insert: createMutation("insert"),
|
|
459
559
|
update: createMutation("update"),
|
|
460
560
|
upsert: createMutation("upsert"),
|
|
561
|
+
getMutationSize: (table, values) => measureMutation(String(table), values),
|
|
461
562
|
loadQuery,
|
|
462
563
|
loadQueries: (queries) => queries.map((query) => loadQuery(query)),
|
|
463
564
|
subscribeQuery: (query) => (listener) => {
|
|
@@ -28,6 +28,15 @@
|
|
|
28
28
|
* - {@link OwnerEncryptionKey}: the symmetric key that protects the data.
|
|
29
29
|
* - {@link OwnerWriteKey}: the rotatable token that authorizes writes.
|
|
30
30
|
*
|
|
31
|
+
* Only holders of the encryption key can create an owner's changes. Each change
|
|
32
|
+
* is encrypted and authenticated together with its timestamp, so a relay, or
|
|
33
|
+
* anyone who can write to a relay for the owner, can store bytes for the owner
|
|
34
|
+
* but cannot forge or move a change. A client stores only the changes it can
|
|
35
|
+
* decrypt, verify, and decode, and syncs only what it stored. It skips any
|
|
36
|
+
* other change, which sync state shows on the route of the relay that holds it,
|
|
37
|
+
* and the relay offers it again on each sync until the client stores a valid
|
|
38
|
+
* change with that timestamp.
|
|
39
|
+
*
|
|
31
40
|
* @module
|
|
32
41
|
*/
|
|
33
42
|
import type { NonEmptyReadonlyArray } from "../Array.ts";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Owner.d.ts","sourceRoot":"","sources":["../../../src/local-first/Owner.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"Owner.d.ts","sourceRoot":"","sources":["../../../src/local-first/Owner.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,6 +28,15 @@
|
|
|
28
28
|
* - {@link OwnerEncryptionKey}: the symmetric key that protects the data.
|
|
29
29
|
* - {@link OwnerWriteKey}: the rotatable token that authorizes writes.
|
|
30
30
|
*
|
|
31
|
+
* Only holders of the encryption key can create an owner's changes. Each change
|
|
32
|
+
* is encrypted and authenticated together with its timestamp, so a relay, or
|
|
33
|
+
* anyone who can write to a relay for the owner, can store bytes for the owner
|
|
34
|
+
* but cannot forge or move a change. A client stores only the changes it can
|
|
35
|
+
* decrypt, verify, and decode, and syncs only what it stored. It skips any
|
|
36
|
+
* other change, which sync state shows on the route of the relay that holds it,
|
|
37
|
+
* and the relay offers it again on each sync until the client stores a valid
|
|
38
|
+
* change with that timestamp.
|
|
39
|
+
*
|
|
31
40
|
* @module
|
|
32
41
|
*/
|
|
33
42
|
import * as bip39 from "@scure/bip39";
|
|
@@ -103,9 +103,9 @@
|
|
|
103
103
|
* fit within the limit, the protocol automatically continues synchronization in
|
|
104
104
|
* subsequent rounds using range-based reconciliation.
|
|
105
105
|
*
|
|
106
|
-
*
|
|
107
|
-
* message
|
|
108
|
-
*
|
|
106
|
+
* Each mutation is limited to {@link maxMutationSize}, so every change fits one
|
|
107
|
+
* message of {@link defaultProtocolMessageMaxSize} next to the largest ranges
|
|
108
|
+
* section.
|
|
109
109
|
*
|
|
110
110
|
* ## Why Binary?
|
|
111
111
|
*
|
|
@@ -304,8 +304,9 @@ export interface ProtocolInvalidDataError extends Typed<"ProtocolInvalidDataErro
|
|
|
304
304
|
export interface ProtocolWriteKeyError extends OwnerError, Typed<"ProtocolWriteKeyError"> {
|
|
305
305
|
}
|
|
306
306
|
/**
|
|
307
|
-
* Error indicating a serious relay-side write failure.
|
|
308
|
-
*
|
|
307
|
+
* Error indicating a serious relay-side write failure. Sync state shows it as
|
|
308
|
+
* the failure of that relay's route; apps show a generic sync error for the
|
|
309
|
+
* owner's `Error` status.
|
|
309
310
|
*/
|
|
310
311
|
export interface ProtocolWriteError extends OwnerError, Typed<"ProtocolWriteError"> {
|
|
311
312
|
}
|
|
@@ -326,8 +327,9 @@ export interface ProtocolWriteError extends OwnerError, Typed<"ProtocolWriteErro
|
|
|
326
327
|
export interface ProtocolQuotaError extends OwnerError, Typed<"ProtocolQuotaError"> {
|
|
327
328
|
}
|
|
328
329
|
/**
|
|
329
|
-
* Error indicating a serious relay-side synchronization failure.
|
|
330
|
-
*
|
|
330
|
+
* Error indicating a serious relay-side synchronization failure. Sync state
|
|
331
|
+
* shows it as the failure of that relay's route; apps show a generic sync error
|
|
332
|
+
* for the owner's `Error` status.
|
|
331
333
|
*/
|
|
332
334
|
export interface ProtocolSyncError extends OwnerError, Typed<"ProtocolSyncError"> {
|
|
333
335
|
}
|
|
@@ -512,6 +514,15 @@ version?: NonNegativeInt) => Task<ApplyProtocolMessageAsRelayResult, ProtocolInv
|
|
|
512
514
|
* data.
|
|
513
515
|
*/
|
|
514
516
|
export declare const encodeAndEncryptDbChange: (deps: RandomBytesDep) => (message: CrdtMessage, key: EncryptionKey) => EncryptedDbChange;
|
|
517
|
+
/**
|
|
518
|
+
* Encodes a {@link CrdtMessage} as {@link encodeAndEncryptDbChange} does before
|
|
519
|
+
* padding and encryption.
|
|
520
|
+
*
|
|
521
|
+
* {@link Evolu.getMutationSize} measures mutations with this encoding, so
|
|
522
|
+
* {@link maxMutationSize} limits exactly what is encoded, and every change
|
|
523
|
+
* within it fits one protocol message.
|
|
524
|
+
*/
|
|
525
|
+
export declare const encodeDbChange: (buffer: Buffer, message: CrdtMessage) => void;
|
|
515
526
|
/**
|
|
516
527
|
* Decrypts and decodes an {@link EncryptedCrdtMessage} using the provided
|
|
517
528
|
* owner's encryption key. Verifies that the embedded timestamp matches the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Protocol.d.ts","sourceRoot":"","sources":["../../../src/local-first/Protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgKG;AAEH;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,aAAa,CAAC;AAQrB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,KAAK,MAAM,
|
|
1
|
+
{"version":3,"file":"Protocol.d.ts","sourceRoot":"","sources":["../../../src/local-first/Protocol.ts"],"names":[],"mappings":"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"}
|