event-sourced-collection 0.0.12 → 0.0.14

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.
@@ -1,5 +1,5 @@
1
- import { $ as InjectedCreateCollection, L as SyncLock, P as SQLiteDriver, et as InjectedModuleFn, p as EventSourcedSharedOptions } from "./types-DrV5f9_t.mjs";
2
- import { r as ModulesInput, t as EventSourcedDBHandle } from "./create-event-sourced-db-handle-Di5qN4QH.mjs";
1
+ import { I as SQLiteDriver, nt as InjectedModuleFn, p as EventSourcedSharedOptions, tt as InjectedCreateCollection, z as SyncLock } from "./types-Dc-_92xv.mjs";
2
+ import { r as ModulesInput, t as EventSourcedDBHandle } from "./create-event-sourced-db-handle-DlUfot8-.mjs";
3
3
  import { PersistedCollectionPersistence } from "@tanstack/db-sqlite-persistence-core";
4
4
 
5
5
  //#region src/platforms/browser-wa-sqlite-driver.d.ts
package/dist/browser.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as resolveModules, t as createEventSourcedDBHandle } from "./create-event-sourced-db-handle-CD8WSjXW.mjs";
1
+ import { n as resolveModules, t as createEventSourcedDBHandle } from "./create-event-sourced-db-handle-BRSDLeq9.mjs";
2
2
  import { t as createWebLocksSyncLock } from "./web-locks-Bi2f732X.mjs";
3
3
  //#region src/platforms/browser-wa-sqlite-driver.ts
4
4
  function assertTransactionCallbackHasDriverArg(fn) {
@@ -115,6 +115,22 @@ async function replayEvent(context, event) {
115
115
  reason
116
116
  };
117
117
  }
118
+ if (context.localOnlyIds.has(collectionId)) {
119
+ const reason = `local-only collection "${collectionId}"`;
120
+ log.debug("replay skipped: local-only collection", {
121
+ eventId,
122
+ collectionId
123
+ });
124
+ context.emit("onEventSkipped", {
125
+ eventId,
126
+ collectionId,
127
+ reason
128
+ });
129
+ return {
130
+ status: "skipped",
131
+ reason
132
+ };
133
+ }
118
134
  const migrated = upcast(context, event);
119
135
  if (migrated.status !== "ok") return migrated.outcome;
120
136
  const target = targets[collectionId];
@@ -1364,6 +1380,18 @@ function generateEventId() {
1364
1380
  }
1365
1381
  //#endregion
1366
1382
  //#region src/core/create-event-sourced-db.ts
1383
+ /**
1384
+ * Thrown by `resetLocalReplica()` while the outbox still holds changes the
1385
+ * server has not accepted. Sync first, or pass `discardPending: true`.
1386
+ */
1387
+ var UnsyncedChangesError = class extends Error {
1388
+ pendingCount;
1389
+ constructor(pendingCount) {
1390
+ super(`${pendingCount} local change(s) have not been pushed yet`);
1391
+ this.pendingCount = pendingCount;
1392
+ this.name = "UnsyncedChangesError";
1393
+ }
1394
+ };
1367
1395
  function emptyResult(overrides = {}) {
1368
1396
  return {
1369
1397
  pushed: 0,
@@ -1459,9 +1487,15 @@ async function createEventSourcedDB(config) {
1459
1487
  };
1460
1488
  const { outbox, inbox, deadletter, syncmeta, rowversions } = meta;
1461
1489
  const userCollections = {};
1490
+ const syncedCollections = [];
1491
+ const localOnlyIds = new Set(Object.keys(config.collections).filter((id) => config.collections[id].localOnly === true));
1462
1492
  for (const collectionId of Object.keys(config.collections)) {
1463
1493
  const def = config.collections[collectionId];
1464
1494
  const getKey = def.getKey;
1495
+ const hook = (type) => def.localOnly ? noOutboxHook : createMutationHook({
1496
+ ...mutationContext,
1497
+ type
1498
+ });
1465
1499
  const mutationContext = {
1466
1500
  outbox,
1467
1501
  rowversions,
@@ -1479,21 +1513,16 @@ async function createEventSourcedDB(config) {
1479
1513
  persistence: config.persistence,
1480
1514
  schemaVersion: def.schemaVersion ?? defaultSchemaVersion,
1481
1515
  gcTime: Number.POSITIVE_INFINITY,
1482
- onInsert: createMutationHook({
1483
- ...mutationContext,
1484
- type: "insert"
1485
- }),
1486
- onUpdate: createMutationHook({
1487
- ...mutationContext,
1488
- type: "update"
1489
- }),
1490
- onDelete: createMutationHook({
1491
- ...mutationContext,
1492
- type: "delete"
1493
- })
1516
+ onInsert: hook("insert"),
1517
+ onUpdate: hook("update"),
1518
+ onDelete: hook("delete")
1494
1519
  });
1495
1520
  const collection = config.createCollection(options);
1496
1521
  applyCollectionIndexes(collection, collectionId, def.indexes, log);
1522
+ if (!def.localOnly) syncedCollections.push({
1523
+ collectionId,
1524
+ collection
1525
+ });
1497
1526
  log.debug("registered collection", {
1498
1527
  collectionId,
1499
1528
  hasAcceptMutations: Boolean(collection.utils?.acceptMutations)
@@ -1532,8 +1561,10 @@ async function createEventSourcedDB(config) {
1532
1561
  clientId: clientId.value,
1533
1562
  pullCursor: readPullCursor(syncmeta, inbox)
1534
1563
  });
1564
+ for (const entry of [...outbox.state.values()]) if (!entry.sync && localOnlyIds.has(entry.collectionId)) await outbox.delete(entry.eventId).isPersisted.promise;
1535
1565
  const replayContext = {
1536
1566
  targets: replayTargets,
1567
+ localOnlyIds,
1537
1568
  rowversions,
1538
1569
  deadletter,
1539
1570
  unknownEventHandling,
@@ -1856,6 +1887,59 @@ async function createEventSourcedDB(config) {
1856
1887
  };
1857
1888
  });
1858
1889
  }
1890
+ function resetLocalReplica(options = {}) {
1891
+ const deferred = {
1892
+ deferred: true,
1893
+ removedRows: 0,
1894
+ discardedPending: 0,
1895
+ clientId: clientId.value
1896
+ };
1897
+ return runExclusive(() => withLock(async () => {
1898
+ const pending = [...outbox.state.values()].filter((entry) => !entry.sync);
1899
+ if (pending.length > 0 && options.discardPending !== true) throw new UnsyncedChangesError(pending.length);
1900
+ let removedRows = 0;
1901
+ for (const { collectionId, collection } of syncedCollections) {
1902
+ const target = replayTargets[collectionId];
1903
+ const rows = [...collection.state.entries()];
1904
+ if (rows.length === 0 || !target?.utils.acceptMutations) continue;
1905
+ await target.utils.acceptMutations({ mutations: rows.map(([key, row]) => ({
1906
+ mutationId: generateEventId(),
1907
+ type: "delete",
1908
+ key,
1909
+ modified: row,
1910
+ original: row,
1911
+ changes: row,
1912
+ collection: target
1913
+ })) });
1914
+ removedRows += rows.length;
1915
+ }
1916
+ for (const meta of [
1917
+ outbox,
1918
+ inbox,
1919
+ deadletter
1920
+ ]) for (const eventId of [...meta.state.keys()]) await meta.delete(eventId).isPersisted.promise;
1921
+ for (const id of [...rowversions.state.keys()]) await rowversions.delete(id).isPersisted.promise;
1922
+ clientId.value = generateEventId();
1923
+ await ensureSyncMeta(syncmeta);
1924
+ await syncmeta.update(SYNCMETA_KEY, (draft) => {
1925
+ draft.clientId = clientId.value;
1926
+ draft.pullCursor = 0;
1927
+ draft.lastError = null;
1928
+ }).isPersisted.promise;
1929
+ log.warn("local replica reset", {
1930
+ removedRows,
1931
+ discardedPending: pending.length,
1932
+ clientId: clientId.value
1933
+ });
1934
+ notifyStatus();
1935
+ return {
1936
+ deferred: false,
1937
+ removedRows,
1938
+ discardedPending: pending.length,
1939
+ clientId: clientId.value
1940
+ };
1941
+ }, deferred));
1942
+ }
1859
1943
  function getSyncEnabled() {
1860
1944
  return syncEnabled;
1861
1945
  }
@@ -1888,6 +1972,7 @@ async function createEventSourcedDB(config) {
1888
1972
  return pushLimits;
1889
1973
  },
1890
1974
  pruneSyncedEvents,
1975
+ resetLocalReplica,
1891
1976
  dispose
1892
1977
  };
1893
1978
  }
@@ -1959,6 +2044,10 @@ function applyCollectionIndexes(collection, collectionId, indexes, log) {
1959
2044
  register();
1960
2045
  indexable.on?.("status:ready", register);
1961
2046
  }
