@sqlite-sync/core 0.12.0 → 0.12.1
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/{crdt-sync-remote-source-Q6P6OiL0.js → crdt-sync-remote-source-CPXzmSIS.js} +2 -2
- package/dist/{crdt-sync-remote-source-Q6P6OiL0.js.map → crdt-sync-remote-source-CPXzmSIS.js.map} +1 -1
- package/dist/{crdt-table-schema-2w_AIpsV.js → crdt-table-schema-BRm_WdcW.js} +19 -2
- package/dist/crdt-table-schema-BRm_WdcW.js.map +1 -0
- package/dist/{index-3zVvNWRd.d.ts → index-BHsKLqcK.d.ts} +6 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +212 -186
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +3 -3
- package/dist/{make-crdt-table-D8VQ-ptj.js → make-crdt-table-C6l0F-o_.js} +2 -2
- package/dist/{make-crdt-table-D8VQ-ptj.js.map → make-crdt-table-C6l0F-o_.js.map} +1 -1
- package/dist/{reset-state-BQi96NLn.js → reset-state-t0tTGqoh.js} +23 -342
- package/dist/reset-state-t0tTGqoh.js.map +1 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.js +2 -2
- package/dist/system-schema-Dvl_BLId.js +523 -0
- package/dist/system-schema-Dvl_BLId.js.map +1 -0
- package/dist/worker.d.ts +2 -1
- package/dist/worker.js +15 -10
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
- package/dist/crdt-table-schema-2w_AIpsV.js.map +0 -1
- package/dist/reset-state-BQi96NLn.js.map +0 -1
- package/dist/system-schema-C2JZDv6L.js +0 -178
- package/dist/system-schema-C2JZDv6L.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as
|
|
3
|
-
import { a as
|
|
4
|
-
import { a as
|
|
1
|
+
import { a as memoryDbConfig, c as createKvStoreTableQuery, d as SQLiteDbWrapper, h as dummyKysely, l as createSQLiteKvStore, m as introspectDb, n as applyWorkerDbSchema, p as startPerformanceLogger, t as applyMemoryDbSchema, u as createStoredValue } from "./system-schema-Dvl_BLId.js";
|
|
2
|
+
import { a as acquireLock, d as noop, h as tryCatchAsync, i as TypedEvent, l as generateId, m as tryCatch, n as isNoOpCrdtEventPayload, o as createDeferredPromise, p as quoteId, r as TypedBroadcastChannel, s as createTypedEventTarget, t as CRDT_EVENT_NO_OP_PAYLOAD, u as jsonSafeParse } from "./crdt-table-schema-BRm_WdcW.js";
|
|
3
|
+
import { C as xxhash, S as createMigrator, T as createImportData, _ as createCrdtApplyFunction, a as acquireReplicaLock, b as verifySyncSchema, c as isWorkerErrorResponseMessage, f as isWorkerResponseMessage, g as createCrdtStorage, h as createCrdtSyncProducer, p as syncDbClientLockName, s as createBroadcastChannels, t as RESET_REQUEST_TTL_MS, u as isWorkerNotificationMessage, v as createSQLiteCrdtApplyFunction, w as createExportData, x as createMigrations, y as formatSchemaVerificationIssues } from "./reset-state-t0tTGqoh.js";
|
|
4
|
+
import { a as HLCCounter, c as serializeHLC, n as CrdtEventValidationError, o as compareHLC, r as validateNewCrdtEvent, s as deserializeHLC, t as createCrdtSyncRemoteSource } from "./crdt-sync-remote-source-CPXzmSIS.js";
|
|
5
5
|
import { n as buildWriteOriginByName, t as admitClientEvents } from "./admit-client-events-BDrJw4SK.js";
|
|
6
|
-
import { a as makeCrdtTable, o as registerCrdtIntentDrainer } from "./make-crdt-table-
|
|
6
|
+
import { a as makeCrdtTable, o as registerCrdtIntentDrainer } from "./make-crdt-table-C6l0F-o_.js";
|
|
7
7
|
import sqlite3InitModule from "@sqlite.org/sqlite-wasm";
|
|
8
8
|
//#region src/bound-map.ts
|
|
9
9
|
var BoundMap = class {
|
|
@@ -689,18 +689,22 @@ const createWorkerDbClient = async ({ broadcastChannels, worker, config }) => {
|
|
|
689
689
|
const queryWorker = (method, args) => {
|
|
690
690
|
if (isDisposed) return Promise.reject(/* @__PURE__ */ new Error("Worker client disposed"));
|
|
691
691
|
const requestId = crypto.randomUUID();
|
|
692
|
-
const promise = createDeferredPromise({
|
|
693
|
-
timeout: 3e4,
|
|
694
|
-
onTimeout: () => workerRequestsMap.delete(requestId)
|
|
695
|
-
});
|
|
696
|
-
workerRequestsMap.set(requestId, promise);
|
|
697
692
|
const request = {
|
|
698
693
|
type: "request",
|
|
699
694
|
requestId,
|
|
700
695
|
method,
|
|
701
696
|
args
|
|
702
697
|
};
|
|
703
|
-
|
|
698
|
+
try {
|
|
699
|
+
broadcastChannels.requests.postMessage(request);
|
|
700
|
+
} catch (error) {
|
|
701
|
+
return Promise.reject(error);
|
|
702
|
+
}
|
|
703
|
+
const promise = createDeferredPromise({
|
|
704
|
+
timeout: 3e4,
|
|
705
|
+
onTimeout: () => workerRequestsMap.delete(requestId)
|
|
706
|
+
});
|
|
707
|
+
workerRequestsMap.set(requestId, promise);
|
|
704
708
|
return promise.promise;
|
|
705
709
|
};
|
|
706
710
|
const handleWorkerResponse = (message) => {
|
|
@@ -734,14 +738,6 @@ const createWorkerDbClient = async ({ broadcastChannels, worker, config }) => {
|
|
|
734
738
|
sync: () => queryWorker("sync", []),
|
|
735
739
|
requestReload: (options) => queryWorker("requestReload", [options])
|
|
736
740
|
};
|
|
737
|
-
const statePromise = awaitWorkerState(eventTarget);
|
|
738
|
-
postWorkerConfig(worker, config);
|
|
739
|
-
rpc.postState().catch(noop);
|
|
740
|
-
let { state: workerState, storageGeneration } = await statePromise;
|
|
741
|
-
eventTarget.addEventListener("state-changed", (event) => {
|
|
742
|
-
workerState = event.payload.state;
|
|
743
|
-
storageGeneration = event.payload.storageGeneration;
|
|
744
|
-
});
|
|
745
741
|
const dispose = () => {
|
|
746
742
|
isDisposed = true;
|
|
747
743
|
broadcastChannels.responses.onmessage = null;
|
|
@@ -750,13 +746,25 @@ const createWorkerDbClient = async ({ broadcastChannels, worker, config }) => {
|
|
|
750
746
|
workerRequestsMap.delete(id);
|
|
751
747
|
}
|
|
752
748
|
};
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
749
|
+
try {
|
|
750
|
+
postWorkerConfig(worker, config);
|
|
751
|
+
rpc.postState().catch(noop);
|
|
752
|
+
let { state: workerState, storageGeneration } = await awaitWorkerState(eventTarget);
|
|
753
|
+
eventTarget.addEventListener("state-changed", (event) => {
|
|
754
|
+
workerState = event.payload.state;
|
|
755
|
+
storageGeneration = event.payload.storageGeneration;
|
|
756
|
+
});
|
|
757
|
+
return {
|
|
758
|
+
...rpc,
|
|
759
|
+
subscribe: eventTarget.addEventListener,
|
|
760
|
+
getState: () => workerState,
|
|
761
|
+
getStorageGeneration: () => storageGeneration,
|
|
762
|
+
dispose
|
|
763
|
+
};
|
|
764
|
+
} catch (error) {
|
|
765
|
+
dispose();
|
|
766
|
+
throw error;
|
|
767
|
+
}
|
|
760
768
|
};
|
|
761
769
|
function awaitWorkerState(eventTarget) {
|
|
762
770
|
const promise = createDeferredPromise({ timeout: 15e3 });
|
|
@@ -822,173 +830,191 @@ async function createSyncedDb(options) {
|
|
|
822
830
|
const instanceId = generateId();
|
|
823
831
|
const tabId = generateId();
|
|
824
832
|
const broadcastChannels = createBroadcastChannels(options.dbId);
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
await clientLockAcquired.promise;
|
|
832
|
-
const workerClient = await createWorkerDbClient({
|
|
833
|
-
worker: options.worker,
|
|
834
|
-
config: {
|
|
835
|
-
clientId: generateId(),
|
|
836
|
-
dbId: options.dbId,
|
|
837
|
-
props: options.workerProps
|
|
838
|
-
},
|
|
839
|
-
broadcastChannels
|
|
840
|
-
});
|
|
841
|
-
const hlcCounter = new HLCCounter(tabId, () => Date.now());
|
|
842
|
-
const workerClientSnapshot = await workerClient.getSnapshot();
|
|
843
|
-
const reactiveDb = await createSQLiteReactiveDb({
|
|
844
|
-
snapshot: workerClientSnapshot.file,
|
|
845
|
-
logger: defaultLogger
|
|
846
|
-
});
|
|
847
|
-
const memoryDbMigrator = {
|
|
848
|
-
currentSchemaVersion: workerClientSnapshot.schemaVersion,
|
|
849
|
-
latestSchemaVersion: workerClientSnapshot.schemaVersion,
|
|
850
|
-
migrateDbToLatest: () => {
|
|
851
|
-
throw new Error("Memory DB migrations are not implemented");
|
|
852
|
-
},
|
|
853
|
-
migrateEvent: (event, targetVersion) => {
|
|
854
|
-
if (event.schema_version === targetVersion) return event;
|
|
855
|
-
throw new Error("Memory DB migrations are not implemented");
|
|
856
|
-
},
|
|
857
|
-
migrateEvents: (events) => events
|
|
858
|
-
};
|
|
859
|
-
const { crdtStorage } = await createMemoryDb({
|
|
860
|
-
nodeId: tabId,
|
|
861
|
-
migrator: memoryDbMigrator,
|
|
862
|
-
reactiveDb,
|
|
863
|
-
hlcCounter,
|
|
864
|
-
crdtTables: options.syncDbSchema.tablesConfig,
|
|
865
|
-
syncDbSchema: options.syncDbSchema
|
|
866
|
-
});
|
|
867
|
-
const pullSyncId = createStoredValue({ initialValue: workerClientSnapshot.syncId });
|
|
868
|
-
const pushSyncId = createStoredValue({ initialValue: 0 });
|
|
869
|
-
const tabRemoteSource = createCrdtSyncRemoteSource({
|
|
870
|
-
bufferSize: 500,
|
|
871
|
-
pullSyncId,
|
|
872
|
-
pushSyncId,
|
|
873
|
-
storage: crdtStorage,
|
|
874
|
-
nodeId: tabId,
|
|
875
|
-
migrator: memoryDbMigrator,
|
|
876
|
-
remoteFactory: ({ onEventsAvailable }) => {
|
|
877
|
-
const subscription = workerClient.subscribe("new-event-chunk-applied", (event) => {
|
|
878
|
-
onEventsAvailable({
|
|
879
|
-
newSyncId: event.payload.newSyncId,
|
|
880
|
-
remoteEventHlcSum: event.payload.eventHlcSum
|
|
881
|
-
});
|
|
882
|
-
});
|
|
883
|
-
return {
|
|
884
|
-
pullEvents: (request) => workerClient.pullEvents(request),
|
|
885
|
-
pushEvents: (request) => workerClient.pushTabEvents(request),
|
|
886
|
-
disconnect: () => {
|
|
887
|
-
subscription.unsubscribe();
|
|
888
|
-
}
|
|
889
|
-
};
|
|
890
|
-
}
|
|
891
|
-
});
|
|
892
|
-
tabRemoteSource.goOnline();
|
|
893
|
-
const reloadRequestedSubscription = workerClient.subscribe("reload-requested", () => {
|
|
894
|
-
globalThis.location?.reload();
|
|
895
|
-
});
|
|
896
|
-
const reloadIfStorageReplaced = (storageGeneration) => {
|
|
897
|
-
if (storageGeneration !== workerClientSnapshot.storageGeneration) {
|
|
898
|
-
storageReplacedSubscription.unsubscribe();
|
|
899
|
-
globalThis.location?.reload();
|
|
900
|
-
}
|
|
901
|
-
};
|
|
902
|
-
const storageReplacedSubscription = workerClient.subscribe("state-changed", (event) => {
|
|
903
|
-
reloadIfStorageReplaced(event.payload.storageGeneration);
|
|
904
|
-
});
|
|
905
|
-
reloadIfStorageReplaced(workerClient.getStorageGeneration());
|
|
906
|
-
const sync = () => {
|
|
907
|
-
workerClient.sync().catch((error) => console.warn("Failed to start sync", error));
|
|
908
|
-
};
|
|
909
|
-
const syncWhenVisible = () => {
|
|
910
|
-
if (globalThis.document?.visibilityState === "visible") sync();
|
|
911
|
-
};
|
|
912
|
-
const dropConnection = () => {
|
|
913
|
-
workerClient.dropConnection().catch((error) => console.warn("Failed to drop connection", error));
|
|
914
|
-
};
|
|
915
|
-
globalThis.document?.addEventListener("visibilitychange", syncWhenVisible);
|
|
916
|
-
globalThis.addEventListener?.("online", sync);
|
|
917
|
-
globalThis.addEventListener?.("offline", dropConnection);
|
|
918
|
-
perf.logEnd("createSyncedDb", "initialized", "info");
|
|
919
|
-
const exportData = createExportData({
|
|
920
|
-
reactiveDb,
|
|
921
|
-
tablesConfig: options.syncDbSchema.tablesConfig,
|
|
922
|
-
schemaVersion: workerClientSnapshot.schemaVersion
|
|
923
|
-
});
|
|
924
|
-
const importData = (data, opts) => workerClient.importData(data, opts);
|
|
925
|
-
let isDisposed = false;
|
|
833
|
+
let releaseClientLock;
|
|
834
|
+
let disposeWorkerClient;
|
|
835
|
+
let releaseReplicaLock;
|
|
836
|
+
let disposeReactiveDb;
|
|
837
|
+
let disposeRemoteSource;
|
|
838
|
+
const cleanupCallbacks = [];
|
|
926
839
|
let unregisterDevtools;
|
|
840
|
+
let isDisposed = false;
|
|
927
841
|
const dispose = async () => {
|
|
928
842
|
if (isDisposed) return;
|
|
929
843
|
isDisposed = true;
|
|
930
844
|
unregisterDevtools?.();
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
const syncedDb = {
|
|
944
|
-
db: createSyncedDbDatabase(reactiveDb),
|
|
945
|
-
state: {
|
|
946
|
-
getState: workerClient.getState.bind(workerClient),
|
|
947
|
-
subscribe: (onChange) => {
|
|
948
|
-
const { unsubscribe } = workerClient.subscribe("state-changed", onChange);
|
|
949
|
-
return unsubscribe;
|
|
950
|
-
},
|
|
951
|
-
goOnline: workerClient.goOnline.bind(workerClient),
|
|
952
|
-
goOffline: workerClient.goOffline.bind(workerClient),
|
|
953
|
-
sync
|
|
954
|
-
},
|
|
955
|
-
/**
|
|
956
|
-
* Ask the elected worker to broadcast a page reload to all tabs for this dbId.
|
|
957
|
-
*
|
|
958
|
-
* With `clean: true` the worker durably records a reset request epoch before
|
|
959
|
-
* broadcasting, so the worker elected on the next startup initializes with
|
|
960
|
-
* `clearOnInit: true` and wipes the persisted DB. Destructive — use as a
|
|
961
|
-
* recovery path when the durable worker DB may be de-synced.
|
|
962
|
-
*
|
|
963
|
-
* Pending in-memory tab events are not preserved, and the returned promise
|
|
964
|
-
* may never settle in the caller — the page typically unloads first.
|
|
965
|
-
*/
|
|
966
|
-
requestReload: async (options) => {
|
|
967
|
-
await workerClient.requestReload(options);
|
|
968
|
-
setTimeout(() => globalThis.location?.reload(), 250);
|
|
969
|
-
},
|
|
970
|
-
subscribe: workerClient.subscribe,
|
|
971
|
-
exportData,
|
|
972
|
-
importData,
|
|
973
|
-
dispose,
|
|
974
|
-
_internal: {
|
|
975
|
-
executeAsync: workerClient.execute.bind(workerClient),
|
|
976
|
-
getMemoryQueryTables: reactiveDb.getTablesUsed.bind(reactiveDb),
|
|
977
|
-
getSharedLiveQueriesSnapshot: reactiveDb.getSharedLiveQueriesSnapshot.bind(reactiveDb),
|
|
978
|
-
crdtTableNames: options.syncDbSchema.tablesConfig.map((table) => table.crdtTableName),
|
|
979
|
-
crdtTablesConfig: options.syncDbSchema.tablesConfig,
|
|
980
|
-
tables: options.syncDbSchema.tables,
|
|
981
|
-
schemaVersion: workerClientSnapshot.schemaVersion,
|
|
982
|
-
migrationVersions: Object.keys(options.syncDbSchema.migrations).map(Number).sort((a, b) => a - b)
|
|
845
|
+
for (const cleanup of cleanupCallbacks) cleanup();
|
|
846
|
+
try {
|
|
847
|
+
await disposeRemoteSource?.();
|
|
848
|
+
} finally {
|
|
849
|
+
broadcastChannels.requests.close();
|
|
850
|
+
broadcastChannels.responses.close();
|
|
851
|
+
disposeWorkerClient?.();
|
|
852
|
+
try {
|
|
853
|
+
disposeReactiveDb?.();
|
|
854
|
+
} finally {
|
|
855
|
+
await Promise.all([releaseClientLock?.(), releaseReplicaLock?.()]);
|
|
856
|
+
}
|
|
983
857
|
}
|
|
984
858
|
};
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
859
|
+
try {
|
|
860
|
+
releaseClientLock = await acquireLock(`${syncDbClientLockName}-${options.dbId}`, { mode: "shared" });
|
|
861
|
+
const workerClient = await createWorkerDbClient({
|
|
862
|
+
worker: options.worker,
|
|
863
|
+
config: {
|
|
864
|
+
clientId: generateId(),
|
|
865
|
+
dbId: options.dbId,
|
|
866
|
+
props: options.workerProps
|
|
867
|
+
},
|
|
868
|
+
broadcastChannels
|
|
869
|
+
});
|
|
870
|
+
disposeWorkerClient = () => workerClient.dispose();
|
|
871
|
+
const hlcCounter = new HLCCounter(tabId, () => Date.now());
|
|
872
|
+
releaseReplicaLock = await acquireReplicaLock({ dbId: options.dbId });
|
|
873
|
+
const workerClientSnapshot = await workerClient.getSnapshot();
|
|
874
|
+
const reactiveDb = await createSQLiteReactiveDb({
|
|
875
|
+
snapshot: workerClientSnapshot.file,
|
|
876
|
+
logger: defaultLogger
|
|
877
|
+
});
|
|
878
|
+
disposeReactiveDb = () => reactiveDb.dispose();
|
|
879
|
+
const memoryDbMigrator = {
|
|
880
|
+
currentSchemaVersion: workerClientSnapshot.schemaVersion,
|
|
881
|
+
latestSchemaVersion: workerClientSnapshot.schemaVersion,
|
|
882
|
+
migrateDbToLatest: () => {
|
|
883
|
+
throw new Error("Memory DB migrations are not implemented");
|
|
884
|
+
},
|
|
885
|
+
migrateEvent: (event, targetVersion) => {
|
|
886
|
+
if (event.schema_version === targetVersion) return event;
|
|
887
|
+
throw new Error("Memory DB migrations are not implemented");
|
|
888
|
+
},
|
|
889
|
+
migrateEvents: (events) => events
|
|
890
|
+
};
|
|
891
|
+
const { crdtStorage } = await createMemoryDb({
|
|
892
|
+
nodeId: tabId,
|
|
893
|
+
migrator: memoryDbMigrator,
|
|
894
|
+
reactiveDb,
|
|
895
|
+
hlcCounter,
|
|
896
|
+
crdtTables: options.syncDbSchema.tablesConfig,
|
|
897
|
+
syncDbSchema: options.syncDbSchema
|
|
898
|
+
});
|
|
899
|
+
const pullSyncId = createStoredValue({ initialValue: workerClientSnapshot.syncId });
|
|
900
|
+
const pushSyncId = createStoredValue({ initialValue: 0 });
|
|
901
|
+
const tabRemoteSource = createCrdtSyncRemoteSource({
|
|
902
|
+
bufferSize: 500,
|
|
903
|
+
pullSyncId,
|
|
904
|
+
pushSyncId,
|
|
905
|
+
storage: crdtStorage,
|
|
906
|
+
nodeId: tabId,
|
|
907
|
+
migrator: memoryDbMigrator,
|
|
908
|
+
remoteFactory: ({ onEventsAvailable }) => {
|
|
909
|
+
const subscription = workerClient.subscribe("new-event-chunk-applied", (event) => {
|
|
910
|
+
onEventsAvailable({
|
|
911
|
+
newSyncId: event.payload.newSyncId,
|
|
912
|
+
remoteEventHlcSum: event.payload.eventHlcSum
|
|
913
|
+
});
|
|
914
|
+
});
|
|
915
|
+
return {
|
|
916
|
+
pullEvents: (request) => workerClient.pullEvents(request),
|
|
917
|
+
pushEvents: (request) => workerClient.pushTabEvents(request),
|
|
918
|
+
disconnect: () => {
|
|
919
|
+
subscription.unsubscribe();
|
|
920
|
+
}
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
disposeRemoteSource = () => tabRemoteSource.dispose();
|
|
925
|
+
tabRemoteSource.goOnline();
|
|
926
|
+
const reloadRequestedSubscription = workerClient.subscribe("reload-requested", () => {
|
|
927
|
+
globalThis.location?.reload();
|
|
928
|
+
});
|
|
929
|
+
cleanupCallbacks.push(reloadRequestedSubscription.unsubscribe);
|
|
930
|
+
const reloadIfStorageReplaced = (storageGeneration) => {
|
|
931
|
+
if (storageGeneration !== workerClientSnapshot.storageGeneration) {
|
|
932
|
+
storageReplacedSubscription.unsubscribe();
|
|
933
|
+
globalThis.location?.reload();
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
const storageReplacedSubscription = workerClient.subscribe("state-changed", (event) => {
|
|
937
|
+
reloadIfStorageReplaced(event.payload.storageGeneration);
|
|
938
|
+
});
|
|
939
|
+
cleanupCallbacks.push(storageReplacedSubscription.unsubscribe);
|
|
940
|
+
reloadIfStorageReplaced(workerClient.getStorageGeneration());
|
|
941
|
+
const sync = () => {
|
|
942
|
+
workerClient.sync().catch((error) => console.warn("Failed to start sync", error));
|
|
943
|
+
};
|
|
944
|
+
const syncWhenVisible = () => {
|
|
945
|
+
if (globalThis.document?.visibilityState === "visible") sync();
|
|
946
|
+
};
|
|
947
|
+
const dropConnection = () => {
|
|
948
|
+
workerClient.dropConnection().catch((error) => console.warn("Failed to drop connection", error));
|
|
949
|
+
};
|
|
950
|
+
cleanupCallbacks.push(() => {
|
|
951
|
+
globalThis.document?.removeEventListener("visibilitychange", syncWhenVisible);
|
|
952
|
+
globalThis.removeEventListener?.("online", sync);
|
|
953
|
+
globalThis.removeEventListener?.("offline", dropConnection);
|
|
954
|
+
});
|
|
955
|
+
globalThis.document?.addEventListener("visibilitychange", syncWhenVisible);
|
|
956
|
+
globalThis.addEventListener?.("online", sync);
|
|
957
|
+
globalThis.addEventListener?.("offline", dropConnection);
|
|
958
|
+
perf.logEnd("createSyncedDb", "initialized", "info");
|
|
959
|
+
const exportData = createExportData({
|
|
960
|
+
reactiveDb,
|
|
961
|
+
tablesConfig: options.syncDbSchema.tablesConfig,
|
|
962
|
+
schemaVersion: workerClientSnapshot.schemaVersion
|
|
963
|
+
});
|
|
964
|
+
const importData = (data, opts) => workerClient.importData(data, opts);
|
|
965
|
+
const syncedDb = {
|
|
966
|
+
db: createSyncedDbDatabase(reactiveDb),
|
|
967
|
+
state: {
|
|
968
|
+
getState: workerClient.getState.bind(workerClient),
|
|
969
|
+
subscribe: (onChange) => {
|
|
970
|
+
const { unsubscribe } = workerClient.subscribe("state-changed", onChange);
|
|
971
|
+
return unsubscribe;
|
|
972
|
+
},
|
|
973
|
+
goOnline: workerClient.goOnline.bind(workerClient),
|
|
974
|
+
goOffline: workerClient.goOffline.bind(workerClient),
|
|
975
|
+
sync
|
|
976
|
+
},
|
|
977
|
+
/**
|
|
978
|
+
* Ask the elected worker to broadcast a page reload to all tabs for this dbId.
|
|
979
|
+
*
|
|
980
|
+
* With `clean: true` the worker durably records a reset request epoch before
|
|
981
|
+
* broadcasting, so the worker elected on the next startup initializes with
|
|
982
|
+
* `clearOnInit: true` and wipes the persisted DB. Destructive — use as a
|
|
983
|
+
* recovery path when the durable worker DB may be de-synced.
|
|
984
|
+
*
|
|
985
|
+
* Pending in-memory tab events are not preserved, and the returned promise
|
|
986
|
+
* may never settle in the caller — the page typically unloads first.
|
|
987
|
+
*/
|
|
988
|
+
requestReload: async (options) => {
|
|
989
|
+
await workerClient.requestReload(options);
|
|
990
|
+
setTimeout(() => globalThis.location?.reload(), 250);
|
|
991
|
+
},
|
|
992
|
+
subscribe: workerClient.subscribe,
|
|
993
|
+
exportData,
|
|
994
|
+
importData,
|
|
995
|
+
dispose,
|
|
996
|
+
_internal: {
|
|
997
|
+
executeAsync: workerClient.execute.bind(workerClient),
|
|
998
|
+
getMemoryQueryTables: reactiveDb.getTablesUsed.bind(reactiveDb),
|
|
999
|
+
getSharedLiveQueriesSnapshot: reactiveDb.getSharedLiveQueriesSnapshot.bind(reactiveDb),
|
|
1000
|
+
crdtTableNames: options.syncDbSchema.tablesConfig.map((table) => table.crdtTableName),
|
|
1001
|
+
crdtTablesConfig: options.syncDbSchema.tablesConfig,
|
|
1002
|
+
tables: options.syncDbSchema.tables,
|
|
1003
|
+
schemaVersion: workerClientSnapshot.schemaVersion,
|
|
1004
|
+
migrationVersions: Object.keys(options.syncDbSchema.migrations).map(Number).sort((a, b) => a - b)
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
unregisterDevtools = getOrCreateSQLiteSyncDevtoolsRegistry().register({
|
|
1008
|
+
instanceId,
|
|
1009
|
+
dbId: options.dbId,
|
|
1010
|
+
createdAt: Date.now(),
|
|
1011
|
+
instance: syncedDb
|
|
1012
|
+
});
|
|
1013
|
+
return syncedDb;
|
|
1014
|
+
} catch (error) {
|
|
1015
|
+
await dispose();
|
|
1016
|
+
throw error;
|
|
1017
|
+
}
|
|
992
1018
|
}
|
|
993
1019
|
//#endregion
|
|
994
1020
|
export { CRDT_EVENT_NO_OP_PAYLOAD, ColumnBuilder, CrdtEventValidationError, HLCCounter, RESET_REQUEST_TTL_MS, SQLiteDbWrapper, SQLiteReactiveDb, TableBuilder, TypedBroadcastChannel, TypedEvent, admitClientEvents, applyMemoryDbSchema, applyWorkerDbSchema, compareHLC, createCrdtApplyFunction, createCrdtStorage, createCrdtStorageMutator, createCrdtSyncProducer, createCrdtSyncRemoteSource, createDeferredPromise, createExportData, createImportData, createKvStoreTableQuery, createMigrations, createMigrator, createSQLiteCrdtApplyFunction, createSQLiteKvStore, createStoredValue, createSyncedDb, createTypedEventTarget, defineSyncSchema, deserializeHLC, dummyKysely, formatSchemaVerificationIssues, generateId, introspectDb, isNoOpCrdtEventPayload, jsonSafeParse, makeCrdtTable, parametersAreEqual, quoteId, serializeHLC, startPerformanceLogger, t, tryCatch, tryCatchAsync, validateNewCrdtEvent, verifySyncSchema, xxhash };
|