@sqlite-sync/core 0.10.0 → 0.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/{crdt-sync-remote-source-Dtvyrk0R.js → crdt-sync-remote-source-CugbiosG.js} +6 -2
- package/dist/crdt-sync-remote-source-CugbiosG.js.map +1 -0
- package/dist/{index-B4s8GFWF.d.ts → index-UfgvV97h.d.ts} +8 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +27 -16
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/{reset-state-BVWEcT_z.js → reset-state-CchMrdoA.js} +2 -6
- package/dist/{reset-state-BVWEcT_z.js.map → reset-state-CchMrdoA.js.map} +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +1 -1
- package/dist/worker.d.ts +1 -1
- package/dist/worker.js +12 -7
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
- package/dist/crdt-sync-remote-source-Dtvyrk0R.js.map +0 -1
|
@@ -247,6 +247,7 @@ const createCrdtSyncRemoteSource = ({ bufferSize, storage, migrator, pullSyncId,
|
|
|
247
247
|
};
|
|
248
248
|
let current = null;
|
|
249
249
|
let disposed = false;
|
|
250
|
+
let wantsOnline = false;
|
|
250
251
|
const disconnectSource = (source) => {
|
|
251
252
|
const watchdog = setTimeout(() => {
|
|
252
253
|
console.error(`Remote source did not disconnect within ${DISCONNECT_WATCHDOG_MS}ms`);
|
|
@@ -448,16 +449,19 @@ const createCrdtSyncRemoteSource = ({ bufferSize, storage, migrator, pullSyncId,
|
|
|
448
449
|
});
|
|
449
450
|
return Promise.resolve();
|
|
450
451
|
}
|
|
452
|
+
wantsOnline = true;
|
|
451
453
|
const connection = createConnection(remoteFactory);
|
|
452
454
|
current = connection;
|
|
453
455
|
patchRemoteState({ type: "pending" });
|
|
454
456
|
return connection.ready;
|
|
455
457
|
};
|
|
456
458
|
const goOffline = async (reason) => {
|
|
459
|
+
wantsOnline = false;
|
|
457
460
|
if (current) closeConnection(current, reason);
|
|
458
461
|
};
|
|
459
462
|
const syncWithRemote = async () => {
|
|
460
|
-
await current
|
|
463
|
+
if (current) await current.sync();
|
|
464
|
+
else if (wantsOnline && !remoteState.schemaVersionMismatched) await goOnline();
|
|
461
465
|
};
|
|
462
466
|
const checkRemoteConsistency = (remoteSyncId, remoteEventHlcSum) => {
|
|
463
467
|
if (remoteEventHlcSum === null) return;
|
|
@@ -501,4 +505,4 @@ const createCrdtSyncRemoteSource = ({ bufferSize, storage, migrator, pullSyncId,
|
|
|
501
505
|
//#endregion
|
|
502
506
|
export { HLCCounter as a, serializeHLC as c, DEFAULT_MAX_DRIFT_MS as i, CrdtEventValidationError as n, compareHLC as o, validateNewCrdtEvent as r, deserializeHLC as s, createCrdtSyncRemoteSource as t };
|
|
503
507
|
|
|
504
|
-
//# sourceMappingURL=crdt-sync-remote-source-
|
|
508
|
+
//# sourceMappingURL=crdt-sync-remote-source-CugbiosG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crdt-sync-remote-source-CugbiosG.js","names":[],"sources":["../src/hlc.ts","../src/schema/validate-crdt-event.ts","../src/sqlite-crdt/retry-remote-operation.ts","../src/sqlite-crdt/crdt-sync-remote-source.ts"],"sourcesContent":["export interface HLC {\n timestamp: number;\n counter: number;\n nodeId: string;\n}\n\nconst MAX_COUNTER = 36 ** 5 - 1; // 60,466,175 — max value that fits in 5-char base36\nexport const DEFAULT_MAX_DRIFT_MS = 6 * 60 * 60 * 1000; // 6 hours\n\nexport class HLCCounter {\n private timestamp: number;\n private counter: number;\n private nodeId: string;\n\n private readonly getTimestamp: () => number;\n private readonly maxDrift: number;\n\n constructor(nodeId: string, getTimestamp: () => number, maxDrift: number = DEFAULT_MAX_DRIFT_MS) {\n this.timestamp = getTimestamp();\n this.counter = 0;\n this.nodeId = nodeId;\n this.getTimestamp = getTimestamp;\n this.maxDrift = maxDrift;\n }\n\n getCurrentHLC(): HLC {\n return {\n timestamp: this.timestamp,\n counter: this.counter,\n nodeId: this.nodeId,\n };\n }\n\n getNextHLC(): HLC {\n const now = this.getTimestamp();\n\n if (now > this.timestamp) {\n this.timestamp = now;\n this.counter = 0;\n return this.getCurrentHLC();\n }\n\n this.counter++;\n this.rollOverCounter();\n return this.getCurrentHLC();\n }\n\n /** Restore already-persisted causal state, regardless of wall-clock drift. */\n restoreHLC(hlc: HLC) {\n if (hlc.timestamp > this.timestamp) {\n this.timestamp = hlc.timestamp;\n this.counter = hlc.counter;\n } else if (hlc.timestamp === this.timestamp) {\n this.counter = Math.max(this.counter, hlc.counter);\n }\n }\n\n mergeHLC(hlc: HLC) {\n const now = this.getTimestamp();\n if (hlc.timestamp - now > this.maxDrift) {\n console.warn(\n `HLC: ignoring far-future timestamp (remote=${hlc.timestamp}, local=${now}, drift=${hlc.timestamp - now}ms)`,\n );\n return;\n }\n\n if (this.timestamp === hlc.timestamp) {\n this.counter = Math.max(this.counter, hlc.counter) + 1;\n } else if (this.timestamp > hlc.timestamp) {\n this.counter++;\n } else {\n this.timestamp = hlc.timestamp;\n this.counter = hlc.counter + 1;\n }\n this.rollOverCounter();\n }\n\n private rollOverCounter() {\n if (this.counter > MAX_COUNTER) {\n this.timestamp += 1;\n this.counter = 0;\n }\n }\n}\n\nexport function serializeHLC(hlc: HLC) {\n return `${hlc.timestamp.toString().padStart(15, \"0\")}:${hlc.counter.toString(36).padStart(5, \"0\")}:${hlc.nodeId}`;\n}\n\nexport function deserializeHLC(serialized: string): HLC {\n const parts = serialized.split(\":\");\n if (parts.length < 3) {\n throw new Error(`Invalid HLC format: expected at least 3 colon-separated segments, got ${parts.length}`);\n }\n\n const timestamp = parseInt(parts[0], 10);\n const counter = parseInt(parts[1], 36);\n\n if (Number.isNaN(timestamp) || Number.isNaN(counter)) {\n throw new Error(`Invalid HLC values: timestamp=${parts[0]}, counter=${parts[1]}`);\n }\n\n return {\n timestamp,\n counter,\n nodeId: parts.slice(2).join(\":\"),\n };\n}\n\nexport function compareHLC(one: HLC, two: HLC) {\n if (one.timestamp === two.timestamp) {\n if (one.counter === two.counter) {\n if (one.nodeId === two.nodeId) {\n return 0;\n }\n return one.nodeId < two.nodeId ? -1 : 1;\n }\n return one.counter - two.counter;\n }\n return one.timestamp - two.timestamp;\n}\n","import type { SyncDbSchema } from \"../sqlite-crdt/crdt-schema\";\nimport type { CrdtEventType, NewCrdtEvent } from \"../sqlite-crdt/crdt-table-schema\";\nimport type { AnyTableBuilder } from \"./table-builder\";\n\nexport type NewCrdtEventValidationResult =\n | { success: true; event: NewCrdtEvent }\n | { success: false; errors: string[] };\n\nexport class CrdtEventValidationError extends Error {\n constructor(readonly errors: string[]) {\n super(`Invalid CRDT events: ${errors.join(\"; \")}`);\n this.name = \"CrdtEventValidationError\";\n }\n}\n\nconst crdtEventTypes = [\"item-created\", \"item-updated\", \"item-deleted\"] as const;\n\nexport function validateNewCrdtEvent(\n schema: Pick<SyncDbSchema, \"tables\" | \"tablesConfig\">,\n input: unknown,\n): NewCrdtEventValidationResult {\n const errors: string[] = [];\n\n if (!isRecord(input)) {\n return { success: false, errors: [\"Event must be an object\"] } satisfies NewCrdtEventValidationResult;\n }\n\n const type = input.type;\n const dataset = input.dataset;\n const itemId = input.item_id;\n\n let payload = input.payload;\n let payloadParseFailed = false;\n if (typeof payload === \"string\") {\n try {\n payload = JSON.parse(payload);\n } catch {\n payloadParseFailed = true;\n errors.push(`Event payload is not valid JSON`);\n }\n }\n\n if (!isCrdtEventType(type)) {\n errors.push(`Invalid event type \"${String(type)}\"`);\n }\n if (typeof dataset !== \"string\") {\n errors.push(`Event dataset must be a string`);\n }\n if (typeof itemId !== \"string\") {\n errors.push(`Event item_id must be a string`);\n }\n if (!payloadParseFailed && !isRecord(payload)) {\n errors.push(`Event payload must be an object`);\n }\n\n const datasetMatch = typeof dataset === \"string\" ? findTableForDataset(schema, dataset) : null;\n if (typeof dataset === \"string\" && !datasetMatch) {\n errors.push(`Unknown dataset \"${dataset}\"`);\n }\n\n if (isCrdtEventType(type) && datasetMatch && isRecord(payload)) {\n switch (type) {\n case \"item-created\": {\n const result = datasetMatch.table.validatePayload(payload, { event: \"item-created\" });\n if (!result.success) {\n errors.push(...result.errors.map((error) => `payload: ${error}`));\n }\n if (typeof itemId === \"string\" && \"id\" in payload && payload.id !== itemId) {\n errors.push(`payload: Column \"id\" must match item_id \"${itemId}\"`);\n }\n break;\n }\n case \"item-updated\": {\n const result = datasetMatch.table.validatePayload(payload, { event: \"item-updated\" });\n if (!result.success) {\n errors.push(...result.errors.map((error) => `payload: ${error}`));\n }\n break;\n }\n case \"item-deleted\":\n if (Object.keys(payload).length > 0) {\n errors.push(`payload: item-deleted events must have an empty payload`);\n }\n break;\n }\n }\n\n if (errors.length > 0) {\n return { success: false, errors } satisfies NewCrdtEventValidationResult;\n }\n\n return {\n success: true,\n event: {\n type: type as CrdtEventType,\n dataset: datasetMatch?.baseTableName ?? (dataset as string),\n item_id: itemId as string,\n payload: payload as Record<string, unknown>,\n },\n } satisfies NewCrdtEventValidationResult;\n}\n\nfunction findTableForDataset(\n schema: Pick<SyncDbSchema, \"tables\" | \"tablesConfig\">,\n dataset: string,\n): { table: AnyTableBuilder; baseTableName: string } | null {\n const config = schema.tablesConfig.find(\n (tableConfig) => tableConfig.baseTableName === dataset || tableConfig.crdtTableName === dataset,\n );\n if (config) {\n const table = schema.tables[config.crdtTableName];\n return table ? { table, baseTableName: config.baseTableName } : null;\n }\n const table = Object.hasOwn(schema.tables, dataset) ? schema.tables[dataset] : undefined;\n return table ? { table, baseTableName: dataset } : null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isCrdtEventType(value: unknown): value is CrdtEventType {\n return typeof value === \"string\" && crdtEventTypes.includes(value as CrdtEventType);\n}\n","type RetryOptions = {\n maxAttempts: number;\n backoffBaseMs: number;\n backoffExponent: number;\n backoffJitterMs: number;\n timeoutMs: number;\n shouldRetry?: (error: unknown) => boolean;\n};\n\nexport const REMOTE_RETRY_OPTIONS: RetryOptions = {\n maxAttempts: 3,\n backoffBaseMs: 100,\n backoffExponent: 1.5,\n backoffJitterMs: 150,\n timeoutMs: 10000,\n};\n\nclass RetryTimeoutError extends Error {\n constructor(\n message: string,\n public previous?: unknown,\n ) {\n super(message);\n this.name = \"TimeoutError\";\n }\n}\n\nconst applyJitter = (delayMs: number, maxJitterMs: number): number => {\n const jitter = Math.random() * maxJitterMs * (Math.random() > 0.5 ? 1 : -1);\n return Math.max(0, delayMs + jitter);\n};\n\nconst delay = (delayMs: number) => new Promise((resolve) => setTimeout(resolve, delayMs));\n\nconst withTimeout = async <T>(operation: () => Promise<T>, timeoutMs: number, previousError?: unknown): Promise<T> => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n try {\n return await Promise.race([\n operation(),\n new Promise<never>((_, reject) => {\n timeoutId = setTimeout(\n () => reject(new RetryTimeoutError(\"Remote operation timed out\", previousError)),\n timeoutMs,\n );\n }),\n ]);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n};\n\nexport const retryRemoteOperation = async <T>(operation: () => Promise<T>, options: RetryOptions): Promise<T> => {\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= options.maxAttempts; attempt++) {\n try {\n return await withTimeout(operation, options.timeoutMs, lastError);\n } catch (error) {\n lastError = error;\n\n if (attempt >= options.maxAttempts || options.shouldRetry?.(error) === false) {\n throw error;\n }\n\n const backoffDelay = applyJitter(\n options.backoffBaseMs * options.backoffExponent ** (attempt - 1),\n options.backoffJitterMs,\n );\n if (backoffDelay > 0) {\n await delay(backoffDelay);\n }\n }\n }\n\n throw lastError;\n};\n","import type { SyncDbMigrator } from \"../migrations/migrator\";\nimport { createTypedEventTarget, ensureSingletonExecution, tryCatchAsync } from \"../utils\";\nimport type { EventsPullResponse, WorkerState } from \"../worker-db/worker-common\";\nimport type { PendingCrdtEvent } from \"./apply-crdt-event\";\nimport type { CrdtStorage } from \"./crdt-storage\";\nimport { REMOTE_RETRY_OPTIONS, retryRemoteOperation } from \"./retry-remote-operation\";\nimport type { StoredValue } from \"./stored-value\";\n\ntype CrdtSyncRemoteSourceConfig = {\n bufferSize: number;\n storage: CrdtStorage;\n migrator: SyncDbMigrator;\n pullSyncId: StoredValue<number>;\n pushSyncId: StoredValue<number>;\n nodeId: string;\n remoteFactory?: CreateRemoteSourceFactory;\n};\n\nexport type EventsPullRequest = {\n afterSyncId: number;\n excludeNodeId?: string;\n};\n\nexport const PUSH_BATCH_SIZE = 75;\nexport const MAX_PUSH_EVENTS = 100;\n\nexport type EventsPushRequest = {\n nodeId: string;\n events: (PendingCrdtEvent & { schema_version: number })[];\n};\nexport type EventsPushResponse = {\n ok: boolean;\n /** Remote sync_id right before the pushed events were enqueued. */\n beforeSyncId?: number;\n /** Remote sync_id right after the pushed events were enqueued. */\n afterSyncId?: number;\n};\n\nconst DISCONNECT_WATCHDOG_MS = 15_000;\n\nexport type CrdtSyncRemoteSource = ReturnType<typeof createCrdtSyncRemoteSource>;\n\nexport type EventsAvailable = {\n newSyncId: number;\n remoteEventHlcSum: string | null;\n};\n\n/**\n * Opens a connection to the remote. Each call must return an independent source: the library calls\n * `disconnect` on every returned source exactly once, including one that resolves after `signal`\n * has aborted. `signal` aborts when the connection attempt is cancelled or the connection is closed.\n * Call `onReconnected` when the transport re-establishes itself without a new source: broadcasts\n * sent while it was down are lost, so the library pulls and pushes to catch up.\n */\nexport type CreateRemoteSourceFactory = (opts: {\n onEventsAvailable: (event: EventsAvailable) => void;\n onReconnected: () => void;\n signal: AbortSignal;\n}) => RemoteSource | Promise<RemoteSource>;\n\ntype RemoteSource = {\n pullEvents: (request: EventsPullRequest) => Promise<EventsPullResponse>;\n pushEvents: (request: EventsPushRequest) => Promise<EventsPushResponse>;\n disconnect?: () => void | Promise<void>;\n};\n\nexport class SchemaVersionMismatchError extends Error {\n constructor(\n public remoteSchemaVersion: number,\n public localSchemaVersion: number,\n ) {\n super(`Schema version mismatch: remote ${remoteSchemaVersion} != local ${localSchemaVersion}`);\n this.name = \"SchemaVersionMismatchError\";\n }\n}\n\ntype RemoteSourceState =\n | {\n type: \"pending\";\n deSynced: boolean;\n schemaVersionMismatched: boolean;\n }\n | {\n type: \"offline\";\n reason: OfflineReason;\n deSynced: boolean;\n schemaVersionMismatched: boolean;\n }\n | {\n type: \"online\";\n deSynced: boolean;\n schemaVersionMismatched: boolean;\n };\n\nexport type OfflineReason =\n | \"NOT_INITIALIZED\"\n | \"INITIALIZATION_FAILED\"\n | \"REMOTE_PUSH_ERROR\"\n | \"REMOTE_PULL_ERROR\"\n | \"DISCONNECTED\";\n\nexport type DeSyncDetectedReason = \"CHECKSUM_MISMATCH\" | \"ERROR_APPLYING_REMOTE_EVENT\";\n\nexport const createCrdtSyncRemoteSource = ({\n bufferSize,\n storage,\n migrator,\n pullSyncId,\n pushSyncId,\n nodeId,\n remoteFactory,\n}: CrdtSyncRemoteSourceConfig) => {\n const eventTarget = createTypedEventTarget<{\n \"state-changed\": RemoteSourceState[\"type\"];\n \"de-sync-detected\": {\n reason: DeSyncDetectedReason;\n };\n \"remote-schema-version-mismatch\": {\n remoteSchemaVersion: number;\n localSchemaVersion: number;\n };\n }>();\n\n let remoteState: RemoteSourceState = {\n type: \"offline\",\n reason: \"NOT_INITIALIZED\",\n deSynced: false,\n schemaVersionMismatched: false,\n };\n\n const patchRemoteState = (state: Partial<RemoteSourceState>) => {\n remoteState = { ...remoteState, ...state } as RemoteSourceState;\n eventTarget.dispatchEvent(\"state-changed\", remoteState.type);\n };\n\n let current: Connection | null = null;\n let disposed = false;\n let wantsOnline = false;\n\n const disconnectSource = (source: RemoteSource) => {\n const watchdog = setTimeout(() => {\n console.error(`Remote source did not disconnect within ${DISCONNECT_WATCHDOG_MS}ms`);\n }, DISCONNECT_WATCHDOG_MS);\n void tryCatchAsync(async () => await source.disconnect?.()).then((result) => {\n clearTimeout(watchdog);\n if (!result.success) {\n console.warn(\"Error while disconnecting from remote source\", result.error);\n }\n });\n };\n\n const closeConnection = (connection: Connection, reason: OfflineReason) => {\n if (current !== connection) {\n return;\n }\n current = null;\n patchRemoteState({ type: \"offline\", reason });\n connection.close();\n };\n\n type Connection = ReturnType<typeof createConnection>;\n const createConnection = (factory: CreateRemoteSourceFactory) => {\n const controller = new AbortController();\n const { signal } = controller;\n let source: RemoteSource | null = null;\n\n const untilClosed = <T>(operation: () => Promise<T>) =>\n new Promise<T>((resolve, reject) => {\n const onAbort = () => reject(new Error(\"Remote connection closed\"));\n if (signal.aborted) {\n onAbort();\n return;\n }\n signal.addEventListener(\"abort\", onAbort, { once: true });\n operation()\n .then(resolve, reject)\n .finally(() => signal.removeEventListener(\"abort\", onAbort));\n });\n\n const retryOptions = { ...REMOTE_RETRY_OPTIONS, shouldRetry: () => !signal.aborted };\n\n const connect = async () => {\n if (signal.aborted) {\n return;\n }\n\n const result = await tryCatchAsync(\n async () =>\n await factory({\n onEventsAvailable: ({ newSyncId, remoteEventHlcSum }) => {\n pull({ remoteSyncId: newSyncId, remoteEventHlcSum, includeSelf: false });\n },\n onReconnected: () => {\n void sync();\n },\n signal,\n }),\n );\n\n if (signal.aborted) {\n if (result.success) {\n disconnectSource(result.data);\n }\n return;\n }\n\n if (!result.success) {\n console.warn(\"Failed to create remote source\", result.error);\n closeConnection(connection, \"INITIALIZATION_FAILED\");\n return;\n }\n\n source = result.data;\n patchRemoteState({ type: \"online\", deSynced: false, schemaVersionMismatched: false });\n void sync();\n };\n\n type ActivePull = { promise: Promise<void>; requestedSyncId: number | null };\n let activePull: ActivePull | null = null;\n const pull = (request?: {\n remoteSyncId?: number;\n remoteEventHlcSum?: string | null;\n includeSelf?: boolean;\n }): Promise<void> => {\n if (!source || signal.aborted) {\n return Promise.resolve();\n }\n const activeSource = source;\n\n const remoteSyncId = request?.remoteSyncId;\n\n if (remoteSyncId !== undefined && remoteSyncId <= pullSyncId.current) {\n // We are already caught up to this broadcast, so there is nothing to pull.\n // This is the quiescent moment to verify we have not diverged from the\n // remote (the check is a no-op unless we are exactly aligned: remoteSyncId\n // === pullSyncId.current).\n checkRemoteConsistency(remoteSyncId, request?.remoteEventHlcSum ?? null);\n return Promise.resolve();\n }\n\n if (activePull) {\n if (remoteSyncId !== undefined && (!activePull.requestedSyncId || activePull.requestedSyncId < remoteSyncId)) {\n activePull.requestedSyncId = remoteSyncId;\n }\n return activePull.promise;\n }\n\n const nextPull: ActivePull = { promise: Promise.resolve(), requestedSyncId: null };\n nextPull.promise = pullAllEvents(activeSource, {\n afterSyncId: pullSyncId.current,\n excludeNodeId: request?.includeSelf ? undefined : nodeId,\n })\n .catch((error) => {\n if (signal.aborted) {\n return;\n }\n console.error(\"Error pulling events. Going offline.\", error);\n closeConnection(connection, \"REMOTE_PULL_ERROR\");\n })\n .finally(() => {\n if (activePull === nextPull) {\n activePull = null;\n }\n\n const nextTarget = nextPull.requestedSyncId;\n if (nextTarget && nextTarget > pullSyncId.current) {\n pull({ remoteSyncId: nextTarget });\n }\n });\n activePull = nextPull;\n return nextPull.promise;\n };\n\n const pullAllEvents = async (activeSource: RemoteSource, opts: EventsPullRequest) => {\n let hasMore = true;\n let afterSyncId = opts.afterSyncId;\n while (hasMore) {\n const response = await retryRemoteOperation(\n () =>\n untilClosed(() =>\n activeSource.pullEvents({\n ...opts,\n afterSyncId,\n }),\n ),\n retryOptions,\n );\n if (signal.aborted) {\n return;\n }\n hasMore = response.hasMore;\n afterSyncId = response.nextSyncId;\n\n if (response.events) {\n const { processed } = storage.enqueueRemoteEvents(\n response.events.map((x) => {\n if (x.schema_version > migrator.currentSchemaVersion) {\n eventTarget.dispatchEvent(\"remote-schema-version-mismatch\", {\n remoteSchemaVersion: x.schema_version,\n localSchemaVersion: migrator.currentSchemaVersion,\n });\n if (remoteState.type === \"online\" && !remoteState.schemaVersionMismatched) {\n patchRemoteState({ schemaVersionMismatched: true });\n }\n throw new SchemaVersionMismatchError(x.schema_version, migrator.currentSchemaVersion);\n }\n return x;\n }),\n );\n await untilClosed(() => processed);\n if (signal.aborted) {\n return;\n }\n }\n if (response.nextSyncId <= pullSyncId.current) {\n break;\n }\n if (response.nextSyncId > pullSyncId.current) {\n pullSyncId.current = response.nextSyncId;\n }\n }\n };\n\n const push = ensureSingletonExecution(async () => {\n while (source && !signal.aborted) {\n const activeSource = source;\n const eventsBatch = storage.getEventsBatch({\n status: \"applied\",\n afterSyncId: pushSyncId.current,\n excludeOrigin: \"remote\",\n limit: bufferSize,\n });\n if (eventsBatch.events.length === 0) {\n break;\n }\n\n let response: EventsPushResponse;\n try {\n response = await retryRemoteOperation(\n () =>\n untilClosed(() =>\n activeSource.pushEvents({\n nodeId,\n events: eventsBatch.events.map((event) => ({\n schema_version: event.schema_version,\n timestamp: event.timestamp,\n type: event.type,\n dataset: event.dataset,\n item_id: event.item_id,\n payload: event.payload,\n })),\n }),\n ),\n retryOptions,\n );\n } catch (error) {\n if (!signal.aborted) {\n console.error(\"Error pushing events. Going offline.\", error);\n closeConnection(connection, \"REMOTE_PUSH_ERROR\");\n }\n return;\n }\n\n if (signal.aborted) {\n return;\n }\n\n if (!response.ok) {\n console.error(\"Remote rejected pushed events. Going offline.\");\n closeConnection(connection, \"REMOTE_PUSH_ERROR\");\n return;\n }\n\n pushSyncId.current = eventsBatch.nextSyncId;\n\n // Fast-forward the pull cursor: the remote assigns sync ids for the pushed\n // events synchronously, so (beforeSyncId, afterSyncId] contains only this\n // node's own events. If we are caught up to at least beforeSyncId, the skipped\n // range (pullSyncId, afterSyncId] contains only our own events, so there is\n // nothing to pull up to afterSyncId.\n if (\n response.beforeSyncId !== undefined &&\n response.afterSyncId !== undefined &&\n response.beforeSyncId <= pullSyncId.current &&\n response.afterSyncId > pullSyncId.current\n ) {\n pullSyncId.current = response.afterSyncId;\n }\n if (!eventsBatch.hasMore) {\n break;\n }\n }\n });\n\n // Waits out in-flight operations first: they may have started before the caller's request.\n const sync = async () => {\n await activePull?.promise;\n await pull();\n await push.promise();\n await push();\n };\n\n const close = () => {\n controller.abort();\n if (source) {\n disconnectSource(source);\n }\n };\n\n const ready = Promise.resolve()\n .then(() => untilClosed(connect))\n .catch((error) => {\n if (!signal.aborted) {\n throw error;\n }\n });\n\n const connection = { ready, close, push, sync };\n return connection;\n };\n\n const goOnline = (): Promise<void> => {\n if (disposed) {\n return Promise.resolve();\n }\n if (current) {\n return current.ready;\n }\n if (!remoteFactory) {\n console.warn(\"Remote source factory not provided. Going offline.\");\n patchRemoteState({ type: \"offline\", reason: \"NOT_INITIALIZED\" });\n return Promise.resolve();\n }\n\n wantsOnline = true;\n const connection = createConnection(remoteFactory);\n current = connection;\n patchRemoteState({ type: \"pending\" });\n return connection.ready;\n };\n\n const goOffline = async (reason: OfflineReason) => {\n wantsOnline = false;\n if (current) {\n closeConnection(current, reason);\n }\n };\n\n // Reconnects only when a connection error, not goOffline, took us offline. Retrying after a schema\n // mismatch would fail the same way.\n const syncWithRemote = async () => {\n if (current) {\n await current.sync();\n } else if (wantsOnline && !remoteState.schemaVersionMismatched) {\n await goOnline();\n }\n };\n\n // De-sync detection: when we are exactly caught up to the remote's broadcast\n // sync id and fully quiescent, our applied-event set must equal the remote's,\n // so our HLC checksums must match. A mismatch means the nodes have diverged.\n const checkRemoteConsistency = (remoteSyncId: number, remoteEventHlcSum: string | null) => {\n // A remote with no accumulator gives us nothing to compare against.\n if (remoteEventHlcSum === null) {\n return;\n }\n\n // Only meaningful when we are exactly caught up: if we are behind we still\n // need to pull; if we are ahead our state covers events the remote checksum\n // does not.\n if (remoteSyncId !== pullSyncId.current) {\n return;\n }\n\n // Quiescence: the accumulator only matches the remote's when nothing is left\n // to apply locally and no local applied events are still waiting to be pushed\n // (those are in our accumulator but the remote has not seen them yet).\n if (!storage.checkIsQuiescent(pushSyncId.current)) {\n return;\n }\n\n const localEventHlcSum = storage.getEventHlcAccumulator();\n if (localEventHlcSum === null) {\n return;\n }\n\n if (localEventHlcSum === remoteEventHlcSum) {\n // No de-sync detected.\n return;\n }\n\n eventTarget.dispatchEvent(\"de-sync-detected\", { reason: \"CHECKSUM_MISMATCH\" });\n console.warn(\n `[sqlite-sync] De-sync detected at syncId ${remoteSyncId}: local HLC checksum ${localEventHlcSum} != remote ${remoteEventHlcSum}. Local and remote have diverged despite being caught up.`,\n );\n if (remoteState.type === \"online\" && !remoteState.deSynced) {\n patchRemoteState({ deSynced: true });\n }\n };\n\n const eventsAppliedSubscription = storage.addEventListener(\"events-applied\", () => {\n current?.push();\n });\n\n const remoteEventApplyFailedSubscription = storage.addEventListener(\"remote-event-apply-failed\", () => {\n eventTarget.dispatchEvent(\"de-sync-detected\", { reason: \"ERROR_APPLYING_REMOTE_EVENT\" });\n if (remoteState.type === \"online\" && !remoteState.deSynced) {\n patchRemoteState({ deSynced: true });\n }\n });\n\n const getState = (): WorkerState => ({\n remoteState: remoteState.type,\n deSynced: remoteState.deSynced,\n schemaVersionMismatched: remoteState.schemaVersionMismatched,\n });\n\n const dispose = async () => {\n disposed = true;\n eventsAppliedSubscription.unsubscribe();\n remoteEventApplyFailedSubscription.unsubscribe();\n await goOffline(\"DISCONNECTED\");\n };\n\n return {\n goOnline,\n goOffline,\n syncWithRemote,\n getState,\n dispose,\n addEventListener: eventTarget.addEventListener,\n removeEventListener: eventTarget.removeEventListener,\n };\n};\n"],"mappings":"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"}
|
|
@@ -603,7 +603,6 @@ type InternalDbSchema = {
|
|
|
603
603
|
declare function createCrdtStorage(storage: DbSyncerStorage): {
|
|
604
604
|
getEventsBatch: (options: GetEventsBatchQuery) => GetEventsBatch;
|
|
605
605
|
enqueueLocalEvents: (events: LocalCrdtEvent[], sourceNodeId: string) => EnqueueEventsResult;
|
|
606
|
-
enqueueOwnEvents: (events: OwnCrdtEvent[]) => EnqueueEventsResult;
|
|
607
606
|
enqueueRemoteEvents: (events: RemoteCrdtEvent[]) => EnqueueEventsResult;
|
|
608
607
|
applyOwnEvents: (events: OwnCrdtEvent[]) => void;
|
|
609
608
|
applyOwnSnapshot: (snapshot: OwnCrdtSnapshot) => void;
|
|
@@ -900,6 +899,7 @@ type CommitEventOptions<Database, Table extends keyof Database & string> = {
|
|
|
900
899
|
dataset: Table;
|
|
901
900
|
item_id: string;
|
|
902
901
|
};
|
|
902
|
+
type AnyCommitEventOptions<Database> = { [Table in keyof Database & string]: CommitEventOptions<Database, Table>; }[keyof Database & string];
|
|
903
903
|
type CreateEventPayload<Database, Table extends keyof Database> = Omit<Database[Table], "tombstone">;
|
|
904
904
|
type UpdateEventPayload<Database, Table extends keyof Database> = Omit<Partial<Database[Table]>, "id" | "tombstone">;
|
|
905
905
|
type SnapshotOptions<Database, Table extends keyof Database & string> = {
|
|
@@ -910,10 +910,9 @@ type SnapshotOptions<Database, Table extends keyof Database & string> = {
|
|
|
910
910
|
declare function createCrdtStorageMutator<Database>({ storage }: {
|
|
911
911
|
storage: CrdtStorage;
|
|
912
912
|
}): {
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
enqueueSnapshot: <Table extends keyof Database & string>(snapshot: SnapshotOptions<Database, Table>) => void;
|
|
913
|
+
applyEvent: <Table extends keyof Database & string>(event: CommitEventOptions<Database, Table>) => void;
|
|
914
|
+
applyEvents: (events: AnyCommitEventOptions<Database>[]) => void;
|
|
915
|
+
applySnapshot: <Table extends keyof Database & string>(snapshot: SnapshotOptions<Database, Table>) => void;
|
|
917
916
|
};
|
|
918
917
|
//#endregion
|
|
919
918
|
//#region src/sqlite-crdt/crdt-sync-producer.d.ts
|
|
@@ -935,6 +934,8 @@ type WorkerNotificationMessage = {
|
|
|
935
934
|
} | {
|
|
936
935
|
notificationType: "state-changed";
|
|
937
936
|
state: WorkerState;
|
|
937
|
+
/** Id of the worker's persisted database. A wiped database gets a new one. */
|
|
938
|
+
storageGeneration: string;
|
|
938
939
|
} | {
|
|
939
940
|
notificationType: "reload-requested";
|
|
940
941
|
reloadEpoch: string;
|
|
@@ -1153,6 +1154,7 @@ declare function createSyncedDb<Database, Props = undefined>(options: SyncedDbOp
|
|
|
1153
1154
|
"state-changed": {
|
|
1154
1155
|
notificationType: "state-changed";
|
|
1155
1156
|
state: WorkerState;
|
|
1157
|
+
storageGeneration: string;
|
|
1156
1158
|
};
|
|
1157
1159
|
"de-sync-detected": {
|
|
1158
1160
|
notificationType: "de-sync-detected";
|
|
@@ -1217,4 +1219,4 @@ type ResetStore = {
|
|
|
1217
1219
|
declare const RESET_REQUEST_TTL_MS: number;
|
|
1218
1220
|
//#endregion
|
|
1219
1221
|
export { createExportData as $, SyncDbSchema as $t, PendingCrdtEvent as A, PersistedCrdtEvent as An, ExecuteParams as At, DefinedSyncSchema as B, Logger as Bt, WorkerConfig as C, createStoredValue as Cn, jsonSafeParse as Ct, CrdtStorageMutator as D, CrdtEventType as Dn, KvStoreItem as Dt, createCrdtSyncProducer as E, CrdtEventStatus as En, tryCatchAsync as Et, verifySyncSchema as F, PreparedStatement as Ft, SQLiteReactiveDb as G, introspectDb as Gt, AdmitClientEventsResult as H, ColumnMetadata as Ht, CrdtEventValidationError as I, QueryBuilderOutput as It, parametersAreEqual as J, compareHLC as Jt, SharedLiveQuery as K, HLC as Kt, NewCrdtEventValidationResult as L, SQLiteDbWrapper as Lt, createSQLiteCrdtApplyFunction as M, dummyKysely as Mn, InternalSQLiteWrapper as Mt, SchemaVerificationIssue as N, KyselyQueryFactory as Nt, SnapshotOptions as O, CrdtUpdateLogItem as On, createKvStoreTableQuery as Ot, formatSchemaVerificationIssues as P, KyselyStatementFactory as Pt, SyncedDbExport as Q, ReadonlyTable as Qt, validateNewCrdtEvent as R, SQLiteTransactionWrapper as Rt, EventsPullResponse as S, StoredValue as Sn, generateId as St, WorkerState as T, CrdtEventOrigin as Tn, tryCatch as Tt, ClientDatasetRejectionReason as U, DatabaseIntrospection as Ut, defineSyncSchema as V, startPerformanceLogger as Vt, admitClientEvents as W, TableMetadata as Wt, ImportDataOptions as X, serializeHLC as Xt, xxhash as Y, deserializeHLC as Yt, ImportDataResult as Z, CrdtTableConfig as Zt, CreateRemoteSourceFactory as _, Migrations as _n, TypedBroadcastChannel as _t, SyncedDbDatabase as a, ColumnMeta as an, OwnCrdtSnapshot as at, EventsPushResponse as b, createMigrations as bn, createDeferredPromise as bt, SyncedDbTransaction as c, PayloadValidationResult as cn, SystemMigration as ct, CRDT_CHANGE_INTENTS_TABLE as d, TableBuilder as dn, applyWorkerDbSchema as dt, AiAccess as en, createImportData as et, crdtViewColumnsFromTable as f, TableColumns as fn, baseSystemMigrations as ft, CrdtSyncRemoteSource as g, MigratableEvent as gn, DistributiveOmit as gt, makeCrdtTable as h, t as hn, DeferredPromise as ht, SyncedDb as i, ColumnKind as in, OwnCrdtEvent as it, createCrdtApplyFunction as j, isNoOpCrdtEventPayload as jn, ExecuteResult as jt, createCrdtStorageMutator as k, CrdtUpdateLogPayload as kn, createSQLiteKvStore as kt, UnsafeSyncedDbSqlExecutor as l, SqliteStorageType as ln, SystemMigrationContext as lt, drainCrdtChangeIntents as m, WriteOrigin as mn, runSystemMigrations as mt, ResetRequest as n, AnyTableBuilder as nn, CrdtStorage as nt, SyncedDbOptions as o, ExportImportMode as on, createCrdtStorage as ot, createCrdtViewStatements as p, TableOptions as pn, createSystemDbConfig as pt, SharedLiveQuerySnapshot as q, HLCCounter as qt, ResetStore as r, ColumnBuilder as rn, GetEventsBatch as rt, SyncedDbSqlExecutor as s, InferRow as sn, SystemDbConfig as st, RESET_REQUEST_TTL_MS as t, AnyColumnBuilder as tn, CrdtChangeIntent as tt, createSyncedDb as u, SyncSchemaTables as un, applyMemoryDbSchema as ut, EventsPullRequest as v, MigrationsDb as vn, TypedEvent as vt, WorkerNotificationMessage as w, CRDT_EVENT_NO_OP_PAYLOAD as wn, quoteId as wt, createCrdtSyncRemoteSource as x, createMigrator as xn, createTypedEventTarget as xt, EventsPushRequest as y, SyncDbMigrator as yn, TypedEventTarget as yt, DefineSyncSchemaConfig as z, LogLevel as zt };
|
|
1220
|
-
//# sourceMappingURL=index-
|
|
1222
|
+
//# sourceMappingURL=index-UfgvV97h.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as createExportData, $t as SyncDbSchema, A as PendingCrdtEvent, An as PersistedCrdtEvent, At as ExecuteParams, B as DefinedSyncSchema, Bt as Logger, C as WorkerConfig, Cn as createStoredValue, Ct as jsonSafeParse, D as CrdtStorageMutator, Dn as CrdtEventType, Dt as KvStoreItem, E as createCrdtSyncProducer, En as CrdtEventStatus, Et as tryCatchAsync, F as verifySyncSchema, Ft as PreparedStatement, G as SQLiteReactiveDb, Gt as introspectDb, H as AdmitClientEventsResult, Ht as ColumnMetadata, I as CrdtEventValidationError, It as QueryBuilderOutput, J as parametersAreEqual, Jt as compareHLC, K as SharedLiveQuery, Kt as HLC, L as NewCrdtEventValidationResult, Lt as SQLiteDbWrapper, M as createSQLiteCrdtApplyFunction, Mn as dummyKysely, N as SchemaVerificationIssue, Nt as KyselyQueryFactory, O as SnapshotOptions, On as CrdtUpdateLogItem, Ot as createKvStoreTableQuery, P as formatSchemaVerificationIssues, Q as SyncedDbExport, Qt as ReadonlyTable, R as validateNewCrdtEvent, Rt as SQLiteTransactionWrapper, Sn as StoredValue, St as generateId, T as WorkerState, Tn as CrdtEventOrigin, Tt as tryCatch, Ut as DatabaseIntrospection, V as defineSyncSchema, Vt as startPerformanceLogger, W as admitClientEvents, Wt as TableMetadata, X as ImportDataOptions, Xt as serializeHLC, Y as xxhash, Yt as deserializeHLC, Z as ImportDataResult, Zt as CrdtTableConfig, _n as Migrations, _t as TypedBroadcastChannel, a as SyncedDbDatabase, an as ColumnMeta, at as OwnCrdtSnapshot, b as EventsPushResponse, bn as createMigrations, bt as createDeferredPromise, c as SyncedDbTransaction, cn as PayloadValidationResult, ct as SystemMigration, dn as TableBuilder, dt as applyWorkerDbSchema, en as AiAccess, et as createImportData, fn as TableColumns, g as CrdtSyncRemoteSource, gn as MigratableEvent, gt as DistributiveOmit, h as makeCrdtTable, hn as t, ht as DeferredPromise, i as SyncedDb, in as ColumnKind, it as OwnCrdtEvent, j as createCrdtApplyFunction, jn as isNoOpCrdtEventPayload, jt as ExecuteResult, k as createCrdtStorageMutator, kn as CrdtUpdateLogPayload, kt as createSQLiteKvStore, l as UnsafeSyncedDbSqlExecutor, ln as SqliteStorageType, lt as SystemMigrationContext, mn as WriteOrigin, n as ResetRequest, nn as AnyTableBuilder, nt as CrdtStorage, o as SyncedDbOptions, on as ExportImportMode, ot as createCrdtStorage, pn as TableOptions, q as SharedLiveQuerySnapshot, qt as HLCCounter, r as ResetStore, rn as ColumnBuilder, s as SyncedDbSqlExecutor, sn as InferRow, st as SystemDbConfig, t as RESET_REQUEST_TTL_MS, tn as AnyColumnBuilder, u as createSyncedDb, un as SyncSchemaTables, ut as applyMemoryDbSchema, v as EventsPullRequest, vn as MigrationsDb, vt as TypedEvent, w as WorkerNotificationMessage, wn as CRDT_EVENT_NO_OP_PAYLOAD, wt as quoteId, x as createCrdtSyncRemoteSource, xn as createMigrator, xt as createTypedEventTarget, y as EventsPushRequest, yn as SyncDbMigrator, yt as TypedEventTarget, z as DefineSyncSchemaConfig, zt as LogLevel } from "./index-
|
|
1
|
+
import { $ as createExportData, $t as SyncDbSchema, A as PendingCrdtEvent, An as PersistedCrdtEvent, At as ExecuteParams, B as DefinedSyncSchema, Bt as Logger, C as WorkerConfig, Cn as createStoredValue, Ct as jsonSafeParse, D as CrdtStorageMutator, Dn as CrdtEventType, Dt as KvStoreItem, E as createCrdtSyncProducer, En as CrdtEventStatus, Et as tryCatchAsync, F as verifySyncSchema, Ft as PreparedStatement, G as SQLiteReactiveDb, Gt as introspectDb, H as AdmitClientEventsResult, Ht as ColumnMetadata, I as CrdtEventValidationError, It as QueryBuilderOutput, J as parametersAreEqual, Jt as compareHLC, K as SharedLiveQuery, Kt as HLC, L as NewCrdtEventValidationResult, Lt as SQLiteDbWrapper, M as createSQLiteCrdtApplyFunction, Mn as dummyKysely, N as SchemaVerificationIssue, Nt as KyselyQueryFactory, O as SnapshotOptions, On as CrdtUpdateLogItem, Ot as createKvStoreTableQuery, P as formatSchemaVerificationIssues, Q as SyncedDbExport, Qt as ReadonlyTable, R as validateNewCrdtEvent, Rt as SQLiteTransactionWrapper, Sn as StoredValue, St as generateId, T as WorkerState, Tn as CrdtEventOrigin, Tt as tryCatch, Ut as DatabaseIntrospection, V as defineSyncSchema, Vt as startPerformanceLogger, W as admitClientEvents, Wt as TableMetadata, X as ImportDataOptions, Xt as serializeHLC, Y as xxhash, Yt as deserializeHLC, Z as ImportDataResult, Zt as CrdtTableConfig, _n as Migrations, _t as TypedBroadcastChannel, a as SyncedDbDatabase, an as ColumnMeta, at as OwnCrdtSnapshot, b as EventsPushResponse, bn as createMigrations, bt as createDeferredPromise, c as SyncedDbTransaction, cn as PayloadValidationResult, ct as SystemMigration, dn as TableBuilder, dt as applyWorkerDbSchema, en as AiAccess, et as createImportData, fn as TableColumns, g as CrdtSyncRemoteSource, gn as MigratableEvent, gt as DistributiveOmit, h as makeCrdtTable, hn as t, ht as DeferredPromise, i as SyncedDb, in as ColumnKind, it as OwnCrdtEvent, j as createCrdtApplyFunction, jn as isNoOpCrdtEventPayload, jt as ExecuteResult, k as createCrdtStorageMutator, kn as CrdtUpdateLogPayload, kt as createSQLiteKvStore, l as UnsafeSyncedDbSqlExecutor, ln as SqliteStorageType, lt as SystemMigrationContext, mn as WriteOrigin, n as ResetRequest, nn as AnyTableBuilder, nt as CrdtStorage, o as SyncedDbOptions, on as ExportImportMode, ot as createCrdtStorage, pn as TableOptions, q as SharedLiveQuerySnapshot, qt as HLCCounter, r as ResetStore, rn as ColumnBuilder, s as SyncedDbSqlExecutor, sn as InferRow, st as SystemDbConfig, t as RESET_REQUEST_TTL_MS, tn as AnyColumnBuilder, u as createSyncedDb, un as SyncSchemaTables, ut as applyMemoryDbSchema, v as EventsPullRequest, vn as MigrationsDb, vt as TypedEvent, w as WorkerNotificationMessage, wn as CRDT_EVENT_NO_OP_PAYLOAD, wt as quoteId, x as createCrdtSyncRemoteSource, xn as createMigrator, xt as createTypedEventTarget, y as EventsPushRequest, yn as SyncDbMigrator, yt as TypedEventTarget, z as DefineSyncSchemaConfig, zt as LogLevel } from "./index-UfgvV97h.js";
|
|
2
2
|
export { type AdmitClientEventsResult, type AiAccess, type AnyColumnBuilder, type AnyTableBuilder, CRDT_EVENT_NO_OP_PAYLOAD, ColumnBuilder, type ColumnKind, type ColumnMeta, type ColumnMetadata, type CrdtEventOrigin, type CrdtEventStatus, type CrdtEventType, CrdtEventValidationError, type CrdtStorage, type CrdtStorageMutator, type CrdtSyncRemoteSource, type CrdtTableConfig, type CrdtUpdateLogItem, type CrdtUpdateLogPayload, type DatabaseIntrospection, type DeferredPromise, type DefineSyncSchemaConfig, type DefinedSyncSchema, type DistributiveOmit, type EventsPullRequest, type EventsPushRequest, type EventsPushResponse, type ExecuteParams, type ExecuteResult, type ExportImportMode, type HLC, HLCCounter, type ImportDataOptions, type ImportDataResult, type InferRow, type KvStoreItem, type KyselyQueryFactory, type LogLevel, type Logger, type MigratableEvent, type Migrations, type MigrationsDb, type NewCrdtEventValidationResult, type OwnCrdtEvent, type OwnCrdtSnapshot, type PayloadValidationResult, type PendingCrdtEvent, type PersistedCrdtEvent, type PreparedStatement, type QueryBuilderOutput, RESET_REQUEST_TTL_MS, type ReadonlyTable, type ResetRequest, type ResetStore, SQLiteDbWrapper, SQLiteReactiveDb, type SQLiteTransactionWrapper, type SchemaVerificationIssue, type SharedLiveQuery, type SharedLiveQuerySnapshot, type SnapshotOptions, type SqliteStorageType, type StoredValue, type SyncDbMigrator, type SyncDbSchema, type SyncSchemaTables, type SyncedDb, type SyncedDbDatabase, type SyncedDbExport, type SyncedDbOptions, type SyncedDbSqlExecutor, type SyncedDbTransaction, type SystemDbConfig, type SystemMigration, type SystemMigrationContext, TableBuilder, type TableColumns, type TableMetadata, type TableOptions, TypedBroadcastChannel, TypedEvent, type TypedEventTarget, type UnsafeSyncedDbSqlExecutor, type WorkerConfig, type WorkerNotificationMessage, type WorkerState, type WriteOrigin, 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 };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as introspectDb, D as dummyKysely, E as createImportData, S as startPerformanceLogger, T as createExportData, _ as formatSchemaVerificationIssues, a as createBroadcastChannels, b as createMigrator, c as isWorkerNotificationMessage, d as syncDbClientLockName, g as createSQLiteCrdtApplyFunction, h as createCrdtApplyFunction, m as createCrdtStorage, o as isWorkerErrorResponseMessage, p as createCrdtSyncProducer, t as RESET_REQUEST_TTL_MS, u as isWorkerResponseMessage, v as verifySyncSchema, w as xxhash, x as SQLiteDbWrapper, y as createMigrations } from "./reset-state-
|
|
1
|
+
import { C as introspectDb, D as dummyKysely, E as createImportData, S as startPerformanceLogger, T as createExportData, _ as formatSchemaVerificationIssues, a as createBroadcastChannels, b as createMigrator, c as isWorkerNotificationMessage, d as syncDbClientLockName, g as createSQLiteCrdtApplyFunction, h as createCrdtApplyFunction, m as createCrdtStorage, o as isWorkerErrorResponseMessage, p as createCrdtSyncProducer, t as RESET_REQUEST_TTL_MS, u as isWorkerResponseMessage, v as verifySyncSchema, w as xxhash, x as SQLiteDbWrapper, y as createMigrations } from "./reset-state-CchMrdoA.js";
|
|
2
2
|
import { a as createDeferredPromise, c as generateId, f as quoteId, i as TypedEvent, l as jsonSafeParse, m as tryCatchAsync, n as isNoOpCrdtEventPayload, o as createTypedEventTarget, p as tryCatch, r as TypedBroadcastChannel, t as CRDT_EVENT_NO_OP_PAYLOAD, u as noop } from "./crdt-table-schema-2w_AIpsV.js";
|
|
3
|
-
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-
|
|
3
|
+
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-CugbiosG.js";
|
|
4
4
|
import { a as memoryDbConfig, c as createKvStoreTableQuery, l as createSQLiteKvStore, n as applyWorkerDbSchema, t as applyMemoryDbSchema, u as createStoredValue } from "./system-schema-C2JZDv6L.js";
|
|
5
5
|
import { n as buildWriteOriginByName, t as admitClientEvents } from "./admit-client-events-BDrJw4SK.js";
|
|
6
6
|
import { a as makeCrdtTable, o as registerCrdtIntentDrainer } from "./make-crdt-table-D8VQ-ptj.js";
|
|
@@ -578,16 +578,13 @@ function createCrdtStorageMutator({ storage }) {
|
|
|
578
578
|
};
|
|
579
579
|
}
|
|
580
580
|
};
|
|
581
|
-
const
|
|
582
|
-
storage.
|
|
581
|
+
const applyEvents = (events) => {
|
|
582
|
+
storage.applyOwnEvents(events.map(mapToStorageEvent));
|
|
583
583
|
};
|
|
584
|
-
const
|
|
585
|
-
|
|
584
|
+
const applyEvent = (event) => {
|
|
585
|
+
storage.applyOwnEvents([mapToStorageEvent(event)]);
|
|
586
586
|
};
|
|
587
|
-
const
|
|
588
|
-
storage.enqueueOwnEvents([mapToStorageEvent(event)]);
|
|
589
|
-
};
|
|
590
|
-
const enqueueSnapshot = (snapshot) => {
|
|
587
|
+
const applySnapshot = (snapshot) => {
|
|
591
588
|
storage.applyOwnSnapshot({
|
|
592
589
|
dataset: snapshot.dataset,
|
|
593
590
|
item_id: snapshot.id,
|
|
@@ -595,10 +592,9 @@ function createCrdtStorageMutator({ storage }) {
|
|
|
595
592
|
});
|
|
596
593
|
};
|
|
597
594
|
return {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
enqueueSnapshot
|
|
595
|
+
applyEvent,
|
|
596
|
+
applyEvents,
|
|
597
|
+
applySnapshot
|
|
602
598
|
};
|
|
603
599
|
}
|
|
604
600
|
//#endregion
|
|
@@ -740,9 +736,10 @@ const createWorkerDbClient = async ({ broadcastChannels, worker, config }) => {
|
|
|
740
736
|
const statePromise = awaitWorkerState(eventTarget);
|
|
741
737
|
postWorkerConfig(worker, config);
|
|
742
738
|
rpc.postState().catch(noop);
|
|
743
|
-
let workerState = await statePromise;
|
|
739
|
+
let { state: workerState, storageGeneration } = await statePromise;
|
|
744
740
|
eventTarget.addEventListener("state-changed", (event) => {
|
|
745
741
|
workerState = event.payload.state;
|
|
742
|
+
storageGeneration = event.payload.storageGeneration;
|
|
746
743
|
});
|
|
747
744
|
const dispose = () => {
|
|
748
745
|
isDisposed = true;
|
|
@@ -756,13 +753,14 @@ const createWorkerDbClient = async ({ broadcastChannels, worker, config }) => {
|
|
|
756
753
|
...rpc,
|
|
757
754
|
subscribe: eventTarget.addEventListener,
|
|
758
755
|
getState: () => workerState,
|
|
756
|
+
getStorageGeneration: () => storageGeneration,
|
|
759
757
|
dispose
|
|
760
758
|
};
|
|
761
759
|
};
|
|
762
760
|
function awaitWorkerState(eventTarget) {
|
|
763
761
|
const promise = createDeferredPromise({ timeout: 15e3 });
|
|
764
762
|
const subscription = eventTarget.addEventListener("state-changed", (event) => {
|
|
765
|
-
promise.resolve(event.payload
|
|
763
|
+
promise.resolve(event.payload);
|
|
766
764
|
subscription.unsubscribe();
|
|
767
765
|
});
|
|
768
766
|
return promise.promise;
|
|
@@ -894,6 +892,16 @@ async function createSyncedDb(options) {
|
|
|
894
892
|
const reloadRequestedSubscription = workerClient.subscribe("reload-requested", () => {
|
|
895
893
|
globalThis.location?.reload();
|
|
896
894
|
});
|
|
895
|
+
const reloadIfStorageReplaced = (storageGeneration) => {
|
|
896
|
+
if (storageGeneration !== workerClientSnapshot.storageGeneration) {
|
|
897
|
+
storageReplacedSubscription.unsubscribe();
|
|
898
|
+
globalThis.location?.reload();
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
const storageReplacedSubscription = workerClient.subscribe("state-changed", (event) => {
|
|
902
|
+
reloadIfStorageReplaced(event.payload.storageGeneration);
|
|
903
|
+
});
|
|
904
|
+
reloadIfStorageReplaced(workerClient.getStorageGeneration());
|
|
897
905
|
const sync = () => {
|
|
898
906
|
workerClient.sync().catch((error) => console.warn("Failed to start sync", error));
|
|
899
907
|
};
|
|
@@ -901,6 +909,7 @@ async function createSyncedDb(options) {
|
|
|
901
909
|
if (globalThis.document?.visibilityState === "visible") sync();
|
|
902
910
|
};
|
|
903
911
|
globalThis.document?.addEventListener("visibilitychange", syncWhenVisible);
|
|
912
|
+
globalThis.addEventListener?.("online", sync);
|
|
904
913
|
perf.logEnd("createSyncedDb", "initialized", "info");
|
|
905
914
|
const exportData = createExportData({
|
|
906
915
|
reactiveDb,
|
|
@@ -915,7 +924,9 @@ async function createSyncedDb(options) {
|
|
|
915
924
|
isDisposed = true;
|
|
916
925
|
unregisterDevtools?.();
|
|
917
926
|
globalThis.document?.removeEventListener("visibilitychange", syncWhenVisible);
|
|
927
|
+
globalThis.removeEventListener?.("online", sync);
|
|
918
928
|
reloadRequestedSubscription.unsubscribe();
|
|
929
|
+
storageReplacedSubscription.unsubscribe();
|
|
919
930
|
clientLockRelease.resolve();
|
|
920
931
|
await tabRemoteSource.dispose();
|
|
921
932
|
broadcastChannels.requests.close();
|