2047
+ /** Handler for `localOnly` collections: persist locally, author no event. */
2048
+ async function noOutboxHook() {
2049
+ return {};
2050
+ }
1962
2051
  function createMutationHook(context) {
1963
2052
  const { outbox, rowversions, collectionId, type, seq, clientId, eventSchemaVersion, conflictDetection, emit, log } = context;
1964
2053
  return async (params) => {
@@ -2181,6 +2270,6 @@ async function resolveModules(modules) {
2181
2270
  return typeof modules === "function" ? await modules() : modules;
2182
2271
  }
2183
2272
  //#endregion
2184
- export { generateEventId as a, resolvePushLimits as c, createHttpTransport as d, BackendMismatchError as f, createEventSourcedDB as i, SyncPullError as l, resolveModules as n, createEventSourcedLogger as o, createLazySingleton as r, SYNC_PUSH_PRESETS as s, createEventSourcedDBHandle as t, SyncPushError as u };
2273
+ export { createEventSourcedDB as a, SYNC_PUSH_PRESETS as c, SyncPushError as d, createHttpTransport as f, UnsyncedChangesError as i, resolvePushLimits as l, resolveModules as n, generateEventId as o, BackendMismatchError as p, createLazySingleton as r, createEventSourcedLogger as s, createEventSourcedDBHandle as t, SyncPullError as u };
2185
2274
 
2186
- //# sourceMappingURL=create-event-sourced-db-handle-CD8WSjXW.mjs.map
2275
+ //# sourceMappingURL=create-event-sourced-db-handle-BRSDLeq9.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-event-sourced-db-handle-BRSDLeq9.mjs","names":[],"sources":["../src/internal/constants.ts","../src/internal/hooks.ts","../src/internal/replay.ts","../src/internal/sync-meta.ts","../src/internal/pull.ts","../src/core/sync.ts","../src/internal/push.ts","../src/core/sync-presets.ts","../src/internal/serial-queue.ts","../src/utils/logger.ts","../src/utils/uuid.ts","../src/core/create-event-sourced-db.ts","../src/core/lazy-singleton.ts","../src/core/create-event-sourced-db-handle.ts"],"sourcesContent":["export const OUTBOX_ID = \"outbox\";\nexport const INBOX_ID = \"inbox\";\nexport const DEADLETTER_ID = \"deadletter\";\nexport const SYNCMETA_ID = \"syncmeta\";\nexport const ROWVERSIONS_ID = \"rowversions\";\n\n/** `syncmeta` holds exactly one row; this is its key. */\nexport const SYNCMETA_KEY = \"singleton\";\n\nexport const RESERVED_IDS: ReadonlySet<string> = new Set([\n OUTBOX_ID,\n INBOX_ID,\n DEADLETTER_ID,\n SYNCMETA_ID,\n ROWVERSIONS_ID,\n]);\n\nexport const DEFAULT_PUSH_BATCH_SIZE = 20;\nexport const MIN_PUSH_BATCH_SIZE = 1;\nexport const MAX_PUSH_BATCH_SIZE = 100;\nexport const PAYLOAD_TOO_LARGE_ERROR_CODE = \"PAYLOAD_TOO_LARGE\";\nexport const DEFAULT_MAX_ATTEMPTS = 8;\nexport const DEFAULT_BASE_DELAY_MS = 1_000;\nexport const DEFAULT_MAX_DELAY_MS = 5 * 60 * 1_000;\nexport const DEFAULT_EVENT_SCHEMA_VERSION = 1;\n\nexport const SYNC_LOCK_PREFIX = \"event-sourced-sync\";\n\n/** Server error code that routes a rejected event to the dead-letter queue as a conflict. */\nexport const CONFLICT_ERROR_CODE = \"CONFLICT\";\n","import type { EventSourcedHooks } from \"../core/types\";\nimport type { EventSourcedLogger } from \"../utils/logger\";\n\n/**\n * Invokes a lifecycle hook. A hook that throws is logged and swallowed — user\n * observation code must never be able to fail a sync.\n *\n * @example\n * ```ts\n * const emit: EmitHook = createHookEmitter(\n * { onSyncStart: ({ trigger }) => console.info(\"sync\", trigger) },\n * log,\n * )\n *\n * emit(\"onSyncStart\", { trigger: \"manualSync\" })\n * emit(\"onDeadLetter\", deadLetterEntry) // no-op when that hook is omitted\n * ```\n */\nexport type EmitHook = <TName extends keyof EventSourcedHooks>(\n name: TName,\n argument: Parameters<NonNullable<EventSourcedHooks[TName]>>[0],\n) => void;\n\n/**\n * Builds an {@link EmitHook} bound to the user-supplied {@link EventSourcedHooks}.\n *\n * @example A throwing hook is logged, then ignored\n * ```ts\n * import { createHookEmitter } from \"./hooks\"\n *\n * const emit = createHookEmitter(\n * {\n * onDeadLetter: () => {\n * throw new Error(\"toast failed\")\n * },\n * },\n * log,\n * )\n *\n * emit(\"onDeadLetter\", entry) // sync continues; log.error(\"lifecycle hook threw\", …)\n * ```\n */\nexport function createHookEmitter(\n hooks: EventSourcedHooks | undefined,\n log: EventSourcedLogger,\n): EmitHook {\n if (!hooks) return () => {};\n\n return (name, argument) => {\n const hook = hooks[name] as ((value: unknown) => void) | undefined;\n if (!hook) return;\n\n try {\n hook(argument);\n } catch (err) {\n log.error(\"lifecycle hook threw\", {\n hook: name,\n message: err instanceof Error ? err.message : String(err),\n });\n }\n };\n}\n","import type { Collection } from \"@tanstack/db\";\n\nimport type { DeadLetterEntry, InboxEntry, RowVersionEntry, UpcastableEvent } from \"../core/types\";\nimport { DEFAULT_EVENT_SCHEMA_VERSION, RESERVED_IDS } from \"./constants\";\nimport type { ReplayableEvent, ReplayContext, ReplayOutcome } from \"./types\";\n\nexport type ReplaySummary = { applied: number; skipped: number; deadLettered: number };\n\nexport function rowVersionId(collectionId: string, key: string | number): string {\n return `${collectionId}::${String(key)}`;\n}\n\n/**\n * Records the version a row is now at. Used to stamp `baseVersion` on future\n * local mutations so the server can detect writes authored against stale state.\n */\nexport async function recordRowVersion(\n rowversions: Collection<RowVersionEntry, string>,\n collectionId: string,\n key: string | number,\n version: string,\n globalSeq: number | null,\n): Promise<void> {\n const id = rowVersionId(collectionId, key);\n\n if (rowversions.has(id)) {\n await rowversions.update(id, (draft) => {\n draft.version = version;\n draft.globalSeq = globalSeq;\n }).isPersisted.promise;\n return;\n }\n\n await rowversions.insert({ id, collectionId, key, version, globalSeq }).isPersisted.promise;\n}\n\nexport function readRowVersion(\n rowversions: Collection<RowVersionEntry, string>,\n collectionId: string,\n key: string | number,\n): string | null {\n return rowversions.get(rowVersionId(collectionId, key))?.version ?? null;\n}\n\n/**\n * After a CONFLICT dead-letter, undo the optimistic `recordRowVersion` that\n * stamped the rejected event id as head. Restores `baseVersion`, or deletes\n * the index row when the mutation was authored against an unknown row.\n */\nexport async function restoreRowVersionAfterConflict(\n rowversions: Collection<RowVersionEntry, string>,\n collectionId: string,\n key: string | number,\n baseVersion: string | null,\n): Promise<void> {\n const id = rowVersionId(collectionId, key);\n\n if (baseVersion === null) {\n if (rowversions.has(id)) {\n await rowversions.delete(id).isPersisted.promise;\n }\n return;\n }\n\n await recordRowVersion(rowversions, collectionId, key, baseVersion, null);\n}\n\nexport async function replayEvent(\n context: ReplayContext,\n event: ReplayableEvent,\n): Promise<ReplayOutcome> {\n const { targets, log } = context;\n const { eventId, collectionId } = event;\n\n // A reserved target can never become valid, so retrying it would wedge the\n // pipeline forever. Unknown collections can become valid after a client\n // upgrade, so those honour unknownEventHandling.\n if (RESERVED_IDS.has(collectionId)) {\n const reason = `reserved collection \"${collectionId}\"`;\n log.warn(\"replay skipped: reserved collection\", {\n eventId,\n collectionId,\n type: event.type,\n key: event.key,\n });\n context.emit(\"onEventSkipped\", { eventId, collectionId, reason });\n return { status: \"skipped\", reason };\n }\n\n if (context.localOnlyIds.has(collectionId)) {\n const reason = `local-only collection \"${collectionId}\"`;\n log.debug(\"replay skipped: local-only collection\", { eventId, collectionId });\n context.emit(\"onEventSkipped\", { eventId, collectionId, reason });\n return { status: \"skipped\", reason };\n }\n\n const migrated = upcast(context, event);\n if (migrated.status !== \"ok\") return migrated.outcome;\n\n const target = targets[collectionId];\n if (!target) {\n return unresolvable(context, event, `unknown collection \"${collectionId}\"`, {\n knownCollections: Object.keys(targets).filter((id) => !RESERVED_IDS.has(id)),\n });\n }\n\n if (!target.utils.acceptMutations) {\n return unresolvable(context, event, `collection \"${collectionId}\" is missing acceptMutations`, {\n targetId: target.id,\n });\n }\n\n const { type, key, payload } = migrated.event;\n\n log.debug(\"replay applying mutation\", { eventId, collectionId, type, key });\n\n try {\n await target.utils.acceptMutations({\n mutations: [\n {\n mutationId: eventId,\n type,\n key,\n modified: payload,\n original: payload,\n changes: payload,\n collection: target,\n },\n ],\n });\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n log.error(\"replay mutation failed\", {\n eventId,\n collectionId,\n type,\n key,\n message: error.message,\n });\n // Reported rather than thrown: one unapplicable event must not be able to\n // wedge the pull pipeline behind it forever.\n return { status: \"failed\", error };\n }\n\n if (context.conflictDetection) {\n await recordRowVersion(\n context.rowversions,\n collectionId,\n key,\n eventId,\n event.globalSeq ?? null,\n );\n }\n\n log.info(\"replay mutation accepted\", { eventId, collectionId, type, key });\n context.emit(\"onEventApplied\", { eventId, collectionId, type, key });\n\n return { status: \"applied\" };\n}\n\ntype UpcastResult =\n | { status: \"ok\"; event: UpcastableEvent }\n | { status: \"blocked\"; outcome: ReplayOutcome };\n\n/**\n * Brings an event authored under a different schema version into the current\n * shape. Without an upcaster, older events are applied as-is (best effort) but\n * newer ones are refused, since this build cannot know what the fields mean.\n */\nfunction upcast(context: ReplayContext, event: ReplayableEvent): UpcastResult {\n const version = event.schemaVersion ?? DEFAULT_EVENT_SCHEMA_VERSION;\n\n const current: UpcastableEvent = {\n eventId: event.eventId,\n collectionId: event.collectionId,\n type: event.type,\n key: event.key,\n payload: event.payload,\n previous: event.previous ?? null,\n schemaVersion: version,\n };\n\n if (version === context.eventSchemaVersion) {\n return { status: \"ok\", event: current };\n }\n\n if (context.upcastEvent) {\n const migrated = context.upcastEvent(current);\n\n if (!migrated) {\n const reason = `upcaster dropped schema version ${version}`;\n context.log.warn(\"replay skipped: upcaster dropped event\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n schemaVersion: version,\n });\n context.emit(\"onEventSkipped\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n reason,\n });\n return { status: \"blocked\", outcome: { status: \"skipped\", reason } };\n }\n\n return { status: \"ok\", event: migrated };\n }\n\n if (version > context.eventSchemaVersion) {\n return {\n status: \"blocked\",\n outcome: unresolvable(\n context,\n event,\n `event schema version ${version} is newer than supported version ${context.eventSchemaVersion}`,\n {},\n ),\n };\n }\n\n context.log.warn(\"replaying older event schema version without an upcaster\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n schemaVersion: version,\n currentVersion: context.eventSchemaVersion,\n });\n\n return { status: \"ok\", event: current };\n}\n\nfunction unresolvable(\n context: ReplayContext,\n event: ReplayableEvent,\n reason: string,\n details: Record<string, unknown>,\n): ReplayOutcome {\n const halt = context.unknownEventHandling === \"fail\";\n\n context.log.warn(halt ? \"replay halted\" : \"replay skipped\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n type: event.type,\n key: event.key,\n reason,\n ...details,\n });\n\n if (halt) return { status: \"halted\", reason };\n\n context.emit(\"onEventSkipped\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n reason,\n });\n\n return { status: \"skipped\", reason };\n}\n\n/**\n * What to do after a replay threw: come back to it next sync, or give up and\n * park it in the dead-letter queue.\n */\nexport type ReplayFailureResolution = \"retry\" | \"deadLettered\";\n\n/**\n * Records a failed replay against its inbox row and, once the attempt budget is\n * spent, moves the event to the dead-letter queue and resolves the inbox row so\n * the cursor can advance past it. Otherwise a single event the local schema\n * cannot accept blocks every event behind it, permanently.\n */\nexport async function handleReplayFailure(\n context: ReplayContext,\n inbox: Collection<InboxEntry, string>,\n event: ReplayableEvent,\n error: Error,\n now: number,\n): Promise<ReplayFailureResolution> {\n const { deadletter, maxReplayAttempts, log } = context;\n const existing = inbox.get(event.eventId);\n const attemptCount = (existing?.attemptCount ?? 0) + 1;\n\n if (existing) {\n await inbox.update(event.eventId, (draft) => {\n draft.attemptCount = attemptCount;\n draft.lastError = error.message;\n }).isPersisted.promise;\n }\n\n if (attemptCount < maxReplayAttempts) {\n log.warn(\"replay failed; retrying on a later sync\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n attemptCount,\n maxReplayAttempts,\n message: error.message,\n });\n\n return \"retry\";\n }\n\n const reason = `replay failed after ${attemptCount} attempts: ${error.message}`;\n\n if (!deadletter.has(event.eventId)) {\n const record: DeadLetterEntry = {\n eventId: event.eventId,\n collectionId: event.collectionId,\n type: event.type,\n key: event.key,\n payload: event.payload,\n previous: event.previous ?? null,\n txId: null,\n clientId: existing?.clientId ?? null,\n schemaVersion: event.schemaVersion ?? DEFAULT_EVENT_SCHEMA_VERSION,\n timestamp: existing?.timestamp ?? now,\n localSeq: null,\n globalSeq: event.globalSeq ?? null,\n direction: \"inbound\",\n reason: \"replayFailed\",\n message: error.message,\n code: null,\n attemptCount,\n failedAt: now,\n };\n\n await deadletter.insert(record).isPersisted.promise;\n context.emit(\"onDeadLetter\", record);\n }\n\n if (existing) {\n await resolveInboxEntry(inbox, event.eventId, { status: \"skipped\", reason });\n }\n\n log.warn(\"inbound event dead-lettered\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n attemptCount,\n message: error.message,\n });\n\n return \"deadLettered\";\n}\n\n/**\n * Marks an inbox row as resolved — either applied or deliberately skipped.\n * Skipped rows still count as resolved so the pull cursor can move past them.\n */\nexport async function resolveInboxEntry(\n inbox: Collection<InboxEntry, string>,\n eventId: string,\n outcome: Extract<ReplayOutcome, { status: \"applied\" | \"skipped\" }>,\n): Promise<void> {\n await inbox.update(eventId, (draft) => {\n draft.sync = true;\n draft.skipped = outcome.status === \"skipped\";\n draft.skipReason = outcome.status === \"skipped\" ? outcome.reason : null;\n }).isPersisted.promise;\n}\n\nexport async function replayInbox(\n inbox: Collection<InboxEntry, string>,\n context: ReplayContext,\n): Promise<ReplaySummary> {\n const { log } = context;\n\n const pending = [...inbox.state.values()]\n .filter((entry) => !entry.sync)\n .sort((a, b) => a.globalSeq - b.globalSeq);\n\n log.info(\"pending inbox replay started\", { pendingCount: pending.length });\n\n let applied = 0;\n let skipped = 0;\n let deadLettered = 0;\n\n for (const entry of pending) {\n const outcome = await replayEvent(context, entry);\n\n if (outcome.status === \"halted\") break;\n\n if (outcome.status === \"failed\") {\n const resolution = await handleReplayFailure(\n context,\n inbox,\n entry,\n outcome.error,\n Date.now(),\n );\n\n // Still retryable: stop here so events stay in order until it resolves.\n if (resolution === \"retry\") break;\n\n deadLettered++;\n continue;\n }\n\n await resolveInboxEntry(inbox, entry.eventId, outcome);\n\n if (outcome.status === \"skipped\") {\n skipped++;\n continue;\n }\n\n applied++;\n\n log.info(\"pending inbox replay applied\", {\n eventId: entry.eventId,\n globalSeq: entry.globalSeq,\n collectionId: entry.collectionId,\n });\n }\n\n log.info(\"pending inbox replay finished\", { applied, skipped, deadLettered });\n\n return { applied, skipped, deadLettered };\n}\n","import type { Collection } from \"@tanstack/db\";\n\nimport type { InboxEntry, SyncMetaEntry } from \"../core/types\";\nimport { SYNCMETA_KEY } from \"./constants\";\n\nconst EMPTY: SyncMetaEntry = {\n id: SYNCMETA_KEY,\n backendId: null,\n clientId: null,\n pullCursor: 0,\n lastSyncAt: null,\n lastError: null,\n};\n\nexport function readSyncMeta(syncmeta: Collection<SyncMetaEntry, string>): SyncMetaEntry {\n return syncmeta.get(SYNCMETA_KEY) ?? EMPTY;\n}\n\nexport async function ensureSyncMeta(syncmeta: Collection<SyncMetaEntry, string>): Promise<void> {\n if (syncmeta.has(SYNCMETA_KEY)) return;\n await syncmeta.insert({ ...EMPTY }).isPersisted.promise;\n}\n\nasync function patch(\n syncmeta: Collection<SyncMetaEntry, string>,\n apply: (draft: SyncMetaEntry) => void,\n): Promise<void> {\n await ensureSyncMeta(syncmeta);\n await syncmeta.update(SYNCMETA_KEY, apply).isPersisted.promise;\n}\n\nexport function readBackendId(syncmeta: Collection<SyncMetaEntry, string>): string | null {\n return readSyncMeta(syncmeta).backendId;\n}\n\n/**\n * Resolves this device's identity, persisting it on first run so it survives\n * reloads. Without that, a client stops recognising its own pulled-back events\n * as soon as the outbox is pruned and will replay its own history as if it were\n * someone else's.\n *\n * Preference: explicit `configured` id, then the stored `syncmeta.clientId`,\n * then `generate()`.\n *\n * @example First open generates and stores an id; the next open reuses it\n * ```ts\n * import { resolveClientId } from \"./sync-meta\"\n *\n * const clientId = await resolveClientId(\n * db.collections.syncmeta,\n * undefined,\n * () => crypto.randomUUID(),\n * )\n * // later, after close + reopen on the same file:\n * const again = await resolveClientId(db.collections.syncmeta, undefined, () => {\n * throw new Error(\"should not generate a second id\")\n * })\n * // again === clientId\n * ```\n */\nexport async function resolveClientId(\n syncmeta: Collection<SyncMetaEntry, string>,\n configured: string | undefined,\n generate: () => string,\n): Promise<string> {\n const stored = readSyncMeta(syncmeta).clientId ?? null;\n const clientId = configured ?? stored ?? generate();\n\n if (stored !== clientId) {\n await patch(syncmeta, (draft) => {\n draft.clientId = clientId;\n });\n }\n\n return clientId;\n}\n\n/**\n * The cursor lives in `syncmeta` so the inbox can be pruned freely. Older\n * databases predate that row, so fall back to the highest resolved inbox\n * sequence and let the first successful pull persist it.\n *\n * @example\n * ```ts\n * import { readPullCursor } from \"./sync-meta\"\n *\n * const since = readPullCursor(db.collections.syncmeta, db.collections.inbox)\n * const page = await transport.pull(since)\n * ```\n */\nexport function readPullCursor(\n syncmeta: Collection<SyncMetaEntry, string>,\n inbox: Collection<InboxEntry, string>,\n): number {\n let cursor = readSyncMeta(syncmeta).pullCursor;\n\n for (const entry of inbox.state.values()) {\n if (entry.sync && entry.globalSeq > cursor) cursor = entry.globalSeq;\n }\n\n return cursor;\n}\n\nexport async function writePullCursor(\n syncmeta: Collection<SyncMetaEntry, string>,\n cursor: number,\n): Promise<void> {\n await patch(syncmeta, (draft) => {\n draft.pullCursor = cursor;\n });\n}\n\nexport async function writeBackendId(\n syncmeta: Collection<SyncMetaEntry, string>,\n backendId: string,\n): Promise<void> {\n await patch(syncmeta, (draft) => {\n draft.backendId = backendId;\n });\n}\n\nexport async function writeSyncOutcome(\n syncmeta: Collection<SyncMetaEntry, string>,\n lastSyncAt: number,\n lastError: string | null,\n): Promise<void> {\n await patch(syncmeta, (draft) => {\n draft.lastSyncAt = lastSyncAt;\n draft.lastError = lastError;\n });\n}\n","import type { Collection } from \"@tanstack/db\";\n\nimport type { NormalizedSyncTransport } from \"../core/sync\";\nimport type {\n BackendMismatchPolicy,\n InboxEntry,\n OutboxEntry,\n ServerEvent,\n SyncMetaEntry,\n} from \"../core/types\";\nimport { DEFAULT_EVENT_SCHEMA_VERSION } from \"./constants\";\nimport { handleReplayFailure, replayEvent, resolveInboxEntry } from \"./replay\";\nimport { readBackendId, readPullCursor, writeBackendId, writePullCursor } from \"./sync-meta\";\nimport type { ReplayContext } from \"./types\";\n\nexport type PullOutcome = {\n pulled: number;\n skipped: number;\n deadLettered: number;\n /** Outbox events put back in the queue by a backend reset, awaiting a push. */\n requeued: number;\n};\n\n/**\n * Thrown when `backendMismatch` is `\"fail\"` and the server reports a different\n * `backendId` than this client last synced with (wiped or swapped event store).\n *\n * @example\n * ```ts\n * import { BackendMismatchError } from \"event-sourced-collection\"\n *\n * const result = await db.sync()\n * const mismatch = result.errors.find((error) => error instanceof BackendMismatchError)\n * if (mismatch) {\n * console.error(\"backend changed\", mismatch.expected, mismatch.received)\n * }\n * ```\n */\nexport class BackendMismatchError extends Error {\n constructor(\n readonly expected: string | null,\n readonly received: string,\n ) {\n super(\n `Sync backend identity changed (was \"${expected ?? \"unknown\"}\", now \"${received}\"). ` +\n `The local pull cursor no longer refers to this backend.`,\n );\n this.name = \"BackendMismatchError\";\n }\n}\n\nexport type PullArgs = {\n outbox: Collection<OutboxEntry, string>;\n inbox: Collection<InboxEntry, string>;\n syncmeta: Collection<SyncMetaEntry, string>;\n pull: NonNullable<NormalizedSyncTransport[\"pull\"]>;\n clientId: string;\n pullOverlap: number;\n /** When false, local-origin pulls advance the cursor without inbox rows. */\n recordLocalEchoes: boolean;\n backendMismatch: BackendMismatchPolicy;\n context: ReplayContext;\n};\n\nexport async function pullInbox(args: PullArgs): Promise<PullOutcome> {\n const { outbox, inbox, syncmeta, pull, clientId, pullOverlap, recordLocalEchoes, context } =\n args;\n const { log } = context;\n\n let pulled = 0;\n let skipped = 0;\n let deadLettered = 0;\n let requeued = 0;\n let hasMore = true;\n let cursor = Math.max(0, readPullCursor(syncmeta, inbox) - pullOverlap);\n let identityChecked = false;\n\n while (hasMore) {\n log.debug(\"pull inbox page\", { since: cursor });\n\n const response = await pull(cursor);\n\n log.debug(\"pull inbox response\", {\n since: cursor,\n eventCount: response.events.length,\n hasMore: response.hasMore,\n cursor: response.cursor,\n backendId: response.backendId,\n });\n\n if (!identityChecked && response.backendId !== undefined) {\n identityChecked = true;\n\n const reconciled = await reconcileBackendIdentity(args, response.backendId);\n if (reconciled.reset) {\n requeued += reconciled.requeued;\n cursor = 0;\n continue;\n }\n }\n\n if (response.events.length === 0) break;\n\n const sorted = [...response.events].sort((a, b) => a.globalSeq - b.globalSeq);\n let halted = false;\n\n for (const event of sorted) {\n if (isLocalOrigin(event, outbox, clientId)) {\n if (recordLocalEchoes) {\n await markInboxEventResolved(inbox, event);\n }\n\n log.debug(\"pull skipped: event originated locally\", {\n eventId: event.eventId,\n globalSeq: event.globalSeq,\n recorded: recordLocalEchoes,\n });\n continue;\n }\n\n const existing = inbox.get(event.eventId);\n if (existing?.sync) {\n log.debug(\"pull skipped: inbox already resolved\", {\n eventId: event.eventId,\n globalSeq: event.globalSeq,\n });\n continue;\n }\n\n if (!existing) {\n await inbox.insert(toInboxEntry(event, false)).isPersisted.promise;\n log.debug(\"inbox entry inserted\", {\n eventId: event.eventId,\n globalSeq: event.globalSeq,\n collectionId: event.collectionId,\n });\n }\n\n const outcome = await replayEvent(context, event);\n\n if (outcome.status === \"halted\") {\n halted = true;\n break;\n }\n\n if (outcome.status === \"failed\") {\n const resolution = await handleReplayFailure(\n context,\n inbox,\n event,\n outcome.error,\n Date.now(),\n );\n\n if (resolution === \"retry\") {\n halted = true;\n break;\n }\n\n deadLettered++;\n continue;\n }\n\n await resolveInboxEntry(inbox, event.eventId, outcome);\n\n if (outcome.status === \"skipped\") {\n skipped++;\n continue;\n }\n\n log.info(\"pull replay applied\", {\n eventId: event.eventId,\n globalSeq: event.globalSeq,\n collectionId: event.collectionId,\n type: event.type,\n key: event.key,\n });\n\n pulled++;\n }\n\n // Leaving the cursor where it is means the halted event is retried on the\n // next sync rather than being stepped over.\n if (halted) break;\n\n const nextCursor = resolveNextCursor(cursor, sorted, response.cursor);\n\n if (nextCursor <= cursor) {\n log.warn(\"pull stopped: cursor did not advance\", {\n cursor,\n nextCursor,\n eventCount: sorted.length,\n });\n break;\n }\n\n cursor = nextCursor;\n await writePullCursor(syncmeta, cursor);\n hasMore = response.hasMore;\n }\n\n log.info(\"pull inbox finished\", { pulled, skipped, deadLettered, requeued, cursor });\n\n return { pulled, skipped, deadLettered, requeued };\n}\n\ntype ReconcileOutcome = { reset: false } | { reset: true; requeued: number };\n\n/**\n * Detects a wiped or swapped backend. Reports `reset` when the caller should\n * restart the pull from zero.\n */\nasync function reconcileBackendIdentity(\n args: PullArgs,\n received: string,\n): Promise<ReconcileOutcome> {\n const { syncmeta, inbox, backendMismatch, context } = args;\n const { log } = context;\n\n const stored = readBackendId(syncmeta);\n\n if (stored === received) return { reset: false };\n\n if (stored === null) {\n await writeBackendId(syncmeta, received);\n log.info(\"sync backend identity recorded\", { backendId: received });\n return { reset: false };\n }\n\n context.emit(\"onBackendMismatch\", {\n expected: stored,\n received,\n policy: backendMismatch,\n });\n\n if (backendMismatch === \"fail\") {\n throw new BackendMismatchError(stored, received);\n }\n\n if (backendMismatch === \"ignore\") {\n log.warn(\"sync backend identity changed; ignoring per configuration\", {\n expected: stored,\n received,\n });\n return { reset: false };\n }\n\n log.warn(\"sync backend identity changed; resetting pull cursor\", {\n expected: stored,\n received,\n });\n\n for (const entry of inbox.state.values()) {\n await inbox.delete(entry.eventId).isPersisted.promise;\n }\n\n const requeued = await requeueSyncedOutbox(args.outbox);\n\n await writeBackendId(syncmeta, received);\n await writePullCursor(syncmeta, 0);\n\n log.info(\"sync backend identity reset complete\", {\n backendId: received,\n inboxCleared: true,\n outboxRequeued: requeued,\n });\n\n return { reset: true, requeued };\n}\n\n/**\n * Marks previously confirmed outbox events as pending again. The new backend\n * has never seen them, so without this the client keeps local rows it believes\n * are safely synced and never uploads them again. Servers deduplicate by\n * `eventId`, so re-pushing to a *restored* backend is a no-op.\n *\n * `baseVersion` is cleared because it refers to event ids from the old\n * backend's history, which the new one cannot resolve.\n */\nasync function requeueSyncedOutbox(outbox: Collection<OutboxEntry, string>): Promise<number> {\n const synced = [...outbox.state.values()].filter((entry) => entry.sync);\n\n for (const entry of synced) {\n await outbox.update(entry.eventId, (draft) => {\n draft.sync = false;\n draft.syncStatus = \"pending\";\n draft.globalSeq = null;\n draft.baseVersion = null;\n draft.attemptCount = 0;\n draft.nextAttemptAt = null;\n draft.lastError = null;\n draft.lastErrorCode = null;\n draft.retryable = null;\n }).isPersisted.promise;\n }\n\n return synced.length;\n}\n\nfunction isLocalOrigin(\n event: ServerEvent,\n outbox: Collection<OutboxEntry, string>,\n clientId: string,\n): boolean {\n // clientId keeps origin detection working after the outbox has been pruned.\n return outbox.has(event.eventId) || event.clientId === clientId;\n}\n\nfunction resolveNextCursor(\n cursor: number,\n events: ReadonlyArray<ServerEvent>,\n serverCursor: string | undefined,\n): number {\n let next = cursor;\n\n for (const event of events) {\n if (event.globalSeq > next) next = event.globalSeq;\n }\n\n const parsed = Number(serverCursor);\n if (serverCursor !== undefined && Number.isFinite(parsed) && parsed > next) {\n next = parsed;\n }\n\n return next;\n}\n\nasync function markInboxEventResolved(\n inbox: Collection<InboxEntry, string>,\n event: ServerEvent,\n): Promise<void> {\n const existing = inbox.get(event.eventId);\n\n if (!existing) {\n await inbox.insert(toInboxEntry(event, true)).isPersisted.promise;\n return;\n }\n\n if (!existing.sync || existing.globalSeq !== event.globalSeq) {\n await inbox.update(event.eventId, (draft) => {\n draft.globalSeq = event.globalSeq;\n draft.sync = true;\n }).isPersisted.promise;\n }\n}\n\nexport function toInboxEntry(event: ServerEvent, sync: boolean): InboxEntry {\n return {\n eventId: event.eventId,\n globalSeq: event.globalSeq,\n collectionId: event.collectionId,\n type: event.type,\n key: event.key,\n payload: event.payload,\n previous: event.previous ?? null,\n clientId: event.clientId ?? null,\n schemaVersion: event.schemaVersion ?? DEFAULT_EVENT_SCHEMA_VERSION,\n timestamp: event.timestamp,\n sync,\n skipped: false,\n skipReason: null,\n attemptCount: 0,\n lastError: null,\n };\n}\n","import type {\n OutboundEvent,\n PullEventsFn,\n PullResponse,\n PushConfirmation,\n PushEventsFn,\n PushResponse,\n SyncHandlersConfig,\n SyncTransport,\n SyncUrlConfig,\n} from \"./types\";\n\nexport type NormalizedSyncTransport = {\n push?: PushEventsFn;\n pull?: (since: number) => Promise<PullResponse>;\n};\n\ntype HeaderConfig = SyncHandlersConfig[\"headers\"];\n\n/**\n * Builds a {@link SyncTransport} that POSTs outbound events and GETs\n * `pull?since=N`. Pass this as `sync` when you already have REST endpoints.\n *\n * @example\n * ```ts\n * import { createHttpTransport } from \"event-sourced-collection\"\n * import { createBrowserEventSourcedDB } from \"event-sourced-collection/browser\"\n *\n * const sync = createHttpTransport({\n * push: \"/api/sync/events\",\n * pull: \"/api/sync/events\",\n * headers: () => ({ Authorization: `Bearer ${localStorage.getItem(\"token\") ?? \"\"}` }),\n * })\n *\n * const { ensureDb } = createBrowserEventSourcedDB({\n * databaseName: \"app.sqlite\",\n * collections: { todos: { getKey: (todo: { id: string }) => todo.id } },\n * sync,\n * modules: async () => {\n * const { createCollection } = await import(\"@tanstack/db\")\n * const persistence = await import(\"@tanstack/browser-db-sqlite-persistence\")\n * return { createCollection, ...persistence }\n * },\n * })\n * ```\n */\nexport function createHttpTransport(config: SyncUrlConfig): SyncTransport {\n return {\n push: createHttpPushEvents(config.push, config.headers),\n pull: createHttpPullEvents(config.pull, config.headers),\n };\n}\n\nexport function createSyncTransport(\n config?: SyncHandlersConfig | SyncUrlConfig | SyncTransport,\n): NormalizedSyncTransport | null {\n if (!config) {\n return null;\n }\n\n if (isTransport(config)) {\n return {\n push: config.push,\n pull: config.pull,\n };\n }\n\n const pushUrl = getPushUrl(config);\n const pullUrl = getPullUrl(config);\n\n const push =\n \"pushEvents\" in config && config.pushEvents\n ? config.pushEvents\n : pushUrl\n ? createHttpPushEvents(pushUrl, config.headers)\n : undefined;\n\n const pullEvents = \"pullEvents\" in config ? config.pullEvents : undefined;\n const pull = pullEvents\n ? createPullFromHandler(pullEvents)\n : pullUrl\n ? createHttpPullEvents(pullUrl, config.headers)\n : undefined;\n\n if (!push && !pull) {\n return null;\n }\n\n return { push, pull };\n}\n\nexport function normalizePushResponse(\n response: PushResponse | ReadonlyArray<PushConfirmation>,\n): PushResponse {\n if (isConfirmationArray(response)) {\n return { confirmed: response };\n }\n\n return {\n confirmed: response.confirmed,\n failed: response.failed,\n };\n}\n\nfunction isConfirmationArray(\n response: PushResponse | ReadonlyArray<PushConfirmation>,\n): response is ReadonlyArray<PushConfirmation> {\n return Array.isArray(response);\n}\n\nfunction createHttpPushEvents(url: string, headers: HeaderConfig): PushEventsFn {\n return async (events: ReadonlyArray<OutboundEvent>): Promise<PushResponse> => {\n if (events.length === 0) return { confirmed: [] };\n\n const resolvedHeaders = await resolveHeaders(headers);\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...resolvedHeaders },\n body: JSON.stringify(events),\n });\n\n if (!response.ok) {\n throw new SyncPushError(response.status, await response.text());\n }\n\n return response.json() as Promise<PushResponse>;\n };\n}\n\nfunction createPullFromHandler(pullEvents: PullEventsFn): (since: number) => Promise<PullResponse> {\n return (since: number) => pullEvents({ since });\n}\n\nfunction createHttpPullEvents(\n url: string,\n headers: HeaderConfig,\n): (since: number) => Promise<PullResponse> {\n return async (since: number): Promise<PullResponse> => {\n const resolvedHeaders = await resolveHeaders(headers);\n const pullUrl = appendSince(url, since);\n\n const response = await fetch(pullUrl, {\n headers: { Accept: \"application/json\", ...resolvedHeaders },\n });\n\n if (!response.ok) {\n throw new SyncPullError(response.status, await response.text());\n }\n\n return response.json() as Promise<PullResponse>;\n };\n}\n\nasync function resolveHeaders(headers: HeaderConfig): Promise<Record<string, string>> {\n if (!headers) return {};\n if (typeof headers === \"function\") return headers();\n return headers;\n}\n\nfunction appendSince(url: string, since: number): string {\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${separator}since=${encodeURIComponent(String(since))}`;\n}\n\nfunction getPushUrl(config: SyncHandlersConfig | SyncUrlConfig): string | undefined {\n if (\"pushUrl\" in config && config.pushUrl) {\n return config.pushUrl;\n }\n\n if (\"push\" in config && typeof config.push === \"string\") {\n return config.push;\n }\n\n return undefined;\n}\n\nfunction getPullUrl(config: SyncHandlersConfig | SyncUrlConfig): string | undefined {\n if (\"pullUrl\" in config && config.pullUrl) {\n return config.pullUrl;\n }\n\n if (\"pull\" in config && typeof config.pull === \"string\") {\n return config.pull;\n }\n\n return undefined;\n}\n\n/**\n * Thrown when the HTTP push endpoint returns a non-OK status.\n *\n * @example\n * ```ts\n * import { createHttpTransport, SyncPushError } from \"event-sourced-collection\"\n *\n * const sync = createHttpTransport({\n * push: \"/api/sync/events\",\n * pull: \"/api/sync/events\",\n * })\n *\n * try {\n * await sync.push(events)\n * } catch (error) {\n * if (error instanceof SyncPushError) {\n * console.error(error.status, error.body)\n * }\n * }\n * ```\n */\nexport class SyncPushError extends Error {\n constructor(\n public readonly status: number,\n public readonly body: string,\n ) {\n super(`Event push failed: HTTP ${status}`);\n this.name = \"SyncPushError\";\n }\n}\n\n/**\n * Thrown when the HTTP pull endpoint returns a non-OK status.\n *\n * @example\n * ```ts\n * import { createHttpTransport, SyncPullError } from \"event-sourced-collection\"\n *\n * const sync = createHttpTransport({\n * push: \"/api/sync/events\",\n * pull: \"/api/sync/events\",\n * })\n *\n * try {\n * await sync.pull(0)\n * } catch (error) {\n * if (error instanceof SyncPullError) {\n * console.error(error.status, error.body)\n * }\n * }\n * ```\n */\nexport class SyncPullError extends Error {\n constructor(\n public readonly status: number,\n public readonly body: string,\n ) {\n super(`Event pull failed: HTTP ${status}`);\n this.name = \"SyncPullError\";\n }\n}\n\nexport function isTransport(\n value: SyncHandlersConfig | SyncUrlConfig | SyncTransport,\n): value is SyncTransport {\n return \"push\" in value && typeof value.push === \"function\";\n}\n","import type { Collection } from \"@tanstack/db\";\n\nimport type { NormalizedSyncTransport } from \"../core/sync\";\nimport { normalizePushResponse } from \"../core/sync\";\nimport type {\n DeadLetterEntry,\n DeadLetterReason,\n OutboundEvent,\n OutboxEntry,\n PushConfirmation,\n PushFailure,\n RowVersionEntry,\n} from \"../core/types\";\nimport type { EventSourcedLogger } from \"../utils/logger\";\nimport {\n CONFLICT_ERROR_CODE,\n DEFAULT_EVENT_SCHEMA_VERSION,\n PAYLOAD_TOO_LARGE_ERROR_CODE,\n} from \"./constants\";\nimport type { EmitHook } from \"./hooks\";\nimport { restoreRowVersionAfterConflict } from \"./replay\";\nimport type { ResolvedRetryConfig } from \"./types\";\n\nexport type PushOutcome = {\n pushed: number;\n deadLettered: number;\n /**\n * Set when a batch failed at the transport level. Reported rather than thrown\n * so the counts from batches that already succeeded are not lost.\n */\n error?: Error;\n};\n\nexport type PushArgs = {\n outbox: Collection<OutboxEntry, string>;\n deadletter: Collection<DeadLetterEntry, string>;\n rowversions: Collection<RowVersionEntry, string>;\n push: NonNullable<NormalizedSyncTransport[\"push\"]>;\n batchSize: number;\n /** JSON byte cap per request; `null` means unlimited. */\n maxBytes: number | null;\n retry: ResolvedRetryConfig;\n now: number;\n emit: EmitHook;\n log: EventSourcedLogger;\n};\n\n/**\n * Backoff for attempt N, doubling from `baseDelayMs` and capped at `maxDelayMs`.\n * Deliberately jitter-free so retry scheduling stays reproducible in tests; if\n * you have many clients hitting one server, add jitter in your push handler.\n */\nexport function backoffDelay(attemptCount: number, retry: ResolvedRetryConfig): number {\n const exponent = Math.max(0, attemptCount - 1);\n const raw = retry.baseDelayMs * 2 ** exponent;\n return Math.min(retry.maxDelayMs, raw);\n}\n\nfunction isDue(entry: OutboxEntry, now: number): boolean {\n if (entry.sync) return false;\n // A permanent rejection is dead-lettered rather than parked, so anything still\n // marked failed here is retryable and just waiting for its backoff window.\n if (entry.syncStatus === \"failed\" && entry.retryable !== true) return false;\n return (entry.nextAttemptAt ?? 0) <= now;\n}\n\nfunction byLocalSeq(a: OutboxEntry, b: OutboxEntry): number {\n if (a.localSeq !== b.localSeq) return a.localSeq - b.localSeq;\n // localSeq can collide across tabs; eventId is a uuidv7 so it breaks the tie\n // in creation order.\n return a.eventId < b.eventId ? -1 : a.eventId > b.eventId ? 1 : 0;\n}\n\nexport function toOutboundEvent(entry: OutboxEntry): OutboundEvent {\n return {\n eventId: entry.eventId,\n collectionId: entry.collectionId,\n type: entry.type,\n key: entry.key,\n payload: entry.payload,\n previous: entry.previous ?? null,\n txId: entry.txId,\n clientId: entry.clientId,\n // Rows written before these fields existed are still in persisted outboxes.\n schemaVersion: entry.schemaVersion ?? DEFAULT_EVENT_SCHEMA_VERSION,\n baseVersion: entry.baseVersion ?? null,\n timestamp: entry.timestamp,\n };\n}\n\nexport async function deadLetter(\n deadletter: Collection<DeadLetterEntry, string>,\n outbox: Collection<OutboxEntry, string>,\n entry: OutboxEntry,\n reason: DeadLetterReason,\n message: string,\n code: string | null,\n now: number,\n emit: EmitHook,\n log: EventSourcedLogger,\n rowversions?: Collection<RowVersionEntry, string>,\n): Promise<void> {\n const record: DeadLetterEntry = {\n eventId: entry.eventId,\n collectionId: entry.collectionId,\n type: entry.type,\n key: entry.key,\n payload: entry.payload,\n previous: entry.previous ?? null,\n txId: entry.txId,\n clientId: entry.clientId,\n schemaVersion: entry.schemaVersion ?? DEFAULT_EVENT_SCHEMA_VERSION,\n baseVersion: entry.baseVersion ?? null,\n timestamp: entry.timestamp,\n localSeq: entry.localSeq,\n globalSeq: entry.globalSeq ?? null,\n direction: \"outbound\",\n reason,\n message,\n code,\n attemptCount: entry.attemptCount,\n failedAt: now,\n };\n\n if (!deadletter.has(entry.eventId)) {\n await deadletter.insert(record).isPersisted.promise;\n }\n\n if (outbox.has(entry.eventId)) {\n await outbox.delete(entry.eventId).isPersisted.promise;\n }\n\n if (reason === \"conflict\" && rowversions) {\n await restoreRowVersionAfterConflict(\n rowversions,\n entry.collectionId,\n entry.key,\n entry.baseVersion ?? null,\n );\n }\n\n log.warn(\"event dead-lettered\", {\n eventId: entry.eventId,\n collectionId: entry.collectionId,\n reason,\n message,\n code,\n attemptCount: entry.attemptCount,\n });\n\n emit(\"onDeadLetter\", record);\n}\n\n/** All events of one transaction, plus the JSON bytes they add to a request body. */\ntype TxGroup = { entries: OutboxEntry[]; bytes: number };\n\ntype Batch = { groups: TxGroup[]; count: number; bytes: number };\n\nconst utf8 = new TextEncoder();\n\nfunction jsonBytes(entry: OutboxEntry): number {\n return utf8.encode(JSON.stringify(toOutboundEvent(entry))).length;\n}\n\n/** Events are ordered by localSeq, so one transaction's events are adjacent. */\nfunction groupByTransaction(events: ReadonlyArray<OutboxEntry>, measure: boolean): TxGroup[] {\n const groups: TxGroup[] = [];\n\n for (let index = 0; index < events.length;) {\n const txId = events[index]!.txId;\n const group: TxGroup = { entries: [], bytes: 0 };\n\n while (index < events.length && events[index]!.txId === txId) {\n const entry = events[index]!;\n group.entries.push(entry);\n // +1 for the comma (or the array bracket) separating it from its neighbour.\n if (measure) group.bytes += jsonBytes(entry) + 1;\n index++;\n }\n\n groups.push(group);\n }\n\n return groups;\n}\n\n/**\n * Packs transaction groups into batches of at most `size` events and\n * `maxBytes` of JSON, never separating events that share a `txId`: the server\n * commits each transaction atomically, which it cannot do if we deliver half\n * of one now and half later. A transaction with more than `size` events is\n * sent whole; one larger than `maxBytes` is returned in `oversized` instead.\n */\nfunction packBatches(\n groups: ReadonlyArray<TxGroup>,\n size: number,\n maxBytes: number | null,\n): { batches: Batch[]; oversized: TxGroup[] } {\n const batches: Batch[] = [];\n const oversized: TxGroup[] = [];\n let current: Batch = { groups: [], count: 0, bytes: 1 };\n\n const close = () => {\n if (current.count > 0) batches.push(current);\n current = { groups: [], count: 0, bytes: 1 };\n };\n\n for (const group of groups) {\n if (maxBytes !== null && group.bytes + 1 > maxBytes) {\n oversized.push(group);\n continue;\n }\n\n const overCount = current.count + group.entries.length > size;\n const overBytes = maxBytes !== null && current.bytes + group.bytes > maxBytes;\n if (current.count > 0 && (overCount || overBytes)) close();\n\n current.groups.push(group);\n current.count += group.entries.length;\n current.bytes += group.bytes;\n\n if (current.count >= size) close();\n }\n\n close();\n return { batches, oversized };\n}\n\nfunction isPayloadTooLarge(err: unknown): boolean {\n return typeof err === \"object\" && err !== null && \"status\" in err && err.status === 413;\n}\n\ntype PostResult = {\n confirmed: PushConfirmation[];\n failed: PushFailure[];\n /** Transactions the server would not accept even when sent alone. */\n tooLarge: OutboxEntry[];\n /** Left unsent because the transport failed; `error` says why. */\n unsent: OutboxEntry[];\n error?: unknown;\n};\n\n/**\n * Posts `groups` as one request. On HTTP 413 the request is halved along\n * transaction boundaries and each half posted in turn, down to a single\n * transaction, so one oversized event cannot hold the rest hostage.\n */\nasync function postGroups(\n push: PushArgs[\"push\"],\n groups: ReadonlyArray<TxGroup>,\n log: EventSourcedLogger,\n): Promise<PostResult> {\n const entries = groups.flatMap((group) => group.entries);\n\n try {\n const response = normalizePushResponse(await push(entries.map(toOutboundEvent)));\n return {\n confirmed: [...response.confirmed],\n failed: [...(response.failed ?? [])],\n tooLarge: [],\n unsent: [],\n };\n } catch (err) {\n if (!isPayloadTooLarge(err)) {\n return { confirmed: [], failed: [], tooLarge: [], unsent: entries, error: err };\n }\n\n if (groups.length === 1) {\n log.warn(\"push transaction too large for the server\", { events: entries.length });\n return { confirmed: [], failed: [], tooLarge: entries, unsent: [] };\n }\n\n const middle = Math.ceil(groups.length / 2);\n log.info(\"push batch hit HTTP 413, splitting\", {\n groups: groups.length,\n events: entries.length,\n });\n\n const first = await postGroups(push, groups.slice(0, middle), log);\n if (first.error !== undefined) {\n const rest = groups.slice(middle).flatMap((group) => group.entries);\n return { ...first, unsent: [...first.unsent, ...rest] };\n }\n\n const second = await postGroups(push, groups.slice(middle), log);\n return {\n confirmed: [...first.confirmed, ...second.confirmed],\n failed: [...first.failed, ...second.failed],\n tooLarge: [...first.tooLarge, ...second.tooLarge],\n unsent: second.unsent,\n error: second.error,\n };\n }\n}\n\nasync function deadLetterTooLarge(\n args: PushArgs,\n entries: ReadonlyArray<OutboxEntry>,\n message: string,\n): Promise<number> {\n for (const entry of entries) {\n await deadLetter(\n args.deadletter,\n args.outbox,\n entry,\n \"rejected\",\n message,\n PAYLOAD_TOO_LARGE_ERROR_CODE,\n args.now,\n args.emit,\n args.log,\n args.rowversions,\n );\n }\n return entries.length;\n}\n\n/**\n * Pushes due outbox events in batches limited by event count and JSON bytes.\n * Each batch's result is persisted before the next is sent, so a failure\n * part-way through keeps the progress already made instead of restarting.\n */\nexport async function pushOutbox(args: PushArgs): Promise<PushOutcome> {\n const { outbox, push, batchSize, maxBytes, now, log } = args;\n\n const due = [...outbox.state.values()].filter((entry) => isDue(entry, now)).sort(byLocalSeq);\n\n log.debug(\"push outbox\", { dueCount: due.length, batchSize, maxBytes });\n\n if (due.length === 0) return { pushed: 0, deadLettered: 0 };\n\n const { batches, oversized } = packBatches(\n groupByTransaction(due, maxBytes !== null),\n batchSize,\n maxBytes,\n );\n\n let pushed = 0;\n let deadLettered = 0;\n\n for (const group of oversized) {\n deadLettered += await deadLetterTooLarge(\n args,\n group.entries,\n `Transaction is ${group.bytes} bytes, over maxPushBytes (${maxBytes})`,\n );\n }\n\n for (const batch of batches) {\n const attempted: OutboxEntry[] = [];\n\n for (const group of batch.groups) {\n for (const entry of group.entries) {\n const attemptCount = (entry.attemptCount ?? 0) + 1;\n\n await outbox.update(entry.eventId, (draft) => {\n draft.syncStatus = \"pending\";\n draft.attemptCount = attemptCount;\n draft.lastAttemptAt = now;\n draft.nextAttemptAt = null;\n draft.lastError = null;\n draft.lastErrorCode = null;\n draft.retryable = null;\n }).isPersisted.promise;\n\n attempted.push({ ...entry, attemptCount });\n }\n }\n\n const byId = new Map(attempted.map((entry) => [entry.eventId, entry]));\n const attemptedGroups = batch.groups.map((group) => ({\n bytes: group.bytes,\n entries: group.entries.map((entry) => byId.get(entry.eventId)!),\n }));\n\n const response = await postGroups(push, attemptedGroups, log);\n\n log.info(\"push batch confirmed\", {\n sent: attempted.length,\n bytes: batch.bytes,\n confirmed: response.confirmed.length,\n failed: response.failed.length,\n tooLarge: response.tooLarge.length,\n });\n\n for (const confirmation of response.confirmed) {\n if (!outbox.has(confirmation.eventId)) continue;\n\n await outbox.update(confirmation.eventId, (draft) => {\n draft.sync = true;\n draft.syncStatus = \"synced\";\n draft.globalSeq = confirmation.globalSeq;\n draft.nextAttemptAt = null;\n draft.lastError = null;\n draft.lastErrorCode = null;\n draft.retryable = null;\n }).isPersisted.promise;\n\n pushed++;\n args.emit(\"onEventPushed\", {\n eventId: confirmation.eventId,\n globalSeq: confirmation.globalSeq,\n });\n }\n\n for (const failure of response.failed) {\n const entry = byId.get(failure.eventId);\n if (!entry) continue;\n\n deadLettered += await handleFailure(args, entry, failure);\n }\n\n deadLettered += await deadLetterTooLarge(\n args,\n response.tooLarge,\n \"Server rejected the transaction as too large (HTTP 413)\",\n );\n\n if (response.error !== undefined) {\n // Transport-level failure: back off what was not acknowledged and stop.\n // Everything confirmed so far stays synced.\n deadLettered += await backoffBatch(args, response.unsent, response.error);\n const error =\n response.error instanceof Error ? response.error : new Error(String(response.error));\n log.warn(\"push stopped after transport failure\", {\n message: error.message,\n pushed,\n remaining: due.length - pushed,\n });\n return { pushed, deadLettered, error };\n }\n }\n\n return { pushed, deadLettered };\n}\n\n/** Returns 1 when the event was dead-lettered, 0 when it stays queued for retry. */\nasync function handleFailure(\n args: PushArgs,\n entry: OutboxEntry,\n failure: PushFailure,\n): Promise<number> {\n const { outbox, deadletter, rowversions, retry, now, emit, log } = args;\n const code = failure.code ?? null;\n\n if (failure.retryable !== true) {\n const reason: DeadLetterReason = code === CONFLICT_ERROR_CODE ? \"conflict\" : \"rejected\";\n await deadLetter(\n deadletter,\n outbox,\n entry,\n reason,\n failure.message,\n code,\n now,\n emit,\n log,\n rowversions,\n );\n return 1;\n }\n\n if (entry.attemptCount >= retry.maxAttempts) {\n await deadLetter(\n deadletter,\n outbox,\n entry,\n \"maxAttemptsExceeded\",\n failure.message,\n code,\n now,\n emit,\n log,\n rowversions,\n );\n return 1;\n }\n\n const delay = backoffDelay(entry.attemptCount, retry);\n\n await outbox.update(entry.eventId, (draft) => {\n draft.sync = false;\n draft.syncStatus = \"failed\";\n draft.retryable = true;\n draft.lastError = failure.message;\n draft.lastErrorCode = code;\n draft.nextAttemptAt = now + delay;\n }).isPersisted.promise;\n\n log.warn(\"push retry scheduled\", {\n eventId: entry.eventId,\n attemptCount: entry.attemptCount,\n retryInMs: delay,\n message: failure.message,\n });\n\n return 0;\n}\n\n/** Applies retry backoff to a whole batch after a transport-level failure. */\nasync function backoffBatch(\n args: PushArgs,\n batch: ReadonlyArray<OutboxEntry>,\n err: unknown,\n): Promise<number> {\n const message = err instanceof Error ? err.message : String(err);\n let deadLettered = 0;\n\n for (const entry of batch) {\n deadLettered += await handleFailure(args, entry, {\n eventId: entry.eventId,\n message,\n retryable: true,\n });\n }\n\n return deadLettered;\n}\n","import {\n DEFAULT_PUSH_BATCH_SIZE,\n MAX_PUSH_BATCH_SIZE,\n MIN_PUSH_BATCH_SIZE,\n} from \"../internal/constants\";\nimport type { SyncPushLimits, SyncPushPreset } from \"./types\";\n\n/**\n * Push limits per hosting platform. Byte caps leave headroom under the\n * platform's request body limit (Vercel functions: 4.5 MB; AWS Lambda and\n * Netlify: 6 MB) for headers and JSON size estimation drift.\n *\n * @example\n * ```ts\n * createBrowserEventSourcedDB({ ..., syncPreset: \"vercel\" })\n * ```\n */\nexport const SYNC_PUSH_PRESETS: Readonly<Record<SyncPushPreset, SyncPushLimits>> = {\n default: { pushBatchSize: DEFAULT_PUSH_BATCH_SIZE, maxPushBytes: null },\n serverless: { pushBatchSize: 25, maxPushBytes: 4_000_000 },\n vercel: { pushBatchSize: 10, maxPushBytes: 3_500_000 },\n};\n\nexport function resolvePushLimits(config: {\n syncPreset?: SyncPushPreset;\n pushBatchSize?: number;\n maxPushBytes?: number;\n}): SyncPushLimits {\n const preset = SYNC_PUSH_PRESETS[config.syncPreset ?? \"default\"];\n const size = Math.floor(config.pushBatchSize ?? preset.pushBatchSize);\n const bytes = config.maxPushBytes ?? preset.maxPushBytes;\n\n return {\n pushBatchSize: Math.min(MAX_PUSH_BATCH_SIZE, Math.max(MIN_PUSH_BATCH_SIZE, size)),\n maxPushBytes: bytes === null ? null : Math.max(1, Math.floor(bytes)),\n };\n}\n","/**\n * Serializes async work so overlapping callers run one after another instead of\n * concurrently. Used to stop two `sync()` calls from reading the same pending\n * set and pushing it twice.\n *\n * A rejected job does not stall the queue: the next caller still runs.\n *\n * @example Overlapping syncs run in order\n * ```ts\n * import { createSerialQueue } from \"./serial-queue\"\n *\n * const runExclusive = createSerialQueue()\n *\n * const first = runExclusive(async () => {\n * await pushPending()\n * return \"first\"\n * })\n * const second = runExclusive(async () => {\n * await pushPending()\n * return \"second\"\n * })\n *\n * await Promise.all([first, second]) // \"first\" finishes before \"second\" starts\n * ```\n */\nexport function createSerialQueue(): <T>(fn: () => Promise<T>) => Promise<T> {\n let tail: Promise<unknown> = Promise.resolve();\n\n return <T>(fn: () => Promise<T>): Promise<T> => {\n const result = tail.then(fn, fn);\n tail = result.catch(() => undefined);\n return result;\n };\n}\n","export type EventSourcedLogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\n/**\n * Structured logger used when `debug` is enabled on a DB factory.\n *\n * @example Custom sink\n * ```ts\n * import type { EventSourcedLogger } from \"event-sourced-collection\"\n *\n * const logger: EventSourcedLogger = {\n * debug: (message, data) => console.debug(message, data),\n * info: (message, data) => console.info(message, data),\n * warn: (message, data) => console.warn(message, data),\n * error: (message, data) => console.error(message, data),\n * }\n * ```\n */\nexport type EventSourcedLogger = {\n debug: (message: string, data?: Record<string, unknown>) => void;\n info: (message: string, data?: Record<string, unknown>) => void;\n warn: (message: string, data?: Record<string, unknown>) => void;\n error: (message: string, data?: Record<string, unknown>) => void;\n};\n\nconst noopLogger: EventSourcedLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\nconst LOG_PREFIX = \"[event-sourced]\";\n\n/**\n * Builds the logger used internally when you pass `debug` to a DB factory.\n * `false` / omitted is a no-op logger; `true` logs to `console`; an object is\n * used as-is.\n *\n * @example\n * ```ts\n * import { createEventSourcedLogger } from \"event-sourced-collection\"\n * import { createBrowserEventSourcedDB } from \"event-sourced-collection/browser\"\n *\n * const debug = createEventSourcedLogger(import.meta.env.DEV)\n *\n * createBrowserEventSourcedDB({\n * databaseName: \"app.sqlite\",\n * debug,\n * collections: { todos: { getKey: (todo: { id: string }) => todo.id } },\n * modules: async () => {\n * const { createCollection } = await import(\"@tanstack/db\")\n * const persistence = await import(\"@tanstack/browser-db-sqlite-persistence\")\n * return { createCollection, ...persistence }\n * },\n * })\n * ```\n */\nexport function createEventSourcedLogger(debug?: boolean | EventSourcedLogger): EventSourcedLogger {\n if (debug === undefined || debug === false) {\n return noopLogger;\n }\n\n if (typeof debug === \"object\") {\n return debug;\n }\n\n return {\n debug: (message, data) => {\n if (data === undefined) {\n console.debug(LOG_PREFIX, message);\n return;\n }\n console.debug(LOG_PREFIX, message, data);\n },\n info: (message, data) => {\n if (data === undefined) {\n console.info(LOG_PREFIX, message);\n return;\n }\n console.info(LOG_PREFIX, message, data);\n },\n warn: (message, data) => {\n if (data === undefined) {\n console.warn(LOG_PREFIX, message);\n return;\n }\n console.warn(LOG_PREFIX, message, data);\n },\n error: (message, data) => {\n if (data === undefined) {\n console.error(LOG_PREFIX, message);\n return;\n }\n console.error(LOG_PREFIX, message, data);\n },\n };\n}\n","import { uuidv7 } from \"uuidv7\";\n\n/**\n * Time-ordered event id (UUIDv7). Used as `eventId` on outbox rows and as the\n * default device `clientId` when you do not pass one.\n *\n * @example\n * ```ts\n * import { generateEventId } from \"event-sourced-collection\"\n *\n * const eventId = generateEventId()\n * const clientId = generateEventId()\n * ```\n */\nexport function generateEventId(): string {\n return uuidv7();\n}\n","import type { Collection } from \"@tanstack/db\";\n\nimport {\n DEADLETTER_ID,\n DEFAULT_BASE_DELAY_MS,\n DEFAULT_EVENT_SCHEMA_VERSION,\n DEFAULT_MAX_ATTEMPTS,\n DEFAULT_MAX_DELAY_MS,\n INBOX_ID,\n OUTBOX_ID,\n RESERVED_IDS,\n ROWVERSIONS_ID,\n SYNCMETA_ID,\n SYNCMETA_KEY,\n SYNC_LOCK_PREFIX,\n} from \"../internal/constants\";\nimport { createHookEmitter } from \"../internal/hooks\";\nimport type { EmitHook } from \"../internal/hooks\";\nimport { pullInbox } from \"../internal/pull\";\nimport { pushOutbox, toOutboundEvent } from \"../internal/push\";\nimport { resolvePushLimits } from \"./sync-presets\";\nimport { readRowVersion, recordRowVersion, replayInbox } from \"../internal/replay\";\nimport { createSerialQueue } from \"../internal/serial-queue\";\nimport {\n ensureSyncMeta,\n readPullCursor,\n readSyncMeta,\n resolveClientId,\n writePullCursor,\n writeSyncOutcome,\n} from \"../internal/sync-meta\";\nimport type {\n AcceptMutationsCollection,\n MetaCollections,\n MutationHookParams,\n ReplayContext,\n ResolvedRetryConfig,\n} from \"../internal/types\";\nimport { createSyncTransport, normalizePushResponse } from \"./sync\";\nimport type {\n CollectionMap,\n DeadLetterEntry,\n EventSourcedDB,\n EventSourcedDBConfig,\n InboxEntry,\n ManualSyncResult,\n MutationType,\n OutboundEvent,\n OutboxEntry,\n PruneOptions,\n PruneResult,\n ResetLocalReplicaOptions,\n ResetLocalReplicaResult,\n RowVersionEntry,\n SyncMetaEntry,\n SyncPushLimits,\n SyncResult,\n SyncStatus,\n SyncTrigger,\n} from \"./types\";\nimport type { EventSourcedLogger } from \"../utils/logger\";\nimport { createEventSourcedLogger } from \"../utils/logger\";\nimport { generateEventId } from \"../utils/uuid\";\n\n/**\n * Thrown by `resetLocalReplica()` while the outbox still holds changes the\n * server has not accepted. Sync first, or pass `discardPending: true`.\n */\nexport class UnsyncedChangesError extends Error {\n constructor(readonly pendingCount: number) {\n super(`${pendingCount} local change(s) have not been pushed yet`);\n this.name = \"UnsyncedChangesError\";\n }\n}\n\ntype CollectionDefConstraint = {\n getKey: (state: never) => string | number;\n schemaVersion?: number;\n localOnly?: boolean;\n indexes?: ReadonlyArray<{\n select: (row: never) => unknown;\n name?: string;\n indexType?: new (id: number, expression: never, name?: string, options?: never) => unknown;\n }>;\n};\n\ntype SeqCounter = { value: number };\n\n/**\n * Lets the mutation hooks, which are built before `syncmeta` has been\n * preloaded, read the persisted client id once it is known.\n */\ntype ClientIdRef = { value: string };\n\ntype MetaCollectionFactory = Pick<\n EventSourcedDBConfig<Record<string, CollectionDefConstraint>>,\n \"createCollection\" | \"persistedCollectionOptions\" | \"persistence\"\n>;\n\ntype MutationContext = {\n outbox: Collection<OutboxEntry, string>;\n rowversions: Collection<RowVersionEntry, string>;\n collectionId: string;\n type: MutationType;\n seq: SeqCounter;\n clientId: ClientIdRef;\n eventSchemaVersion: number;\n conflictDetection: boolean;\n emit: EmitHook;\n log: EventSourcedLogger;\n};\n\nfunction emptyResult(overrides: Partial<SyncResult> = {}): SyncResult {\n return {\n pushed: 0,\n pulled: 0,\n skipped: 0,\n deadLettered: 0,\n deferred: false,\n errors: [],\n ...overrides,\n };\n}\n\n/**\n * Low-level factory: wires persistence, collections, outbox/inbox, and sync.\n * Prefer a platform helper (`createBrowserEventSourcedDB`,\n * `createNodeEventSourcedDB`, `createReactNativeEventSourcedDB`) unless you are\n * supplying your own persistence.\n *\n * @param config - See {@link EventSourcedDBConfig} for every option.\n *\n * @example Node SQLite, opened immediately\n * ```ts\n * import { createCollection } from \"@tanstack/db\"\n * import {\n * createNodeSQLitePersistence,\n * persistedCollectionOptions,\n * } from \"@tanstack/node-db-sqlite-persistence\"\n * import Database from \"better-sqlite3\"\n * import { createEventSourcedDB } from \"event-sourced-collection\"\n *\n * type Todo = { id: string; title: string }\n *\n * const sqlite = new Database(\"app.sqlite\")\n * const db = await createEventSourcedDB({\n * persistence: createNodeSQLitePersistence({ database: sqlite }),\n * createCollection,\n * persistedCollectionOptions,\n * collections: {\n * todos: { getKey: (todo: Todo) => todo.id },\n * },\n * sync: {\n * push: \"/api/sync/events\",\n * pull: \"/api/sync/events\",\n * },\n * })\n *\n * await db.collections.todos.insert({ id: \"t1\", title: \"Ship\" }).isPersisted.promise\n * await db.sync()\n * ```\n */\nexport async function createEventSourcedDB<\n const TDefs extends Record<string, CollectionDefConstraint>,\n>(config: EventSourcedDBConfig<TDefs>): Promise<EventSourcedDB<TDefs>> {\n assertReservedNamesAvailable(config.collections);\n\n const log = createEventSourcedLogger(config.debug);\n const emit = createHookEmitter(config.hooks, log);\n\n const transport = createSyncTransport(config.sync);\n let syncEnabled = config.syncEnabled ?? true;\n\n // Provisional until `syncmeta` is preloaded and the persisted id is known.\n const clientId: ClientIdRef = { value: config.clientId ?? generateEventId() };\n const unknownEventHandling = config.unknownEventHandling ?? \"skip\";\n const pullOverlap = Math.max(0, config.pullOverlap ?? 0);\n const recordLocalEchoes = config.recordLocalEchoes ?? true;\n const eventSchemaVersion = config.eventSchemaVersion ?? DEFAULT_EVENT_SCHEMA_VERSION;\n let pushLimits: SyncPushLimits = resolvePushLimits(config);\n const { pushBatchSize, maxPushBytes } = pushLimits;\n const backendMismatch = config.backendMismatch ?? \"resetCursor\";\n const conflictDetection = config.conflictDetection ?? false;\n const lockName = `${SYNC_LOCK_PREFIX}:${config.lockName ?? \"default\"}`;\n\n const retry: ResolvedRetryConfig = {\n maxAttempts: Math.max(1, config.retry?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS),\n baseDelayMs: Math.max(0, config.retry?.baseDelayMs ?? DEFAULT_BASE_DELAY_MS),\n maxDelayMs: Math.max(0, config.retry?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS),\n };\n\n log.info(\"creating event-sourced db\", {\n collectionIds: Object.keys(config.collections),\n hasTransport: transport !== null,\n hasLock: Boolean(config.lock),\n syncEnabled,\n unknownEventHandling,\n pullOverlap,\n recordLocalEchoes,\n pushBatchSize,\n maxPushBytes,\n backendMismatch,\n conflictDetection,\n eventSchemaVersion,\n });\n\n const defaultSchemaVersion = config.schemaVersion ?? 1;\n const seq: SeqCounter = { value: 0 };\n\n const meta: MetaCollections = {\n outbox: createMetaCollection<OutboxEntry>(\n config,\n OUTBOX_ID,\n (entry) => entry.eventId,\n defaultSchemaVersion,\n ),\n inbox: createMetaCollection<InboxEntry>(\n config,\n INBOX_ID,\n (entry) => entry.eventId,\n defaultSchemaVersion,\n ),\n deadletter: createMetaCollection<DeadLetterEntry>(\n config,\n DEADLETTER_ID,\n (entry) => entry.eventId,\n defaultSchemaVersion,\n ),\n syncmeta: createMetaCollection<SyncMetaEntry>(\n config,\n SYNCMETA_ID,\n (entry) => entry.id,\n defaultSchemaVersion,\n ),\n rowversions: createMetaCollection<RowVersionEntry>(\n config,\n ROWVERSIONS_ID,\n (entry) => entry.id,\n defaultSchemaVersion,\n ),\n };\n\n const { outbox, inbox, deadletter, syncmeta, rowversions } = meta;\n const userCollections = {} as CollectionMap<TDefs>;\n const syncedCollections: Array<{\n collectionId: string;\n collection: Collection<Record<string, unknown>, string | number>;\n }> = [];\n const localOnlyIds = new Set(\n Object.keys(config.collections).filter((id) => config.collections[id]!.localOnly === true),\n );\n\n for (const collectionId of Object.keys(config.collections)) {\n const def = config.collections[collectionId]!;\n const getKey = def.getKey as (item: Record<string, unknown>) => string | number;\n const hook = (type: MutationType) =>\n def.localOnly ? noOutboxHook : createMutationHook({ ...mutationContext, type });\n\n const mutationContext = {\n outbox,\n rowversions,\n collectionId,\n seq,\n clientId,\n eventSchemaVersion,\n conflictDetection,\n emit,\n log,\n };\n\n const options = config.persistedCollectionOptions<Record<string, unknown>, string | number>({\n id: collectionId,\n getKey,\n persistence: config.persistence,\n schemaVersion: def.schemaVersion ?? defaultSchemaVersion,\n gcTime: Number.POSITIVE_INFINITY,\n onInsert: hook(\"insert\"),\n onUpdate: hook(\"update\"),\n onDelete: hook(\"delete\"),\n });\n\n const collection = config.createCollection(options);\n applyCollectionIndexes(collection, collectionId, def.indexes, log);\n if (!def.localOnly) syncedCollections.push({ collectionId, collection });\n\n log.debug(\"registered collection\", {\n collectionId,\n hasAcceptMutations: Boolean((collection as AcceptMutationsCollection).utils?.acceptMutations),\n });\n\n (userCollections as Record<string, unknown>)[collectionId] = collection;\n }\n\n const collections = {\n ...(userCollections as CollectionMap<TDefs>),\n ...meta,\n } as EventSourcedDB<TDefs>[\"collections\"];\n\n const replayTargets = collections as unknown as Record<string, AcceptMutationsCollection>;\n\n let isSyncing = false;\n const statusListeners = new Set<(status: SyncStatus) => void>();\n\n const notifyStatus = (): void => {\n if (statusListeners.size === 0) return;\n const status = getSyncStatus();\n for (const listener of statusListeners) listener(status);\n };\n\n const subscriptions = [\n outbox.subscribeChanges(notifyStatus),\n inbox.subscribeChanges(() => {}),\n deadletter.subscribeChanges(notifyStatus),\n syncmeta.subscribeChanges(notifyStatus),\n ];\n\n for (const collection of Object.values(meta)) {\n await collection.preload();\n }\n\n await ensureSyncMeta(syncmeta);\n\n clientId.value = await resolveClientId(syncmeta, config.clientId, generateEventId);\n\n seq.value = nextLocalSeq(outbox);\n\n // User collections must be hydrated before we hand the DB to the app.\n // Otherwise seeders like `ensureAppSettings` see an empty `get()` and\n // re-insert rows that already exist on disk / on the server.\n for (const collection of Object.values(userCollections)) {\n await collection.preload();\n }\n\n log.info(\"preloaded collections\", {\n outboxCount: outbox.state.size,\n inboxCount: inbox.state.size,\n deadLetterCount: deadletter.state.size,\n userCollectionIds: Object.keys(userCollections),\n nextLocalSeq: seq.value,\n clientId: clientId.value,\n pullCursor: readPullCursor(syncmeta, inbox),\n });\n\n // Outbox entries authored before a collection became local-only would\n // otherwise still be pushed.\n for (const entry of [...outbox.state.values()]) {\n if (!entry.sync && localOnlyIds.has(entry.collectionId)) {\n await outbox.delete(entry.eventId).isPersisted.promise;\n }\n }\n\n const replayContext: ReplayContext = {\n targets: replayTargets,\n localOnlyIds,\n rowversions,\n deadletter,\n unknownEventHandling,\n eventSchemaVersion,\n upcastEvent: config.upcastEvent,\n conflictDetection,\n maxReplayAttempts: retry.maxAttempts,\n emit,\n log,\n };\n\n await replayInbox(inbox, replayContext);\n\n emit(\"onReady\", { clientId: clientId.value, pullCursor: readPullCursor(syncmeta, inbox) });\n\n // Serializes callers within this context; the optional lock extends that\n // across tabs so only one of them syncs at a time.\n const runExclusive = createSerialQueue();\n\n function recordError(phase: \"push\" | \"pull\" | \"replay\", label: string, err: unknown): Error {\n const error = toError(err);\n log.error(`${label} ${phase} failed`, { message: error.message });\n emit(\"onSyncError\", { phase, error });\n return error;\n }\n\n async function pushPull(label: string): Promise<SyncResult> {\n await outbox.preload();\n await inbox.preload();\n\n const errors: Error[] = [];\n let pushed = 0;\n let pulled = 0;\n let skipped = 0;\n let deadLettered = 0;\n\n async function runPush(): Promise<void> {\n if (!transport?.push) {\n log.debug(`${label} push skipped: no push transport configured`);\n return;\n }\n\n try {\n const outcome = await pushOutbox({\n outbox,\n deadletter,\n rowversions,\n push: transport.push,\n batchSize: pushLimits.pushBatchSize,\n maxBytes: pushLimits.maxPushBytes,\n retry,\n now: Date.now(),\n emit,\n log,\n });\n pushed += outcome.pushed;\n deadLettered += outcome.deadLettered;\n if (outcome.error) {\n errors.push(recordError(\"push\", label, outcome.error));\n }\n } catch (err) {\n errors.push(recordError(\"push\", label, err));\n }\n }\n\n await runPush();\n\n let requeued = 0;\n\n try {\n if (transport?.pull) {\n const outcome = await pullInbox({\n outbox,\n inbox,\n syncmeta,\n pull: transport.pull,\n clientId: clientId.value,\n pullOverlap,\n recordLocalEchoes,\n backendMismatch,\n context: replayContext,\n });\n pulled = outcome.pulled;\n skipped = outcome.skipped;\n deadLettered += outcome.deadLettered;\n requeued = outcome.requeued;\n } else {\n log.debug(`${label} pull skipped: no pull transport configured`);\n }\n } catch (err) {\n errors.push(recordError(\"pull\", label, err));\n }\n\n // A backend reset is only discovered during pull, by which point this\n // sync's push has already run. Upload the requeued history now so a single\n // sync is enough to recover rather than leaving the gap open until the next.\n if (requeued > 0) {\n log.info(`${label} re-pushing history after backend reset`, { requeued });\n await runPush();\n }\n\n await writeSyncOutcome(syncmeta, Date.now(), errors[0]?.message ?? null);\n\n return { pushed, pulled, skipped, deadLettered, deferred: false, errors };\n }\n\n /** Runs `fn` under the cross-context lock when one is configured. */\n async function withLock<T>(fn: () => Promise<T>, deferred: T): Promise<T> {\n if (!config.lock) return fn();\n\n const outcome = await config.lock.tryRun(lockName, fn);\n\n if (!outcome.acquired) {\n log.debug(\"sync deferred: lock held by another context\", { lockName });\n return deferred;\n }\n\n return outcome.result;\n }\n\n async function tracked<T extends SyncResult>(\n trigger: SyncTrigger,\n fn: () => Promise<T>,\n ): Promise<T> {\n isSyncing = true;\n notifyStatus();\n emit(\"onSyncStart\", { trigger });\n\n try {\n const result = await fn();\n emit(\"onSyncComplete\", { trigger, result });\n return result;\n } finally {\n isSyncing = false;\n notifyStatus();\n }\n }\n\n function sync(): Promise<SyncResult> {\n return runExclusive(async () => {\n if (!syncEnabled) {\n log.debug(\"sync skipped: sync disabled\");\n return emptyResult();\n }\n\n if (!transport) {\n log.warn(\"sync skipped: no transport configured\");\n return emptyResult();\n }\n\n return withLock(\n () =>\n tracked(\"sync\", async () => {\n log.info(\"sync started\");\n const result = await pushPull(\"sync\");\n log.info(\"sync finished\", {\n pushed: result.pushed,\n pulled: result.pulled,\n skipped: result.skipped,\n deadLettered: result.deadLettered,\n errorCount: result.errors.length,\n });\n return result;\n }),\n emptyResult({ deferred: true }),\n );\n });\n }\n\n function manualSync(): Promise<ManualSyncResult> {\n return runExclusive(() =>\n withLock<ManualSyncResult>(\n () =>\n tracked(\"manualSync\", async () => {\n log.info(\"manual sync started\");\n\n await outbox.preload();\n await inbox.preload();\n\n let result: SyncResult = emptyResult();\n\n if (syncEnabled && transport) {\n result = await pushPull(\"manual sync\");\n } else if (!syncEnabled) {\n log.debug(\"manual sync push/pull skipped: sync disabled\");\n } else {\n log.warn(\"manual sync: no transport configured, skipping push/pull\");\n }\n\n const errors = [...result.errors];\n let replayed = 0;\n\n try {\n const outcome = await replayInbox(inbox, replayContext);\n replayed = outcome.applied;\n result = { ...result, skipped: result.skipped + outcome.skipped };\n } catch (err) {\n errors.push(recordError(\"replay\", \"manual sync\", err));\n }\n\n log.info(\"manual sync finished\", {\n pushed: result.pushed,\n pulled: result.pulled,\n skipped: result.skipped,\n deadLettered: result.deadLettered,\n replayed,\n errorCount: errors.length,\n });\n\n return { ...result, replayed, errors };\n }),\n { ...emptyResult({ deferred: true }), replayed: 0 },\n ),\n );\n }\n\n function getSyncStatus(): SyncStatus {\n let pendingCount = 0;\n let failedCount = 0;\n\n for (const entry of outbox.state.values()) {\n if (entry.sync) continue;\n pendingCount++;\n if (entry.syncStatus === \"failed\") failedCount++;\n }\n\n const stored = readSyncMeta(syncmeta);\n\n return {\n isSyncing,\n isSynced: pendingCount === 0,\n pendingCount,\n failedCount,\n deadLetterCount: deadletter.state.size,\n pullCursor: readPullCursor(syncmeta, inbox),\n backendId: stored.backendId,\n lastSyncAt: stored.lastSyncAt,\n lastError: stored.lastError,\n };\n }\n\n function subscribeSyncStatus(listener: (status: SyncStatus) => void): () => void {\n statusListeners.add(listener);\n listener(getSyncStatus());\n return () => statusListeners.delete(listener);\n }\n\n /**\n * Retries dead-lettered events.\n * - Outbound: pushes directly to the sync transport (does not requeue the outbox).\n * - Inbound: requeues into the inbox and replays immediately.\n * Omit `eventId` to retry everything. Returns how many were successfully\n * cleared from the dead-letter queue.\n */\n function retryDeadLetter(eventId?: string): Promise<number> {\n return runExclusive(async () => {\n const targets = selectDeadLetters(deadletter, eventId);\n const outbound: DeadLetterEntry[] = [];\n let cleared = 0;\n let inboundRequeued = 0;\n\n for (const entry of targets) {\n if ((entry.direction ?? \"outbound\") === \"inbound\") {\n await requeueInboundDeadLetter(inbox, entry);\n await deadletter.delete(entry.eventId).isPersisted.promise;\n inboundRequeued++;\n cleared++;\n } else {\n outbound.push(entry);\n }\n }\n\n if (inboundRequeued > 0) {\n await replayInbox(inbox, replayContext);\n }\n\n if (outbound.length > 0) {\n if (!transport?.push) {\n throw new Error(\n \"Cannot retry outbound dead-letter events: no push transport is configured.\",\n );\n }\n\n const events: OutboundEvent[] = outbound.map((entry) =>\n toOutboundEvent({\n eventId: entry.eventId,\n collectionId: entry.collectionId,\n type: entry.type,\n key: entry.key,\n payload: entry.payload,\n previous: entry.previous,\n txId: entry.txId ?? entry.eventId,\n clientId: entry.clientId ?? clientId.value,\n schemaVersion: entry.schemaVersion,\n baseVersion: entry.baseVersion ?? null,\n timestamp: entry.timestamp,\n localSeq: entry.localSeq ?? 0,\n globalSeq: null,\n sync: false,\n syncStatus: \"pending\",\n attemptCount: entry.attemptCount,\n lastAttemptAt: null,\n nextAttemptAt: null,\n lastError: null,\n lastErrorCode: null,\n retryable: null,\n }),\n );\n\n const response = normalizePushResponse(await transport.push(events));\n const confirmed = new Set(response.confirmed.map((item) => item.eventId));\n const failedById = new Map((response.failed ?? []).map((item) => [item.eventId, item]));\n const now = Date.now();\n\n for (const confirmation of response.confirmed) {\n const entry = outbound.find((row) => row.eventId === confirmation.eventId);\n if (!entry) continue;\n\n if (deadletter.has(entry.eventId)) {\n await deadletter.delete(entry.eventId).isPersisted.promise;\n }\n\n if (conflictDetection) {\n await recordRowVersion(\n rowversions,\n entry.collectionId,\n entry.key,\n entry.eventId,\n confirmation.globalSeq,\n );\n }\n\n emit(\"onEventPushed\", {\n eventId: confirmation.eventId,\n globalSeq: confirmation.globalSeq,\n });\n cleared++;\n }\n\n for (const entry of outbound) {\n if (confirmed.has(entry.eventId)) continue;\n\n const failure = failedById.get(entry.eventId);\n const message = failure?.message ?? \"push failed during dead-letter retry\";\n const code = failure?.code ?? null;\n\n if (deadletter.has(entry.eventId)) {\n await deadletter.update(entry.eventId, (draft) => {\n draft.attemptCount = (draft.attemptCount ?? 0) + 1;\n draft.message = message;\n draft.code = code;\n draft.failedAt = now;\n }).isPersisted.promise;\n }\n }\n\n log.info(\"outbound dead-letter events pushed\", {\n attempted: outbound.length,\n confirmed: response.confirmed.length,\n failed: response.failed?.length ?? 0,\n });\n } else {\n log.info(\"dead-letter events retried\", {\n count: targets.length,\n inbound: inboundRequeued,\n });\n }\n\n return cleared;\n });\n }\n\n function discardDeadLetter(eventId?: string): Promise<number> {\n return runExclusive(async () => {\n const targets = selectDeadLetters(deadletter, eventId);\n\n for (const entry of targets) {\n await deadletter.delete(entry.eventId).isPersisted.promise;\n }\n\n log.info(\"dead-letter events discarded\", { count: targets.length });\n\n return targets.length;\n });\n }\n\n function pruneSyncedEvents(options: PruneOptions = {}): Promise<PruneResult> {\n return runExclusive(async () => {\n const olderThanMs = Math.max(0, options.olderThanMs ?? 0);\n const keepLast = Math.max(0, options.keepLast ?? 0);\n const cutoff = Date.now() - olderThanMs;\n\n // The cursor is derived partly from resolved inbox rows, so persist it\n // before those rows are removed.\n await writePullCursor(syncmeta, readPullCursor(syncmeta, inbox));\n\n const outboxTargets = trimKeepLast(\n [...outbox.state.values()]\n .filter((entry) => entry.sync && entry.timestamp <= cutoff)\n .sort((a, b) => a.localSeq - b.localSeq),\n keepLast,\n );\n\n const inboxTargets = trimKeepLast(\n [...inbox.state.values()]\n .filter((entry) => entry.sync && entry.timestamp <= cutoff)\n .sort((a, b) => a.globalSeq - b.globalSeq),\n keepLast,\n );\n\n for (const entry of outboxTargets) {\n await outbox.delete(entry.eventId).isPersisted.promise;\n }\n\n for (const entry of inboxTargets) {\n await inbox.delete(entry.eventId).isPersisted.promise;\n }\n\n log.info(\"pruned synced events\", {\n outbox: outboxTargets.length,\n inbox: inboxTargets.length,\n });\n\n return { outbox: outboxTargets.length, inbox: inboxTargets.length };\n });\n }\n\n function resetLocalReplica(\n options: ResetLocalReplicaOptions = {},\n ): Promise<ResetLocalReplicaResult> {\n const deferred: ResetLocalReplicaResult = {\n deferred: true,\n removedRows: 0,\n discardedPending: 0,\n clientId: clientId.value,\n };\n\n return runExclusive(() =>\n withLock(async () => {\n const pending = [...outbox.state.values()].filter((entry) => !entry.sync);\n if (pending.length > 0 && options.discardPending !== true) {\n throw new UnsyncedChangesError(pending.length);\n }\n\n // acceptMutations is the replay path: it writes the collection and its\n // persistence without calling onDelete, so no outbox event is authored.\n let removedRows = 0;\n for (const { collectionId, collection } of syncedCollections) {\n const target = replayTargets[collectionId];\n const rows = [...collection.state.entries()];\n if (rows.length === 0 || !target?.utils.acceptMutations) continue;\n\n await target.utils.acceptMutations({\n mutations: rows.map(([key, row]) => ({\n mutationId: generateEventId(),\n type: \"delete\" as const,\n key,\n modified: row,\n original: row,\n changes: row,\n collection: target,\n })),\n });\n removedRows += rows.length;\n }\n\n for (const meta of [outbox, inbox, deadletter] as const) {\n for (const eventId of [...meta.state.keys()]) {\n await meta.delete(eventId).isPersisted.promise;\n }\n }\n for (const id of [...rowversions.state.keys()]) {\n await rowversions.delete(id).isPersisted.promise;\n }\n\n // Pulled events are skipped when their clientId is ours. A fresh id\n // makes this device's own history replay like anyone else's.\n clientId.value = generateEventId();\n await ensureSyncMeta(syncmeta);\n await syncmeta.update(SYNCMETA_KEY, (draft) => {\n draft.clientId = clientId.value;\n draft.pullCursor = 0;\n draft.lastError = null;\n }).isPersisted.promise;\n\n log.warn(\"local replica reset\", {\n removedRows,\n discardedPending: pending.length,\n clientId: clientId.value,\n });\n notifyStatus();\n\n return {\n deferred: false,\n removedRows,\n discardedPending: pending.length,\n clientId: clientId.value,\n };\n }, deferred),\n );\n }\n\n function getSyncEnabled(): boolean {\n return syncEnabled;\n }\n\n function setSyncEnabled(enabled: boolean): void {\n syncEnabled = enabled;\n log.debug(\"sync enabled updated\", { syncEnabled: enabled });\n }\n\n function dispose(): void {\n log.debug(\"disposing event-sourced db\");\n statusListeners.clear();\n for (const subscription of subscriptions) {\n subscription.unsubscribe();\n }\n }\n\n return {\n collections,\n sync,\n manualSync,\n getSyncEnabled,\n setSyncEnabled,\n getSyncStatus,\n subscribeSyncStatus,\n retryDeadLetter,\n discardDeadLetter,\n getPushLimits: () => pushLimits,\n setPushLimits(next: Partial<SyncPushLimits>) {\n pushLimits = resolvePushLimits({\n pushBatchSize: next.pushBatchSize ?? pushLimits.pushBatchSize,\n maxPushBytes:\n (next.maxPushBytes === undefined ? pushLimits.maxPushBytes : next.maxPushBytes) ??\n undefined,\n });\n log.info(\"push limits updated\", pushLimits);\n return pushLimits;\n },\n pruneSyncedEvents,\n resetLocalReplica,\n dispose,\n };\n}\n\nfunction selectDeadLetters(\n deadletter: Collection<DeadLetterEntry, string>,\n eventId?: string,\n): DeadLetterEntry[] {\n if (eventId === undefined) {\n return [...deadletter.state.values()].sort(\n (a, b) => (a.localSeq ?? a.globalSeq ?? 0) - (b.localSeq ?? b.globalSeq ?? 0),\n );\n }\n\n const entry = deadletter.get(eventId);\n return entry ? [entry] : [];\n}\n\n/** Puts a parked inbound event back in the inbox so replay can pick it up again. */\nasync function requeueInboundDeadLetter(\n inbox: Collection<InboxEntry, string>,\n entry: DeadLetterEntry,\n): Promise<void> {\n if (inbox.has(entry.eventId)) {\n await inbox.update(entry.eventId, (draft) => {\n draft.sync = false;\n draft.skipped = false;\n draft.skipReason = null;\n draft.attemptCount = 0;\n draft.lastError = null;\n }).isPersisted.promise;\n return;\n }\n\n await inbox.insert({\n eventId: entry.eventId,\n globalSeq: entry.globalSeq ?? 0,\n collectionId: entry.collectionId,\n type: entry.type,\n key: entry.key,\n payload: entry.payload,\n previous: entry.previous,\n clientId: entry.clientId,\n schemaVersion: entry.schemaVersion,\n timestamp: entry.timestamp,\n sync: false,\n skipped: false,\n skipReason: null,\n attemptCount: 0,\n lastError: null,\n }).isPersisted.promise;\n}\n\n/** Drops the newest `keepLast` items from an ascending-sorted removal list. */\nfunction trimKeepLast<T>(items: ReadonlyArray<T>, keepLast: number): T[] {\n if (keepLast <= 0) return [...items];\n return items.slice(0, Math.max(0, items.length - keepLast));\n}\n\nfunction createMetaCollection<TEntry extends object>(\n config: MetaCollectionFactory,\n id: string,\n getKey: (entry: TEntry) => string,\n schemaVersion: number,\n): Collection<TEntry, string> {\n const options = config.persistedCollectionOptions<TEntry, string>({\n id,\n getKey,\n persistence: config.persistence,\n schemaVersion,\n });\n\n return config.createCollection(options);\n}\n\ntype IndexableCollection = {\n createIndex: (\n indexCallback: (row: Record<string, unknown>) => unknown,\n config?: {\n name?: string;\n indexType?: new (id: number, expression: never, name?: string, options?: never) => unknown;\n },\n ) => unknown;\n getIndexMetadata?: () => ReadonlyArray<unknown>;\n on?: (event: \"status:ready\", callback: () => void) => () => void;\n};\n\nfunction applyCollectionIndexes(\n collection: Collection<Record<string, unknown>, string | number>,\n collectionId: string,\n indexes: CollectionDefConstraint[\"indexes\"],\n log: EventSourcedLogger,\n): void {\n if (!indexes?.length) return;\n\n const indexable = collection as IndexableCollection;\n\n const register = (): void => {\n if ((indexable.getIndexMetadata?.().length ?? 0) > 0) return;\n\n for (const indexDef of indexes) {\n indexable.createIndex(indexDef.select as (row: Record<string, unknown>) => unknown, {\n name: indexDef.name,\n indexType: indexDef.indexType,\n });\n\n log.debug(\"registered collection index\", { collectionId, name: indexDef.name });\n }\n };\n\n register();\n\n indexable.on?.(\"status:ready\", register);\n}\n\n/** Handler for `localOnly` collections: persist locally, author no event. */\nasync function noOutboxHook(): Promise<Record<string, unknown>> {\n return {};\n}\n\nfunction createMutationHook(context: MutationContext) {\n const {\n outbox,\n rowversions,\n collectionId,\n type,\n seq,\n clientId,\n eventSchemaVersion,\n conflictDetection,\n emit,\n log,\n } = context;\n\n return async (params: MutationHookParams): Promise<Record<string, unknown>> => {\n const txId = generateEventId();\n const timestamp = Date.now();\n\n for (const mutation of params.transaction.mutations) {\n const payload = type === \"delete\" ? mutation.original : mutation.modified;\n const eventId = generateEventId();\n\n const entry: OutboxEntry = {\n eventId,\n collectionId,\n type,\n key: mutation.key,\n payload,\n previous: type === \"insert\" ? null : mutation.original,\n txId,\n clientId: clientId.value,\n schemaVersion: eventSchemaVersion,\n baseVersion: conflictDetection\n ? readRowVersion(rowversions, collectionId, mutation.key)\n : null,\n timestamp,\n localSeq: allocateLocalSeq(outbox, seq),\n globalSeq: null,\n sync: false,\n syncStatus: \"pending\",\n attemptCount: 0,\n lastAttemptAt: null,\n nextAttemptAt: null,\n lastError: null,\n lastErrorCode: null,\n retryable: null,\n };\n\n await outbox.insert(entry).isPersisted.promise;\n\n if (conflictDetection) {\n await recordRowVersion(rowversions, collectionId, mutation.key, eventId, null);\n }\n\n log.debug(\"outbox entry created\", {\n eventId,\n collectionId,\n type,\n key: entry.key,\n localSeq: entry.localSeq,\n txId,\n });\n\n emit(\"onMutation\", entry);\n }\n\n return {};\n };\n}\n\n/**\n * Reads the high-water mark from live outbox state rather than trusting the\n * cached counter alone, so a second tab writing to the same persisted store\n * cannot hand out a localSeq that has already been used.\n */\nfunction allocateLocalSeq(outbox: Collection<OutboxEntry, string>, seq: SeqCounter): number {\n const allocated = Math.max(seq.value, nextLocalSeq(outbox));\n seq.value = allocated + 1;\n return allocated;\n}\n\nfunction nextLocalSeq(outbox: Collection<OutboxEntry, string>): number {\n let max = -1;\n\n for (const entry of outbox.state.values()) {\n if (entry.localSeq > max) max = entry.localSeq;\n }\n\n return max + 1;\n}\n\nfunction assertReservedNamesAvailable(collections: Record<string, unknown>): void {\n for (const id of Object.keys(collections)) {\n if (RESERVED_IDS.has(id)) {\n throw new Error(\n `Collection id \"${id}\" is reserved. Built-in collections are: ${[...RESERVED_IDS]\n .map((name) => `\"${name}\"`)\n .join(\", \")}.`,\n );\n }\n }\n}\n\nfunction toError(err: unknown): Error {\n return err instanceof Error ? err : new Error(String(err));\n}\n","export type LazySingletonOptions = {\n /** Runs on every `ensure()` / proxy access (e.g. `typeof window` checks). */\n guard?: () => void;\n /** Thrown when `proxy` is used before `ensure()` resolves. */\n notInitializedMessage?: string;\n};\n\n/**\n * Result of {@link createLazySingleton}.\n *\n * @example\n * ```ts\n * import { createLazySingleton } from \"event-sourced-collection\"\n *\n * const { ensure, proxy, reset } = createLazySingleton(async () => ({ ready: true }))\n * await ensure()\n * console.log(proxy.ready) // true\n * reset()\n * ```\n */\nexport type LazySingleton<T extends object> = {\n ensure: () => Promise<T>;\n proxy: T;\n reset: () => void;\n};\n\n/**\n * One-shot async factory with a proxy that is safe to export as a module\n * singleton. Platform DB helpers are built on this.\n *\n * @example Export a proxy, initialize at app startup\n * ```ts\n * import { createLazySingleton } from \"event-sourced-collection\"\n *\n * type Client = { ping: () => Promise<string> }\n *\n * const { ensure, proxy: client } = createLazySingleton<Client>(async () => ({\n * ping: async () => \"ok\",\n * }))\n *\n * export async function start() {\n * await ensure()\n * }\n *\n * export { client }\n * // client.ping() throws until start() has run\n * ```\n */\nexport function createLazySingleton<T extends object>(\n factory: () => Promise<T>,\n options: LazySingletonOptions = {},\n): LazySingleton<T> {\n let instance: T | null = null;\n let initPromise: Promise<T> | null = null;\n\n const ensure = async (): Promise<T> => {\n options.guard?.();\n\n if (instance) {\n return instance;\n }\n\n if (!initPromise) {\n initPromise = factory()\n .then((resolved) => {\n instance = resolved;\n return resolved;\n })\n .catch((error: unknown) => {\n initPromise = null;\n throw error;\n });\n }\n\n return initPromise;\n };\n\n const message =\n options.notInitializedMessage ?? \"Instance is not initialized. Call ensure() first.\";\n\n const proxy = new Proxy({} as T, {\n get(_target, prop, receiver) {\n if (!instance) {\n throw new Error(message);\n }\n return Reflect.get(instance, prop, receiver);\n },\n has(_target, prop) {\n if (!instance) {\n throw new Error(message);\n }\n return Reflect.has(instance, prop);\n },\n getPrototypeOf() {\n if (!instance) {\n throw new Error(message);\n }\n return Reflect.getPrototypeOf(instance);\n },\n });\n\n const reset = (): void => {\n instance = null;\n initPromise = null;\n };\n\n return { ensure, proxy, reset };\n}\n","import { createEventSourcedDB } from \"./create-event-sourced-db\";\nimport { createLazySingleton } from \"./lazy-singleton\";\nimport type { EventSourcedDB, EventSourcedDBConfig } from \"./types\";\n\ntype CollectionDefConstraint = {\n getKey: (state: never) => string | number;\n};\n\n/**\n * Lazy handle returned by platform helpers and {@link createEventSourcedDBHandle}.\n *\n * @example\n * ```ts\n * import { createBrowserEventSourcedDB } from \"event-sourced-collection/browser\"\n *\n * const { ensureDb, db, close } = createBrowserEventSourcedDB({\n * databaseName: \"app.sqlite\",\n * collections: { todos: { getKey: (todo: { id: string }) => todo.id } },\n * modules: async () => {\n * const { createCollection } = await import(\"@tanstack/db\")\n * const persistence = await import(\"@tanstack/browser-db-sqlite-persistence\")\n * return { createCollection, ...persistence }\n * },\n * })\n *\n * await ensureDb()\n * await db.collections.todos.insert({ id: \"t1\" }).isPersisted.promise\n * await close()\n * ```\n */\nexport type EventSourcedDBHandle<TDefs extends Record<string, CollectionDefConstraint>> = {\n /** Opens (or returns) the singleton DB. Call once at app startup before using `db`. */\n ensureDb: () => Promise<EventSourcedDB<TDefs>>;\n /**\n * Proxy that forwards to the live DB after `ensureDb()` resolves. Accessing a\n * property before initialization throws.\n */\n db: EventSourcedDB<TDefs>;\n /** Disposes the DB, runs platform cleanup, and resets the singleton. */\n close: () => Promise<void>;\n};\n\nexport type EventSourcedDBHandleSetup<TDefs extends Record<string, CollectionDefConstraint>> =\n EventSourcedDBConfig<TDefs> & {\n /** Optional platform teardown (close SQLite, dispose coordinators). */\n close?: () => Promise<void> | void;\n };\n\n/**\n * Lazy singleton around {@link createEventSourcedDB}. Platform helpers use this\n * after they have turned TanStack persistence modules into `persistence`.\n * Call this yourself only when you need a custom open/close path.\n *\n * @example Custom persistence, still lazy like the platform helpers\n * ```ts\n * import { createCollection } from \"@tanstack/db\"\n * import {\n * createNodeSQLitePersistence,\n * persistedCollectionOptions,\n * } from \"@tanstack/node-db-sqlite-persistence\"\n * import Database from \"better-sqlite3\"\n * import { createEventSourcedDBHandle } from \"event-sourced-collection\"\n *\n * type Todo = { id: string; title: string }\n *\n * const { ensureDb, db, close } = createEventSourcedDBHandle({\n * setup: async () => {\n * const sqlite = new Database(\"app.sqlite\")\n * return {\n * persistence: createNodeSQLitePersistence({ database: sqlite }),\n * createCollection,\n * persistedCollectionOptions,\n * collections: { todos: { getKey: (todo: Todo) => todo.id } },\n * close: () => sqlite.close(),\n * }\n * },\n * })\n *\n * await ensureDb()\n * console.log(db.collections.todos.size)\n * await close()\n * ```\n */\nexport function createEventSourcedDBHandle<\n const TDefs extends Record<string, CollectionDefConstraint>,\n>(options: {\n setup: () => Promise<EventSourcedDBHandleSetup<TDefs>>;\n guard?: () => void;\n notInitializedMessage?: string;\n}): EventSourcedDBHandle<TDefs> {\n let activeDb: EventSourcedDB<TDefs> | null = null;\n let closePlatform: (() => Promise<void> | void) | null = null;\n\n const factory = async (): Promise<EventSourcedDB<TDefs>> => {\n const { close, ...dbConfig } = await options.setup();\n closePlatform = close ?? null;\n const database = await createEventSourcedDB<TDefs>(dbConfig);\n activeDb = database;\n return database;\n };\n\n const singleton = createLazySingleton<EventSourcedDB<TDefs>>(factory, {\n guard: options.guard,\n notInitializedMessage:\n options.notInitializedMessage ??\n \"Event-sourced DB is not initialized. Call ensureDb() before using db.\",\n });\n\n const close = async (): Promise<void> => {\n if (activeDb) {\n activeDb.dispose();\n activeDb = null;\n }\n if (closePlatform) {\n await closePlatform();\n closePlatform = null;\n }\n singleton.reset();\n };\n\n return {\n ensureDb: singleton.ensure,\n db: singleton.proxy,\n close,\n };\n}\n\n/** Bindings object, or a function that loads them on first `ensureDb()`. */\nexport type ModulesInput<T> = T | (() => T | Promise<T>);\n\n/**\n * Resolves {@link ModulesInput}: returns the object, or awaits the loader.\n *\n * @example Keep WASM off the SSR bundle until the first `ensureDb()`\n * ```ts\n * import { resolveModules, type ModulesInput } from \"event-sourced-collection\"\n *\n * type BrowserModules = {\n * createCollection: typeof import(\"@tanstack/db\").createCollection\n * }\n *\n * const modules: ModulesInput<BrowserModules> = async () => {\n * const { createCollection } = await import(\"@tanstack/db\")\n * return { createCollection }\n * }\n *\n * const resolved = await resolveModules(modules)\n * ```\n */\nexport async function resolveModules<T>(modules: ModulesInput<T>): Promise<T> {\n return typeof modules === \"function\" ? await (modules as () => T | Promise<T>)() : modules;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { l as EventSourcedDB, u as EventSourcedDBConfig } from "./types-DrV5f9_t.mjs";
1
+ import { l as EventSourcedDB, u as EventSourcedDBConfig } from "./types-Dc-_92xv.mjs";
2
2
 
3
3
  //#region src/core/create-event-sourced-db-handle.d.ts
4
4
  type CollectionDefConstraint = {
@@ -102,4 +102,4 @@ type ModulesInput<T> = T | (() => T | Promise<T>);
102
102
  declare function resolveModules<T>(modules: ModulesInput<T>): Promise<T>;
103
103
  //#endregion
104
104
  export { resolveModules as a, createEventSourcedDBHandle as i, EventSourcedDBHandleSetup as n, ModulesInput as r, EventSourcedDBHandle as t };
105
- //# sourceMappingURL=create-event-sourced-db-handle-Di5qN4QH.d.mts.map
105
+ //# sourceMappingURL=create-event-sourced-db-handle-DlUfot8-.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-event-sourced-db-handle-Di5qN4QH.d.mts","names":[],"sources":["../src/core/create-event-sourced-db-handle.ts"],"mappings":";;;KAIK,uBAAA;EACH,MAAA,GAAS,KAAY;AAAA;;;;AAAA;AAyBvB;;;;;;;;;;;;;;;;;;KAAY,oBAAA,eAAmC,MAAA,SAAe,uBAAA;EAErB,uFAAvC,QAAA,QAAgB,OAAA,CAAQ,cAAA,CAAe,KAAA;EAKnC;;;;EAAJ,EAAA,EAAI,cAAA,CAAe,KAAA,GAEC;EAApB,KAAA,QAAa,OAAA;AAAA;AAAA,KAGH,yBAAA,eAAwC,MAAA,SAAe,uBAAA,KACjE,oBAAA,CAAqB,KAAA;EAD4C,uEAG/D,KAAA,SAAc,OAAA;AAAA;;;;;;;;;;;;;AAAO;AAsCzB;;;;;;;;;;;;;;;;;;;;;;iBAAgB,0BAAA,qBACM,MAAA,SAAe,uBAAA,GACnC,OAAA;EACA,KAAA,QAAa,OAAA,CAAQ,yBAAA,CAA0B,KAAA;EAC/C,KAAA;EACA,qBAAA;AAAA,IACE,oBAAA,CAAqB,KAAA;;KAuCb,YAAA,MAAkB,CAAA,UAAW,CAAA,GAAI,OAAA,CAAQ,CAAA;;;;;;;;;;;;;AAAC;AAqBtD;;;;;;iBAAsB,cAAA,IAAkB,OAAA,EAAS,YAAA,CAAa,CAAA,IAAK,OAAA,CAAQ,CAAA"}
1
+ {"version":3,"file":"create-event-sourced-db-handle-DlUfot8-.d.mts","names":[],"sources":["../src/core/create-event-sourced-db-handle.ts"],"mappings":";;;KAIK,uBAAA;EACH,MAAA,GAAS,KAAY;AAAA;;;;AAAA;AAyBvB;;;;;;;;;;;;;;;;;;KAAY,oBAAA,eAAmC,MAAA,SAAe,uBAAA;EAErB,uFAAvC,QAAA,QAAgB,OAAA,CAAQ,cAAA,CAAe,KAAA;EAKnC;;;;EAAJ,EAAA,EAAI,cAAA,CAAe,KAAA,GAEC;EAApB,KAAA,QAAa,OAAA;AAAA;AAAA,KAGH,yBAAA,eAAwC,MAAA,SAAe,uBAAA,KACjE,oBAAA,CAAqB,KAAA;EAD4C,uEAG/D,KAAA,SAAc,OAAA;AAAA;;;;;;;;;;;;;AAAO;AAsCzB;;;;;;;;;;;;;;;;;;;;;;iBAAgB,0BAAA,qBACM,MAAA,SAAe,uBAAA,GACnC,OAAA;EACA,KAAA,QAAa,OAAA,CAAQ,yBAAA,CAA0B,KAAA;EAC/C,KAAA;EACA,qBAAA;AAAA,IACE,oBAAA,CAAqB,KAAA;;KAuCb,YAAA,MAAkB,CAAA,UAAW,CAAA,GAAI,OAAA,CAAQ,CAAA;;;;;;;;;;;;;AAAC;AAqBtD;;;;;;iBAAsB,cAAA,IAAkB,OAAA,EAAS,YAAA,CAAa,CAAA,IAAK,OAAA,CAAQ,CAAA"}
package/dist/index.d.mts CHANGED
@@ -1,11 +1,20 @@
1
- import { $ as InjectedCreateCollection, A as PushResponse, B as SyncPushLimits, C as PruneOptions, D as PushConfirmation, E as PullResponse, F as ServerEvent, G as SyncTrigger, H as SyncResult, I as SyncHandlersConfig, J as UpcastEventFn, K as SyncUrlConfig, L as SyncLock, M as RetryConfig, N as RowVersionEntry, O as PushEventsFn, P as SQLiteDriver, Q as CreateCollectionFn, R as SyncMetaEntry, S as PersistedCollectionPersistence, T as PullEventsFn, U as SyncStatus, V as SyncPushPreset, W as SyncTransport, X as EventSourcedLogger, Y as UpcastableEvent, Z as createEventSourcedLogger, _ as ManualSyncResult, a as CollectionMap, b as OutboxEntry, c as DeadLetterReason, d as EventSourcedHooks, et as InjectedModuleFn, f as EventSourcedOptions, g as InferState, h as InferKey, i as CollectionIndexDef, j as ReservedCollections, k as PushFailure, l as EventSourcedDB, m as InboxEntry, n as CollectionDef, o as DeadLetterDirection, p as EventSourcedSharedOptions, q as UnknownEventHandling, r as CollectionIndexConstructor, s as DeadLetterEntry, t as BackendMismatchPolicy, tt as PersistedCollectionOptionsFn, u as EventSourcedDBConfig, v as MutationType, w as PruneResult, x as OutboxSyncStatus, y as OutboundEvent, z as SyncPhase } from "./types-DrV5f9_t.mjs";
2
- import { a as resolveModules, i as createEventSourcedDBHandle, n as EventSourcedDBHandleSetup, r as ModulesInput, t as EventSourcedDBHandle } from "./create-event-sourced-db-handle-Di5qN4QH.mjs";
1
+ import { $ as createEventSourcedLogger, A as PushResponse, B as SyncMetaEntry, C as PruneOptions, D as PushConfirmation, E as PullResponse, F as RowVersionEntry, G as SyncStatus, H as SyncPushLimits, I as SQLiteDriver, J as SyncUrlConfig, K as SyncTransport, L as ServerEvent, M as ResetLocalReplicaOptions, N as ResetLocalReplicaResult, O as PushEventsFn, P as RetryConfig, Q as EventSourcedLogger, R as SyncHandlersConfig, S as PersistedCollectionPersistence, T as PullEventsFn, U as SyncPushPreset, V as SyncPhase, W as SyncResult, X as UpcastEventFn, Y as UnknownEventHandling, Z as UpcastableEvent, _ as ManualSyncResult, a as CollectionMap, b as OutboxEntry, c as DeadLetterReason, d as EventSourcedHooks, et as CreateCollectionFn, f as EventSourcedOptions, g as InferState, h as InferKey, i as CollectionIndexDef, j as ReservedCollections, k as PushFailure, l as EventSourcedDB, m as InboxEntry, n as CollectionDef, nt as InjectedModuleFn, o as DeadLetterDirection, p as EventSourcedSharedOptions, q as SyncTrigger, r as CollectionIndexConstructor, rt as PersistedCollectionOptionsFn, s as DeadLetterEntry, t as BackendMismatchPolicy, tt as InjectedCreateCollection, u as EventSourcedDBConfig, v as MutationType, w as PruneResult, x as OutboxSyncStatus, y as OutboundEvent, z as SyncLock } from "./types-Dc-_92xv.mjs";
2
+ import { a as resolveModules, i as createEventSourcedDBHandle, n as EventSourcedDBHandleSetup, r as ModulesInput, t as EventSourcedDBHandle } from "./create-event-sourced-db-handle-DlUfot8-.mjs";
3
3
  import { Collection } from "@tanstack/db";
4
4
 
5
5
  //#region src/core/create-event-sourced-db.d.ts
6
+ /**
7
+ * Thrown by `resetLocalReplica()` while the outbox still holds changes the
8
+ * server has not accepted. Sync first, or pass `discardPending: true`.
9
+ */
10
+ declare class UnsyncedChangesError extends Error {
11
+ readonly pendingCount: number;
12
+ constructor(pendingCount: number);
13
+ }
6
14
  type CollectionDefConstraint = {
7
15
  getKey: (state: never) => string | number;
8
16
  schemaVersion?: number;
17
+ localOnly?: boolean;
9
18
  indexes?: ReadonlyArray<{
10
19
  select: (row: never) => unknown;
11
20
  name?: string;
@@ -342,5 +351,5 @@ declare class BackendMismatchError extends Error {
342
351
  constructor(expected: string | null, received: string);
343
352
  }
344
353
  //#endregion
345
- export { BackendMismatchError, type BackendMismatchPolicy, type CollectionDef, type CollectionIndexConstructor, type CollectionIndexDef, type CollectionMap, type CreateCollectionFn, type DeadLetterDirection, type DeadLetterEntry, type DeadLetterReason, type EventSourcedDB, type EventSourcedDBConfig, type EventSourcedDBHandle, type EventSourcedDBHandleSetup, type EventSourcedHooks, type EventSourcedLogger, type EventSourcedOptions, type EventSourcedSharedOptions, type InboxEntry, type InferKey, type InferState, type InjectedCreateCollection, type InjectedModuleFn, type LazySingleton, type LazySingletonOptions, type ManualSyncResult, type MockRejectFn, type MockRejection, type MockSyncBackend, type MockSyncBackendOptions, type ModulesInput, type MutationType, type OutboundEvent, type OutboxEntry, type OutboxSyncStatus, type PersistedCollectionOptionsFn, type PersistedCollectionPersistence, type PruneOptions, type PruneResult, type PullEventsFn, type PullResponse, type PushConfirmation, type PushEventsFn, type PushFailure, type PushResponse, type ReservedCollections, type RetryConfig, type RowVersionEntry, type SQLiteDriver, SYNC_PUSH_PRESETS, type ServerEvent, type SyncHandlersConfig, type SyncLock, type SyncMetaEntry, type SyncPhase, SyncPullError, SyncPushError, type SyncPushLimits, type SyncPushPreset, type SyncResult, type SyncStatus, type SyncTransport, type SyncTrigger, type SyncUrlConfig, type UnknownEventHandling, type UpcastEventFn, type UpcastableEvent, createEventSourcedDB, createEventSourcedDBHandle, createEventSourcedLogger, createHttpTransport, createLazySingleton, createMockSyncBackend, createWebLocksSyncLock, generateEventId, resolveModules, resolvePushLimits, supportsWebLocks };
354
+ export { BackendMismatchError, type BackendMismatchPolicy, type CollectionDef, type CollectionIndexConstructor, type CollectionIndexDef, type CollectionMap, type CreateCollectionFn, type DeadLetterDirection, type DeadLetterEntry, type DeadLetterReason, type EventSourcedDB, type EventSourcedDBConfig, type EventSourcedDBHandle, type EventSourcedDBHandleSetup, type EventSourcedHooks, type EventSourcedLogger, type EventSourcedOptions, type EventSourcedSharedOptions, type InboxEntry, type InferKey, type InferState, type InjectedCreateCollection, type InjectedModuleFn, type LazySingleton, type LazySingletonOptions, type ManualSyncResult, type MockRejectFn, type MockRejection, type MockSyncBackend, type MockSyncBackendOptions, type ModulesInput, type MutationType, type OutboundEvent, type OutboxEntry, type OutboxSyncStatus, type PersistedCollectionOptionsFn, type PersistedCollectionPersistence, type PruneOptions, type PruneResult, type PullEventsFn, type PullResponse, type PushConfirmation, type PushEventsFn, type PushFailure, type PushResponse, type ReservedCollections, type ResetLocalReplicaOptions, type ResetLocalReplicaResult, type RetryConfig, type RowVersionEntry, type SQLiteDriver, SYNC_PUSH_PRESETS, type ServerEvent, type SyncHandlersConfig, type SyncLock, type SyncMetaEntry, type SyncPhase, SyncPullError, SyncPushError, type SyncPushLimits, type SyncPushPreset, type SyncResult, type SyncStatus, type SyncTransport, type SyncTrigger, type SyncUrlConfig, type UnknownEventHandling, UnsyncedChangesError, type UpcastEventFn, type UpcastableEvent, createEventSourcedDB, createEventSourcedDBHandle, createEventSourcedLogger, createHttpTransport, createLazySingleton, createMockSyncBackend, createWebLocksSyncLock, generateEventId, resolveModules, resolvePushLimits, supportsWebLocks };
346
355
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/create-event-sourced-db.ts","../src/core/lazy-singleton.ts","../src/core/sync.ts","../src/core/sync-presets.ts","../src/testing/mock-sync-backend.ts","../src/platforms/web-locks.ts","../src/utils/uuid.ts","../src/internal/pull.ts"],"mappings":";;;;;KA6DK,uBAAA;EACH,MAAA,GAAS,KAAA;EACT,aAAA;EACA,OAAA,GAAU,aAAa;IACrB,MAAA,GAAS,GAAA;IACT,IAAA;IACA,SAAA,QAAiB,EAAA,UAAY,UAAA,SAAmB,IAAA,WAAe,OAAA;EAAA;AAAA;;;;;;;;;;;;;;AAAe;AAgFlF;;;;;;;;;;;;;;;;;;;;;;AAEoE;;iBAF9C,oBAAA,qBACA,MAAA,SAAe,uBAAA,GACnC,MAAA,EAAQ,oBAAA,CAAqB,KAAA,IAAS,OAAA,CAAQ,cAAA,CAAe,KAAA;;;KCrJnD,oBAAA;+EAEV,KAAA;EAEA,qBAAqB;AAAA;;;;;;;;;;;;;;KAgBX,aAAA;EACV,MAAA,QAAc,OAAA,CAAQ,CAAA;EACtB,KAAA,EAAO,CAAA;EACP,KAAA;AAAA;AD4HF;;;;;;;;;;;;;;;;;;;;;;AAAA,iBCnGgB,mBAAA,mBACd,OAAA,QAAe,OAAA,CAAQ,CAAA,GACvB,OAAA,GAAS,oBAAA,GACR,aAAA,CAAc,CAAA;;;ADKA;;;;;;;;;;;;;;;;;;AAWiE;AAgFlF;;;;;;;;AA3FiB,iBEVD,mBAAA,CAAoB,MAAA,EAAQ,aAAA,GAAgB,aAAa;;;;;;;;;;;;AFuGL;;;;ACrJpE;;;;AAIuB;AAgBvB;cC8La,aAAA,SAAsB,KAAK;EAAA,SAEpB,MAAA;EAAA,SACA,IAAA;cADA,MAAA,UACA,IAAA;AAAA;;;;;;;;;;;AD9Lb;AAyBP;;;;;;;;;;cCiMa,aAAA,SAAsB,KAAK;EAAA,SAEpB,MAAA;EAAA,SACA,IAAA;cADA,MAAA,UACA,IAAA;AAAA;;;;;;;AF5LH;;;;;;cGvCJ,iBAAA,EAAmB,QAAA,CAAS,MAAA,CAAO,cAAA,EAAgB,cAAA;AAAA,iBAMhD,iBAAA,CAAkB,MAAA;EAChC,UAAA,GAAa,cAAA;EACb,aAAA;EACA,YAAA;AAAA,IACE,cAAc;;;KChBN,aAAA;EACV,OAAA;EACA,IAAA;EACA,SAAA;AAAA;;;;;KAOU,YAAA,IAAgB,KAAA,EAAO,aAAA,EAAe,OAAA,aAAoB,aAAa;AAAA,KAEvE,sBAAA;EJyCV,yEIvCA,SAAA,WJwCE;EItCF,QAAA,WJuCE;EIrCF,UAAA,GAAa,YAAY;AAAA;AAAA,KAGf,eAAA,GAAkB,aAAA;EJmCsB,sEIjCzC,MAAA,EAAQ,aAAA,CAAc,WAAA;EAAA,SACtB,SAAA;EAAA,SACA,SAAA,UJ+GW;EAAA,SI7GX,cAAA,EAAgB,aAAA,UJ6Ge;EI3GxC,IAAA,GAAO,KAAA;IACL,YAAA;IACA,IAAA,GAAO,YAAA;IACP,GAAA;IACA,OAAA,EAAS,MAAA;IACT,OAAA;IACA,QAAA;EAAA,MACI,WAAA,EJsGuC;EIpG7C,cAAA,GAAiB,KAAA,UAAe,OAAA,oBJmGZ;EIjGpB,YAAA,GAAe,SAAA,mBJkGP;EIhGR,KAAA;AAAA;;;;;AJgGkE;;;;ACrJpE;;;;AAIuB;AAgBvB;;;;;;;;iBGyDgB,qBAAA,CAAsB,OAAA,GAAS,sBAAA,GAA8B,eAAe;;;;;;;AJrB3E;;;;;;;;;;;;;;iBKvBD,gBAAA;;;;ALkCkE;AAgFlF;;;;;;;;;;;;;;;;;;;;;;AAEoE;;iBKpFpD,sBAAA,IAA0B,QAAQ;;;;;;;;ALTjC;;;;;;;iBM1CD,eAAA;;;;;;;;;;;;;;;ANqDkE;AAgFlF;;cO7Ga,oBAAA,SAA6B,KAAK;EAAA,SAElC,QAAA;EAAA,SACA,QAAA;cADA,QAAA,iBACA,QAAA;AAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/create-event-sourced-db.ts","../src/core/lazy-singleton.ts","../src/core/sync.ts","../src/core/sync-presets.ts","../src/testing/mock-sync-backend.ts","../src/platforms/web-locks.ts","../src/utils/uuid.ts","../src/internal/pull.ts"],"mappings":";;;;;;;;;cAoEa,oBAAA,SAA6B,KAAK;EAAA,SACxB,YAAA;cAAA,YAAA;AAAA;AAAA,KAMlB,uBAAA;EACH,MAAA,GAAS,KAAA;EACT,aAAA;EACA,SAAA;EACA,OAAA,GAAU,aAAa;IACrB,MAAA,GAAS,GAAA;IACT,IAAA;IACA,SAAA,QAAiB,EAAA,UAAY,UAAA,SAAmB,IAAA,WAAe,OAAA;EAAA;AAAA;;;;;;;;;;;;;;;;AAAe;AAgFlF;;;;;;;;;;;;;;;;;;;;;;iBAAsB,oBAAA,qBACA,MAAA,SAAe,uBAAA,GACnC,MAAA,EAAQ,oBAAA,CAAqB,KAAA,IAAS,OAAA,CAAQ,cAAA,CAAe,KAAA;;;KCpKnD,oBAAA;+EAEV,KAAA;EAEA,qBAAqB;AAAA;;;;;;;;;ADiEoB;AAI1C;;;;KCrDW,aAAA;EACV,MAAA,QAAc,OAAA,CAAQ,CAAA;EACtB,KAAA,EAAO,CAAA;EACP,KAAA;AAAA;;;;;;;;;;;AD2DgF;AAgFlF;;;;;;;;;;;iBClHgB,mBAAA,mBACd,OAAA,QAAe,OAAA,CAAQ,CAAA,GACvB,OAAA,GAAS,oBAAA,GACR,aAAA,CAAc,CAAA;;;ADiBjB;;;;;;;;;AAC2C;AAI1C;;;;;;;;;;;;;;;;;AALD,iBEtBgB,mBAAA,CAAoB,MAAA,EAAQ,aAAA,GAAgB,aAAa;AFoHzE;;;;;;;;;;;;;;;;;;;;;AAAA,cEgDa,aAAA,SAAsB,KAAK;EAAA,SAEpB,MAAA;EAAA,SACA,IAAA;cADA,MAAA,UACA,IAAA;AAAA;ADrNpB;;;;AAIuB;AAgBvB;;;;;;;;;;;;;;;;AApBA,cCiPa,aAAA,SAAsB,KAAK;EAAA,SAEpB,MAAA;EAAA,SACA,IAAA;cADA,MAAA,UACA,IAAA;AAAA;;;;;;;AFhLpB;;;;;;cGnDa,iBAAA,EAAmB,QAAA,CAAS,MAAA,CAAO,cAAA,EAAgB,cAAA;AAAA,iBAMhD,iBAAA,CAAkB,MAAA;EAChC,UAAA,GAAa,cAAA;EACb,aAAA;EACA,YAAA;AAAA,IACE,cAAc;;;KChBN,aAAA;EACV,OAAA;EACA,IAAA;EACA,SAAA;AAAA;;;;;KAOU,YAAA,IAAgB,KAAA,EAAO,aAAA,EAAe,OAAA,aAAoB,aAAa;AAAA,KAEvE,sBAAA;EJ8CW,yEI5CrB,SAAA,WJ4CyC;EI1CzC,QAAA,WJgD0B;EI9C1B,UAAA,GAAa,YAAY;AAAA;AAAA,KAGf,eAAA,GAAkB,aAAA;EJ4CnB,sEI1CA,MAAA,EAAQ,aAAA,CAAc,WAAA;EAAA,SACtB,SAAA;EAAA,SACA,SAAA,UJ2CC;EAAA,SIzCD,cAAA,EAAgB,aAAA,UJ0Cd;EIxCX,IAAA,GAAO,KAAA;IACL,YAAA;IACA,IAAA,GAAO,YAAA;IACP,GAAA;IACA,OAAA,EAAS,MAAA;IACT,OAAA;IACA,QAAA;EAAA,MACI,WAAA,EJmHc;EIjHpB,cAAA,GAAiB,KAAA,UAAe,OAAA,oBJiHQ;EI/GxC,YAAA,GAAe,SAAA,mBJgHK;EI9GpB,KAAA;AAAA;;;;;;;;;;;;;;;;AJ+GkE;;;;ACpKpE;;iBG6EgB,qBAAA,CAAsB,OAAA,GAAS,sBAAA,GAA8B,eAAe;;;;;;;AJT5F;;;;;;;;;AAC2C;AAI1C;;;;iBKxCe,gBAAA;;;;;;;;;;;;;;;ALiDkE;AAgFlF;;;;;;;;;;;;;iBKjGgB,sBAAA,IAA0B,QAAQ;;;;;;;;ALGlD;;;;;;;iBMtDgB,eAAA;;;;;;ANuD2B;AAI1C;;;;;;;;;;;cOnCY,oBAAA,SAA6B,KAAK;EAAA,SAElC,QAAA;EAAA,SACA,QAAA;cADA,QAAA,iBACA,QAAA;AAAA"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as generateEventId, c as resolvePushLimits, d as createHttpTransport, f as BackendMismatchError, i as createEventSourcedDB, l as SyncPullError, n as resolveModules, o as createEventSourcedLogger, r as createLazySingleton, s as SYNC_PUSH_PRESETS, t as createEventSourcedDBHandle, u as SyncPushError } from "./create-event-sourced-db-handle-CD8WSjXW.mjs";
1
+ import { a as createEventSourcedDB, c as SYNC_PUSH_PRESETS, d as SyncPushError, f as createHttpTransport, i as UnsyncedChangesError, l as resolvePushLimits, n as resolveModules, o as generateEventId, p as BackendMismatchError, r as createLazySingleton, s as createEventSourcedLogger, t as createEventSourcedDBHandle, u as SyncPullError } from "./create-event-sourced-db-handle-BRSDLeq9.mjs";
2
2
  import { n as supportsWebLocks, t as createWebLocksSyncLock } from "./web-locks-Bi2f732X.mjs";
3
3
  //#region src/testing/mock-sync-backend.ts
4
4
  /**
@@ -141,6 +141,6 @@ function createMockSyncBackend(options = {}) {
141
141
  };
142
142
  }
143
143
  //#endregion
144
- export { BackendMismatchError, SYNC_PUSH_PRESETS, SyncPullError, SyncPushError, createEventSourcedDB, createEventSourcedDBHandle, createEventSourcedLogger, createHttpTransport, createLazySingleton, createMockSyncBackend, createWebLocksSyncLock, generateEventId, resolveModules, resolvePushLimits, supportsWebLocks };
144
+ export { BackendMismatchError, SYNC_PUSH_PRESETS, SyncPullError, SyncPushError, UnsyncedChangesError, createEventSourcedDB, createEventSourcedDBHandle, createEventSourcedLogger, createHttpTransport, createLazySingleton, createMockSyncBackend, createWebLocksSyncLock, generateEventId, resolveModules, resolvePushLimits, supportsWebLocks };
145
145
 
146
146
  //# sourceMappingURL=index.mjs.map
package/dist/node.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { $ as InjectedCreateCollection, S as PersistedCollectionPersistence, et as InjectedModuleFn, p as EventSourcedSharedOptions } from "./types-DrV5f9_t.mjs";
2
- import { r as ModulesInput, t as EventSourcedDBHandle } from "./create-event-sourced-db-handle-Di5qN4QH.mjs";
1
+ import { S as PersistedCollectionPersistence, nt as InjectedModuleFn, p as EventSourcedSharedOptions, tt as InjectedCreateCollection } from "./types-Dc-_92xv.mjs";
2
+ import { r as ModulesInput, t as EventSourcedDBHandle } from "./create-event-sourced-db-handle-DlUfot8-.mjs";
3
3
  //#region src/platforms/node.d.ts
4
4
  type NodePlatformDeps = {
5
5
  createNodeSQLitePersistence: (options: {
package/dist/node.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as resolveModules, t as createEventSourcedDBHandle } from "./create-event-sourced-db-handle-CD8WSjXW.mjs";
1
+ import { n as resolveModules, t as createEventSourcedDBHandle } from "./create-event-sourced-db-handle-BRSDLeq9.mjs";
2
2
  //#region src/platforms/node.ts
3
3
  /**
4
4
  * Wraps an already-opened better-sqlite3 database as TanStack persistence.
@@ -1,5 +1,5 @@
1
- import { $ as InjectedCreateCollection, S as PersistedCollectionPersistence, et as InjectedModuleFn, p as EventSourcedSharedOptions } from "./types-DrV5f9_t.mjs";
2
- import { r as ModulesInput, t as EventSourcedDBHandle } from "./create-event-sourced-db-handle-Di5qN4QH.mjs";
1
+ import { S as PersistedCollectionPersistence, nt as InjectedModuleFn, p as EventSourcedSharedOptions, tt as InjectedCreateCollection } from "./types-Dc-_92xv.mjs";
2
+ import { r as ModulesInput, t as EventSourcedDBHandle } from "./create-event-sourced-db-handle-DlUfot8-.mjs";
3
3
 
4
4
  //#region src/platforms/react-native-event-sourced-db.d.ts
5
5
  type CollectionDefConstraint = {
@@ -58,4 +58,4 @@ type ReactNativeEventSourcedDBConfig<TDefs extends Record<string, CollectionDefC
58
58
  declare function createReactNativeEventSourcedDB<const TDefs extends Record<string, CollectionDefConstraint>>(config: ReactNativeEventSourcedDBConfig<TDefs>): EventSourcedDBHandle<TDefs>;
59
59
  //#endregion
60
60
  export { ReactNativeEventSourcedModules as n, createReactNativeEventSourcedDB as r, ReactNativeEventSourcedDBConfig as t };
61
- //# sourceMappingURL=react-native-event-sourced-db-CL1Rcfq_.d.mts.map
61
+ //# sourceMappingURL=react-native-event-sourced-db-DmbQ6TFS.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react-native-event-sourced-db-CL1Rcfq_.d.mts","names":[],"sources":["../src/platforms/react-native-event-sourced-db.ts"],"mappings":";;;;KAcK,uBAAA;EACH,MAAA,GAAS,KAAY;AAAA;AAAA,KAGX,8BAAA;EACV,kCAAA,GAAqC,OAAA;IACnC,QAAA;EAAA,MACI,8BAAA,EAHkC;EAKxC,QAAA;EACA,gBAAA,EAAkB,wBAAA;EAClB,0BAAA,EAA4B,gBAAA;AAAA;;;;;;KAQlB,+BAAA,eAA8C,MAAA,SAAe,uBAAA,KACvE,yBAAA;EACE,WAAA,EAAa,KAAA;EAXf;;;;;EAiBE,OAAA,EAAS,YAAA,CAAa,8BAAA;AAAA;;;;;;;;;;;;;;;;;;;;AAA8B;AAiCxD;;;;;;;;iBAAgB,+BAAA,qBACM,MAAA,SAAe,uBAAA,GACnC,MAAA,EAAQ,+BAAA,CAAgC,KAAA,IAAM,oBAAA,CAAA,KAAA"}
1
+ {"version":3,"file":"react-native-event-sourced-db-DmbQ6TFS.d.mts","names":[],"sources":["../src/platforms/react-native-event-sourced-db.ts"],"mappings":";;;;KAcK,uBAAA;EACH,MAAA,GAAS,KAAY;AAAA;AAAA,KAGX,8BAAA;EACV,kCAAA,GAAqC,OAAA;IACnC,QAAA;EAAA,MACI,8BAAA,EAHkC;EAKxC,QAAA;EACA,gBAAA,EAAkB,wBAAA;EAClB,0BAAA,EAA4B,gBAAA;AAAA;;;;;;KAQlB,+BAAA,eAA8C,MAAA,SAAe,uBAAA,KACvE,yBAAA;EACE,WAAA,EAAa,KAAA;EAXf;;;;;EAiBE,OAAA,EAAS,YAAA,CAAa,8BAAA;AAAA;;;;;;;;;;;;;;;;;;;;AAA8B;AAiCxD;;;;;;;;iBAAgB,+BAAA,qBACM,MAAA,SAAe,uBAAA,GACnC,MAAA,EAAQ,+BAAA,CAAgC,KAAA,IAAM,oBAAA,CAAA,KAAA"}
@@ -1,6 +1,6 @@
1
- import { S as PersistedCollectionPersistence } from "./types-DrV5f9_t.mjs";
2
- import { t as EventSourcedDBHandle } from "./create-event-sourced-db-handle-Di5qN4QH.mjs";
3
- import { n as ReactNativeEventSourcedModules, r as createReactNativeEventSourcedDB, t as ReactNativeEventSourcedDBConfig } from "./react-native-event-sourced-db-CL1Rcfq_.mjs";
1
+ import { S as PersistedCollectionPersistence } from "./types-Dc-_92xv.mjs";
2
+ import { t as EventSourcedDBHandle } from "./create-event-sourced-db-handle-DlUfot8-.mjs";
3
+ import { n as ReactNativeEventSourcedModules, r as createReactNativeEventSourcedDB, t as ReactNativeEventSourcedDBConfig } from "./react-native-event-sourced-db-DmbQ6TFS.mjs";
4
4
 
5
5
  //#region src/platforms/react-native.d.ts
6
6
  type ReactNativePlatformDeps = {
@@ -1,4 +1,4 @@
1
- import { n as resolveModules, t as createEventSourcedDBHandle } from "./create-event-sourced-db-handle-CD8WSjXW.mjs";
1
+ import { n as resolveModules, t as createEventSourcedDBHandle } from "./create-event-sourced-db-handle-BRSDLeq9.mjs";
2
2
  //#region src/platforms/react-native.ts
3
3
  /**
4
4
  * Wraps an already-opened native SQLite database as TanStack persistence.
package/dist/react.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { U as SyncStatus, _ as ManualSyncResult } from "./types-DrV5f9_t.mjs";
1
+ import { G as SyncStatus, _ as ManualSyncResult } from "./types-Dc-_92xv.mjs";
2
2
 
3
3
  //#region src/react/format-manual-sync-message.d.ts
4
4
  declare function formatManualSyncMessage(result: ManualSyncResult): string;
@@ -465,6 +465,12 @@ type CollectionDef<TState = object, TKey extends string | number = string> = {
465
465
  */
466
466
  schemaVersion?: number; /** Secondary indexes created when the collection is opened. */
467
467
  indexes?: ReadonlyArray<CollectionIndexDef<TState, TKey>>;
468
+ /**
469
+ * Persist locally but never sync: mutations author no outbox events, and
470
+ * pulled events for this collection are skipped so server history cannot
471
+ * overwrite local rows. Outbox entries queued before the switch are dropped.
472
+ */
473
+ localOnly?: boolean;
468
474
  };
469
475
  type InferState<T> = T extends {
470
476
  getKey: (state: infer S) => string | number;
@@ -475,6 +481,7 @@ type InferKey<T> = T extends {
475
481
  type CollectionDefConstraint = {
476
482
  getKey: (state: never) => string | number;
477
483
  schemaVersion?: number;
484
+ localOnly?: boolean;
478
485
  indexes?: ReadonlyArray<{
479
486
  select: (row: never) => unknown;
480
487
  name?: string;
@@ -560,6 +567,15 @@ type PruneOptions = {
560
567
  /** Only prune rows older than this, in milliseconds. Defaults to 0 (all). */olderThanMs?: number; /** Always retain at least this many of the most recent rows per collection. */
561
568
  keepLast?: number;
562
569
  };
570
+ type ResetLocalReplicaOptions = {
571
+ /** Drop outbox changes the server has not accepted instead of throwing. */discardPending?: boolean;
572
+ };
573
+ type ResetLocalReplicaResult = {
574
+ /** True when another tab holds the sync lock; nothing was changed. */deferred: boolean; /** User rows removed across synced collections. */
575
+ removedRows: number; /** Unpushed outbox events that were thrown away (only with `discardPending`). */
576
+ discardedPending: number; /** The device's new client id. */
577
+ clientId: string;
578
+ };
563
579
  type PruneResult = {
564
580
  outbox: number;
565
581
  inbox: number;
@@ -840,7 +856,17 @@ type EventSourcedDB<TDefs extends Record<string, CollectionDefConstraint>> = {
840
856
  * Compacts the event log by deleting confirmed outbox rows and resolved inbox
841
857
  * rows. Safe because the pull cursor lives in `syncmeta`, not in the inbox.
842
858
  */
843
- pruneSyncedEvents: (options?: PruneOptions) => Promise<PruneResult>; /** Current push limits after preset, overrides and clamping. */
859
+ pruneSyncedEvents: (options?: PruneOptions) => Promise<PruneResult>;
860
+ /**
861
+ * Empties this device's copy so the next sync rebuilds it from the server.
862
+ * Rows are removed through the replay path, so no delete events are pushed.
863
+ * Clears outbox, inbox, dead-letter and row versions, rewinds the pull cursor
864
+ * to zero and assigns a new `clientId` so this device's own history replays.
865
+ * `localOnly` collections are kept. Throws {@link UnsyncedChangesError} while
866
+ * the outbox has unpushed changes unless `discardPending` is set. Call
867
+ * `sync()` afterwards to pull everything back.
868
+ */
869
+ resetLocalReplica: (options?: ResetLocalReplicaOptions) => Promise<ResetLocalReplicaResult>; /** Current push limits after preset, overrides and clamping. */
844
870
  getPushLimits: () => SyncPushLimits;
845
871
  /**
846
872
  * Changes push limits for future batches (the batch in flight is unaffected).
@@ -861,5 +887,5 @@ type ManualSyncResult = SyncResult & {
861
887
  replayed: number;
862
888
  };
863
889
  //#endregion
864
- export { InjectedCreateCollection as $, PushResponse as A, SyncPushLimits as B, PruneOptions as C, PushConfirmation as D, PullResponse as E, ServerEvent as F, SyncTrigger as G, SyncResult as H, SyncHandlersConfig as I, UpcastEventFn as J, SyncUrlConfig as K, SyncLock as L, RetryConfig as M, RowVersionEntry as N, PushEventsFn as O, SQLiteDriver as P, CreateCollectionFn as Q, SyncMetaEntry as R, PersistedCollectionPersistence$1 as S, PullEventsFn as T, SyncStatus as U, SyncPushPreset as V, SyncTransport as W, EventSourcedLogger as X, UpcastableEvent as Y, createEventSourcedLogger as Z, ManualSyncResult as _, CollectionMap as a, OutboxEntry as b, DeadLetterReason as c, EventSourcedHooks as d, InjectedModuleFn as et, EventSourcedOptions as f, InferState as g, InferKey as h, CollectionIndexDef as i, ReservedCollections as j, PushFailure as k, EventSourcedDB as l, InboxEntry as m, CollectionDef as n, DeadLetterDirection as o, EventSourcedSharedOptions as p, UnknownEventHandling as q, CollectionIndexConstructor as r, DeadLetterEntry as s, BackendMismatchPolicy as t, PersistedCollectionOptionsFn as tt, EventSourcedDBConfig as u, MutationType as v, PruneResult as w, OutboxSyncStatus as x, OutboundEvent as y, SyncPhase as z };
865
- //# sourceMappingURL=types-DrV5f9_t.d.mts.map
890
+ export { createEventSourcedLogger as $, PushResponse as A, SyncMetaEntry as B, PruneOptions as C, PushConfirmation as D, PullResponse as E, RowVersionEntry as F, SyncStatus as G, SyncPushLimits as H, SQLiteDriver as I, SyncUrlConfig as J, SyncTransport as K, ServerEvent as L, ResetLocalReplicaOptions as M, ResetLocalReplicaResult as N, PushEventsFn as O, RetryConfig as P, EventSourcedLogger as Q, SyncHandlersConfig as R, PersistedCollectionPersistence$1 as S, PullEventsFn as T, SyncPushPreset as U, SyncPhase as V, SyncResult as W, UpcastEventFn as X, UnknownEventHandling as Y, UpcastableEvent as Z, ManualSyncResult as _, CollectionMap as a, OutboxEntry as b, DeadLetterReason as c, EventSourcedHooks as d, CreateCollectionFn as et, EventSourcedOptions as f, InferState as g, InferKey as h, CollectionIndexDef as i, ReservedCollections as j, PushFailure as k, EventSourcedDB as l, InboxEntry as m, CollectionDef as n, InjectedModuleFn as nt, DeadLetterDirection as o, EventSourcedSharedOptions as p, SyncTrigger as q, CollectionIndexConstructor as r, PersistedCollectionOptionsFn as rt, DeadLetterEntry as s, BackendMismatchPolicy as t, InjectedCreateCollection as tt, EventSourcedDBConfig as u, MutationType as v, PruneResult as w, OutboxSyncStatus as x, OutboundEvent as y, SyncLock as z };
891
+ //# sourceMappingURL=types-Dc-_92xv.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types-DrV5f9_t.d.mts","names":[],"sources":["../src/core/persisted-collection.ts","../src/utils/logger.ts","../src/core/types.ts"],"mappings":"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"}
1
+ {"version":3,"file":"types-Dc-_92xv.d.mts","names":[],"sources":["../src/core/persisted-collection.ts","../src/utils/logger.ts","../src/core/types.ts"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "event-sourced-collection",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "Event-sourced local-first database built on TanStack DB persistence",
5
5
  "keywords": [
6
6
  "event-sourcing",
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-event-sourced-db-handle-CD8WSjXW.mjs","names":[],"sources":["../src/internal/constants.ts","../src/internal/hooks.ts","../src/internal/replay.ts","../src/internal/sync-meta.ts","../src/internal/pull.ts","../src/core/sync.ts","../src/internal/push.ts","../src/core/sync-presets.ts","../src/internal/serial-queue.ts","../src/utils/logger.ts","../src/utils/uuid.ts","../src/core/create-event-sourced-db.ts","../src/core/lazy-singleton.ts","../src/core/create-event-sourced-db-handle.ts"],"sourcesContent":["export const OUTBOX_ID = \"outbox\";\nexport const INBOX_ID = \"inbox\";\nexport const DEADLETTER_ID = \"deadletter\";\nexport const SYNCMETA_ID = \"syncmeta\";\nexport const ROWVERSIONS_ID = \"rowversions\";\n\n/** `syncmeta` holds exactly one row; this is its key. */\nexport const SYNCMETA_KEY = \"singleton\";\n\nexport const RESERVED_IDS: ReadonlySet<string> = new Set([\n OUTBOX_ID,\n INBOX_ID,\n DEADLETTER_ID,\n SYNCMETA_ID,\n ROWVERSIONS_ID,\n]);\n\nexport const DEFAULT_PUSH_BATCH_SIZE = 20;\nexport const MIN_PUSH_BATCH_SIZE = 1;\nexport const MAX_PUSH_BATCH_SIZE = 100;\nexport const PAYLOAD_TOO_LARGE_ERROR_CODE = \"PAYLOAD_TOO_LARGE\";\nexport const DEFAULT_MAX_ATTEMPTS = 8;\nexport const DEFAULT_BASE_DELAY_MS = 1_000;\nexport const DEFAULT_MAX_DELAY_MS = 5 * 60 * 1_000;\nexport const DEFAULT_EVENT_SCHEMA_VERSION = 1;\n\nexport const SYNC_LOCK_PREFIX = \"event-sourced-sync\";\n\n/** Server error code that routes a rejected event to the dead-letter queue as a conflict. */\nexport const CONFLICT_ERROR_CODE = \"CONFLICT\";\n","import type { EventSourcedHooks } from \"../core/types\";\nimport type { EventSourcedLogger } from \"../utils/logger\";\n\n/**\n * Invokes a lifecycle hook. A hook that throws is logged and swallowed — user\n * observation code must never be able to fail a sync.\n *\n * @example\n * ```ts\n * const emit: EmitHook = createHookEmitter(\n * { onSyncStart: ({ trigger }) => console.info(\"sync\", trigger) },\n * log,\n * )\n *\n * emit(\"onSyncStart\", { trigger: \"manualSync\" })\n * emit(\"onDeadLetter\", deadLetterEntry) // no-op when that hook is omitted\n * ```\n */\nexport type EmitHook = <TName extends keyof EventSourcedHooks>(\n name: TName,\n argument: Parameters<NonNullable<EventSourcedHooks[TName]>>[0],\n) => void;\n\n/**\n * Builds an {@link EmitHook} bound to the user-supplied {@link EventSourcedHooks}.\n *\n * @example A throwing hook is logged, then ignored\n * ```ts\n * import { createHookEmitter } from \"./hooks\"\n *\n * const emit = createHookEmitter(\n * {\n * onDeadLetter: () => {\n * throw new Error(\"toast failed\")\n * },\n * },\n * log,\n * )\n *\n * emit(\"onDeadLetter\", entry) // sync continues; log.error(\"lifecycle hook threw\", …)\n * ```\n */\nexport function createHookEmitter(\n hooks: EventSourcedHooks | undefined,\n log: EventSourcedLogger,\n): EmitHook {\n if (!hooks) return () => {};\n\n return (name, argument) => {\n const hook = hooks[name] as ((value: unknown) => void) | undefined;\n if (!hook) return;\n\n try {\n hook(argument);\n } catch (err) {\n log.error(\"lifecycle hook threw\", {\n hook: name,\n message: err instanceof Error ? err.message : String(err),\n });\n }\n };\n}\n","import type { Collection } from \"@tanstack/db\";\n\nimport type { DeadLetterEntry, InboxEntry, RowVersionEntry, UpcastableEvent } from \"../core/types\";\nimport { DEFAULT_EVENT_SCHEMA_VERSION, RESERVED_IDS } from \"./constants\";\nimport type { ReplayableEvent, ReplayContext, ReplayOutcome } from \"./types\";\n\nexport type ReplaySummary = { applied: number; skipped: number; deadLettered: number };\n\nexport function rowVersionId(collectionId: string, key: string | number): string {\n return `${collectionId}::${String(key)}`;\n}\n\n/**\n * Records the version a row is now at. Used to stamp `baseVersion` on future\n * local mutations so the server can detect writes authored against stale state.\n */\nexport async function recordRowVersion(\n rowversions: Collection<RowVersionEntry, string>,\n collectionId: string,\n key: string | number,\n version: string,\n globalSeq: number | null,\n): Promise<void> {\n const id = rowVersionId(collectionId, key);\n\n if (rowversions.has(id)) {\n await rowversions.update(id, (draft) => {\n draft.version = version;\n draft.globalSeq = globalSeq;\n }).isPersisted.promise;\n return;\n }\n\n await rowversions.insert({ id, collectionId, key, version, globalSeq }).isPersisted.promise;\n}\n\nexport function readRowVersion(\n rowversions: Collection<RowVersionEntry, string>,\n collectionId: string,\n key: string | number,\n): string | null {\n return rowversions.get(rowVersionId(collectionId, key))?.version ?? null;\n}\n\n/**\n * After a CONFLICT dead-letter, undo the optimistic `recordRowVersion` that\n * stamped the rejected event id as head. Restores `baseVersion`, or deletes\n * the index row when the mutation was authored against an unknown row.\n */\nexport async function restoreRowVersionAfterConflict(\n rowversions: Collection<RowVersionEntry, string>,\n collectionId: string,\n key: string | number,\n baseVersion: string | null,\n): Promise<void> {\n const id = rowVersionId(collectionId, key);\n\n if (baseVersion === null) {\n if (rowversions.has(id)) {\n await rowversions.delete(id).isPersisted.promise;\n }\n return;\n }\n\n await recordRowVersion(rowversions, collectionId, key, baseVersion, null);\n}\n\nexport async function replayEvent(\n context: ReplayContext,\n event: ReplayableEvent,\n): Promise<ReplayOutcome> {\n const { targets, log } = context;\n const { eventId, collectionId } = event;\n\n // A reserved target can never become valid, so retrying it would wedge the\n // pipeline forever. Unknown collections can become valid after a client\n // upgrade, so those honour unknownEventHandling.\n if (RESERVED_IDS.has(collectionId)) {\n const reason = `reserved collection \"${collectionId}\"`;\n log.warn(\"replay skipped: reserved collection\", {\n eventId,\n collectionId,\n type: event.type,\n key: event.key,\n });\n context.emit(\"onEventSkipped\", { eventId, collectionId, reason });\n return { status: \"skipped\", reason };\n }\n\n const migrated = upcast(context, event);\n if (migrated.status !== \"ok\") return migrated.outcome;\n\n const target = targets[collectionId];\n if (!target) {\n return unresolvable(context, event, `unknown collection \"${collectionId}\"`, {\n knownCollections: Object.keys(targets).filter((id) => !RESERVED_IDS.has(id)),\n });\n }\n\n if (!target.utils.acceptMutations) {\n return unresolvable(context, event, `collection \"${collectionId}\" is missing acceptMutations`, {\n targetId: target.id,\n });\n }\n\n const { type, key, payload } = migrated.event;\n\n log.debug(\"replay applying mutation\", { eventId, collectionId, type, key });\n\n try {\n await target.utils.acceptMutations({\n mutations: [\n {\n mutationId: eventId,\n type,\n key,\n modified: payload,\n original: payload,\n changes: payload,\n collection: target,\n },\n ],\n });\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n log.error(\"replay mutation failed\", {\n eventId,\n collectionId,\n type,\n key,\n message: error.message,\n });\n // Reported rather than thrown: one unapplicable event must not be able to\n // wedge the pull pipeline behind it forever.\n return { status: \"failed\", error };\n }\n\n if (context.conflictDetection) {\n await recordRowVersion(\n context.rowversions,\n collectionId,\n key,\n eventId,\n event.globalSeq ?? null,\n );\n }\n\n log.info(\"replay mutation accepted\", { eventId, collectionId, type, key });\n context.emit(\"onEventApplied\", { eventId, collectionId, type, key });\n\n return { status: \"applied\" };\n}\n\ntype UpcastResult =\n | { status: \"ok\"; event: UpcastableEvent }\n | { status: \"blocked\"; outcome: ReplayOutcome };\n\n/**\n * Brings an event authored under a different schema version into the current\n * shape. Without an upcaster, older events are applied as-is (best effort) but\n * newer ones are refused, since this build cannot know what the fields mean.\n */\nfunction upcast(context: ReplayContext, event: ReplayableEvent): UpcastResult {\n const version = event.schemaVersion ?? DEFAULT_EVENT_SCHEMA_VERSION;\n\n const current: UpcastableEvent = {\n eventId: event.eventId,\n collectionId: event.collectionId,\n type: event.type,\n key: event.key,\n payload: event.payload,\n previous: event.previous ?? null,\n schemaVersion: version,\n };\n\n if (version === context.eventSchemaVersion) {\n return { status: \"ok\", event: current };\n }\n\n if (context.upcastEvent) {\n const migrated = context.upcastEvent(current);\n\n if (!migrated) {\n const reason = `upcaster dropped schema version ${version}`;\n context.log.warn(\"replay skipped: upcaster dropped event\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n schemaVersion: version,\n });\n context.emit(\"onEventSkipped\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n reason,\n });\n return { status: \"blocked\", outcome: { status: \"skipped\", reason } };\n }\n\n return { status: \"ok\", event: migrated };\n }\n\n if (version > context.eventSchemaVersion) {\n return {\n status: \"blocked\",\n outcome: unresolvable(\n context,\n event,\n `event schema version ${version} is newer than supported version ${context.eventSchemaVersion}`,\n {},\n ),\n };\n }\n\n context.log.warn(\"replaying older event schema version without an upcaster\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n schemaVersion: version,\n currentVersion: context.eventSchemaVersion,\n });\n\n return { status: \"ok\", event: current };\n}\n\nfunction unresolvable(\n context: ReplayContext,\n event: ReplayableEvent,\n reason: string,\n details: Record<string, unknown>,\n): ReplayOutcome {\n const halt = context.unknownEventHandling === \"fail\";\n\n context.log.warn(halt ? \"replay halted\" : \"replay skipped\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n type: event.type,\n key: event.key,\n reason,\n ...details,\n });\n\n if (halt) return { status: \"halted\", reason };\n\n context.emit(\"onEventSkipped\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n reason,\n });\n\n return { status: \"skipped\", reason };\n}\n\n/**\n * What to do after a replay threw: come back to it next sync, or give up and\n * park it in the dead-letter queue.\n */\nexport type ReplayFailureResolution = \"retry\" | \"deadLettered\";\n\n/**\n * Records a failed replay against its inbox row and, once the attempt budget is\n * spent, moves the event to the dead-letter queue and resolves the inbox row so\n * the cursor can advance past it. Otherwise a single event the local schema\n * cannot accept blocks every event behind it, permanently.\n */\nexport async function handleReplayFailure(\n context: ReplayContext,\n inbox: Collection<InboxEntry, string>,\n event: ReplayableEvent,\n error: Error,\n now: number,\n): Promise<ReplayFailureResolution> {\n const { deadletter, maxReplayAttempts, log } = context;\n const existing = inbox.get(event.eventId);\n const attemptCount = (existing?.attemptCount ?? 0) + 1;\n\n if (existing) {\n await inbox.update(event.eventId, (draft) => {\n draft.attemptCount = attemptCount;\n draft.lastError = error.message;\n }).isPersisted.promise;\n }\n\n if (attemptCount < maxReplayAttempts) {\n log.warn(\"replay failed; retrying on a later sync\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n attemptCount,\n maxReplayAttempts,\n message: error.message,\n });\n\n return \"retry\";\n }\n\n const reason = `replay failed after ${attemptCount} attempts: ${error.message}`;\n\n if (!deadletter.has(event.eventId)) {\n const record: DeadLetterEntry = {\n eventId: event.eventId,\n collectionId: event.collectionId,\n type: event.type,\n key: event.key,\n payload: event.payload,\n previous: event.previous ?? null,\n txId: null,\n clientId: existing?.clientId ?? null,\n schemaVersion: event.schemaVersion ?? DEFAULT_EVENT_SCHEMA_VERSION,\n timestamp: existing?.timestamp ?? now,\n localSeq: null,\n globalSeq: event.globalSeq ?? null,\n direction: \"inbound\",\n reason: \"replayFailed\",\n message: error.message,\n code: null,\n attemptCount,\n failedAt: now,\n };\n\n await deadletter.insert(record).isPersisted.promise;\n context.emit(\"onDeadLetter\", record);\n }\n\n if (existing) {\n await resolveInboxEntry(inbox, event.eventId, { status: \"skipped\", reason });\n }\n\n log.warn(\"inbound event dead-lettered\", {\n eventId: event.eventId,\n collectionId: event.collectionId,\n attemptCount,\n message: error.message,\n });\n\n return \"deadLettered\";\n}\n\n/**\n * Marks an inbox row as resolved — either applied or deliberately skipped.\n * Skipped rows still count as resolved so the pull cursor can move past them.\n */\nexport async function resolveInboxEntry(\n inbox: Collection<InboxEntry, string>,\n eventId: string,\n outcome: Extract<ReplayOutcome, { status: \"applied\" | \"skipped\" }>,\n): Promise<void> {\n await inbox.update(eventId, (draft) => {\n draft.sync = true;\n draft.skipped = outcome.status === \"skipped\";\n draft.skipReason = outcome.status === \"skipped\" ? outcome.reason : null;\n }).isPersisted.promise;\n}\n\nexport async function replayInbox(\n inbox: Collection<InboxEntry, string>,\n context: ReplayContext,\n): Promise<ReplaySummary> {\n const { log } = context;\n\n const pending = [...inbox.state.values()]\n .filter((entry) => !entry.sync)\n .sort((a, b) => a.globalSeq - b.globalSeq);\n\n log.info(\"pending inbox replay started\", { pendingCount: pending.length });\n\n let applied = 0;\n let skipped = 0;\n let deadLettered = 0;\n\n for (const entry of pending) {\n const outcome = await replayEvent(context, entry);\n\n if (outcome.status === \"halted\") break;\n\n if (outcome.status === \"failed\") {\n const resolution = await handleReplayFailure(\n context,\n inbox,\n entry,\n outcome.error,\n Date.now(),\n );\n\n // Still retryable: stop here so events stay in order until it resolves.\n if (resolution === \"retry\") break;\n\n deadLettered++;\n continue;\n }\n\n await resolveInboxEntry(inbox, entry.eventId, outcome);\n\n if (outcome.status === \"skipped\") {\n skipped++;\n continue;\n }\n\n applied++;\n\n log.info(\"pending inbox replay applied\", {\n eventId: entry.eventId,\n globalSeq: entry.globalSeq,\n collectionId: entry.collectionId,\n });\n }\n\n log.info(\"pending inbox replay finished\", { applied, skipped, deadLettered });\n\n return { applied, skipped, deadLettered };\n}\n","import type { Collection } from \"@tanstack/db\";\n\nimport type { InboxEntry, SyncMetaEntry } from \"../core/types\";\nimport { SYNCMETA_KEY } from \"./constants\";\n\nconst EMPTY: SyncMetaEntry = {\n id: SYNCMETA_KEY,\n backendId: null,\n clientId: null,\n pullCursor: 0,\n lastSyncAt: null,\n lastError: null,\n};\n\nexport function readSyncMeta(syncmeta: Collection<SyncMetaEntry, string>): SyncMetaEntry {\n return syncmeta.get(SYNCMETA_KEY) ?? EMPTY;\n}\n\nexport async function ensureSyncMeta(syncmeta: Collection<SyncMetaEntry, string>): Promise<void> {\n if (syncmeta.has(SYNCMETA_KEY)) return;\n await syncmeta.insert({ ...EMPTY }).isPersisted.promise;\n}\n\nasync function patch(\n syncmeta: Collection<SyncMetaEntry, string>,\n apply: (draft: SyncMetaEntry) => void,\n): Promise<void> {\n await ensureSyncMeta(syncmeta);\n await syncmeta.update(SYNCMETA_KEY, apply).isPersisted.promise;\n}\n\nexport function readBackendId(syncmeta: Collection<SyncMetaEntry, string>): string | null {\n return readSyncMeta(syncmeta).backendId;\n}\n\n/**\n * Resolves this device's identity, persisting it on first run so it survives\n * reloads. Without that, a client stops recognising its own pulled-back events\n * as soon as the outbox is pruned and will replay its own history as if it were\n * someone else's.\n *\n * Preference: explicit `configured` id, then the stored `syncmeta.clientId`,\n * then `generate()`.\n *\n * @example First open generates and stores an id; the next open reuses it\n * ```ts\n * import { resolveClientId } from \"./sync-meta\"\n *\n * const clientId = await resolveClientId(\n * db.collections.syncmeta,\n * undefined,\n * () => crypto.randomUUID(),\n * )\n * // later, after close + reopen on the same file:\n * const again = await resolveClientId(db.collections.syncmeta, undefined, () => {\n * throw new Error(\"should not generate a second id\")\n * })\n * // again === clientId\n * ```\n */\nexport async function resolveClientId(\n syncmeta: Collection<SyncMetaEntry, string>,\n configured: string | undefined,\n generate: () => string,\n): Promise<string> {\n const stored = readSyncMeta(syncmeta).clientId ?? null;\n const clientId = configured ?? stored ?? generate();\n\n if (stored !== clientId) {\n await patch(syncmeta, (draft) => {\n draft.clientId = clientId;\n });\n }\n\n return clientId;\n}\n\n/**\n * The cursor lives in `syncmeta` so the inbox can be pruned freely. Older\n * databases predate that row, so fall back to the highest resolved inbox\n * sequence and let the first successful pull persist it.\n *\n * @example\n * ```ts\n * import { readPullCursor } from \"./sync-meta\"\n *\n * const since = readPullCursor(db.collections.syncmeta, db.collections.inbox)\n * const page = await transport.pull(since)\n * ```\n */\nexport function readPullCursor(\n syncmeta: Collection<SyncMetaEntry, string>,\n inbox: Collection<InboxEntry, string>,\n): number {\n let cursor = readSyncMeta(syncmeta).pullCursor;\n\n for (const entry of inbox.state.values()) {\n if (entry.sync && entry.globalSeq > cursor) cursor = entry.globalSeq;\n }\n\n return cursor;\n}\n\nexport async function writePullCursor(\n syncmeta: Collection<SyncMetaEntry, string>,\n cursor: number,\n): Promise<void> {\n await patch(syncmeta, (draft) => {\n draft.pullCursor = cursor;\n });\n}\n\nexport async function writeBackendId(\n syncmeta: Collection<SyncMetaEntry, string>,\n backendId: string,\n): Promise<void> {\n await patch(syncmeta, (draft) => {\n draft.backendId = backendId;\n });\n}\n\nexport async function writeSyncOutcome(\n syncmeta: Collection<SyncMetaEntry, string>,\n lastSyncAt: number,\n lastError: string | null,\n): Promise<void> {\n await patch(syncmeta, (draft) => {\n draft.lastSyncAt = lastSyncAt;\n draft.lastError = lastError;\n });\n}\n","import type { Collection } from \"@tanstack/db\";\n\nimport type { NormalizedSyncTransport } from \"../core/sync\";\nimport type {\n BackendMismatchPolicy,\n InboxEntry,\n OutboxEntry,\n ServerEvent,\n SyncMetaEntry,\n} from \"../core/types\";\nimport { DEFAULT_EVENT_SCHEMA_VERSION } from \"./constants\";\nimport { handleReplayFailure, replayEvent, resolveInboxEntry } from \"./replay\";\nimport { readBackendId, readPullCursor, writeBackendId, writePullCursor } from \"./sync-meta\";\nimport type { ReplayContext } from \"./types\";\n\nexport type PullOutcome = {\n pulled: number;\n skipped: number;\n deadLettered: number;\n /** Outbox events put back in the queue by a backend reset, awaiting a push. */\n requeued: number;\n};\n\n/**\n * Thrown when `backendMismatch` is `\"fail\"` and the server reports a different\n * `backendId` than this client last synced with (wiped or swapped event store).\n *\n * @example\n * ```ts\n * import { BackendMismatchError } from \"event-sourced-collection\"\n *\n * const result = await db.sync()\n * const mismatch = result.errors.find((error) => error instanceof BackendMismatchError)\n * if (mismatch) {\n * console.error(\"backend changed\", mismatch.expected, mismatch.received)\n * }\n * ```\n */\nexport class BackendMismatchError extends Error {\n constructor(\n readonly expected: string | null,\n readonly received: string,\n ) {\n super(\n `Sync backend identity changed (was \"${expected ?? \"unknown\"}\", now \"${received}\"). ` +\n `The local pull cursor no longer refers to this backend.`,\n );\n this.name = \"BackendMismatchError\";\n }\n}\n\nexport type PullArgs = {\n outbox: Collection<OutboxEntry, string>;\n inbox: Collection<InboxEntry, string>;\n syncmeta: Collection<SyncMetaEntry, string>;\n pull: NonNullable<NormalizedSyncTransport[\"pull\"]>;\n clientId: string;\n pullOverlap: number;\n /** When false, local-origin pulls advance the cursor without inbox rows. */\n recordLocalEchoes: boolean;\n backendMismatch: BackendMismatchPolicy;\n context: ReplayContext;\n};\n\nexport async function pullInbox(args: PullArgs): Promise<PullOutcome> {\n const { outbox, inbox, syncmeta, pull, clientId, pullOverlap, recordLocalEchoes, context } =\n args;\n const { log } = context;\n\n let pulled = 0;\n let skipped = 0;\n let deadLettered = 0;\n let requeued = 0;\n let hasMore = true;\n let cursor = Math.max(0, readPullCursor(syncmeta, inbox) - pullOverlap);\n let identityChecked = false;\n\n while (hasMore) {\n log.debug(\"pull inbox page\", { since: cursor });\n\n const response = await pull(cursor);\n\n log.debug(\"pull inbox response\", {\n since: cursor,\n eventCount: response.events.length,\n hasMore: response.hasMore,\n cursor: response.cursor,\n backendId: response.backendId,\n });\n\n if (!identityChecked && response.backendId !== undefined) {\n identityChecked = true;\n\n const reconciled = await reconcileBackendIdentity(args, response.backendId);\n if (reconciled.reset) {\n requeued += reconciled.requeued;\n cursor = 0;\n continue;\n }\n }\n\n if (response.events.length === 0) break;\n\n const sorted = [...response.events].sort((a, b) => a.globalSeq - b.globalSeq);\n let halted = false;\n\n for (const event of sorted) {\n if (isLocalOrigin(event, outbox, clientId)) {\n if (recordLocalEchoes) {\n await markInboxEventResolved(inbox, event);\n }\n\n log.debug(\"pull skipped: event originated locally\", {\n eventId: event.eventId,\n globalSeq: event.globalSeq,\n recorded: recordLocalEchoes,\n });\n continue;\n }\n\n const existing = inbox.get(event.eventId);\n if (existing?.sync) {\n log.debug(\"pull skipped: inbox already resolved\", {\n eventId: event.eventId,\n globalSeq: event.globalSeq,\n });\n continue;\n }\n\n if (!existing) {\n await inbox.insert(toInboxEntry(event, false)).isPersisted.promise;\n log.debug(\"inbox entry inserted\", {\n eventId: event.eventId,\n globalSeq: event.globalSeq,\n collectionId: event.collectionId,\n });\n }\n\n const outcome = await replayEvent(context, event);\n\n if (outcome.status === \"halted\") {\n halted = true;\n break;\n }\n\n if (outcome.status === \"failed\") {\n const resolution = await handleReplayFailure(\n context,\n inbox,\n event,\n outcome.error,\n Date.now(),\n );\n\n if (resolution === \"retry\") {\n halted = true;\n break;\n }\n\n deadLettered++;\n continue;\n }\n\n await resolveInboxEntry(inbox, event.eventId, outcome);\n\n if (outcome.status === \"skipped\") {\n skipped++;\n continue;\n }\n\n log.info(\"pull replay applied\", {\n eventId: event.eventId,\n globalSeq: event.globalSeq,\n collectionId: event.collectionId,\n type: event.type,\n key: event.key,\n });\n\n pulled++;\n }\n\n // Leaving the cursor where it is means the halted event is retried on the\n // next sync rather than being stepped over.\n if (halted) break;\n\n const nextCursor = resolveNextCursor(cursor, sorted, response.cursor);\n\n if (nextCursor <= cursor) {\n log.warn(\"pull stopped: cursor did not advance\", {\n cursor,\n nextCursor,\n eventCount: sorted.length,\n });\n break;\n }\n\n cursor = nextCursor;\n await writePullCursor(syncmeta, cursor);\n hasMore = response.hasMore;\n }\n\n log.info(\"pull inbox finished\", { pulled, skipped, deadLettered, requeued, cursor });\n\n return { pulled, skipped, deadLettered, requeued };\n}\n\ntype ReconcileOutcome = { reset: false } | { reset: true; requeued: number };\n\n/**\n * Detects a wiped or swapped backend. Reports `reset` when the caller should\n * restart the pull from zero.\n */\nasync function reconcileBackendIdentity(\n args: PullArgs,\n received: string,\n): Promise<ReconcileOutcome> {\n const { syncmeta, inbox, backendMismatch, context } = args;\n const { log } = context;\n\n const stored = readBackendId(syncmeta);\n\n if (stored === received) return { reset: false };\n\n if (stored === null) {\n await writeBackendId(syncmeta, received);\n log.info(\"sync backend identity recorded\", { backendId: received });\n return { reset: false };\n }\n\n context.emit(\"onBackendMismatch\", {\n expected: stored,\n received,\n policy: backendMismatch,\n });\n\n if (backendMismatch === \"fail\") {\n throw new BackendMismatchError(stored, received);\n }\n\n if (backendMismatch === \"ignore\") {\n log.warn(\"sync backend identity changed; ignoring per configuration\", {\n expected: stored,\n received,\n });\n return { reset: false };\n }\n\n log.warn(\"sync backend identity changed; resetting pull cursor\", {\n expected: stored,\n received,\n });\n\n for (const entry of inbox.state.values()) {\n await inbox.delete(entry.eventId).isPersisted.promise;\n }\n\n const requeued = await requeueSyncedOutbox(args.outbox);\n\n await writeBackendId(syncmeta, received);\n await writePullCursor(syncmeta, 0);\n\n log.info(\"sync backend identity reset complete\", {\n backendId: received,\n inboxCleared: true,\n outboxRequeued: requeued,\n });\n\n return { reset: true, requeued };\n}\n\n/**\n * Marks previously confirmed outbox events as pending again. The new backend\n * has never seen them, so without this the client keeps local rows it believes\n * are safely synced and never uploads them again. Servers deduplicate by\n * `eventId`, so re-pushing to a *restored* backend is a no-op.\n *\n * `baseVersion` is cleared because it refers to event ids from the old\n * backend's history, which the new one cannot resolve.\n */\nasync function requeueSyncedOutbox(outbox: Collection<OutboxEntry, string>): Promise<number> {\n const synced = [...outbox.state.values()].filter((entry) => entry.sync);\n\n for (const entry of synced) {\n await outbox.update(entry.eventId, (draft) => {\n draft.sync = false;\n draft.syncStatus = \"pending\";\n draft.globalSeq = null;\n draft.baseVersion = null;\n draft.attemptCount = 0;\n draft.nextAttemptAt = null;\n draft.lastError = null;\n draft.lastErrorCode = null;\n draft.retryable = null;\n }).isPersisted.promise;\n }\n\n return synced.length;\n}\n\nfunction isLocalOrigin(\n event: ServerEvent,\n outbox: Collection<OutboxEntry, string>,\n clientId: string,\n): boolean {\n // clientId keeps origin detection working after the outbox has been pruned.\n return outbox.has(event.eventId) || event.clientId === clientId;\n}\n\nfunction resolveNextCursor(\n cursor: number,\n events: ReadonlyArray<ServerEvent>,\n serverCursor: string | undefined,\n): number {\n let next = cursor;\n\n for (const event of events) {\n if (event.globalSeq > next) next = event.globalSeq;\n }\n\n const parsed = Number(serverCursor);\n if (serverCursor !== undefined && Number.isFinite(parsed) && parsed > next) {\n next = parsed;\n }\n\n return next;\n}\n\nasync function markInboxEventResolved(\n inbox: Collection<InboxEntry, string>,\n event: ServerEvent,\n): Promise<void> {\n const existing = inbox.get(event.eventId);\n\n if (!existing) {\n await inbox.insert(toInboxEntry(event, true)).isPersisted.promise;\n return;\n }\n\n if (!existing.sync || existing.globalSeq !== event.globalSeq) {\n await inbox.update(event.eventId, (draft) => {\n draft.globalSeq = event.globalSeq;\n draft.sync = true;\n }).isPersisted.promise;\n }\n}\n\nexport function toInboxEntry(event: ServerEvent, sync: boolean): InboxEntry {\n return {\n eventId: event.eventId,\n globalSeq: event.globalSeq,\n collectionId: event.collectionId,\n type: event.type,\n key: event.key,\n payload: event.payload,\n previous: event.previous ?? null,\n clientId: event.clientId ?? null,\n schemaVersion: event.schemaVersion ?? DEFAULT_EVENT_SCHEMA_VERSION,\n timestamp: event.timestamp,\n sync,\n skipped: false,\n skipReason: null,\n attemptCount: 0,\n lastError: null,\n };\n}\n","import type {\n OutboundEvent,\n PullEventsFn,\n PullResponse,\n PushConfirmation,\n PushEventsFn,\n PushResponse,\n SyncHandlersConfig,\n SyncTransport,\n SyncUrlConfig,\n} from \"./types\";\n\nexport type NormalizedSyncTransport = {\n push?: PushEventsFn;\n pull?: (since: number) => Promise<PullResponse>;\n};\n\ntype HeaderConfig = SyncHandlersConfig[\"headers\"];\n\n/**\n * Builds a {@link SyncTransport} that POSTs outbound events and GETs\n * `pull?since=N`. Pass this as `sync` when you already have REST endpoints.\n *\n * @example\n * ```ts\n * import { createHttpTransport } from \"event-sourced-collection\"\n * import { createBrowserEventSourcedDB } from \"event-sourced-collection/browser\"\n *\n * const sync = createHttpTransport({\n * push: \"/api/sync/events\",\n * pull: \"/api/sync/events\",\n * headers: () => ({ Authorization: `Bearer ${localStorage.getItem(\"token\") ?? \"\"}` }),\n * })\n *\n * const { ensureDb } = createBrowserEventSourcedDB({\n * databaseName: \"app.sqlite\",\n * collections: { todos: { getKey: (todo: { id: string }) => todo.id } },\n * sync,\n * modules: async () => {\n * const { createCollection } = await import(\"@tanstack/db\")\n * const persistence = await import(\"@tanstack/browser-db-sqlite-persistence\")\n * return { createCollection, ...persistence }\n * },\n * })\n * ```\n */\nexport function createHttpTransport(config: SyncUrlConfig): SyncTransport {\n return {\n push: createHttpPushEvents(config.push, config.headers),\n pull: createHttpPullEvents(config.pull, config.headers),\n };\n}\n\nexport function createSyncTransport(\n config?: SyncHandlersConfig | SyncUrlConfig | SyncTransport,\n): NormalizedSyncTransport | null {\n if (!config) {\n return null;\n }\n\n if (isTransport(config)) {\n return {\n push: config.push,\n pull: config.pull,\n };\n }\n\n const pushUrl = getPushUrl(config);\n const pullUrl = getPullUrl(config);\n\n const push =\n \"pushEvents\" in config && config.pushEvents\n ? config.pushEvents\n : pushUrl\n ? createHttpPushEvents(pushUrl, config.headers)\n : undefined;\n\n const pullEvents = \"pullEvents\" in config ? config.pullEvents : undefined;\n const pull = pullEvents\n ? createPullFromHandler(pullEvents)\n : pullUrl\n ? createHttpPullEvents(pullUrl, config.headers)\n : undefined;\n\n if (!push && !pull) {\n return null;\n }\n\n return { push, pull };\n}\n\nexport function normalizePushResponse(\n response: PushResponse | ReadonlyArray<PushConfirmation>,\n): PushResponse {\n if (isConfirmationArray(response)) {\n return { confirmed: response };\n }\n\n return {\n confirmed: response.confirmed,\n failed: response.failed,\n };\n}\n\nfunction isConfirmationArray(\n response: PushResponse | ReadonlyArray<PushConfirmation>,\n): response is ReadonlyArray<PushConfirmation> {\n return Array.isArray(response);\n}\n\nfunction createHttpPushEvents(url: string, headers: HeaderConfig): PushEventsFn {\n return async (events: ReadonlyArray<OutboundEvent>): Promise<PushResponse> => {\n if (events.length === 0) return { confirmed: [] };\n\n const resolvedHeaders = await resolveHeaders(headers);\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...resolvedHeaders },\n body: JSON.stringify(events),\n });\n\n if (!response.ok) {\n throw new SyncPushError(response.status, await response.text());\n }\n\n return response.json() as Promise<PushResponse>;\n };\n}\n\nfunction createPullFromHandler(pullEvents: PullEventsFn): (since: number) => Promise<PullResponse> {\n return (since: number) => pullEvents({ since });\n}\n\nfunction createHttpPullEvents(\n url: string,\n headers: HeaderConfig,\n): (since: number) => Promise<PullResponse> {\n return async (since: number): Promise<PullResponse> => {\n const resolvedHeaders = await resolveHeaders(headers);\n const pullUrl = appendSince(url, since);\n\n const response = await fetch(pullUrl, {\n headers: { Accept: \"application/json\", ...resolvedHeaders },\n });\n\n if (!response.ok) {\n throw new SyncPullError(response.status, await response.text());\n }\n\n return response.json() as Promise<PullResponse>;\n };\n}\n\nasync function resolveHeaders(headers: HeaderConfig): Promise<Record<string, string>> {\n if (!headers) return {};\n if (typeof headers === \"function\") return headers();\n return headers;\n}\n\nfunction appendSince(url: string, since: number): string {\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${separator}since=${encodeURIComponent(String(since))}`;\n}\n\nfunction getPushUrl(config: SyncHandlersConfig | SyncUrlConfig): string | undefined {\n if (\"pushUrl\" in config && config.pushUrl) {\n return config.pushUrl;\n }\n\n if (\"push\" in config && typeof config.push === \"string\") {\n return config.push;\n }\n\n return undefined;\n}\n\nfunction getPullUrl(config: SyncHandlersConfig | SyncUrlConfig): string | undefined {\n if (\"pullUrl\" in config && config.pullUrl) {\n return config.pullUrl;\n }\n\n if (\"pull\" in config && typeof config.pull === \"string\") {\n return config.pull;\n }\n\n return undefined;\n}\n\n/**\n * Thrown when the HTTP push endpoint returns a non-OK status.\n *\n * @example\n * ```ts\n * import { createHttpTransport, SyncPushError } from \"event-sourced-collection\"\n *\n * const sync = createHttpTransport({\n * push: \"/api/sync/events\",\n * pull: \"/api/sync/events\",\n * })\n *\n * try {\n * await sync.push(events)\n * } catch (error) {\n * if (error instanceof SyncPushError) {\n * console.error(error.status, error.body)\n * }\n * }\n * ```\n */\nexport class SyncPushError extends Error {\n constructor(\n public readonly status: number,\n public readonly body: string,\n ) {\n super(`Event push failed: HTTP ${status}`);\n this.name = \"SyncPushError\";\n }\n}\n\n/**\n * Thrown when the HTTP pull endpoint returns a non-OK status.\n *\n * @example\n * ```ts\n * import { createHttpTransport, SyncPullError } from \"event-sourced-collection\"\n *\n * const sync = createHttpTransport({\n * push: \"/api/sync/events\",\n * pull: \"/api/sync/events\",\n * })\n *\n * try {\n * await sync.pull(0)\n * } catch (error) {\n * if (error instanceof SyncPullError) {\n * console.error(error.status, error.body)\n * }\n * }\n * ```\n */\nexport class SyncPullError extends Error {\n constructor(\n public readonly status: number,\n public readonly body: string,\n ) {\n super(`Event pull failed: HTTP ${status}`);\n this.name = \"SyncPullError\";\n }\n}\n\nexport function isTransport(\n value: SyncHandlersConfig | SyncUrlConfig | SyncTransport,\n): value is SyncTransport {\n return \"push\" in value && typeof value.push === \"function\";\n}\n","import type { Collection } from \"@tanstack/db\";\n\nimport type { NormalizedSyncTransport } from \"../core/sync\";\nimport { normalizePushResponse } from \"../core/sync\";\nimport type {\n DeadLetterEntry,\n DeadLetterReason,\n OutboundEvent,\n OutboxEntry,\n PushConfirmation,\n PushFailure,\n RowVersionEntry,\n} from \"../core/types\";\nimport type { EventSourcedLogger } from \"../utils/logger\";\nimport {\n CONFLICT_ERROR_CODE,\n DEFAULT_EVENT_SCHEMA_VERSION,\n PAYLOAD_TOO_LARGE_ERROR_CODE,\n} from \"./constants\";\nimport type { EmitHook } from \"./hooks\";\nimport { restoreRowVersionAfterConflict } from \"./replay\";\nimport type { ResolvedRetryConfig } from \"./types\";\n\nexport type PushOutcome = {\n pushed: number;\n deadLettered: number;\n /**\n * Set when a batch failed at the transport level. Reported rather than thrown\n * so the counts from batches that already succeeded are not lost.\n */\n error?: Error;\n};\n\nexport type PushArgs = {\n outbox: Collection<OutboxEntry, string>;\n deadletter: Collection<DeadLetterEntry, string>;\n rowversions: Collection<RowVersionEntry, string>;\n push: NonNullable<NormalizedSyncTransport[\"push\"]>;\n batchSize: number;\n /** JSON byte cap per request; `null` means unlimited. */\n maxBytes: number | null;\n retry: ResolvedRetryConfig;\n now: number;\n emit: EmitHook;\n log: EventSourcedLogger;\n};\n\n/**\n * Backoff for attempt N, doubling from `baseDelayMs` and capped at `maxDelayMs`.\n * Deliberately jitter-free so retry scheduling stays reproducible in tests; if\n * you have many clients hitting one server, add jitter in your push handler.\n */\nexport function backoffDelay(attemptCount: number, retry: ResolvedRetryConfig): number {\n const exponent = Math.max(0, attemptCount - 1);\n const raw = retry.baseDelayMs * 2 ** exponent;\n return Math.min(retry.maxDelayMs, raw);\n}\n\nfunction isDue(entry: OutboxEntry, now: number): boolean {\n if (entry.sync) return false;\n // A permanent rejection is dead-lettered rather than parked, so anything still\n // marked failed here is retryable and just waiting for its backoff window.\n if (entry.syncStatus === \"failed\" && entry.retryable !== true) return false;\n return (entry.nextAttemptAt ?? 0) <= now;\n}\n\nfunction byLocalSeq(a: OutboxEntry, b: OutboxEntry): number {\n if (a.localSeq !== b.localSeq) return a.localSeq - b.localSeq;\n // localSeq can collide across tabs; eventId is a uuidv7 so it breaks the tie\n // in creation order.\n return a.eventId < b.eventId ? -1 : a.eventId > b.eventId ? 1 : 0;\n}\n\nexport function toOutboundEvent(entry: OutboxEntry): OutboundEvent {\n return {\n eventId: entry.eventId,\n collectionId: entry.collectionId,\n type: entry.type,\n key: entry.key,\n payload: entry.payload,\n previous: entry.previous ?? null,\n txId: entry.txId,\n clientId: entry.clientId,\n // Rows written before these fields existed are still in persisted outboxes.\n schemaVersion: entry.schemaVersion ?? DEFAULT_EVENT_SCHEMA_VERSION,\n baseVersion: entry.baseVersion ?? null,\n timestamp: entry.timestamp,\n };\n}\n\nexport async function deadLetter(\n deadletter: Collection<DeadLetterEntry, string>,\n outbox: Collection<OutboxEntry, string>,\n entry: OutboxEntry,\n reason: DeadLetterReason,\n message: string,\n code: string | null,\n now: number,\n emit: EmitHook,\n log: EventSourcedLogger,\n rowversions?: Collection<RowVersionEntry, string>,\n): Promise<void> {\n const record: DeadLetterEntry = {\n eventId: entry.eventId,\n collectionId: entry.collectionId,\n type: entry.type,\n key: entry.key,\n payload: entry.payload,\n previous: entry.previous ?? null,\n txId: entry.txId,\n clientId: entry.clientId,\n schemaVersion: entry.schemaVersion ?? DEFAULT_EVENT_SCHEMA_VERSION,\n baseVersion: entry.baseVersion ?? null,\n timestamp: entry.timestamp,\n localSeq: entry.localSeq,\n globalSeq: entry.globalSeq ?? null,\n direction: \"outbound\",\n reason,\n message,\n code,\n attemptCount: entry.attemptCount,\n failedAt: now,\n };\n\n if (!deadletter.has(entry.eventId)) {\n await deadletter.insert(record).isPersisted.promise;\n }\n\n if (outbox.has(entry.eventId)) {\n await outbox.delete(entry.eventId).isPersisted.promise;\n }\n\n if (reason === \"conflict\" && rowversions) {\n await restoreRowVersionAfterConflict(\n rowversions,\n entry.collectionId,\n entry.key,\n entry.baseVersion ?? null,\n );\n }\n\n log.warn(\"event dead-lettered\", {\n eventId: entry.eventId,\n collectionId: entry.collectionId,\n reason,\n message,\n code,\n attemptCount: entry.attemptCount,\n });\n\n emit(\"onDeadLetter\", record);\n}\n\n/** All events of one transaction, plus the JSON bytes they add to a request body. */\ntype TxGroup = { entries: OutboxEntry[]; bytes: number };\n\ntype Batch = { groups: TxGroup[]; count: number; bytes: number };\n\nconst utf8 = new TextEncoder();\n\nfunction jsonBytes(entry: OutboxEntry): number {\n return utf8.encode(JSON.stringify(toOutboundEvent(entry))).length;\n}\n\n/** Events are ordered by localSeq, so one transaction's events are adjacent. */\nfunction groupByTransaction(events: ReadonlyArray<OutboxEntry>, measure: boolean): TxGroup[] {\n const groups: TxGroup[] = [];\n\n for (let index = 0; index < events.length;) {\n const txId = events[index]!.txId;\n const group: TxGroup = { entries: [], bytes: 0 };\n\n while (index < events.length && events[index]!.txId === txId) {\n const entry = events[index]!;\n group.entries.push(entry);\n // +1 for the comma (or the array bracket) separating it from its neighbour.\n if (measure) group.bytes += jsonBytes(entry) + 1;\n index++;\n }\n\n groups.push(group);\n }\n\n return groups;\n}\n\n/**\n * Packs transaction groups into batches of at most `size` events and\n * `maxBytes` of JSON, never separating events that share a `txId`: the server\n * commits each transaction atomically, which it cannot do if we deliver half\n * of one now and half later. A transaction with more than `size` events is\n * sent whole; one larger than `maxBytes` is returned in `oversized` instead.\n */\nfunction packBatches(\n groups: ReadonlyArray<TxGroup>,\n size: number,\n maxBytes: number | null,\n): { batches: Batch[]; oversized: TxGroup[] } {\n const batches: Batch[] = [];\n const oversized: TxGroup[] = [];\n let current: Batch = { groups: [], count: 0, bytes: 1 };\n\n const close = () => {\n if (current.count > 0) batches.push(current);\n current = { groups: [], count: 0, bytes: 1 };\n };\n\n for (const group of groups) {\n if (maxBytes !== null && group.bytes + 1 > maxBytes) {\n oversized.push(group);\n continue;\n }\n\n const overCount = current.count + group.entries.length > size;\n const overBytes = maxBytes !== null && current.bytes + group.bytes > maxBytes;\n if (current.count > 0 && (overCount || overBytes)) close();\n\n current.groups.push(group);\n current.count += group.entries.length;\n current.bytes += group.bytes;\n\n if (current.count >= size) close();\n }\n\n close();\n return { batches, oversized };\n}\n\nfunction isPayloadTooLarge(err: unknown): boolean {\n return typeof err === \"object\" && err !== null && \"status\" in err && err.status === 413;\n}\n\ntype PostResult = {\n confirmed: PushConfirmation[];\n failed: PushFailure[];\n /** Transactions the server would not accept even when sent alone. */\n tooLarge: OutboxEntry[];\n /** Left unsent because the transport failed; `error` says why. */\n unsent: OutboxEntry[];\n error?: unknown;\n};\n\n/**\n * Posts `groups` as one request. On HTTP 413 the request is halved along\n * transaction boundaries and each half posted in turn, down to a single\n * transaction, so one oversized event cannot hold the rest hostage.\n */\nasync function postGroups(\n push: PushArgs[\"push\"],\n groups: ReadonlyArray<TxGroup>,\n log: EventSourcedLogger,\n): Promise<PostResult> {\n const entries = groups.flatMap((group) => group.entries);\n\n try {\n const response = normalizePushResponse(await push(entries.map(toOutboundEvent)));\n return {\n confirmed: [...response.confirmed],\n failed: [...(response.failed ?? [])],\n tooLarge: [],\n unsent: [],\n };\n } catch (err) {\n if (!isPayloadTooLarge(err)) {\n return { confirmed: [], failed: [], tooLarge: [], unsent: entries, error: err };\n }\n\n if (groups.length === 1) {\n log.warn(\"push transaction too large for the server\", { events: entries.length });\n return { confirmed: [], failed: [], tooLarge: entries, unsent: [] };\n }\n\n const middle = Math.ceil(groups.length / 2);\n log.info(\"push batch hit HTTP 413, splitting\", {\n groups: groups.length,\n events: entries.length,\n });\n\n const first = await postGroups(push, groups.slice(0, middle), log);\n if (first.error !== undefined) {\n const rest = groups.slice(middle).flatMap((group) => group.entries);\n return { ...first, unsent: [...first.unsent, ...rest] };\n }\n\n const second = await postGroups(push, groups.slice(middle), log);\n return {\n confirmed: [...first.confirmed, ...second.confirmed],\n failed: [...first.failed, ...second.failed],\n tooLarge: [...first.tooLarge, ...second.tooLarge],\n unsent: second.unsent,\n error: second.error,\n };\n }\n}\n\nasync function deadLetterTooLarge(\n args: PushArgs,\n entries: ReadonlyArray<OutboxEntry>,\n message: string,\n): Promise<number> {\n for (const entry of entries) {\n await deadLetter(\n args.deadletter,\n args.outbox,\n entry,\n \"rejected\",\n message,\n PAYLOAD_TOO_LARGE_ERROR_CODE,\n args.now,\n args.emit,\n args.log,\n args.rowversions,\n );\n }\n return entries.length;\n}\n\n/**\n * Pushes due outbox events in batches limited by event count and JSON bytes.\n * Each batch's result is persisted before the next is sent, so a failure\n * part-way through keeps the progress already made instead of restarting.\n */\nexport async function pushOutbox(args: PushArgs): Promise<PushOutcome> {\n const { outbox, push, batchSize, maxBytes, now, log } = args;\n\n const due = [...outbox.state.values()].filter((entry) => isDue(entry, now)).sort(byLocalSeq);\n\n log.debug(\"push outbox\", { dueCount: due.length, batchSize, maxBytes });\n\n if (due.length === 0) return { pushed: 0, deadLettered: 0 };\n\n const { batches, oversized } = packBatches(\n groupByTransaction(due, maxBytes !== null),\n batchSize,\n maxBytes,\n );\n\n let pushed = 0;\n let deadLettered = 0;\n\n for (const group of oversized) {\n deadLettered += await deadLetterTooLarge(\n args,\n group.entries,\n `Transaction is ${group.bytes} bytes, over maxPushBytes (${maxBytes})`,\n );\n }\n\n for (const batch of batches) {\n const attempted: OutboxEntry[] = [];\n\n for (const group of batch.groups) {\n for (const entry of group.entries) {\n const attemptCount = (entry.attemptCount ?? 0) + 1;\n\n await outbox.update(entry.eventId, (draft) => {\n draft.syncStatus = \"pending\";\n draft.attemptCount = attemptCount;\n draft.lastAttemptAt = now;\n draft.nextAttemptAt = null;\n draft.lastError = null;\n draft.lastErrorCode = null;\n draft.retryable = null;\n }).isPersisted.promise;\n\n attempted.push({ ...entry, attemptCount });\n }\n }\n\n const byId = new Map(attempted.map((entry) => [entry.eventId, entry]));\n const attemptedGroups = batch.groups.map((group) => ({\n bytes: group.bytes,\n entries: group.entries.map((entry) => byId.get(entry.eventId)!),\n }));\n\n const response = await postGroups(push, attemptedGroups, log);\n\n log.info(\"push batch confirmed\", {\n sent: attempted.length,\n bytes: batch.bytes,\n confirmed: response.confirmed.length,\n failed: response.failed.length,\n tooLarge: response.tooLarge.length,\n });\n\n for (const confirmation of response.confirmed) {\n if (!outbox.has(confirmation.eventId)) continue;\n\n await outbox.update(confirmation.eventId, (draft) => {\n draft.sync = true;\n draft.syncStatus = \"synced\";\n draft.globalSeq = confirmation.globalSeq;\n draft.nextAttemptAt = null;\n draft.lastError = null;\n draft.lastErrorCode = null;\n draft.retryable = null;\n }).isPersisted.promise;\n\n pushed++;\n args.emit(\"onEventPushed\", {\n eventId: confirmation.eventId,\n globalSeq: confirmation.globalSeq,\n });\n }\n\n for (const failure of response.failed) {\n const entry = byId.get(failure.eventId);\n if (!entry) continue;\n\n deadLettered += await handleFailure(args, entry, failure);\n }\n\n deadLettered += await deadLetterTooLarge(\n args,\n response.tooLarge,\n \"Server rejected the transaction as too large (HTTP 413)\",\n );\n\n if (response.error !== undefined) {\n // Transport-level failure: back off what was not acknowledged and stop.\n // Everything confirmed so far stays synced.\n deadLettered += await backoffBatch(args, response.unsent, response.error);\n const error =\n response.error instanceof Error ? response.error : new Error(String(response.error));\n log.warn(\"push stopped after transport failure\", {\n message: error.message,\n pushed,\n remaining: due.length - pushed,\n });\n return { pushed, deadLettered, error };\n }\n }\n\n return { pushed, deadLettered };\n}\n\n/** Returns 1 when the event was dead-lettered, 0 when it stays queued for retry. */\nasync function handleFailure(\n args: PushArgs,\n entry: OutboxEntry,\n failure: PushFailure,\n): Promise<number> {\n const { outbox, deadletter, rowversions, retry, now, emit, log } = args;\n const code = failure.code ?? null;\n\n if (failure.retryable !== true) {\n const reason: DeadLetterReason = code === CONFLICT_ERROR_CODE ? \"conflict\" : \"rejected\";\n await deadLetter(\n deadletter,\n outbox,\n entry,\n reason,\n failure.message,\n code,\n now,\n emit,\n log,\n rowversions,\n );\n return 1;\n }\n\n if (entry.attemptCount >= retry.maxAttempts) {\n await deadLetter(\n deadletter,\n outbox,\n entry,\n \"maxAttemptsExceeded\",\n failure.message,\n code,\n now,\n emit,\n log,\n rowversions,\n );\n return 1;\n }\n\n const delay = backoffDelay(entry.attemptCount, retry);\n\n await outbox.update(entry.eventId, (draft) => {\n draft.sync = false;\n draft.syncStatus = \"failed\";\n draft.retryable = true;\n draft.lastError = failure.message;\n draft.lastErrorCode = code;\n draft.nextAttemptAt = now + delay;\n }).isPersisted.promise;\n\n log.warn(\"push retry scheduled\", {\n eventId: entry.eventId,\n attemptCount: entry.attemptCount,\n retryInMs: delay,\n message: failure.message,\n });\n\n return 0;\n}\n\n/** Applies retry backoff to a whole batch after a transport-level failure. */\nasync function backoffBatch(\n args: PushArgs,\n batch: ReadonlyArray<OutboxEntry>,\n err: unknown,\n): Promise<number> {\n const message = err instanceof Error ? err.message : String(err);\n let deadLettered = 0;\n\n for (const entry of batch) {\n deadLettered += await handleFailure(args, entry, {\n eventId: entry.eventId,\n message,\n retryable: true,\n });\n }\n\n return deadLettered;\n}\n","import {\n DEFAULT_PUSH_BATCH_SIZE,\n MAX_PUSH_BATCH_SIZE,\n MIN_PUSH_BATCH_SIZE,\n} from \"../internal/constants\";\nimport type { SyncPushLimits, SyncPushPreset } from \"./types\";\n\n/**\n * Push limits per hosting platform. Byte caps leave headroom under the\n * platform's request body limit (Vercel functions: 4.5 MB; AWS Lambda and\n * Netlify: 6 MB) for headers and JSON size estimation drift.\n *\n * @example\n * ```ts\n * createBrowserEventSourcedDB({ ..., syncPreset: \"vercel\" })\n * ```\n */\nexport const SYNC_PUSH_PRESETS: Readonly<Record<SyncPushPreset, SyncPushLimits>> = {\n default: { pushBatchSize: DEFAULT_PUSH_BATCH_SIZE, maxPushBytes: null },\n serverless: { pushBatchSize: 25, maxPushBytes: 4_000_000 },\n vercel: { pushBatchSize: 10, maxPushBytes: 3_500_000 },\n};\n\nexport function resolvePushLimits(config: {\n syncPreset?: SyncPushPreset;\n pushBatchSize?: number;\n maxPushBytes?: number;\n}): SyncPushLimits {\n const preset = SYNC_PUSH_PRESETS[config.syncPreset ?? \"default\"];\n const size = Math.floor(config.pushBatchSize ?? preset.pushBatchSize);\n const bytes = config.maxPushBytes ?? preset.maxPushBytes;\n\n return {\n pushBatchSize: Math.min(MAX_PUSH_BATCH_SIZE, Math.max(MIN_PUSH_BATCH_SIZE, size)),\n maxPushBytes: bytes === null ? null : Math.max(1, Math.floor(bytes)),\n };\n}\n","/**\n * Serializes async work so overlapping callers run one after another instead of\n * concurrently. Used to stop two `sync()` calls from reading the same pending\n * set and pushing it twice.\n *\n * A rejected job does not stall the queue: the next caller still runs.\n *\n * @example Overlapping syncs run in order\n * ```ts\n * import { createSerialQueue } from \"./serial-queue\"\n *\n * const runExclusive = createSerialQueue()\n *\n * const first = runExclusive(async () => {\n * await pushPending()\n * return \"first\"\n * })\n * const second = runExclusive(async () => {\n * await pushPending()\n * return \"second\"\n * })\n *\n * await Promise.all([first, second]) // \"first\" finishes before \"second\" starts\n * ```\n */\nexport function createSerialQueue(): <T>(fn: () => Promise<T>) => Promise<T> {\n let tail: Promise<unknown> = Promise.resolve();\n\n return <T>(fn: () => Promise<T>): Promise<T> => {\n const result = tail.then(fn, fn);\n tail = result.catch(() => undefined);\n return result;\n };\n}\n","export type EventSourcedLogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\n/**\n * Structured logger used when `debug` is enabled on a DB factory.\n *\n * @example Custom sink\n * ```ts\n * import type { EventSourcedLogger } from \"event-sourced-collection\"\n *\n * const logger: EventSourcedLogger = {\n * debug: (message, data) => console.debug(message, data),\n * info: (message, data) => console.info(message, data),\n * warn: (message, data) => console.warn(message, data),\n * error: (message, data) => console.error(message, data),\n * }\n * ```\n */\nexport type EventSourcedLogger = {\n debug: (message: string, data?: Record<string, unknown>) => void;\n info: (message: string, data?: Record<string, unknown>) => void;\n warn: (message: string, data?: Record<string, unknown>) => void;\n error: (message: string, data?: Record<string, unknown>) => void;\n};\n\nconst noopLogger: EventSourcedLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\nconst LOG_PREFIX = \"[event-sourced]\";\n\n/**\n * Builds the logger used internally when you pass `debug` to a DB factory.\n * `false` / omitted is a no-op logger; `true` logs to `console`; an object is\n * used as-is.\n *\n * @example\n * ```ts\n * import { createEventSourcedLogger } from \"event-sourced-collection\"\n * import { createBrowserEventSourcedDB } from \"event-sourced-collection/browser\"\n *\n * const debug = createEventSourcedLogger(import.meta.env.DEV)\n *\n * createBrowserEventSourcedDB({\n * databaseName: \"app.sqlite\",\n * debug,\n * collections: { todos: { getKey: (todo: { id: string }) => todo.id } },\n * modules: async () => {\n * const { createCollection } = await import(\"@tanstack/db\")\n * const persistence = await import(\"@tanstack/browser-db-sqlite-persistence\")\n * return { createCollection, ...persistence }\n * },\n * })\n * ```\n */\nexport function createEventSourcedLogger(debug?: boolean | EventSourcedLogger): EventSourcedLogger {\n if (debug === undefined || debug === false) {\n return noopLogger;\n }\n\n if (typeof debug === \"object\") {\n return debug;\n }\n\n return {\n debug: (message, data) => {\n if (data === undefined) {\n console.debug(LOG_PREFIX, message);\n return;\n }\n console.debug(LOG_PREFIX, message, data);\n },\n info: (message, data) => {\n if (data === undefined) {\n console.info(LOG_PREFIX, message);\n return;\n }\n console.info(LOG_PREFIX, message, data);\n },\n warn: (message, data) => {\n if (data === undefined) {\n console.warn(LOG_PREFIX, message);\n return;\n }\n console.warn(LOG_PREFIX, message, data);\n },\n error: (message, data) => {\n if (data === undefined) {\n console.error(LOG_PREFIX, message);\n return;\n }\n console.error(LOG_PREFIX, message, data);\n },\n };\n}\n","import { uuidv7 } from \"uuidv7\";\n\n/**\n * Time-ordered event id (UUIDv7). Used as `eventId` on outbox rows and as the\n * default device `clientId` when you do not pass one.\n *\n * @example\n * ```ts\n * import { generateEventId } from \"event-sourced-collection\"\n *\n * const eventId = generateEventId()\n * const clientId = generateEventId()\n * ```\n */\nexport function generateEventId(): string {\n return uuidv7();\n}\n","import type { Collection } from \"@tanstack/db\";\n\nimport {\n DEADLETTER_ID,\n DEFAULT_BASE_DELAY_MS,\n DEFAULT_EVENT_SCHEMA_VERSION,\n DEFAULT_MAX_ATTEMPTS,\n DEFAULT_MAX_DELAY_MS,\n INBOX_ID,\n OUTBOX_ID,\n RESERVED_IDS,\n ROWVERSIONS_ID,\n SYNCMETA_ID,\n SYNC_LOCK_PREFIX,\n} from \"../internal/constants\";\nimport { createHookEmitter } from \"../internal/hooks\";\nimport type { EmitHook } from \"../internal/hooks\";\nimport { pullInbox } from \"../internal/pull\";\nimport { pushOutbox, toOutboundEvent } from \"../internal/push\";\nimport { resolvePushLimits } from \"./sync-presets\";\nimport { readRowVersion, recordRowVersion, replayInbox } from \"../internal/replay\";\nimport { createSerialQueue } from \"../internal/serial-queue\";\nimport {\n ensureSyncMeta,\n readPullCursor,\n readSyncMeta,\n resolveClientId,\n writePullCursor,\n writeSyncOutcome,\n} from \"../internal/sync-meta\";\nimport type {\n AcceptMutationsCollection,\n MetaCollections,\n MutationHookParams,\n ReplayContext,\n ResolvedRetryConfig,\n} from \"../internal/types\";\nimport { createSyncTransport, normalizePushResponse } from \"./sync\";\nimport type {\n CollectionMap,\n DeadLetterEntry,\n EventSourcedDB,\n EventSourcedDBConfig,\n InboxEntry,\n ManualSyncResult,\n MutationType,\n OutboundEvent,\n OutboxEntry,\n PruneOptions,\n PruneResult,\n RowVersionEntry,\n SyncMetaEntry,\n SyncPushLimits,\n SyncResult,\n SyncStatus,\n SyncTrigger,\n} from \"./types\";\nimport type { EventSourcedLogger } from \"../utils/logger\";\nimport { createEventSourcedLogger } from \"../utils/logger\";\nimport { generateEventId } from \"../utils/uuid\";\n\ntype CollectionDefConstraint = {\n getKey: (state: never) => string | number;\n schemaVersion?: number;\n indexes?: ReadonlyArray<{\n select: (row: never) => unknown;\n name?: string;\n indexType?: new (id: number, expression: never, name?: string, options?: never) => unknown;\n }>;\n};\n\ntype SeqCounter = { value: number };\n\n/**\n * Lets the mutation hooks, which are built before `syncmeta` has been\n * preloaded, read the persisted client id once it is known.\n */\ntype ClientIdRef = { value: string };\n\ntype MetaCollectionFactory = Pick<\n EventSourcedDBConfig<Record<string, CollectionDefConstraint>>,\n \"createCollection\" | \"persistedCollectionOptions\" | \"persistence\"\n>;\n\ntype MutationContext = {\n outbox: Collection<OutboxEntry, string>;\n rowversions: Collection<RowVersionEntry, string>;\n collectionId: string;\n type: MutationType;\n seq: SeqCounter;\n clientId: ClientIdRef;\n eventSchemaVersion: number;\n conflictDetection: boolean;\n emit: EmitHook;\n log: EventSourcedLogger;\n};\n\nfunction emptyResult(overrides: Partial<SyncResult> = {}): SyncResult {\n return {\n pushed: 0,\n pulled: 0,\n skipped: 0,\n deadLettered: 0,\n deferred: false,\n errors: [],\n ...overrides,\n };\n}\n\n/**\n * Low-level factory: wires persistence, collections, outbox/inbox, and sync.\n * Prefer a platform helper (`createBrowserEventSourcedDB`,\n * `createNodeEventSourcedDB`, `createReactNativeEventSourcedDB`) unless you are\n * supplying your own persistence.\n *\n * @param config - See {@link EventSourcedDBConfig} for every option.\n *\n * @example Node SQLite, opened immediately\n * ```ts\n * import { createCollection } from \"@tanstack/db\"\n * import {\n * createNodeSQLitePersistence,\n * persistedCollectionOptions,\n * } from \"@tanstack/node-db-sqlite-persistence\"\n * import Database from \"better-sqlite3\"\n * import { createEventSourcedDB } from \"event-sourced-collection\"\n *\n * type Todo = { id: string; title: string }\n *\n * const sqlite = new Database(\"app.sqlite\")\n * const db = await createEventSourcedDB({\n * persistence: createNodeSQLitePersistence({ database: sqlite }),\n * createCollection,\n * persistedCollectionOptions,\n * collections: {\n * todos: { getKey: (todo: Todo) => todo.id },\n * },\n * sync: {\n * push: \"/api/sync/events\",\n * pull: \"/api/sync/events\",\n * },\n * })\n *\n * await db.collections.todos.insert({ id: \"t1\", title: \"Ship\" }).isPersisted.promise\n * await db.sync()\n * ```\n */\nexport async function createEventSourcedDB<\n const TDefs extends Record<string, CollectionDefConstraint>,\n>(config: EventSourcedDBConfig<TDefs>): Promise<EventSourcedDB<TDefs>> {\n assertReservedNamesAvailable(config.collections);\n\n const log = createEventSourcedLogger(config.debug);\n const emit = createHookEmitter(config.hooks, log);\n\n const transport = createSyncTransport(config.sync);\n let syncEnabled = config.syncEnabled ?? true;\n\n // Provisional until `syncmeta` is preloaded and the persisted id is known.\n const clientId: ClientIdRef = { value: config.clientId ?? generateEventId() };\n const unknownEventHandling = config.unknownEventHandling ?? \"skip\";\n const pullOverlap = Math.max(0, config.pullOverlap ?? 0);\n const recordLocalEchoes = config.recordLocalEchoes ?? true;\n const eventSchemaVersion = config.eventSchemaVersion ?? DEFAULT_EVENT_SCHEMA_VERSION;\n let pushLimits: SyncPushLimits = resolvePushLimits(config);\n const { pushBatchSize, maxPushBytes } = pushLimits;\n const backendMismatch = config.backendMismatch ?? \"resetCursor\";\n const conflictDetection = config.conflictDetection ?? false;\n const lockName = `${SYNC_LOCK_PREFIX}:${config.lockName ?? \"default\"}`;\n\n const retry: ResolvedRetryConfig = {\n maxAttempts: Math.max(1, config.retry?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS),\n baseDelayMs: Math.max(0, config.retry?.baseDelayMs ?? DEFAULT_BASE_DELAY_MS),\n maxDelayMs: Math.max(0, config.retry?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS),\n };\n\n log.info(\"creating event-sourced db\", {\n collectionIds: Object.keys(config.collections),\n hasTransport: transport !== null,\n hasLock: Boolean(config.lock),\n syncEnabled,\n unknownEventHandling,\n pullOverlap,\n recordLocalEchoes,\n pushBatchSize,\n maxPushBytes,\n backendMismatch,\n conflictDetection,\n eventSchemaVersion,\n });\n\n const defaultSchemaVersion = config.schemaVersion ?? 1;\n const seq: SeqCounter = { value: 0 };\n\n const meta: MetaCollections = {\n outbox: createMetaCollection<OutboxEntry>(\n config,\n OUTBOX_ID,\n (entry) => entry.eventId,\n defaultSchemaVersion,\n ),\n inbox: createMetaCollection<InboxEntry>(\n config,\n INBOX_ID,\n (entry) => entry.eventId,\n defaultSchemaVersion,\n ),\n deadletter: createMetaCollection<DeadLetterEntry>(\n config,\n DEADLETTER_ID,\n (entry) => entry.eventId,\n defaultSchemaVersion,\n ),\n syncmeta: createMetaCollection<SyncMetaEntry>(\n config,\n SYNCMETA_ID,\n (entry) => entry.id,\n defaultSchemaVersion,\n ),\n rowversions: createMetaCollection<RowVersionEntry>(\n config,\n ROWVERSIONS_ID,\n (entry) => entry.id,\n defaultSchemaVersion,\n ),\n };\n\n const { outbox, inbox, deadletter, syncmeta, rowversions } = meta;\n const userCollections = {} as CollectionMap<TDefs>;\n\n for (const collectionId of Object.keys(config.collections)) {\n const def = config.collections[collectionId]!;\n const getKey = def.getKey as (item: Record<string, unknown>) => string | number;\n\n const mutationContext = {\n outbox,\n rowversions,\n collectionId,\n seq,\n clientId,\n eventSchemaVersion,\n conflictDetection,\n emit,\n log,\n };\n\n const options = config.persistedCollectionOptions<Record<string, unknown>, string | number>({\n id: collectionId,\n getKey,\n persistence: config.persistence,\n schemaVersion: def.schemaVersion ?? defaultSchemaVersion,\n gcTime: Number.POSITIVE_INFINITY,\n onInsert: createMutationHook({ ...mutationContext, type: \"insert\" }),\n onUpdate: createMutationHook({ ...mutationContext, type: \"update\" }),\n onDelete: createMutationHook({ ...mutationContext, type: \"delete\" }),\n });\n\n const collection = config.createCollection(options);\n applyCollectionIndexes(collection, collectionId, def.indexes, log);\n\n log.debug(\"registered collection\", {\n collectionId,\n hasAcceptMutations: Boolean((collection as AcceptMutationsCollection).utils?.acceptMutations),\n });\n\n (userCollections as Record<string, unknown>)[collectionId] = collection;\n }\n\n const collections = {\n ...(userCollections as CollectionMap<TDefs>),\n ...meta,\n } as EventSourcedDB<TDefs>[\"collections\"];\n\n const replayTargets = collections as unknown as Record<string, AcceptMutationsCollection>;\n\n let isSyncing = false;\n const statusListeners = new Set<(status: SyncStatus) => void>();\n\n const notifyStatus = (): void => {\n if (statusListeners.size === 0) return;\n const status = getSyncStatus();\n for (const listener of statusListeners) listener(status);\n };\n\n const subscriptions = [\n outbox.subscribeChanges(notifyStatus),\n inbox.subscribeChanges(() => {}),\n deadletter.subscribeChanges(notifyStatus),\n syncmeta.subscribeChanges(notifyStatus),\n ];\n\n for (const collection of Object.values(meta)) {\n await collection.preload();\n }\n\n await ensureSyncMeta(syncmeta);\n\n clientId.value = await resolveClientId(syncmeta, config.clientId, generateEventId);\n\n seq.value = nextLocalSeq(outbox);\n\n // User collections must be hydrated before we hand the DB to the app.\n // Otherwise seeders like `ensureAppSettings` see an empty `get()` and\n // re-insert rows that already exist on disk / on the server.\n for (const collection of Object.values(userCollections)) {\n await collection.preload();\n }\n\n log.info(\"preloaded collections\", {\n outboxCount: outbox.state.size,\n inboxCount: inbox.state.size,\n deadLetterCount: deadletter.state.size,\n userCollectionIds: Object.keys(userCollections),\n nextLocalSeq: seq.value,\n clientId: clientId.value,\n pullCursor: readPullCursor(syncmeta, inbox),\n });\n\n const replayContext: ReplayContext = {\n targets: replayTargets,\n rowversions,\n deadletter,\n unknownEventHandling,\n eventSchemaVersion,\n upcastEvent: config.upcastEvent,\n conflictDetection,\n maxReplayAttempts: retry.maxAttempts,\n emit,\n log,\n };\n\n await replayInbox(inbox, replayContext);\n\n emit(\"onReady\", { clientId: clientId.value, pullCursor: readPullCursor(syncmeta, inbox) });\n\n // Serializes callers within this context; the optional lock extends that\n // across tabs so only one of them syncs at a time.\n const runExclusive = createSerialQueue();\n\n function recordError(phase: \"push\" | \"pull\" | \"replay\", label: string, err: unknown): Error {\n const error = toError(err);\n log.error(`${label} ${phase} failed`, { message: error.message });\n emit(\"onSyncError\", { phase, error });\n return error;\n }\n\n async function pushPull(label: string): Promise<SyncResult> {\n await outbox.preload();\n await inbox.preload();\n\n const errors: Error[] = [];\n let pushed = 0;\n let pulled = 0;\n let skipped = 0;\n let deadLettered = 0;\n\n async function runPush(): Promise<void> {\n if (!transport?.push) {\n log.debug(`${label} push skipped: no push transport configured`);\n return;\n }\n\n try {\n const outcome = await pushOutbox({\n outbox,\n deadletter,\n rowversions,\n push: transport.push,\n batchSize: pushLimits.pushBatchSize,\n maxBytes: pushLimits.maxPushBytes,\n retry,\n now: Date.now(),\n emit,\n log,\n });\n pushed += outcome.pushed;\n deadLettered += outcome.deadLettered;\n if (outcome.error) {\n errors.push(recordError(\"push\", label, outcome.error));\n }\n } catch (err) {\n errors.push(recordError(\"push\", label, err));\n }\n }\n\n await runPush();\n\n let requeued = 0;\n\n try {\n if (transport?.pull) {\n const outcome = await pullInbox({\n outbox,\n inbox,\n syncmeta,\n pull: transport.pull,\n clientId: clientId.value,\n pullOverlap,\n recordLocalEchoes,\n backendMismatch,\n context: replayContext,\n });\n pulled = outcome.pulled;\n skipped = outcome.skipped;\n deadLettered += outcome.deadLettered;\n requeued = outcome.requeued;\n } else {\n log.debug(`${label} pull skipped: no pull transport configured`);\n }\n } catch (err) {\n errors.push(recordError(\"pull\", label, err));\n }\n\n // A backend reset is only discovered during pull, by which point this\n // sync's push has already run. Upload the requeued history now so a single\n // sync is enough to recover rather than leaving the gap open until the next.\n if (requeued > 0) {\n log.info(`${label} re-pushing history after backend reset`, { requeued });\n await runPush();\n }\n\n await writeSyncOutcome(syncmeta, Date.now(), errors[0]?.message ?? null);\n\n return { pushed, pulled, skipped, deadLettered, deferred: false, errors };\n }\n\n /** Runs `fn` under the cross-context lock when one is configured. */\n async function withLock<T>(fn: () => Promise<T>, deferred: T): Promise<T> {\n if (!config.lock) return fn();\n\n const outcome = await config.lock.tryRun(lockName, fn);\n\n if (!outcome.acquired) {\n log.debug(\"sync deferred: lock held by another context\", { lockName });\n return deferred;\n }\n\n return outcome.result;\n }\n\n async function tracked<T extends SyncResult>(\n trigger: SyncTrigger,\n fn: () => Promise<T>,\n ): Promise<T> {\n isSyncing = true;\n notifyStatus();\n emit(\"onSyncStart\", { trigger });\n\n try {\n const result = await fn();\n emit(\"onSyncComplete\", { trigger, result });\n return result;\n } finally {\n isSyncing = false;\n notifyStatus();\n }\n }\n\n function sync(): Promise<SyncResult> {\n return runExclusive(async () => {\n if (!syncEnabled) {\n log.debug(\"sync skipped: sync disabled\");\n return emptyResult();\n }\n\n if (!transport) {\n log.warn(\"sync skipped: no transport configured\");\n return emptyResult();\n }\n\n return withLock(\n () =>\n tracked(\"sync\", async () => {\n log.info(\"sync started\");\n const result = await pushPull(\"sync\");\n log.info(\"sync finished\", {\n pushed: result.pushed,\n pulled: result.pulled,\n skipped: result.skipped,\n deadLettered: result.deadLettered,\n errorCount: result.errors.length,\n });\n return result;\n }),\n emptyResult({ deferred: true }),\n );\n });\n }\n\n function manualSync(): Promise<ManualSyncResult> {\n return runExclusive(() =>\n withLock<ManualSyncResult>(\n () =>\n tracked(\"manualSync\", async () => {\n log.info(\"manual sync started\");\n\n await outbox.preload();\n await inbox.preload();\n\n let result: SyncResult = emptyResult();\n\n if (syncEnabled && transport) {\n result = await pushPull(\"manual sync\");\n } else if (!syncEnabled) {\n log.debug(\"manual sync push/pull skipped: sync disabled\");\n } else {\n log.warn(\"manual sync: no transport configured, skipping push/pull\");\n }\n\n const errors = [...result.errors];\n let replayed = 0;\n\n try {\n const outcome = await replayInbox(inbox, replayContext);\n replayed = outcome.applied;\n result = { ...result, skipped: result.skipped + outcome.skipped };\n } catch (err) {\n errors.push(recordError(\"replay\", \"manual sync\", err));\n }\n\n log.info(\"manual sync finished\", {\n pushed: result.pushed,\n pulled: result.pulled,\n skipped: result.skipped,\n deadLettered: result.deadLettered,\n replayed,\n errorCount: errors.length,\n });\n\n return { ...result, replayed, errors };\n }),\n { ...emptyResult({ deferred: true }), replayed: 0 },\n ),\n );\n }\n\n function getSyncStatus(): SyncStatus {\n let pendingCount = 0;\n let failedCount = 0;\n\n for (const entry of outbox.state.values()) {\n if (entry.sync) continue;\n pendingCount++;\n if (entry.syncStatus === \"failed\") failedCount++;\n }\n\n const stored = readSyncMeta(syncmeta);\n\n return {\n isSyncing,\n isSynced: pendingCount === 0,\n pendingCount,\n failedCount,\n deadLetterCount: deadletter.state.size,\n pullCursor: readPullCursor(syncmeta, inbox),\n backendId: stored.backendId,\n lastSyncAt: stored.lastSyncAt,\n lastError: stored.lastError,\n };\n }\n\n function subscribeSyncStatus(listener: (status: SyncStatus) => void): () => void {\n statusListeners.add(listener);\n listener(getSyncStatus());\n return () => statusListeners.delete(listener);\n }\n\n /**\n * Retries dead-lettered events.\n * - Outbound: pushes directly to the sync transport (does not requeue the outbox).\n * - Inbound: requeues into the inbox and replays immediately.\n * Omit `eventId` to retry everything. Returns how many were successfully\n * cleared from the dead-letter queue.\n */\n function retryDeadLetter(eventId?: string): Promise<number> {\n return runExclusive(async () => {\n const targets = selectDeadLetters(deadletter, eventId);\n const outbound: DeadLetterEntry[] = [];\n let cleared = 0;\n let inboundRequeued = 0;\n\n for (const entry of targets) {\n if ((entry.direction ?? \"outbound\") === \"inbound\") {\n await requeueInboundDeadLetter(inbox, entry);\n await deadletter.delete(entry.eventId).isPersisted.promise;\n inboundRequeued++;\n cleared++;\n } else {\n outbound.push(entry);\n }\n }\n\n if (inboundRequeued > 0) {\n await replayInbox(inbox, replayContext);\n }\n\n if (outbound.length > 0) {\n if (!transport?.push) {\n throw new Error(\n \"Cannot retry outbound dead-letter events: no push transport is configured.\",\n );\n }\n\n const events: OutboundEvent[] = outbound.map((entry) =>\n toOutboundEvent({\n eventId: entry.eventId,\n collectionId: entry.collectionId,\n type: entry.type,\n key: entry.key,\n payload: entry.payload,\n previous: entry.previous,\n txId: entry.txId ?? entry.eventId,\n clientId: entry.clientId ?? clientId.value,\n schemaVersion: entry.schemaVersion,\n baseVersion: entry.baseVersion ?? null,\n timestamp: entry.timestamp,\n localSeq: entry.localSeq ?? 0,\n globalSeq: null,\n sync: false,\n syncStatus: \"pending\",\n attemptCount: entry.attemptCount,\n lastAttemptAt: null,\n nextAttemptAt: null,\n lastError: null,\n lastErrorCode: null,\n retryable: null,\n }),\n );\n\n const response = normalizePushResponse(await transport.push(events));\n const confirmed = new Set(response.confirmed.map((item) => item.eventId));\n const failedById = new Map((response.failed ?? []).map((item) => [item.eventId, item]));\n const now = Date.now();\n\n for (const confirmation of response.confirmed) {\n const entry = outbound.find((row) => row.eventId === confirmation.eventId);\n if (!entry) continue;\n\n if (deadletter.has(entry.eventId)) {\n await deadletter.delete(entry.eventId).isPersisted.promise;\n }\n\n if (conflictDetection) {\n await recordRowVersion(\n rowversions,\n entry.collectionId,\n entry.key,\n entry.eventId,\n confirmation.globalSeq,\n );\n }\n\n emit(\"onEventPushed\", {\n eventId: confirmation.eventId,\n globalSeq: confirmation.globalSeq,\n });\n cleared++;\n }\n\n for (const entry of outbound) {\n if (confirmed.has(entry.eventId)) continue;\n\n const failure = failedById.get(entry.eventId);\n const message = failure?.message ?? \"push failed during dead-letter retry\";\n const code = failure?.code ?? null;\n\n if (deadletter.has(entry.eventId)) {\n await deadletter.update(entry.eventId, (draft) => {\n draft.attemptCount = (draft.attemptCount ?? 0) + 1;\n draft.message = message;\n draft.code = code;\n draft.failedAt = now;\n }).isPersisted.promise;\n }\n }\n\n log.info(\"outbound dead-letter events pushed\", {\n attempted: outbound.length,\n confirmed: response.confirmed.length,\n failed: response.failed?.length ?? 0,\n });\n } else {\n log.info(\"dead-letter events retried\", {\n count: targets.length,\n inbound: inboundRequeued,\n });\n }\n\n return cleared;\n });\n }\n\n function discardDeadLetter(eventId?: string): Promise<number> {\n return runExclusive(async () => {\n const targets = selectDeadLetters(deadletter, eventId);\n\n for (const entry of targets) {\n await deadletter.delete(entry.eventId).isPersisted.promise;\n }\n\n log.info(\"dead-letter events discarded\", { count: targets.length });\n\n return targets.length;\n });\n }\n\n function pruneSyncedEvents(options: PruneOptions = {}): Promise<PruneResult> {\n return runExclusive(async () => {\n const olderThanMs = Math.max(0, options.olderThanMs ?? 0);\n const keepLast = Math.max(0, options.keepLast ?? 0);\n const cutoff = Date.now() - olderThanMs;\n\n // The cursor is derived partly from resolved inbox rows, so persist it\n // before those rows are removed.\n await writePullCursor(syncmeta, readPullCursor(syncmeta, inbox));\n\n const outboxTargets = trimKeepLast(\n [...outbox.state.values()]\n .filter((entry) => entry.sync && entry.timestamp <= cutoff)\n .sort((a, b) => a.localSeq - b.localSeq),\n keepLast,\n );\n\n const inboxTargets = trimKeepLast(\n [...inbox.state.values()]\n .filter((entry) => entry.sync && entry.timestamp <= cutoff)\n .sort((a, b) => a.globalSeq - b.globalSeq),\n keepLast,\n );\n\n for (const entry of outboxTargets) {\n await outbox.delete(entry.eventId).isPersisted.promise;\n }\n\n for (const entry of inboxTargets) {\n await inbox.delete(entry.eventId).isPersisted.promise;\n }\n\n log.info(\"pruned synced events\", {\n outbox: outboxTargets.length,\n inbox: inboxTargets.length,\n });\n\n return { outbox: outboxTargets.length, inbox: inboxTargets.length };\n });\n }\n\n function getSyncEnabled(): boolean {\n return syncEnabled;\n }\n\n function setSyncEnabled(enabled: boolean): void {\n syncEnabled = enabled;\n log.debug(\"sync enabled updated\", { syncEnabled: enabled });\n }\n\n function dispose(): void {\n log.debug(\"disposing event-sourced db\");\n statusListeners.clear();\n for (const subscription of subscriptions) {\n subscription.unsubscribe();\n }\n }\n\n return {\n collections,\n sync,\n manualSync,\n getSyncEnabled,\n setSyncEnabled,\n getSyncStatus,\n subscribeSyncStatus,\n retryDeadLetter,\n discardDeadLetter,\n getPushLimits: () => pushLimits,\n setPushLimits(next: Partial<SyncPushLimits>) {\n pushLimits = resolvePushLimits({\n pushBatchSize: next.pushBatchSize ?? pushLimits.pushBatchSize,\n maxPushBytes:\n (next.maxPushBytes === undefined ? pushLimits.maxPushBytes : next.maxPushBytes) ??\n undefined,\n });\n log.info(\"push limits updated\", pushLimits);\n return pushLimits;\n },\n pruneSyncedEvents,\n dispose,\n };\n}\n\nfunction selectDeadLetters(\n deadletter: Collection<DeadLetterEntry, string>,\n eventId?: string,\n): DeadLetterEntry[] {\n if (eventId === undefined) {\n return [...deadletter.state.values()].sort(\n (a, b) => (a.localSeq ?? a.globalSeq ?? 0) - (b.localSeq ?? b.globalSeq ?? 0),\n );\n }\n\n const entry = deadletter.get(eventId);\n return entry ? [entry] : [];\n}\n\n/** Puts a parked inbound event back in the inbox so replay can pick it up again. */\nasync function requeueInboundDeadLetter(\n inbox: Collection<InboxEntry, string>,\n entry: DeadLetterEntry,\n): Promise<void> {\n if (inbox.has(entry.eventId)) {\n await inbox.update(entry.eventId, (draft) => {\n draft.sync = false;\n draft.skipped = false;\n draft.skipReason = null;\n draft.attemptCount = 0;\n draft.lastError = null;\n }).isPersisted.promise;\n return;\n }\n\n await inbox.insert({\n eventId: entry.eventId,\n globalSeq: entry.globalSeq ?? 0,\n collectionId: entry.collectionId,\n type: entry.type,\n key: entry.key,\n payload: entry.payload,\n previous: entry.previous,\n clientId: entry.clientId,\n schemaVersion: entry.schemaVersion,\n timestamp: entry.timestamp,\n sync: false,\n skipped: false,\n skipReason: null,\n attemptCount: 0,\n lastError: null,\n }).isPersisted.promise;\n}\n\n/** Drops the newest `keepLast` items from an ascending-sorted removal list. */\nfunction trimKeepLast<T>(items: ReadonlyArray<T>, keepLast: number): T[] {\n if (keepLast <= 0) return [...items];\n return items.slice(0, Math.max(0, items.length - keepLast));\n}\n\nfunction createMetaCollection<TEntry extends object>(\n config: MetaCollectionFactory,\n id: string,\n getKey: (entry: TEntry) => string,\n schemaVersion: number,\n): Collection<TEntry, string> {\n const options = config.persistedCollectionOptions<TEntry, string>({\n id,\n getKey,\n persistence: config.persistence,\n schemaVersion,\n });\n\n return config.createCollection(options);\n}\n\ntype IndexableCollection = {\n createIndex: (\n indexCallback: (row: Record<string, unknown>) => unknown,\n config?: {\n name?: string;\n indexType?: new (id: number, expression: never, name?: string, options?: never) => unknown;\n },\n ) => unknown;\n getIndexMetadata?: () => ReadonlyArray<unknown>;\n on?: (event: \"status:ready\", callback: () => void) => () => void;\n};\n\nfunction applyCollectionIndexes(\n collection: Collection<Record<string, unknown>, string | number>,\n collectionId: string,\n indexes: CollectionDefConstraint[\"indexes\"],\n log: EventSourcedLogger,\n): void {\n if (!indexes?.length) return;\n\n const indexable = collection as IndexableCollection;\n\n const register = (): void => {\n if ((indexable.getIndexMetadata?.().length ?? 0) > 0) return;\n\n for (const indexDef of indexes) {\n indexable.createIndex(indexDef.select as (row: Record<string, unknown>) => unknown, {\n name: indexDef.name,\n indexType: indexDef.indexType,\n });\n\n log.debug(\"registered collection index\", { collectionId, name: indexDef.name });\n }\n };\n\n register();\n\n indexable.on?.(\"status:ready\", register);\n}\n\nfunction createMutationHook(context: MutationContext) {\n const {\n outbox,\n rowversions,\n collectionId,\n type,\n seq,\n clientId,\n eventSchemaVersion,\n conflictDetection,\n emit,\n log,\n } = context;\n\n return async (params: MutationHookParams): Promise<Record<string, unknown>> => {\n const txId = generateEventId();\n const timestamp = Date.now();\n\n for (const mutation of params.transaction.mutations) {\n const payload = type === \"delete\" ? mutation.original : mutation.modified;\n const eventId = generateEventId();\n\n const entry: OutboxEntry = {\n eventId,\n collectionId,\n type,\n key: mutation.key,\n payload,\n previous: type === \"insert\" ? null : mutation.original,\n txId,\n clientId: clientId.value,\n schemaVersion: eventSchemaVersion,\n baseVersion: conflictDetection\n ? readRowVersion(rowversions, collectionId, mutation.key)\n : null,\n timestamp,\n localSeq: allocateLocalSeq(outbox, seq),\n globalSeq: null,\n sync: false,\n syncStatus: \"pending\",\n attemptCount: 0,\n lastAttemptAt: null,\n nextAttemptAt: null,\n lastError: null,\n lastErrorCode: null,\n retryable: null,\n };\n\n await outbox.insert(entry).isPersisted.promise;\n\n if (conflictDetection) {\n await recordRowVersion(rowversions, collectionId, mutation.key, eventId, null);\n }\n\n log.debug(\"outbox entry created\", {\n eventId,\n collectionId,\n type,\n key: entry.key,\n localSeq: entry.localSeq,\n txId,\n });\n\n emit(\"onMutation\", entry);\n }\n\n return {};\n };\n}\n\n/**\n * Reads the high-water mark from live outbox state rather than trusting the\n * cached counter alone, so a second tab writing to the same persisted store\n * cannot hand out a localSeq that has already been used.\n */\nfunction allocateLocalSeq(outbox: Collection<OutboxEntry, string>, seq: SeqCounter): number {\n const allocated = Math.max(seq.value, nextLocalSeq(outbox));\n seq.value = allocated + 1;\n return allocated;\n}\n\nfunction nextLocalSeq(outbox: Collection<OutboxEntry, string>): number {\n let max = -1;\n\n for (const entry of outbox.state.values()) {\n if (entry.localSeq > max) max = entry.localSeq;\n }\n\n return max + 1;\n}\n\nfunction assertReservedNamesAvailable(collections: Record<string, unknown>): void {\n for (const id of Object.keys(collections)) {\n if (RESERVED_IDS.has(id)) {\n throw new Error(\n `Collection id \"${id}\" is reserved. Built-in collections are: ${[...RESERVED_IDS]\n .map((name) => `\"${name}\"`)\n .join(\", \")}.`,\n );\n }\n }\n}\n\nfunction toError(err: unknown): Error {\n return err instanceof Error ? err : new Error(String(err));\n}\n","export type LazySingletonOptions = {\n /** Runs on every `ensure()` / proxy access (e.g. `typeof window` checks). */\n guard?: () => void;\n /** Thrown when `proxy` is used before `ensure()` resolves. */\n notInitializedMessage?: string;\n};\n\n/**\n * Result of {@link createLazySingleton}.\n *\n * @example\n * ```ts\n * import { createLazySingleton } from \"event-sourced-collection\"\n *\n * const { ensure, proxy, reset } = createLazySingleton(async () => ({ ready: true }))\n * await ensure()\n * console.log(proxy.ready) // true\n * reset()\n * ```\n */\nexport type LazySingleton<T extends object> = {\n ensure: () => Promise<T>;\n proxy: T;\n reset: () => void;\n};\n\n/**\n * One-shot async factory with a proxy that is safe to export as a module\n * singleton. Platform DB helpers are built on this.\n *\n * @example Export a proxy, initialize at app startup\n * ```ts\n * import { createLazySingleton } from \"event-sourced-collection\"\n *\n * type Client = { ping: () => Promise<string> }\n *\n * const { ensure, proxy: client } = createLazySingleton<Client>(async () => ({\n * ping: async () => \"ok\",\n * }))\n *\n * export async function start() {\n * await ensure()\n * }\n *\n * export { client }\n * // client.ping() throws until start() has run\n * ```\n */\nexport function createLazySingleton<T extends object>(\n factory: () => Promise<T>,\n options: LazySingletonOptions = {},\n): LazySingleton<T> {\n let instance: T | null = null;\n let initPromise: Promise<T> | null = null;\n\n const ensure = async (): Promise<T> => {\n options.guard?.();\n\n if (instance) {\n return instance;\n }\n\n if (!initPromise) {\n initPromise = factory()\n .then((resolved) => {\n instance = resolved;\n return resolved;\n })\n .catch((error: unknown) => {\n initPromise = null;\n throw error;\n });\n }\n\n return initPromise;\n };\n\n const message =\n options.notInitializedMessage ?? \"Instance is not initialized. Call ensure() first.\";\n\n const proxy = new Proxy({} as T, {\n get(_target, prop, receiver) {\n if (!instance) {\n throw new Error(message);\n }\n return Reflect.get(instance, prop, receiver);\n },\n has(_target, prop) {\n if (!instance) {\n throw new Error(message);\n }\n return Reflect.has(instance, prop);\n },\n getPrototypeOf() {\n if (!instance) {\n throw new Error(message);\n }\n return Reflect.getPrototypeOf(instance);\n },\n });\n\n const reset = (): void => {\n instance = null;\n initPromise = null;\n };\n\n return { ensure, proxy, reset };\n}\n","import { createEventSourcedDB } from \"./create-event-sourced-db\";\nimport { createLazySingleton } from \"./lazy-singleton\";\nimport type { EventSourcedDB, EventSourcedDBConfig } from \"./types\";\n\ntype CollectionDefConstraint = {\n getKey: (state: never) => string | number;\n};\n\n/**\n * Lazy handle returned by platform helpers and {@link createEventSourcedDBHandle}.\n *\n * @example\n * ```ts\n * import { createBrowserEventSourcedDB } from \"event-sourced-collection/browser\"\n *\n * const { ensureDb, db, close } = createBrowserEventSourcedDB({\n * databaseName: \"app.sqlite\",\n * collections: { todos: { getKey: (todo: { id: string }) => todo.id } },\n * modules: async () => {\n * const { createCollection } = await import(\"@tanstack/db\")\n * const persistence = await import(\"@tanstack/browser-db-sqlite-persistence\")\n * return { createCollection, ...persistence }\n * },\n * })\n *\n * await ensureDb()\n * await db.collections.todos.insert({ id: \"t1\" }).isPersisted.promise\n * await close()\n * ```\n */\nexport type EventSourcedDBHandle<TDefs extends Record<string, CollectionDefConstraint>> = {\n /** Opens (or returns) the singleton DB. Call once at app startup before using `db`. */\n ensureDb: () => Promise<EventSourcedDB<TDefs>>;\n /**\n * Proxy that forwards to the live DB after `ensureDb()` resolves. Accessing a\n * property before initialization throws.\n */\n db: EventSourcedDB<TDefs>;\n /** Disposes the DB, runs platform cleanup, and resets the singleton. */\n close: () => Promise<void>;\n};\n\nexport type EventSourcedDBHandleSetup<TDefs extends Record<string, CollectionDefConstraint>> =\n EventSourcedDBConfig<TDefs> & {\n /** Optional platform teardown (close SQLite, dispose coordinators). */\n close?: () => Promise<void> | void;\n };\n\n/**\n * Lazy singleton around {@link createEventSourcedDB}. Platform helpers use this\n * after they have turned TanStack persistence modules into `persistence`.\n * Call this yourself only when you need a custom open/close path.\n *\n * @example Custom persistence, still lazy like the platform helpers\n * ```ts\n * import { createCollection } from \"@tanstack/db\"\n * import {\n * createNodeSQLitePersistence,\n * persistedCollectionOptions,\n * } from \"@tanstack/node-db-sqlite-persistence\"\n * import Database from \"better-sqlite3\"\n * import { createEventSourcedDBHandle } from \"event-sourced-collection\"\n *\n * type Todo = { id: string; title: string }\n *\n * const { ensureDb, db, close } = createEventSourcedDBHandle({\n * setup: async () => {\n * const sqlite = new Database(\"app.sqlite\")\n * return {\n * persistence: createNodeSQLitePersistence({ database: sqlite }),\n * createCollection,\n * persistedCollectionOptions,\n * collections: { todos: { getKey: (todo: Todo) => todo.id } },\n * close: () => sqlite.close(),\n * }\n * },\n * })\n *\n * await ensureDb()\n * console.log(db.collections.todos.size)\n * await close()\n * ```\n */\nexport function createEventSourcedDBHandle<\n const TDefs extends Record<string, CollectionDefConstraint>,\n>(options: {\n setup: () => Promise<EventSourcedDBHandleSetup<TDefs>>;\n guard?: () => void;\n notInitializedMessage?: string;\n}): EventSourcedDBHandle<TDefs> {\n let activeDb: EventSourcedDB<TDefs> | null = null;\n let closePlatform: (() => Promise<void> | void) | null = null;\n\n const factory = async (): Promise<EventSourcedDB<TDefs>> => {\n const { close, ...dbConfig } = await options.setup();\n closePlatform = close ?? null;\n const database = await createEventSourcedDB<TDefs>(dbConfig);\n activeDb = database;\n return database;\n };\n\n const singleton = createLazySingleton<EventSourcedDB<TDefs>>(factory, {\n guard: options.guard,\n notInitializedMessage:\n options.notInitializedMessage ??\n \"Event-sourced DB is not initialized. Call ensureDb() before using db.\",\n });\n\n const close = async (): Promise<void> => {\n if (activeDb) {\n activeDb.dispose();\n activeDb = null;\n }\n if (closePlatform) {\n await closePlatform();\n closePlatform = null;\n }\n singleton.reset();\n };\n\n return {\n ensureDb: singleton.ensure,\n db: singleton.proxy,\n close,\n };\n}\n\n/** Bindings object, or a function that loads them on first `ensureDb()`. */\nexport type ModulesInput<T> = T | (() => T | Promise<T>);\n\n/**\n * Resolves {@link ModulesInput}: returns the object, or awaits the loader.\n *\n * @example Keep WASM off the SSR bundle until the first `ensureDb()`\n * ```ts\n * import { resolveModules, type ModulesInput } from \"event-sourced-collection\"\n *\n * type BrowserModules = {\n * createCollection: typeof import(\"@tanstack/db\").createCollection\n * }\n *\n * const modules: ModulesInput<BrowserModules> = async () => {\n * const { createCollection } = await import(\"@tanstack/db\")\n * return { createCollection }\n * }\n *\n * const resolved = await resolveModules(modules)\n * ```\n */\nexport async function resolveModules<T>(modules: ModulesInput<T>): Promise<T> {\n return typeof modules === \"function\" ? await (modules as () => T | Promise<T>)() : modules;\n}\n"],"mappings":"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"}