@firtoz/collection-sync 5.0.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/README.md +46 -0
  2. package/dist/cache-manager.d.ts +52 -0
  3. package/dist/cache-manager.js +5 -0
  4. package/dist/cache-manager.js.map +1 -0
  5. package/dist/chunk-3EHHMLSV.js +57 -0
  6. package/dist/chunk-3EHHMLSV.js.map +1 -0
  7. package/dist/chunk-43KYAIKY.js +46 -0
  8. package/dist/chunk-43KYAIKY.js.map +1 -0
  9. package/dist/chunk-4BEXLBCH.js +64 -0
  10. package/dist/chunk-4BEXLBCH.js.map +1 -0
  11. package/dist/chunk-5V6BSQAB.js +148 -0
  12. package/dist/chunk-5V6BSQAB.js.map +1 -0
  13. package/dist/chunk-5VMFQT5Z.js +112 -0
  14. package/dist/chunk-5VMFQT5Z.js.map +1 -0
  15. package/dist/chunk-6EHROJFY.js +111 -0
  16. package/dist/chunk-6EHROJFY.js.map +1 -0
  17. package/dist/chunk-6X3434GJ.js +21 -0
  18. package/dist/chunk-6X3434GJ.js.map +1 -0
  19. package/dist/chunk-BGJH6PH2.js +175 -0
  20. package/dist/chunk-BGJH6PH2.js.map +1 -0
  21. package/dist/chunk-BJJEAKXL.js +252 -0
  22. package/dist/chunk-BJJEAKXL.js.map +1 -0
  23. package/dist/chunk-GWIOC5CP.js +51 -0
  24. package/dist/chunk-GWIOC5CP.js.map +1 -0
  25. package/dist/chunk-HMLY7DHA.js +12 -0
  26. package/dist/chunk-HMLY7DHA.js.map +1 -0
  27. package/dist/chunk-I6RJWBGF.js +112 -0
  28. package/dist/chunk-I6RJWBGF.js.map +1 -0
  29. package/dist/chunk-M5MJHS6A.js +10 -0
  30. package/dist/chunk-M5MJHS6A.js.map +1 -0
  31. package/dist/chunk-O3KBDCEI.js +615 -0
  32. package/dist/chunk-O3KBDCEI.js.map +1 -0
  33. package/dist/chunk-OP53UBPN.js +19 -0
  34. package/dist/chunk-OP53UBPN.js.map +1 -0
  35. package/dist/chunk-P3JOTUAB.js +802 -0
  36. package/dist/chunk-P3JOTUAB.js.map +1 -0
  37. package/dist/chunk-QJP4GSJH.js +373 -0
  38. package/dist/chunk-QJP4GSJH.js.map +1 -0
  39. package/dist/chunk-RDDS7JQW.js +623 -0
  40. package/dist/chunk-RDDS7JQW.js.map +1 -0
  41. package/dist/chunk-TEH7V76G.js +209 -0
  42. package/dist/chunk-TEH7V76G.js.map +1 -0
  43. package/dist/chunk-UJ24XW52.js +20 -0
  44. package/dist/chunk-UJ24XW52.js.map +1 -0
  45. package/dist/chunk-UVZJL6QV.js +18 -0
  46. package/dist/chunk-UVZJL6QV.js.map +1 -0
  47. package/dist/chunk-XC4QNFSQ.js +238 -0
  48. package/dist/chunk-XC4QNFSQ.js.map +1 -0
  49. package/dist/chunk-YD5LVGWX.js +125 -0
  50. package/dist/chunk-YD5LVGWX.js.map +1 -0
  51. package/dist/chunk-YYGPIHHJ.js +166 -0
  52. package/dist/chunk-YYGPIHHJ.js.map +1 -0
  53. package/dist/connect-partial-sync.d.ts +41 -0
  54. package/dist/connect-partial-sync.js +6 -0
  55. package/dist/connect-partial-sync.js.map +1 -0
  56. package/dist/connect-sync.d.ts +26 -0
  57. package/dist/connect-sync.js +5 -0
  58. package/dist/connect-sync.js.map +1 -0
  59. package/dist/create-partial-synced-collection.d.ts +24 -0
  60. package/dist/create-partial-synced-collection.js +8 -0
  61. package/dist/create-partial-synced-collection.js.map +1 -0
  62. package/dist/create-synced-collection.d.ts +26 -0
  63. package/dist/create-synced-collection.js +8 -0
  64. package/dist/create-synced-collection.js.map +1 -0
  65. package/dist/index.d.ts +18 -0
  66. package/dist/index.js +18 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/partial-sync-client-bridge.d.ts +157 -0
  69. package/dist/partial-sync-client-bridge.js +6 -0
  70. package/dist/partial-sync-client-bridge.js.map +1 -0
  71. package/dist/partial-sync-interest.d.ts +48 -0
  72. package/dist/partial-sync-interest.js +6 -0
  73. package/dist/partial-sync-interest.js.map +1 -0
  74. package/dist/partial-sync-mutation-handler.d.ts +31 -0
  75. package/dist/partial-sync-mutation-handler.js +6 -0
  76. package/dist/partial-sync-mutation-handler.js.map +1 -0
  77. package/dist/partial-sync-predicate-match.d.ts +8 -0
  78. package/dist/partial-sync-predicate-match.js +4 -0
  79. package/dist/partial-sync-predicate-match.js.map +1 -0
  80. package/dist/partial-sync-row-key.d.ts +41 -0
  81. package/dist/partial-sync-row-key.js +4 -0
  82. package/dist/partial-sync-row-key.js.map +1 -0
  83. package/dist/partial-sync-server-bridge.d.ts +102 -0
  84. package/dist/partial-sync-server-bridge.js +8 -0
  85. package/dist/partial-sync-server-bridge.js.map +1 -0
  86. package/dist/react/constants.d.ts +12 -0
  87. package/dist/react/constants.js +4 -0
  88. package/dist/react/constants.js.map +1 -0
  89. package/dist/react/index.d.ts +19 -0
  90. package/dist/react/index.js +17 -0
  91. package/dist/react/index.js.map +1 -0
  92. package/dist/react/partial-sync-adapter.d.ts +40 -0
  93. package/dist/react/partial-sync-adapter.js +4 -0
  94. package/dist/react/partial-sync-adapter.js.map +1 -0
  95. package/dist/react/partial-sync-utils.d.ts +42 -0
  96. package/dist/react/partial-sync-utils.js +5 -0
  97. package/dist/react/partial-sync-utils.js.map +1 -0
  98. package/dist/react/range-conditions-expression.d.ts +49 -0
  99. package/dist/react/range-conditions-expression.js +4 -0
  100. package/dist/react/range-conditions-expression.js.map +1 -0
  101. package/dist/react/types.d.ts +196 -0
  102. package/dist/react/types.js +3 -0
  103. package/dist/react/types.js.map +1 -0
  104. package/dist/react/usePartialSyncCollection.d.ts +20 -0
  105. package/dist/react/usePartialSyncCollection.js +10 -0
  106. package/dist/react/usePartialSyncCollection.js.map +1 -0
  107. package/dist/react/usePartialSyncViewport.d.ts +20 -0
  108. package/dist/react/usePartialSyncViewport.js +7 -0
  109. package/dist/react/usePartialSyncViewport.js.map +1 -0
  110. package/dist/react/usePartialSyncWindow.d.ts +17 -0
  111. package/dist/react/usePartialSyncWindow.js +12 -0
  112. package/dist/react/usePartialSyncWindow.js.map +1 -0
  113. package/dist/react/usePredicateFilteredRows.d.ts +20 -0
  114. package/dist/react/usePredicateFilteredRows.js +6 -0
  115. package/dist/react/usePredicateFilteredRows.js.map +1 -0
  116. package/dist/sync-client-bridge.d.ts +48 -0
  117. package/dist/sync-client-bridge.js +6 -0
  118. package/dist/sync-client-bridge.js.map +1 -0
  119. package/dist/sync-protocol.d.ts +378 -0
  120. package/dist/sync-protocol.js +4 -0
  121. package/dist/sync-protocol.js.map +1 -0
  122. package/dist/sync-server-bridge.d.ts +35 -0
  123. package/dist/sync-server-bridge.js +6 -0
  124. package/dist/sync-server-bridge.js.map +1 -0
  125. package/dist/with-sync.d.ts +107 -0
  126. package/dist/with-sync.js +7 -0
  127. package/dist/with-sync.js.map +1 -0
  128. package/package.json +23 -17
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/partial-sync-server-bridge.ts"],"names":["totalCount"],"mappings":"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","file":"chunk-RDDS7JQW.js","sourcesContent":["import type { SyncMessage } from \"@firtoz/db-helpers\";\nimport { exhaustiveGuard } from \"@firtoz/maybe-error\";\nimport {\n\tclassifyPartialSyncRangePatch,\n\tfilterSyncMessagesForPredicateRange,\n\ttype DeliveredRange,\n\ttype PartialSyncPatchResult,\n} from \"./partial-sync-interest\";\nimport { defaultPredicateColumnValue } from \"./partial-sync-predicate-match\";\nimport type { PartialSyncRowId } from \"./partial-sync-row-key\";\nimport {\n\tpartialSyncRowKey,\n\tpartialSyncRowVersionWatermarkMs,\n} from \"./partial-sync-row-key\";\n\nfunction deliveredRowIdKey(id: PartialSyncRowId): string {\n\treturn String(partialSyncRowKey(id));\n}\nimport type {\n\tRangeCondition,\n\tSyncClientMessage,\n\tSyncRange,\n\tSyncRangeSort,\n\tSyncServerMessage,\n\tSyncServerMessageBody,\n} from \"./sync-protocol\";\nimport { DEFAULT_SYNC_COLLECTION_ID } from \"./sync-protocol\";\nimport type { PartialSyncRowShape } from \"./partial-sync-row-key\";\n\nexport type { DeliveredRange } from \"./partial-sync-interest\";\n\nexport type ClientQueryState<\n\tTItem extends PartialSyncRowShape = { id: string; updatedAt: null },\n> = {\n\tclientId: string;\n\tdeliveredRanges: DeliveredRange[];\n\t/** Each entry is one predicate query's `conditions` (AND); OR across entries. */\n\tpredicateGroups: RangeCondition[][];\n\t/** Row ids delivered to this client in the current interest session (for scoped deletes). */\n\tdeliveredRowIds: Set<string>;\n\tpendingPatches: PartialSyncPatchResult<TItem>[];\n\tstreaming: boolean;\n};\n\nexport interface PartialSyncServerBridgeStore<\n\tTItem extends PartialSyncRowShape,\n> {\n\tqueryRange: (options: {\n\t\tsort: SyncRangeSort;\n\t\tlimit: number;\n\t\tafterCursor: unknown | null;\n\t\tchunkSize: number;\n\t}) => AsyncIterable<TItem[]>;\n\tqueryByOffset: (options: {\n\t\tsort: SyncRangeSort;\n\t\tlimit: number;\n\t\toffset: number;\n\t\tchunkSize: number;\n\t}) => AsyncIterable<TItem[]>;\n\tgetTotalCount: () => Promise<number>;\n\tgetSortValue: (row: TItem, column: string) => unknown;\n\n\t/** Predicate-based range (optional). */\n\tqueryByPredicate?: (options: {\n\t\tconditions: RangeCondition[];\n\t\tsort?: SyncRangeSort;\n\t\tlimit?: number;\n\t\tchunkSize: number;\n\t}) => AsyncIterable<TItem[]>;\n\n\tgetPredicateCount?: (conditions: RangeCondition[]) => Promise<number>;\n\n\t/**\n\t * Changes since `sinceVersion` within `range`. `null` if changelog cannot answer\n\t * (caller should full-fetch).\n\t */\n\tchangesSince?: (options: {\n\t\trange: SyncRange;\n\t\tsinceVersion: number;\n\t\tchunkSize: number;\n\t}) => Promise<{ changes: SyncMessage<TItem>[]; totalCount: number } | null>;\n\n\t/** Authoritative row lookup (e.g. for {@link PartialSyncServerBridgeOptions.resolveMovedHint}). */\n\tgetRow?: (key: string | number) => Promise<TItem | undefined>;\n}\n\nexport type PartialSyncPushServerChangesOptions = {\n\t/**\n\t * Do not emit `rangePatch` to this client (e.g. the mutation author already applied the change\n\t * locally and receives `ack` with the same payload).\n\t */\n\texcludeClientId?: string;\n};\n\nexport interface PartialSyncServerBridgeOptions<\n\tTItem extends PartialSyncRowShape,\n> {\n\tstore: PartialSyncServerBridgeStore<TItem>;\n\tsendToClient: (clientId: string, message: SyncServerMessage<TItem>) => void;\n\tqueryChunkSize?: number;\n\t/** Multiplex key for sync messages. Default {@link DEFAULT_SYNC_COLLECTION_ID}. */\n\tcollectionId?: string;\n\t/**\n\t * Narrow client-requested predicate conditions (e.g. fog of war). Applied before querying and\n\t * before interest tracking for predicate `rangeQuery`.\n\t */\n\tresolveClientVisibility?: (\n\t\tclientId: string,\n\t\trequestedConditions: RangeCondition[],\n\t) => RangeCondition[] | Promise<RangeCondition[]>;\n\t/**\n\t * Optional hint for rows that left the client's range during `rangeReconcile`.\n\t * Return `null` to enforce fog of war (default when omitted).\n\t */\n\tresolveMovedHint?: (\n\t\trow: TItem,\n\t\trange: SyncRange,\n\t) => Record<string, unknown> | null | Promise<Record<string, unknown> | null>;\n}\n\nexport class PartialSyncServerBridge<TItem extends PartialSyncRowShape> {\n\t#clientStates = new Map<string, ClientQueryState<TItem>>();\n\treadonly #cid: string;\n\n\tconstructor(private readonly options: PartialSyncServerBridgeOptions<TItem>) {\n\t\tthis.#cid = options.collectionId ?? DEFAULT_SYNC_COLLECTION_ID;\n\t}\n\n\tget collectionId(): string {\n\t\treturn this.#cid;\n\t}\n\n\t#emit(clientId: string, body: SyncServerMessageBody<TItem>): void {\n\t\tthis.options.sendToClient(clientId, {\n\t\t\t...body,\n\t\t\tcollectionId: this.#cid,\n\t\t} as SyncServerMessage<TItem>);\n\t}\n\n\tasync handleClientMessage(message: SyncClientMessage): Promise<void> {\n\t\tconst mid = message.collectionId ?? DEFAULT_SYNC_COLLECTION_ID;\n\t\tif (mid !== this.#cid) return;\n\t\tswitch (message.type) {\n\t\t\tcase \"ping\":\n\t\t\t\tthis.#emit(message.clientId, {\n\t\t\t\t\ttype: \"pong\",\n\t\t\t\t\ttimestamp: message.timestamp,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\tcase \"queryRange\":\n\t\t\t\tawait this.#handleQueryRange(message);\n\t\t\t\treturn;\n\t\t\tcase \"queryByOffset\":\n\t\t\t\tawait this.#handleQueryByOffset(message);\n\t\t\t\treturn;\n\t\t\tcase \"rangeQuery\":\n\t\t\t\tawait this.#handleRangeQuery(message);\n\t\t\t\treturn;\n\t\t\tcase \"rangeReconcile\":\n\t\t\t\tawait this.#handleRangeReconcile(message);\n\t\t\t\treturn;\n\t\t\tcase \"syncHello\":\n\t\t\tcase \"mutateBatch\":\n\t\t\t\t// Partial sync query bridge is read-focused. Mutations use PartialSyncMutationHandler.\n\t\t\t\treturn;\n\t\t\tdefault:\n\t\t\t\texhaustiveGuard(message);\n\t\t}\n\t}\n\n\tasync pushServerChanges(\n\t\tchanges: SyncMessage<TItem>[],\n\t\toptions?: PartialSyncPushServerChangesOptions,\n\t): Promise<void> {\n\t\tconst exclude = options?.excludeClientId;\n\t\tfor (const state of this.#clientStates.values()) {\n\t\t\tif (exclude !== undefined && state.clientId === exclude) continue;\n\t\t\tfor (const change of changes) {\n\t\t\t\tconst patch = classifyPartialSyncRangePatch(\n\t\t\t\t\tstate.deliveredRanges,\n\t\t\t\t\tstate.predicateGroups,\n\t\t\t\t\tchange,\n\t\t\t\t\t(row, column) => this.options.store.getSortValue(row, column),\n\t\t\t\t\t(row, column) => defaultPredicateColumnValue(row, column),\n\t\t\t\t\t{ deliveredRowIds: state.deliveredRowIds },\n\t\t\t\t);\n\t\t\t\tif (patch === null) continue;\n\t\t\t\tif (state.streaming) {\n\t\t\t\t\tstate.pendingPatches.push(patch);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthis.#emit(state.clientId, {\n\t\t\t\t\ttype: \"rangePatch\",\n\t\t\t\t\tchange: patch.change,\n\t\t\t\t\t...(patch.viewTransition !== undefined\n\t\t\t\t\t\t? { viewTransition: patch.viewTransition }\n\t\t\t\t\t\t: {}),\n\t\t\t\t});\n\t\t\t\tthis.#applyPatchToDeliveredRowIds(state, patch);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Drop partial-sync interest for a disconnected client (prevents unbounded `#clientStates`\n\t * growth and stale subscriptions).\n\t */\n\tremoveClient(clientId: string): void {\n\t\tthis.#clientStates.delete(clientId);\n\t}\n\n\t/**\n\t * Replace predicate interest for a client (server-authoritative visibility). Clears sort-range\n\t * tracking; the next `rangeQuery` should re-establish delivered ranges from fresh chunks.\n\t */\n\tsetClientVisibility(clientId: string, conditions: RangeCondition[]): void {\n\t\tconst state = this.#getOrCreateClientState(clientId);\n\t\tstate.predicateGroups = [[...conditions]];\n\t\tstate.deliveredRanges.length = 0;\n\t\tstate.deliveredRowIds.clear();\n\t}\n\n\tgetClientState(clientId: string): ClientQueryState<TItem> | undefined {\n\t\treturn this.#clientStates.get(clientId);\n\t}\n\n\t#resetClientInterest(state: ClientQueryState<TItem>): void {\n\t\tstate.deliveredRanges.length = 0;\n\t\tstate.predicateGroups.length = 0;\n\t\tstate.pendingPatches.length = 0;\n\t\tstate.deliveredRowIds.clear();\n\t}\n\n\t#trackDeliveredRowIdsFromRows(\n\t\tstate: ClientQueryState<TItem>,\n\t\trows: TItem[],\n\t): void {\n\t\tfor (const row of rows) {\n\t\t\tstate.deliveredRowIds.add(deliveredRowIdKey(row.id));\n\t\t}\n\t}\n\n\t#trackDeliveredRowIdsFromMessages(\n\t\tstate: ClientQueryState<TItem>,\n\t\tmessages: SyncMessage<TItem>[],\n\t): void {\n\t\tfor (const c of messages) {\n\t\t\tif (c.type === \"insert\" || c.type === \"update\") {\n\t\t\t\tstate.deliveredRowIds.add(deliveredRowIdKey(c.value.id));\n\t\t\t}\n\t\t\tif (c.type === \"delete\") {\n\t\t\t\tstate.deliveredRowIds.delete(deliveredRowIdKey(c.key));\n\t\t\t}\n\t\t\tif (c.type === \"truncate\") {\n\t\t\t\tstate.deliveredRowIds.clear();\n\t\t\t}\n\t\t}\n\t}\n\n\t#applyPatchToDeliveredRowIds(\n\t\tstate: ClientQueryState<TItem>,\n\t\tpatch: PartialSyncPatchResult<TItem>,\n\t): void {\n\t\tconst ch = patch.change;\n\t\tif (ch.type === \"truncate\") {\n\t\t\tstate.deliveredRowIds.clear();\n\t\t\treturn;\n\t\t}\n\t\tif (ch.type === \"delete\") {\n\t\t\tstate.deliveredRowIds.delete(deliveredRowIdKey(ch.key));\n\t\t\treturn;\n\t\t}\n\t\tif (ch.type === \"insert\") {\n\t\t\tstate.deliveredRowIds.add(deliveredRowIdKey(ch.value.id));\n\t\t\treturn;\n\t\t}\n\t\tif (ch.type === \"update\") {\n\t\t\tconst id = deliveredRowIdKey(ch.value.id);\n\t\t\tif (patch.viewTransition === \"exitView\") {\n\t\t\t\tstate.deliveredRowIds.delete(id);\n\t\t\t} else {\n\t\t\t\tstate.deliveredRowIds.add(id);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #handleRangeQuery(\n\t\tmessage: Extract<SyncClientMessage, { type: \"rangeQuery\" }>,\n\t): Promise<void> {\n\t\tconst { clientId, requestId, fingerprint } = message;\n\t\tlet range: SyncRange = message.range;\n\t\tconst state = this.#getOrCreateClientState(clientId);\n\t\t/** Predicate viewport queries replace interest; index fingerprint refresh must keep sort ranges. */\n\t\tif (range.kind === \"predicate\") {\n\t\t\tthis.#resetClientInterest(state);\n\t\t} else {\n\t\t\tstate.predicateGroups.length = 0;\n\t\t\tstate.pendingPatches.length = 0;\n\t\t}\n\n\t\tif (range.kind === \"predicate\") {\n\t\t\tconst resolved =\n\t\t\t\tthis.options.resolveClientVisibility !== undefined\n\t\t\t\t\t? await this.options.resolveClientVisibility(\n\t\t\t\t\t\t\tclientId,\n\t\t\t\t\t\t\trange.conditions,\n\t\t\t\t\t\t)\n\t\t\t\t\t: range.conditions;\n\t\t\trange = { ...range, conditions: resolved };\n\t\t\tstate.predicateGroups.push([...resolved]);\n\t\t}\n\n\t\tconst rangeLimit =\n\t\t\trange.kind === \"index\" ? range.limit : (range.limit ?? 200);\n\n\t\tif (fingerprint !== undefined && this.options.store.changesSince) {\n\t\t\tconst delta = await this.options.store.changesSince({\n\t\t\t\trange,\n\t\t\t\tsinceVersion: fingerprint.version,\n\t\t\t\tchunkSize: Math.max(1, this.options.queryChunkSize ?? 200),\n\t\t\t});\n\t\t\tif (delta !== null) {\n\t\t\t\tif (delta.changes.length === 0) {\n\t\t\t\t\tthis.#emit(clientId, {\n\t\t\t\t\t\ttype: \"rangeUpToDate\",\n\t\t\t\t\t\trequestId,\n\t\t\t\t\t\ttotalCount: delta.totalCount,\n\t\t\t\t\t});\n\t\t\t\t\tthis.#mergeDeliveredRangesFromChanges(state, range, delta.changes);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst maxDelta = Math.max(1, Math.ceil(rangeLimit * 0.5));\n\t\t\t\tif (delta.changes.length <= maxDelta) {\n\t\t\t\t\tconst filteredDelta =\n\t\t\t\t\t\trange.kind === \"predicate\"\n\t\t\t\t\t\t\t? filterSyncMessagesForPredicateRange(\n\t\t\t\t\t\t\t\t\trange.conditions,\n\t\t\t\t\t\t\t\t\tdelta.changes,\n\t\t\t\t\t\t\t\t\t(row, column) => this.options.store.getSortValue(row, column),\n\t\t\t\t\t\t\t\t\tdefaultPredicateColumnValue,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: delta.changes;\n\t\t\t\t\tthis.#emit(clientId, {\n\t\t\t\t\t\ttype: \"rangeDelta\",\n\t\t\t\t\t\trequestId,\n\t\t\t\t\t\ttotalCount: delta.totalCount,\n\t\t\t\t\t\tchanges: filteredDelta,\n\t\t\t\t\t});\n\t\t\t\t\tthis.#mergeDeliveredRangesFromChanges(state, range, filteredDelta);\n\t\t\t\t\tthis.#trackDeliveredRowIdsFromMessages(state, filteredDelta);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (range.kind === \"index\" && range.mode === \"cursor\") {\n\t\t\tawait this.#handleQueryRange({\n\t\t\t\ttype: \"queryRange\",\n\t\t\t\tcollectionId: this.#cid,\n\t\t\t\tclientId,\n\t\t\t\trequestId,\n\t\t\t\tsort: range.sort,\n\t\t\t\tlimit: range.limit,\n\t\t\t\tafterCursor: range.afterCursor,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (range.kind === \"index\" && range.mode === \"offset\") {\n\t\t\tawait this.#handleQueryByOffset({\n\t\t\t\ttype: \"queryByOffset\",\n\t\t\t\tcollectionId: this.#cid,\n\t\t\t\tclientId,\n\t\t\t\trequestId,\n\t\t\t\tsort: range.sort,\n\t\t\t\tlimit: range.limit,\n\t\t\t\toffset: range.offset,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (range.kind === \"predicate\") {\n\t\t\tawait this.#handleQueryPredicate(message, range);\n\t\t\treturn;\n\t\t}\n\t\texhaustiveGuard(range);\n\t}\n\n\tasync #handleRangeReconcile(\n\t\tmessage: Extract<SyncClientMessage, { type: \"rangeReconcile\" }>,\n\t): Promise<void> {\n\t\tconst { clientId, requestId, manifest } = message;\n\t\tlet range: SyncRange = message.range;\n\t\tconst state = this.#getOrCreateClientState(clientId);\n\t\tif (range.kind === \"predicate\") {\n\t\t\tthis.#resetClientInterest(state);\n\t\t} else {\n\t\t\tstate.predicateGroups.length = 0;\n\t\t\tstate.pendingPatches.length = 0;\n\t\t}\n\t\tif (range.kind === \"predicate\") {\n\t\t\tconst resolved =\n\t\t\t\tthis.options.resolveClientVisibility !== undefined\n\t\t\t\t\t? await this.options.resolveClientVisibility(\n\t\t\t\t\t\t\tclientId,\n\t\t\t\t\t\t\trange.conditions,\n\t\t\t\t\t\t)\n\t\t\t\t\t: range.conditions;\n\t\t\trange = { ...range, conditions: resolved };\n\t\t\tstate.predicateGroups.push([...resolved]);\n\t\t}\n\n\t\tconst { rows, totalCount } = await this.#collectRowsForRange(range);\n\t\tconst byKey = new Map<string, TItem>();\n\t\tfor (const row of rows) {\n\t\t\tbyKey.set(deliveredRowIdKey(row.id), row);\n\t\t}\n\n\t\tconst manifestKeys = new Set(\n\t\t\tmanifest.map((m) => String(partialSyncRowKey(m.id))),\n\t\t);\n\n\t\tconst added: SyncMessage<TItem>[] = [];\n\t\tconst updated: SyncMessage<TItem>[] = [];\n\t\tconst stale: Array<string | number> = [];\n\t\tconst movedHints: Array<{\n\t\t\tid: string | number;\n\t\t\thint: Record<string, unknown>;\n\t\t}> = [];\n\n\t\tfor (const row of rows) {\n\t\t\tconst k = deliveredRowIdKey(row.id);\n\t\t\tif (!manifestKeys.has(k)) {\n\t\t\t\tadded.push({ type: \"insert\", value: row });\n\t\t\t}\n\t\t}\n\n\t\tfor (const entry of manifest) {\n\t\t\tconst k = String(partialSyncRowKey(entry.id));\n\t\t\tconst serverRow = byKey.get(k);\n\t\t\tif (serverRow === undefined) {\n\t\t\t\tstale.push(entry.id);\n\t\t\t\tconst getRow = this.options.store.getRow;\n\t\t\t\tconst resolveMovedHint = this.options.resolveMovedHint;\n\t\t\t\tif (getRow !== undefined && resolveMovedHint !== undefined) {\n\t\t\t\t\tconst current = await getRow(entry.id);\n\t\t\t\t\tif (current !== undefined) {\n\t\t\t\t\t\tconst hint = await resolveMovedHint(current, range);\n\t\t\t\t\t\tif (hint !== null) {\n\t\t\t\t\t\t\tmovedHints.push({ id: entry.id, hint });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst serverV = partialSyncRowVersionWatermarkMs(serverRow);\n\t\t\tif (serverV !== entry.version) {\n\t\t\t\tupdated.push({\n\t\t\t\t\ttype: \"update\",\n\t\t\t\t\tvalue: serverRow,\n\t\t\t\t\tpreviousValue: {\n\t\t\t\t\t\t...(serverRow as object),\n\t\t\t\t\t\tupdatedAt: entry.version,\n\t\t\t\t\t} as TItem,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tthis.#syncInterestAfterReconcile(state, range, rows);\n\n\t\tthis.#emit(clientId, {\n\t\t\ttype: \"rangeReconcileResult\",\n\t\t\trequestId,\n\t\t\tadded,\n\t\t\tupdated,\n\t\t\tstale,\n\t\t\tmovedHints,\n\t\t\ttotalCount,\n\t\t});\n\t}\n\n\tasync #collectRowsForRange(\n\t\trange: SyncRange,\n\t): Promise<{ rows: TItem[]; totalCount: number }> {\n\t\tconst chunkSize = Math.max(1, this.options.queryChunkSize ?? 200);\n\t\tif (range.kind === \"predicate\") {\n\t\t\tconst queryByPredicate = this.options.store.queryByPredicate;\n\t\t\tif (!queryByPredicate) {\n\t\t\t\treturn {\n\t\t\t\t\trows: [],\n\t\t\t\t\ttotalCount: await this.options.store.getTotalCount(),\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst limit = range.limit ?? chunkSize;\n\t\t\tconst totalCount = this.options.store.getPredicateCount\n\t\t\t\t? await this.options.store.getPredicateCount(range.conditions)\n\t\t\t\t: await this.options.store.getTotalCount();\n\t\t\tconst rows: TItem[] = [];\n\t\t\tfor await (const chunk of queryByPredicate({\n\t\t\t\tconditions: range.conditions,\n\t\t\t\tsort: range.sort,\n\t\t\t\tlimit,\n\t\t\t\tchunkSize,\n\t\t\t})) {\n\t\t\t\trows.push(...chunk);\n\t\t\t\tif (rows.length >= limit) break;\n\t\t\t}\n\t\t\treturn { rows: rows.slice(0, limit), totalCount };\n\t\t}\n\t\tif (range.kind === \"index\" && range.mode === \"offset\") {\n\t\t\tconst totalCount = await this.options.store.getTotalCount();\n\t\t\tconst rows: TItem[] = [];\n\t\t\tfor await (const chunk of this.options.store.queryByOffset({\n\t\t\t\tsort: range.sort,\n\t\t\t\tlimit: range.limit,\n\t\t\t\toffset: range.offset,\n\t\t\t\tchunkSize,\n\t\t\t})) {\n\t\t\t\trows.push(...chunk);\n\t\t\t\tif (rows.length >= range.limit) break;\n\t\t\t}\n\t\t\treturn { rows: rows.slice(0, range.limit), totalCount };\n\t\t}\n\t\tif (range.kind === \"index\" && range.mode === \"cursor\") {\n\t\t\tconst totalCount = await this.options.store.getTotalCount();\n\t\t\tconst rows: TItem[] = [];\n\t\t\tfor await (const chunk of this.options.store.queryRange({\n\t\t\t\tsort: range.sort,\n\t\t\t\tlimit: range.limit,\n\t\t\t\tafterCursor: range.afterCursor,\n\t\t\t\tchunkSize,\n\t\t\t})) {\n\t\t\t\trows.push(...chunk);\n\t\t\t\tif (rows.length >= range.limit) break;\n\t\t\t}\n\t\t\treturn { rows: rows.slice(0, range.limit), totalCount };\n\t\t}\n\t\texhaustiveGuard(range);\n\t}\n\n\t#syncInterestAfterReconcile(\n\t\tstate: ClientQueryState<TItem>,\n\t\trange: SyncRange,\n\t\trows: TItem[],\n\t): void {\n\t\tstate.deliveredRowIds.clear();\n\t\tfor (const row of rows) {\n\t\t\tstate.deliveredRowIds.add(deliveredRowIdKey(row.id));\n\t\t}\n\t\tstate.deliveredRanges.length = 0;\n\t\tconst sort =\n\t\t\trange.kind === \"index\"\n\t\t\t\t? range.sort\n\t\t\t\t: range.kind === \"predicate\"\n\t\t\t\t\t? range.sort\n\t\t\t\t\t: undefined;\n\t\tif (sort !== undefined && rows.length > 0) {\n\t\t\tthis.#trackDeliveredRange(state, sort, null, rows);\n\t\t}\n\t}\n\n\tasync #handleQueryPredicate(\n\t\tmessage: Extract<SyncClientMessage, { type: \"rangeQuery\" }>,\n\t\trange: Extract<SyncRange, { kind: \"predicate\" }>,\n\t): Promise<void> {\n\t\tconst queryByPredicate = this.options.store.queryByPredicate;\n\t\tif (!queryByPredicate) {\n\t\t\tconst totalCount = await this.options.store.getTotalCount();\n\t\t\tthis.#emit(message.clientId, {\n\t\t\t\ttype: \"queryRangeChunk\",\n\t\t\t\trequestId: message.requestId,\n\t\t\t\trows: [],\n\t\t\t\ttotalCount,\n\t\t\t\tlastCursor: null,\n\t\t\t\thasMore: false,\n\t\t\t\tchunkIndex: 0,\n\t\t\t\tdone: true,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst state = this.#getOrCreateClientState(message.clientId);\n\t\tstate.streaming = true;\n\t\tconst chunkSize = Math.max(1, this.options.queryChunkSize ?? 200);\n\t\tconst limit = range.limit ?? chunkSize;\n\t\tconst totalCount = this.options.store.getPredicateCount\n\t\t\t? await this.options.store.getPredicateCount(range.conditions)\n\t\t\t: await this.options.store.getTotalCount();\n\n\t\tconst iterable = queryByPredicate({\n\t\t\tconditions: range.conditions,\n\t\t\tsort: range.sort,\n\t\t\tlimit,\n\t\t\tchunkSize,\n\t\t});\n\n\t\tlet chunkIndex = 0;\n\t\tlet totalDelivered = 0;\n\t\tlet emittedAny = false;\n\t\tconst sortForTrack = range.sort;\n\t\tfor await (const rows of iterable) {\n\t\t\temittedAny = true;\n\t\t\ttotalDelivered += rows.length;\n\t\t\tconst reachedLimit = totalDelivered >= limit;\n\t\t\tconst likelyFinalChunk = rows.length < chunkSize || reachedLimit;\n\t\t\tconst isFinalChunk = likelyFinalChunk;\n\t\t\tconst lastRow = rows[rows.length - 1];\n\t\t\tconst lastCursor =\n\t\t\t\tlastRow === undefined || sortForTrack === undefined\n\t\t\t\t\t? null\n\t\t\t\t\t: this.options.store.getSortValue(lastRow, sortForTrack.column);\n\t\t\tconst hasMoreForClient = isFinalChunk\n\t\t\t\t? totalDelivered === limit && totalDelivered < totalCount\n\t\t\t\t: true;\n\t\t\tthis.#emit(message.clientId, {\n\t\t\t\ttype: \"queryRangeChunk\",\n\t\t\t\trequestId: message.requestId,\n\t\t\t\trows,\n\t\t\t\ttotalCount,\n\t\t\t\tlastCursor,\n\t\t\t\thasMore: hasMoreForClient,\n\t\t\t\tchunkIndex,\n\t\t\t\tdone: isFinalChunk,\n\t\t\t});\n\t\t\tif (sortForTrack !== undefined) {\n\t\t\t\tthis.#trackDeliveredRange(state, sortForTrack, null, rows);\n\t\t\t}\n\t\t\tthis.#trackDeliveredRowIdsFromRows(state, rows as TItem[]);\n\t\t\tchunkIndex += 1;\n\t\t\tif (isFinalChunk) break;\n\t\t}\n\n\t\tif (!emittedAny) {\n\t\t\tthis.#emit(message.clientId, {\n\t\t\t\ttype: \"queryRangeChunk\",\n\t\t\t\trequestId: message.requestId,\n\t\t\t\trows: [],\n\t\t\t\ttotalCount,\n\t\t\t\tlastCursor: null,\n\t\t\t\thasMore: false,\n\t\t\t\tchunkIndex,\n\t\t\t\tdone: true,\n\t\t\t});\n\t\t}\n\n\t\tstate.streaming = false;\n\t\tthis.#flushPendingPatches(state);\n\t}\n\n\t#mergeDeliveredRangesFromChanges(\n\t\tstate: ClientQueryState<TItem>,\n\t\trange: SyncRange,\n\t\tchanges: SyncMessage<TItem>[],\n\t): void {\n\t\tconst sort =\n\t\t\trange.kind === \"index\"\n\t\t\t\t? range.sort\n\t\t\t\t: range.kind === \"predicate\"\n\t\t\t\t\t? range.sort\n\t\t\t\t\t: undefined;\n\t\tif (sort === undefined) return;\n\t\tconst rows: TItem[] = [];\n\t\tfor (const change of changes) {\n\t\t\tif (change.type === \"insert\" || change.type === \"update\") {\n\t\t\t\trows.push(change.value);\n\t\t\t}\n\t\t}\n\t\tif (rows.length === 0) return;\n\t\tthis.#trackDeliveredRange(state, sort, null, rows);\n\t\tthis.#trackDeliveredRowIdsFromRows(state, rows);\n\t}\n\n\tasync #handleQueryRange(\n\t\tmessage: Extract<SyncClientMessage, { type: \"queryRange\" }>,\n\t): Promise<void> {\n\t\tconst state = this.#getOrCreateClientState(message.clientId);\n\t\tstate.streaming = true;\n\t\tconst totalCount = await this.options.store.getTotalCount();\n\t\tconst chunkSize = Math.max(1, this.options.queryChunkSize ?? 200);\n\t\tconst iterable = this.options.store.queryRange({\n\t\t\tsort: message.sort,\n\t\t\tlimit: message.limit,\n\t\t\tafterCursor: message.afterCursor,\n\t\t\tchunkSize,\n\t\t});\n\t\tlet chunkIndex = 0;\n\t\tlet totalDelivered = 0;\n\t\tlet emittedAny = false;\n\t\tfor await (const rows of iterable) {\n\t\t\temittedAny = true;\n\t\t\ttotalDelivered += rows.length;\n\t\t\tconst reachedLimit = totalDelivered >= message.limit;\n\t\t\tconst likelyFinalChunk = rows.length < chunkSize || reachedLimit;\n\t\t\tconst isFinalChunk = likelyFinalChunk;\n\t\t\tconst lastRow = rows[rows.length - 1];\n\t\t\tconst lastCursor =\n\t\t\t\tlastRow === undefined\n\t\t\t\t\t? message.afterCursor\n\t\t\t\t\t: this.options.store.getSortValue(lastRow, message.sort.column);\n\t\t\t// Pagination: more pages may exist if this request returned a full page and\n\t\t\t// the table still has rows beyond what we returned (not `!isFinalChunk`, which\n\t\t\t// only meant \"more chunks in this stream\" and wrongly set hasMore=false on the\n\t\t\t// last chunk of a single-page response).\n\t\t\tconst hasMoreForClient = isFinalChunk\n\t\t\t\t? totalDelivered === message.limit && totalDelivered < totalCount\n\t\t\t\t: true;\n\t\t\tthis.#emit(message.clientId, {\n\t\t\t\ttype: \"queryRangeChunk\",\n\t\t\t\trequestId: message.requestId,\n\t\t\t\trows,\n\t\t\t\ttotalCount,\n\t\t\t\tlastCursor,\n\t\t\t\thasMore: hasMoreForClient,\n\t\t\t\tchunkIndex,\n\t\t\t\tdone: isFinalChunk,\n\t\t\t});\n\t\t\tthis.#trackDeliveredRange(state, message.sort, message.afterCursor, rows);\n\t\t\tthis.#trackDeliveredRowIdsFromRows(state, rows as TItem[]);\n\t\t\tchunkIndex += 1;\n\t\t\tif (isFinalChunk) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!emittedAny) {\n\t\t\tthis.#emit(message.clientId, {\n\t\t\t\ttype: \"queryRangeChunk\",\n\t\t\t\trequestId: message.requestId,\n\t\t\t\trows: [],\n\t\t\t\ttotalCount,\n\t\t\t\tlastCursor: message.afterCursor,\n\t\t\t\thasMore: false,\n\t\t\t\tchunkIndex,\n\t\t\t\tdone: true,\n\t\t\t});\n\t\t}\n\n\t\tstate.streaming = false;\n\t\tthis.#flushPendingPatches(state);\n\t}\n\n\tasync #handleQueryByOffset(\n\t\tmessage: Extract<SyncClientMessage, { type: \"queryByOffset\" }>,\n\t): Promise<void> {\n\t\tconst state = this.#getOrCreateClientState(message.clientId);\n\t\tstate.streaming = true;\n\t\tconst totalCount = await this.options.store.getTotalCount();\n\t\tconst chunkSize = Math.max(1, this.options.queryChunkSize ?? 200);\n\t\tconst iterable = this.options.store.queryByOffset({\n\t\t\tsort: message.sort,\n\t\t\tlimit: message.limit,\n\t\t\toffset: message.offset,\n\t\t\tchunkSize,\n\t\t});\n\t\tlet chunkIndex = 0;\n\t\tlet totalDelivered = 0;\n\t\tlet emittedAny = false;\n\t\tfor await (const rows of iterable) {\n\t\t\temittedAny = true;\n\t\t\ttotalDelivered += rows.length;\n\t\t\tconst reachedLimit = totalDelivered >= message.limit;\n\t\t\tconst likelyFinalChunk = rows.length < chunkSize || reachedLimit;\n\t\t\tconst isFinalChunk = likelyFinalChunk;\n\t\t\tconst lastRow = rows[rows.length - 1];\n\t\t\tconst lastCursor =\n\t\t\t\tlastRow === undefined\n\t\t\t\t\t? null\n\t\t\t\t\t: this.options.store.getSortValue(lastRow, message.sort.column);\n\t\t\tconst hasMoreForClient = isFinalChunk\n\t\t\t\t? totalDelivered === message.limit &&\n\t\t\t\t\tmessage.offset + totalDelivered < totalCount\n\t\t\t\t: true;\n\t\t\tthis.#emit(message.clientId, {\n\t\t\t\ttype: \"queryRangeChunk\",\n\t\t\t\trequestId: message.requestId,\n\t\t\t\trows,\n\t\t\t\ttotalCount,\n\t\t\t\tlastCursor,\n\t\t\t\thasMore: hasMoreForClient,\n\t\t\t\tchunkIndex,\n\t\t\t\tdone: isFinalChunk,\n\t\t\t});\n\t\t\tthis.#trackDeliveredRange(state, message.sort, null, rows);\n\t\t\tthis.#trackDeliveredRowIdsFromRows(state, rows as TItem[]);\n\t\t\tchunkIndex += 1;\n\t\t\tif (isFinalChunk) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!emittedAny) {\n\t\t\tthis.#emit(message.clientId, {\n\t\t\t\ttype: \"queryRangeChunk\",\n\t\t\t\trequestId: message.requestId,\n\t\t\t\trows: [],\n\t\t\t\ttotalCount,\n\t\t\t\tlastCursor: null,\n\t\t\t\thasMore: false,\n\t\t\t\tchunkIndex,\n\t\t\t\tdone: true,\n\t\t\t});\n\t\t}\n\n\t\tstate.streaming = false;\n\t\tthis.#flushPendingPatches(state);\n\t}\n\n\t#getOrCreateClientState(clientId: string): ClientQueryState<TItem> {\n\t\tlet state = this.#clientStates.get(clientId);\n\t\tif (!state) {\n\t\t\tstate = {\n\t\t\t\tclientId,\n\t\t\t\tdeliveredRanges: [],\n\t\t\t\tpredicateGroups: [],\n\t\t\t\tdeliveredRowIds: new Set(),\n\t\t\t\tpendingPatches: [],\n\t\t\t\tstreaming: false,\n\t\t\t};\n\t\t\tthis.#clientStates.set(clientId, state);\n\t\t}\n\t\treturn state;\n\t}\n\n\t#trackDeliveredRange(\n\t\tstate: ClientQueryState<TItem>,\n\t\tsort: SyncRangeSort,\n\t\tafterCursor: unknown | null,\n\t\trows: TItem[],\n\t): void {\n\t\tif (rows.length === 0) return;\n\t\tconst firstValue =\n\t\t\tafterCursor ??\n\t\t\tthis.options.store.getSortValue(rows[0] as TItem, sort.column);\n\t\tconst lastValue = this.options.store.getSortValue(\n\t\t\trows[rows.length - 1] as TItem,\n\t\t\tsort.column,\n\t\t);\n\t\tconst range: DeliveredRange = {\n\t\t\tsortColumn: sort.column,\n\t\t\tsortDirection: sort.direction,\n\t\t\tfromValue: firstValue,\n\t\t\ttoValue: lastValue,\n\t\t};\n\t\tstate.deliveredRanges.push(range);\n\t}\n\n\t#flushPendingPatches(state: ClientQueryState<TItem>): void {\n\t\tif (state.pendingPatches.length === 0) return;\n\t\tfor (const patch of state.pendingPatches) {\n\t\t\tthis.#emit(state.clientId, {\n\t\t\t\ttype: \"rangePatch\",\n\t\t\t\tchange: patch.change,\n\t\t\t\t...(patch.viewTransition !== undefined\n\t\t\t\t\t? { viewTransition: patch.viewTransition }\n\t\t\t\t\t: {}),\n\t\t\t});\n\t\t\tthis.#applyPatchToDeliveredRowIds(state, patch);\n\t\t}\n\t\tstate.pendingPatches.length = 0;\n\t}\n}\n"]}
@@ -0,0 +1,209 @@
1
+ import { DEFAULT_SYNC_COLLECTION_ID, toSyncMessage } from './chunk-BJJEAKXL.js';
2
+ import { partialSyncRowKey } from './chunk-UJ24XW52.js';
3
+ import { __privateAdd, __privateSet, __privateGet, __privateMethod } from './chunk-HMLY7DHA.js';
4
+ import { exhaustiveGuard } from '@firtoz/maybe-error';
5
+
6
+ var _serverVersion, _changeLog, _cid, _SyncServerBridge_instances, emit_fn, broadcastExcept_fn, broadcastAll_fn, handleMutateBatch_fn, intentToMessageLww_fn, toMillis_fn, resolveBackfill_fn, chunkBackfillChanges_fn;
7
+ var SyncServerBridge = class {
8
+ constructor(options) {
9
+ this.options = options;
10
+ __privateAdd(this, _SyncServerBridge_instances);
11
+ __privateAdd(this, _serverVersion, 0);
12
+ __privateAdd(this, _changeLog, []);
13
+ __privateAdd(this, _cid);
14
+ __privateSet(this, _cid, options.collectionId ?? DEFAULT_SYNC_COLLECTION_ID);
15
+ }
16
+ get collectionId() {
17
+ return __privateGet(this, _cid);
18
+ }
19
+ get serverVersion() {
20
+ return __privateGet(this, _serverVersion);
21
+ }
22
+ async handleClientMessage(message) {
23
+ const mid = message.collectionId ?? DEFAULT_SYNC_COLLECTION_ID;
24
+ if (mid !== __privateGet(this, _cid)) return;
25
+ switch (message.type) {
26
+ case "ping":
27
+ __privateMethod(this, _SyncServerBridge_instances, emit_fn).call(this, message.clientId, {
28
+ type: "pong",
29
+ timestamp: message.timestamp
30
+ });
31
+ return;
32
+ case "syncHello": {
33
+ const { mode, changes } = await __privateMethod(this, _SyncServerBridge_instances, resolveBackfill_fn).call(this, message.lastAckedServerVersion);
34
+ const chunks = __privateMethod(this, _SyncServerBridge_instances, chunkBackfillChanges_fn).call(this, changes);
35
+ const totalChunks = chunks.length;
36
+ for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex += 1) {
37
+ __privateMethod(this, _SyncServerBridge_instances, emit_fn).call(this, message.clientId, {
38
+ type: "syncBackfill",
39
+ mode,
40
+ serverVersion: __privateGet(this, _serverVersion),
41
+ changes: chunks[chunkIndex],
42
+ chunkIndex,
43
+ totalChunks
44
+ });
45
+ }
46
+ return;
47
+ }
48
+ case "mutateBatch":
49
+ await __privateMethod(this, _SyncServerBridge_instances, handleMutateBatch_fn).call(this, message);
50
+ return;
51
+ case "queryRange":
52
+ case "queryByOffset":
53
+ case "rangeQuery":
54
+ case "rangeReconcile":
55
+ return;
56
+ default:
57
+ exhaustiveGuard(message);
58
+ }
59
+ }
60
+ /**
61
+ * Apply mutations that originated on the server (cron, admin API, etc.) and fan out to all clients.
62
+ */
63
+ async pushServerChanges(changes) {
64
+ if (changes.length === 0) return;
65
+ await this.options.store.applySyncMessages(changes);
66
+ __privateSet(this, _serverVersion, __privateGet(this, _serverVersion) + 1);
67
+ __privateGet(this, _changeLog).push({
68
+ serverVersion: __privateGet(this, _serverVersion),
69
+ changes
70
+ });
71
+ __privateMethod(this, _SyncServerBridge_instances, broadcastAll_fn).call(this, {
72
+ type: "syncBatch",
73
+ serverVersion: __privateGet(this, _serverVersion),
74
+ changes
75
+ });
76
+ }
77
+ };
78
+ _serverVersion = new WeakMap();
79
+ _changeLog = new WeakMap();
80
+ _cid = new WeakMap();
81
+ _SyncServerBridge_instances = new WeakSet();
82
+ emit_fn = function(clientId, body) {
83
+ this.options.sendToClient(clientId, {
84
+ ...body,
85
+ collectionId: __privateGet(this, _cid)
86
+ });
87
+ };
88
+ broadcastExcept_fn = function(excludeClientId, body) {
89
+ return this.options.broadcastExcept(excludeClientId, {
90
+ ...body,
91
+ collectionId: __privateGet(this, _cid)
92
+ });
93
+ };
94
+ broadcastAll_fn = function(body) {
95
+ this.options.broadcastAll?.({
96
+ ...body,
97
+ collectionId: __privateGet(this, _cid)
98
+ });
99
+ };
100
+ handleMutateBatch_fn = async function(message) {
101
+ const resolvedChanges = [];
102
+ const acceptedMutationIds = [];
103
+ for (const mutation of message.mutations) {
104
+ try {
105
+ const change = await __privateMethod(this, _SyncServerBridge_instances, intentToMessageLww_fn).call(this, mutation);
106
+ if (!change) {
107
+ continue;
108
+ }
109
+ resolvedChanges.push(change);
110
+ acceptedMutationIds.push(mutation.clientMutationId);
111
+ } catch (error) {
112
+ __privateMethod(this, _SyncServerBridge_instances, emit_fn).call(this, message.clientId, {
113
+ type: "reject",
114
+ clientId: message.clientId,
115
+ clientMutationId: mutation.clientMutationId,
116
+ reason: error instanceof Error ? error.message : String(error),
117
+ correctiveChanges: []
118
+ });
119
+ }
120
+ }
121
+ if (resolvedChanges.length === 0) return;
122
+ await this.options.store.applySyncMessages(resolvedChanges);
123
+ __privateSet(this, _serverVersion, __privateGet(this, _serverVersion) + 1);
124
+ __privateGet(this, _changeLog).push({
125
+ serverVersion: __privateGet(this, _serverVersion),
126
+ changes: resolvedChanges
127
+ });
128
+ __privateMethod(this, _SyncServerBridge_instances, emit_fn).call(this, message.clientId, {
129
+ type: "ack",
130
+ clientId: message.clientId,
131
+ clientMutationIds: acceptedMutationIds,
132
+ serverVersion: __privateGet(this, _serverVersion),
133
+ changes: resolvedChanges
134
+ });
135
+ await Promise.resolve(
136
+ __privateMethod(this, _SyncServerBridge_instances, broadcastExcept_fn).call(this, message.clientId, {
137
+ type: "syncBatch",
138
+ serverVersion: __privateGet(this, _serverVersion),
139
+ changes: resolvedChanges
140
+ })
141
+ );
142
+ };
143
+ intentToMessageLww_fn = async function(intent) {
144
+ const base = toSyncMessage(intent);
145
+ if (base.type !== "update") {
146
+ return base;
147
+ }
148
+ const key = partialSyncRowKey(intent.key ?? base.value.id);
149
+ const existing = await this.options.store.getRow(key);
150
+ if (!existing) {
151
+ return base;
152
+ }
153
+ const incomingUpdatedAt = __privateMethod(this, _SyncServerBridge_instances, toMillis_fn).call(this, base.value.updatedAt);
154
+ const existingUpdatedAt = __privateMethod(this, _SyncServerBridge_instances, toMillis_fn).call(this, existing.updatedAt);
155
+ if (incomingUpdatedAt <= existingUpdatedAt) {
156
+ return {
157
+ type: "update",
158
+ value: existing,
159
+ previousValue: base.previousValue
160
+ };
161
+ }
162
+ return base;
163
+ };
164
+ toMillis_fn = function(value) {
165
+ if (typeof value === "number") return value;
166
+ if (value instanceof Date) return value.getTime();
167
+ return 0;
168
+ };
169
+ resolveBackfill_fn = async function(lastAckedServerVersion) {
170
+ if (lastAckedServerVersion <= 0) {
171
+ return {
172
+ mode: "snapshot",
173
+ changes: await this.options.store.getSnapshotMessages()
174
+ };
175
+ }
176
+ if (lastAckedServerVersion > __privateGet(this, _serverVersion)) {
177
+ return {
178
+ mode: "snapshot",
179
+ changes: await this.options.store.getSnapshotMessages()
180
+ };
181
+ }
182
+ const oldestLogged = __privateGet(this, _changeLog)[0]?.serverVersion;
183
+ if (oldestLogged !== void 0 && lastAckedServerVersion < oldestLogged - 1) {
184
+ return {
185
+ mode: "snapshot",
186
+ changes: await this.options.store.getSnapshotMessages()
187
+ };
188
+ }
189
+ const changes = [];
190
+ for (const entry of __privateGet(this, _changeLog)) {
191
+ if (entry.serverVersion > lastAckedServerVersion) {
192
+ changes.push(...entry.changes);
193
+ }
194
+ }
195
+ return { mode: "delta", changes };
196
+ };
197
+ chunkBackfillChanges_fn = function(changes) {
198
+ const chunkSize = Math.max(1, this.options.backfillChunkSize ?? 500);
199
+ if (changes.length === 0) return [[]];
200
+ const chunks = [];
201
+ for (let i = 0; i < changes.length; i += chunkSize) {
202
+ chunks.push(changes.slice(i, i + chunkSize));
203
+ }
204
+ return chunks;
205
+ };
206
+
207
+ export { SyncServerBridge };
208
+ //# sourceMappingURL=chunk-TEH7V76G.js.map
209
+ //# sourceMappingURL=chunk-TEH7V76G.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sync-server-bridge.ts"],"names":[],"mappings":"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","file":"chunk-TEH7V76G.js","sourcesContent":["import type { SyncMessage } from \"@firtoz/db-helpers\";\nimport { exhaustiveGuard } from \"@firtoz/maybe-error\";\nimport type {\n\tMutationIntent,\n\tSyncBackfillMode,\n\tSyncClientMessage,\n\tSyncServerMessage,\n\tSyncServerMessageBody,\n} from \"./sync-protocol\";\nimport { DEFAULT_SYNC_COLLECTION_ID } from \"./sync-protocol\";\nimport { toSyncMessage } from \"./sync-protocol\";\nimport {\n\tpartialSyncRowKey,\n\ttype PartialSyncRowShape,\n} from \"./partial-sync-row-key\";\n\nexport interface SyncServerBridgeStore<TItem> {\n\tapplySyncMessages: (messages: SyncMessage<TItem>[]) => Promise<void>;\n\tgetSnapshotMessages: () => Promise<SyncMessage<TItem>[]>;\n\tgetRow: (key: string | number) => Promise<TItem | undefined>;\n}\n\nexport interface SyncServerBridgeOptions<TItem> {\n\tstore: SyncServerBridgeStore<TItem>;\n\tsendToClient: (clientId: string, message: SyncServerMessage<TItem>) => void;\n\tbroadcastExcept: (\n\t\texcludeClientId: string,\n\t\tmessage: SyncServerMessage<TItem>,\n\t) => void | Promise<void>;\n\t/** Deliver a server message to every connected client (e.g. {@link SyncServerBridge.pushServerChanges}). */\n\tbroadcastAll?: (message: SyncServerMessage<TItem>) => void;\n\t/** Maximum number of changes per `syncBackfill` frame. Defaults to 500. */\n\tbackfillChunkSize?: number;\n\t/** Multiplex key for sync messages. Default {@link DEFAULT_SYNC_COLLECTION_ID}. */\n\tcollectionId?: string;\n}\n\nexport class SyncServerBridge<TItem extends PartialSyncRowShape> {\n\t#serverVersion = 0;\n\t#changeLog: Array<{ serverVersion: number; changes: SyncMessage<TItem>[] }> =\n\t\t[];\n\treadonly #cid: string;\n\n\tconstructor(private readonly options: SyncServerBridgeOptions<TItem>) {\n\t\tthis.#cid = options.collectionId ?? DEFAULT_SYNC_COLLECTION_ID;\n\t}\n\n\tget collectionId(): string {\n\t\treturn this.#cid;\n\t}\n\n\t#emit(clientId: string, body: SyncServerMessageBody<TItem>): void {\n\t\tthis.options.sendToClient(clientId, {\n\t\t\t...body,\n\t\t\tcollectionId: this.#cid,\n\t\t} as SyncServerMessage<TItem>);\n\t}\n\n\t#broadcastExcept(\n\t\texcludeClientId: string,\n\t\tbody: SyncServerMessageBody<TItem>,\n\t): void | Promise<void> {\n\t\treturn this.options.broadcastExcept(excludeClientId, {\n\t\t\t...body,\n\t\t\tcollectionId: this.#cid,\n\t\t} as SyncServerMessage<TItem>);\n\t}\n\n\t#broadcastAll(body: SyncServerMessageBody<TItem>): void {\n\t\tthis.options.broadcastAll?.({\n\t\t\t...body,\n\t\t\tcollectionId: this.#cid,\n\t\t} as SyncServerMessage<TItem>);\n\t}\n\n\tget serverVersion(): number {\n\t\treturn this.#serverVersion;\n\t}\n\n\tasync handleClientMessage(message: SyncClientMessage): Promise<void> {\n\t\tconst mid = message.collectionId ?? DEFAULT_SYNC_COLLECTION_ID;\n\t\tif (mid !== this.#cid) return;\n\t\tswitch (message.type) {\n\t\t\tcase \"ping\":\n\t\t\t\tthis.#emit(message.clientId, {\n\t\t\t\t\ttype: \"pong\",\n\t\t\t\t\ttimestamp: message.timestamp,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\tcase \"syncHello\": {\n\t\t\t\tconst { mode, changes } = await this.#resolveBackfill(\n\t\t\t\t\tmessage.lastAckedServerVersion,\n\t\t\t\t);\n\t\t\t\tconst chunks = this.#chunkBackfillChanges(changes);\n\t\t\t\tconst totalChunks = chunks.length;\n\t\t\t\tfor (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex += 1) {\n\t\t\t\t\tthis.#emit(message.clientId, {\n\t\t\t\t\t\ttype: \"syncBackfill\",\n\t\t\t\t\t\tmode,\n\t\t\t\t\t\tserverVersion: this.#serverVersion,\n\t\t\t\t\t\tchanges: chunks[chunkIndex],\n\t\t\t\t\t\tchunkIndex,\n\t\t\t\t\t\ttotalChunks,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase \"mutateBatch\":\n\t\t\t\tawait this.#handleMutateBatch(message);\n\t\t\t\treturn;\n\t\t\tcase \"queryRange\":\n\t\t\tcase \"queryByOffset\":\n\t\t\tcase \"rangeQuery\":\n\t\t\tcase \"rangeReconcile\":\n\t\t\t\t// Not supported by the full-sync bridge; partial sync uses PartialSyncServerBridge.\n\t\t\t\treturn;\n\t\t\tdefault:\n\t\t\t\texhaustiveGuard(message);\n\t\t}\n\t}\n\n\tasync #handleMutateBatch(\n\t\tmessage: Extract<SyncClientMessage, { type: \"mutateBatch\" }>,\n\t): Promise<void> {\n\t\tconst resolvedChanges: SyncMessage<TItem>[] = [];\n\t\tconst acceptedMutationIds: string[] = [];\n\n\t\tfor (const mutation of message.mutations) {\n\t\t\ttry {\n\t\t\t\tconst change = await this.#intentToMessageLww(mutation);\n\t\t\t\tif (!change) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tresolvedChanges.push(change);\n\t\t\t\tacceptedMutationIds.push(mutation.clientMutationId);\n\t\t\t} catch (error) {\n\t\t\t\tthis.#emit(message.clientId, {\n\t\t\t\t\ttype: \"reject\",\n\t\t\t\t\tclientId: message.clientId,\n\t\t\t\t\tclientMutationId: mutation.clientMutationId,\n\t\t\t\t\treason: error instanceof Error ? error.message : String(error),\n\t\t\t\t\tcorrectiveChanges: [],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (resolvedChanges.length === 0) return;\n\n\t\tawait this.options.store.applySyncMessages(resolvedChanges);\n\t\tthis.#serverVersion += 1;\n\t\tthis.#changeLog.push({\n\t\t\tserverVersion: this.#serverVersion,\n\t\t\tchanges: resolvedChanges,\n\t\t});\n\n\t\tthis.#emit(message.clientId, {\n\t\t\ttype: \"ack\",\n\t\t\tclientId: message.clientId,\n\t\t\tclientMutationIds: acceptedMutationIds,\n\t\t\tserverVersion: this.#serverVersion,\n\t\t\tchanges: resolvedChanges,\n\t\t});\n\n\t\tawait Promise.resolve(\n\t\t\tthis.#broadcastExcept(message.clientId, {\n\t\t\t\ttype: \"syncBatch\",\n\t\t\t\tserverVersion: this.#serverVersion,\n\t\t\t\tchanges: resolvedChanges,\n\t\t\t}),\n\t\t);\n\t}\n\n\tasync #intentToMessageLww(\n\t\tintent: MutationIntent,\n\t): Promise<SyncMessage<TItem> | null> {\n\t\tconst base = toSyncMessage(intent) as SyncMessage<TItem>;\n\t\tif (base.type !== \"update\") {\n\t\t\treturn base;\n\t\t}\n\t\tconst key = partialSyncRowKey(intent.key ?? base.value.id);\n\t\tconst existing = await this.options.store.getRow(key);\n\t\tif (!existing) {\n\t\t\treturn base;\n\t\t}\n\t\tconst incomingUpdatedAt = this.#toMillis(base.value.updatedAt);\n\t\tconst existingUpdatedAt = this.#toMillis(existing.updatedAt);\n\t\tif (incomingUpdatedAt <= existingUpdatedAt) {\n\t\t\treturn {\n\t\t\t\ttype: \"update\",\n\t\t\t\tvalue: existing,\n\t\t\t\tpreviousValue: base.previousValue,\n\t\t\t};\n\t\t}\n\t\treturn base;\n\t}\n\n\t#toMillis(value: number | Date | null | undefined): number {\n\t\tif (typeof value === \"number\") return value;\n\t\tif (value instanceof Date) return value.getTime();\n\t\treturn 0;\n\t}\n\n\tasync #resolveBackfill(lastAckedServerVersion: number): Promise<{\n\t\tmode: SyncBackfillMode;\n\t\tchanges: SyncMessage<TItem>[];\n\t}> {\n\t\tif (lastAckedServerVersion <= 0) {\n\t\t\treturn {\n\t\t\t\tmode: \"snapshot\",\n\t\t\t\tchanges: await this.options.store.getSnapshotMessages(),\n\t\t\t};\n\t\t}\n\t\t// Client can be \"ahead\" after server restart/reset; force a full snapshot.\n\t\tif (lastAckedServerVersion > this.#serverVersion) {\n\t\t\treturn {\n\t\t\t\tmode: \"snapshot\",\n\t\t\t\tchanges: await this.options.store.getSnapshotMessages(),\n\t\t\t};\n\t\t}\n\t\tconst oldestLogged = this.#changeLog[0]?.serverVersion;\n\t\tif (\n\t\t\toldestLogged !== undefined &&\n\t\t\tlastAckedServerVersion < oldestLogged - 1\n\t\t) {\n\t\t\treturn {\n\t\t\t\tmode: \"snapshot\",\n\t\t\t\tchanges: await this.options.store.getSnapshotMessages(),\n\t\t\t};\n\t\t}\n\n\t\tconst changes: SyncMessage<TItem>[] = [];\n\t\tfor (const entry of this.#changeLog) {\n\t\t\tif (entry.serverVersion > lastAckedServerVersion) {\n\t\t\t\tchanges.push(...entry.changes);\n\t\t\t}\n\t\t}\n\t\treturn { mode: \"delta\", changes };\n\t}\n\n\t#chunkBackfillChanges(changes: SyncMessage<TItem>[]): SyncMessage<TItem>[][] {\n\t\tconst chunkSize = Math.max(1, this.options.backfillChunkSize ?? 500);\n\t\tif (changes.length === 0) return [[]];\n\t\tconst chunks: SyncMessage<TItem>[][] = [];\n\t\tfor (let i = 0; i < changes.length; i += chunkSize) {\n\t\t\tchunks.push(changes.slice(i, i + chunkSize));\n\t\t}\n\t\treturn chunks;\n\t}\n\n\t/**\n\t * Apply mutations that originated on the server (cron, admin API, etc.) and fan out to all clients.\n\t */\n\tasync pushServerChanges(changes: SyncMessage<TItem>[]): Promise<void> {\n\t\tif (changes.length === 0) return;\n\t\tawait this.options.store.applySyncMessages(changes);\n\t\tthis.#serverVersion += 1;\n\t\tthis.#changeLog.push({\n\t\t\tserverVersion: this.#serverVersion,\n\t\t\tchanges,\n\t\t});\n\t\tthis.#broadcastAll({\n\t\t\ttype: \"syncBatch\",\n\t\t\tserverVersion: this.#serverVersion,\n\t\t\tchanges,\n\t\t});\n\t}\n}\n"]}
@@ -0,0 +1,20 @@
1
+ // src/partial-sync-row-key.ts
2
+ function partialSyncRowVersionWatermarkMs(row) {
3
+ const v = row.updatedAt;
4
+ if (v === null || v === void 0) return 0;
5
+ if (typeof v === "number") return v;
6
+ if (v instanceof Date) return v.getTime();
7
+ return 0;
8
+ }
9
+ function partialSyncRowVersionWatermarkMsUnknown(row) {
10
+ if (!row || typeof row !== "object" || !("updatedAt" in row)) return 0;
11
+ return partialSyncRowVersionWatermarkMs(row);
12
+ }
13
+ function partialSyncRowKey(id) {
14
+ if (typeof id === "string" || typeof id === "number") return id;
15
+ return String(id);
16
+ }
17
+
18
+ export { partialSyncRowKey, partialSyncRowVersionWatermarkMs, partialSyncRowVersionWatermarkMsUnknown };
19
+ //# sourceMappingURL=chunk-UJ24XW52.js.map
20
+ //# sourceMappingURL=chunk-UJ24XW52.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/partial-sync-row-key.ts"],"names":[],"mappings":";AAiCO,SAAS,iCACf,GAAA,EACS;AACT,EAAA,MAAM,IAAI,GAAA,CAAI,SAAA;AACd,EAAA,IAAI,CAAA,KAAM,IAAA,IAAQ,CAAA,KAAM,MAAA,EAAW,OAAO,CAAA;AAC1C,EAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,CAAA;AAClC,EAAA,IAAI,CAAA,YAAa,IAAA,EAAM,OAAO,CAAA,CAAE,OAAA,EAAQ;AACxC,EAAA,OAAO,CAAA;AACR;AAOO,SAAS,wCAAwC,GAAA,EAAsB;AAC7E,EAAA,IAAI,CAAC,OAAO,OAAO,GAAA,KAAQ,YAAY,EAAE,WAAA,IAAe,MAAM,OAAO,CAAA;AACrE,EAAA,OAAO,iCAAiC,GAA4B,CAAA;AACrE;AAEO,SAAS,kBAAkB,EAAA,EAAuC;AACxE,EAAA,IAAI,OAAO,EAAA,KAAO,QAAA,IAAY,OAAO,EAAA,KAAO,UAAU,OAAO,EAAA;AAC7D,EAAA,OAAO,OAAO,EAAE,CAAA;AACjB","file":"chunk-UJ24XW52.js","sourcesContent":["/**\n * Row `id` values accepted by partial-sync (plain keys and ORM outputs such as drizzle-sqlite-wasm\n * insert-schema types that are string-like but not assignable to `string | number` in TypeScript).\n */\nexport type PartialSyncRowId = string | number | { toString(): string };\n\n/**\n * Minimal object shape keyed by a partial-sync row id. Use when only identity matters (e.g. cache\n * keys). Prefer {@link PartialSyncRowShape} for sync / partial-sync bridges and hooks.\n */\nexport type PartialSyncRowRef = {\n\tid: PartialSyncRowId;\n};\n\n/**\n * Version watermark for sync / partial-sync (fingerprints, reconciliation). The **`updatedAt` key\n * must exist** on the object; `null` or `undefined` mean “no ms watermark” at runtime (treated as\n * `0` where a number is needed). Rows or ORM types **without** this property are not suitable for\n * sync / partial-sync APIs—use {@link PartialSyncRowRef} only when you only need identity (e.g.\n * cache keys). (`undefined` is included in the union so Drizzle `InferSelectModel` / optional\n * columns remain assignable.)\n */\nexport type PartialSyncRowVersion = {\n\tupdatedAt: number | Date | null | undefined;\n};\n\n/**\n * Row shape required across {@link PartialSyncClientBridge}, {@link SyncClientBridge}, and React\n * partial-sync hooks: stable id plus a mandatory {@link PartialSyncRowVersion} key (see there).\n */\nexport type PartialSyncRowShape = PartialSyncRowRef & PartialSyncRowVersion;\n\n/** Max `updatedAt` as epoch ms; `null` / `undefined` → 0. */\nexport function partialSyncRowVersionWatermarkMs(\n\trow: PartialSyncRowVersion,\n): number {\n\tconst v = row.updatedAt;\n\tif (v === null || v === undefined) return 0;\n\tif (typeof v === \"number\") return v;\n\tif (v instanceof Date) return v.getTime();\n\treturn 0;\n}\n\n/**\n * Like {@link partialSyncRowVersionWatermarkMs} for decoded protocol payloads that are not yet\n * narrowed to {@link PartialSyncRowVersion} (e.g. mutate-batch `value` fields). Missing\n * `updatedAt` → 0.\n */\nexport function partialSyncRowVersionWatermarkMsUnknown(row: unknown): number {\n\tif (!row || typeof row !== \"object\" || !(\"updatedAt\" in row)) return 0;\n\treturn partialSyncRowVersionWatermarkMs(row as PartialSyncRowVersion);\n}\n\nexport function partialSyncRowKey(id: PartialSyncRowId): string | number {\n\tif (typeof id === \"string\" || typeof id === \"number\") return id;\n\treturn String(id);\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import { withSync } from './chunk-YYGPIHHJ.js';
2
+ import { createCollection } from '@tanstack/db';
3
+
4
+ function createSyncedCollection(baseOptions, syncOptions) {
5
+ const { options, bridge, setTransportSend } = withSync(
6
+ baseOptions,
7
+ syncOptions
8
+ );
9
+ const collection = createCollection(
10
+ options
11
+ );
12
+ bridge.setRowGet((key) => collection.get(key));
13
+ return { collection, bridge, setTransportSend };
14
+ }
15
+
16
+ export { createSyncedCollection };
17
+ //# sourceMappingURL=chunk-UVZJL6QV.js.map
18
+ //# sourceMappingURL=chunk-UVZJL6QV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/create-synced-collection.ts"],"names":[],"mappings":";;;AAkBO,SAAS,sBAAA,CAEd,aAAsB,WAAA,EAA+B;AAEtD,EAAA,MAAM,EAAE,OAAA,EAAS,MAAA,EAAQ,gBAAA,EAAiB,GAAI,QAAA;AAAA,IAC7C,WAAA;AAAA,IACA;AAAA,GACD;AACA,EAAA,MAAM,UAAA,GAAa,gBAAA;AAAA,IAClB;AAAA,GACD;AACA,EAAA,MAAA,CAAO,UAAU,CAAC,GAAA,KAAQ,UAAA,CAAW,GAAA,CAAI,GAAG,CAAC,CAAA;AAC7C,EAAA,OAAO,EAAE,UAAA,EAAY,MAAA,EAAQ,gBAAA,EAAiB;AAC/C","file":"chunk-UVZJL6QV.js","sourcesContent":["import type { Collection } from \"@tanstack/db\";\nimport { createCollection } from \"@tanstack/db\";\nimport {\n\twithSync,\n\ttype AnyWithSyncableCollectionConfig,\n\ttype InferItemFromCollectionOptions,\n\ttype WithSyncOptions,\n} from \"./with-sync\";\n\n/**\n * Builds a {@link withSync} wrapper and a TanStack {@link createCollection} in one step.\n * Row type is inferred from the collection config (see {@link InferItemFromCollectionOptions}).\n * (The internal `as unknown as Collection<TItem>` bridges `createCollection`'s overloads to the inferred row type.)\n *\n * Pass `syncOptions` for durable backends (IndexedDB, sqlite-wasm): use `syncStateKey` so incremental\n * reconnect works. Omit `syncOptions` (or omit `syncStateKey`) for in-memory collections that need a\n * full snapshot every load — see the module doc on {@link withSync} / `with-sync.ts`.\n */\nexport function createSyncedCollection<\n\tTConfig extends AnyWithSyncableCollectionConfig,\n>(baseOptions: TConfig, syncOptions?: WithSyncOptions) {\n\ttype TItem = InferItemFromCollectionOptions<TConfig>;\n\tconst { options, bridge, setTransportSend } = withSync(\n\t\tbaseOptions,\n\t\tsyncOptions,\n\t);\n\tconst collection = createCollection(\n\t\toptions as never,\n\t) as unknown as Collection<TItem>;\n\tbridge.setRowGet((key) => collection.get(key));\n\treturn { collection, bridge, setTransportSend };\n}\n"]}
@@ -0,0 +1,238 @@
1
+ import { DEFAULT_SYNC_COLLECTION_ID, createClientMessageSchema, createServerMessageSchema } from './chunk-BJJEAKXL.js';
2
+ import { partialSyncRowKey } from './chunk-UJ24XW52.js';
3
+ import { exhaustiveGuard } from '@firtoz/maybe-error';
4
+ import { StandardSchemaWebSocketClient } from '@firtoz/websocket-do/schema-client';
5
+
6
+ function pageVisibilityDocument() {
7
+ return globalThis.document;
8
+ }
9
+ async function dispatchPartialSyncServerMessage(msg, partialBridge, mutationBridge) {
10
+ const mid = msg.collectionId ?? DEFAULT_SYNC_COLLECTION_ID;
11
+ const forPartial = mid === partialBridge.collectionId;
12
+ const forMutation = mutationBridge !== void 0 && mid === mutationBridge.collectionId;
13
+ if (mutationBridge === void 0) {
14
+ if (!forPartial) return;
15
+ await partialBridge.handleServerMessage(msg);
16
+ return;
17
+ }
18
+ switch (msg.type) {
19
+ case "queryRangeChunk":
20
+ case "rangeUpToDate":
21
+ case "rangeDelta":
22
+ case "rangeReconcileResult":
23
+ case "rangePatch":
24
+ case "pong":
25
+ if (!forPartial) return;
26
+ await partialBridge.handleServerMessage(msg);
27
+ return;
28
+ case "ack":
29
+ case "reject":
30
+ case "syncBackfill":
31
+ if (!forMutation) return;
32
+ await mutationBridge.handleServerMessage(msg);
33
+ return;
34
+ case "syncBatch": {
35
+ if (!forMutation) return;
36
+ await mutationBridge.handleServerMessage(msg);
37
+ if (forPartial) {
38
+ const changes = msg.changes;
39
+ partialBridge.syncTrackedIdsFromMessages(changes);
40
+ }
41
+ return;
42
+ }
43
+ default:
44
+ exhaustiveGuard(msg);
45
+ }
46
+ }
47
+ function mergeCoalescedRangePatches(patches) {
48
+ let truncateWinner;
49
+ const byRow = /* @__PURE__ */ new Map();
50
+ for (const p of patches) {
51
+ const ch = p.change;
52
+ switch (ch.type) {
53
+ case "truncate":
54
+ truncateWinner = p;
55
+ byRow.clear();
56
+ break;
57
+ case "insert":
58
+ case "update": {
59
+ const k = partialSyncRowKey(ch.value.id);
60
+ byRow.set(k, p);
61
+ break;
62
+ }
63
+ case "delete":
64
+ byRow.set(ch.key, p);
65
+ break;
66
+ default:
67
+ exhaustiveGuard(ch);
68
+ }
69
+ }
70
+ if (truncateWinner !== void 0) return [truncateWinner];
71
+ return [...byRow.values()];
72
+ }
73
+ function connectPartialSync(bridge, options) {
74
+ const clientSchema = createClientMessageSchema();
75
+ const serverSchema = createServerMessageSchema();
76
+ const useMsgpack = options.transport === "msgpack";
77
+ const mutationBridge = options.mutationBridge;
78
+ const inboundWorkQueue = [];
79
+ let inboundPumpRunning = false;
80
+ let connectDisposed = false;
81
+ const runInboundPump = async () => {
82
+ if (inboundPumpRunning) return;
83
+ inboundPumpRunning = true;
84
+ try {
85
+ do {
86
+ while (inboundWorkQueue.length > 0) {
87
+ const job = inboundWorkQueue.shift();
88
+ if (job === void 0) continue;
89
+ try {
90
+ await job();
91
+ } catch (err) {
92
+ console.error("[connectPartialSync] inbound job error", err);
93
+ }
94
+ if (connectDisposed) return;
95
+ }
96
+ try {
97
+ await bridge.flushPendingCoalescedInboundUpdates();
98
+ } catch (err) {
99
+ console.error("[connectPartialSync] coalesced flush error", err);
100
+ }
101
+ } while (!connectDisposed && inboundWorkQueue.length > 0);
102
+ } finally {
103
+ inboundPumpRunning = false;
104
+ if (!connectDisposed && inboundWorkQueue.length > 0) {
105
+ void runInboundPump();
106
+ }
107
+ }
108
+ };
109
+ const enqueueInbound = (job) => {
110
+ inboundWorkQueue.push(job);
111
+ void runInboundPump();
112
+ };
113
+ let rangePatchCoalesceBuffer = [];
114
+ let rangePatchFlushMicrotaskQueued = false;
115
+ const drainRangePatchCoalesceBuffer = async () => {
116
+ if (rangePatchCoalesceBuffer.length === 0) return;
117
+ const merged = mergeCoalescedRangePatches(rangePatchCoalesceBuffer);
118
+ rangePatchCoalesceBuffer = [];
119
+ for (const m of merged) {
120
+ await dispatchPartialSyncServerMessage(m, bridge, mutationBridge);
121
+ }
122
+ };
123
+ const scheduleCoalescedRangePatchFlushMicrotask = () => {
124
+ if (rangePatchFlushMicrotaskQueued) return;
125
+ rangePatchFlushMicrotaskQueued = true;
126
+ queueMicrotask(() => {
127
+ rangePatchFlushMicrotaskQueued = false;
128
+ enqueueInbound(async () => {
129
+ await drainRangePatchCoalesceBuffer();
130
+ });
131
+ });
132
+ };
133
+ const cancelCoalescedRangePatchDeferredFlush = () => {
134
+ rangePatchFlushMicrotaskQueued = false;
135
+ };
136
+ const flushCoalescedRangePatchesInline = async () => {
137
+ cancelCoalescedRangePatchDeferredFlush();
138
+ await drainRangePatchCoalesceBuffer();
139
+ };
140
+ const schemaClient = new StandardSchemaWebSocketClient({
141
+ url: options.url,
142
+ clientSchema,
143
+ serverSchema,
144
+ enableBufferMessages: useMsgpack,
145
+ ...useMsgpack ? {} : {
146
+ serializeJson: options.serializeJson ?? JSON.stringify,
147
+ deserializeJson: options.deserializeJson ?? JSON.parse
148
+ },
149
+ onMessage: (msg) => {
150
+ enqueueInbound(async () => {
151
+ options.onServerMessage?.(msg);
152
+ if (mutationBridge === void 0) {
153
+ await dispatchPartialSyncServerMessage(msg, bridge, mutationBridge);
154
+ return;
155
+ }
156
+ const mid = msg.collectionId ?? DEFAULT_SYNC_COLLECTION_ID;
157
+ const forPartial = mid === bridge.collectionId;
158
+ if (msg.type === "rangePatch" && forPartial) {
159
+ rangePatchCoalesceBuffer.push(msg);
160
+ scheduleCoalescedRangePatchFlushMicrotask();
161
+ return;
162
+ }
163
+ await flushCoalescedRangePatchesInline();
164
+ await dispatchPartialSyncServerMessage(msg, bridge, mutationBridge);
165
+ });
166
+ }
167
+ });
168
+ const pendingOutbound = [];
169
+ const flushPendingOutbound = () => {
170
+ while (pendingOutbound.length > 0 && schemaClient.socket.readyState === WebSocket.OPEN) {
171
+ const message = pendingOutbound.shift();
172
+ if (message !== void 0) {
173
+ void schemaClient.send(message).catch((err) => {
174
+ console.error("[connectPartialSync] WebSocket send failed", err);
175
+ });
176
+ }
177
+ }
178
+ };
179
+ options.setTransportSend((message) => {
180
+ if (schemaClient.socket.readyState === WebSocket.OPEN) {
181
+ void schemaClient.send(message).catch((err) => {
182
+ console.error("[connectPartialSync] WebSocket send failed", err);
183
+ });
184
+ } else {
185
+ pendingOutbound.push(message);
186
+ }
187
+ });
188
+ bridge.setConnecting();
189
+ const onOpen = () => {
190
+ flushPendingOutbound();
191
+ bridge.setConnected(true);
192
+ mutationBridge?.setConnected(true);
193
+ };
194
+ const onClose = () => {
195
+ pendingOutbound.length = 0;
196
+ bridge.setConnected(false);
197
+ mutationBridge?.setConnected(false);
198
+ };
199
+ schemaClient.socket.addEventListener("open", onOpen);
200
+ schemaClient.socket.addEventListener("close", onClose);
201
+ if (schemaClient.socket.readyState === WebSocket.OPEN) {
202
+ onOpen();
203
+ }
204
+ const onVisibilityFlush = () => {
205
+ const doc = pageVisibilityDocument();
206
+ if (doc === void 0) return;
207
+ if (doc.visibilityState !== "visible") return;
208
+ enqueueInbound(async () => {
209
+ await flushCoalescedRangePatchesInline();
210
+ });
211
+ };
212
+ const visibilityDoc = pageVisibilityDocument();
213
+ if (visibilityDoc !== void 0) {
214
+ visibilityDoc.addEventListener("visibilitychange", onVisibilityFlush);
215
+ }
216
+ return () => {
217
+ connectDisposed = true;
218
+ const docCleanup = pageVisibilityDocument();
219
+ if (docCleanup !== void 0) {
220
+ docCleanup.removeEventListener("visibilitychange", onVisibilityFlush);
221
+ }
222
+ cancelCoalescedRangePatchDeferredFlush();
223
+ inboundWorkQueue.length = 0;
224
+ rangePatchCoalesceBuffer = [];
225
+ schemaClient.socket.removeEventListener("open", onOpen);
226
+ schemaClient.socket.removeEventListener("close", onClose);
227
+ pendingOutbound.length = 0;
228
+ bridge.setConnected(false);
229
+ mutationBridge?.setConnected(false);
230
+ options.setTransportSend(() => {
231
+ });
232
+ schemaClient.close();
233
+ };
234
+ }
235
+
236
+ export { connectPartialSync, dispatchPartialSyncServerMessage, mergeCoalescedRangePatches };
237
+ //# sourceMappingURL=chunk-XC4QNFSQ.js.map
238
+ //# sourceMappingURL=chunk-XC4QNFSQ.js.map