@abloatai/ablo 0.26.0 → 0.27.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 (398) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +101 -85
  3. package/dist/BaseSyncedStore.d.ts +85 -88
  4. package/dist/BaseSyncedStore.js +131 -147
  5. package/dist/Database.d.ts +54 -68
  6. package/dist/Database.js +97 -113
  7. package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
  8. package/dist/{ObjectPool.js → InstanceCache.js} +85 -83
  9. package/dist/LazyReferenceCollection.d.ts +11 -15
  10. package/dist/LazyReferenceCollection.js +12 -16
  11. package/dist/Model.d.ts +37 -52
  12. package/dist/Model.js +46 -61
  13. package/dist/ModelRegistry.d.ts +21 -19
  14. package/dist/ModelRegistry.js +23 -27
  15. package/dist/NetworkMonitor.d.ts +5 -6
  16. package/dist/NetworkMonitor.js +5 -6
  17. package/dist/SyncClient.d.ts +112 -112
  18. package/dist/SyncClient.js +165 -172
  19. package/dist/adapters/alwaysOnline.d.ts +6 -8
  20. package/dist/adapters/alwaysOnline.js +6 -8
  21. package/dist/adapters/inMemoryStorage.d.ts +9 -9
  22. package/dist/adapters/inMemoryStorage.js +9 -9
  23. package/dist/agent/Agent.d.ts +27 -32
  24. package/dist/agent/Agent.js +18 -19
  25. package/dist/agent/index.d.ts +4 -4
  26. package/dist/agent/index.js +5 -5
  27. package/dist/agent/session.d.ts +47 -44
  28. package/dist/agent/session.js +37 -48
  29. package/dist/agent/types.d.ts +26 -31
  30. package/dist/agent/types.js +6 -7
  31. package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
  32. package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
  33. package/dist/ai-sdk/coordinationContext.d.ts +46 -0
  34. package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +26 -33
  35. package/dist/ai-sdk/index.d.ts +25 -22
  36. package/dist/ai-sdk/index.js +25 -22
  37. package/dist/ai-sdk/wrap.d.ts +6 -7
  38. package/dist/ai-sdk/wrap.js +1 -1
  39. package/dist/auth/credentialPolicy.d.ts +69 -74
  40. package/dist/auth/credentialPolicy.js +51 -56
  41. package/dist/auth/credentialSource.d.ts +6 -5
  42. package/dist/auth/credentialSource.js +9 -10
  43. package/dist/auth/index.d.ts +59 -58
  44. package/dist/auth/index.js +31 -37
  45. package/dist/auth/schemas.d.ts +5 -4
  46. package/dist/auth/schemas.js +5 -4
  47. package/dist/batching/index.d.ts +19 -21
  48. package/dist/batching/index.js +14 -17
  49. package/dist/cli.cjs +167 -119
  50. package/dist/client/Ablo.d.ts +73 -73
  51. package/dist/client/Ablo.js +125 -160
  52. package/dist/client/ApiClient.d.ts +30 -19
  53. package/dist/client/ApiClient.js +133 -38
  54. package/dist/client/auth.d.ts +47 -47
  55. package/dist/client/auth.js +108 -117
  56. package/dist/client/claimHeartbeatLoop.d.ts +50 -0
  57. package/dist/client/claimHeartbeatLoop.js +88 -0
  58. package/dist/client/consoleLogger.d.ts +5 -6
  59. package/dist/client/consoleLogger.js +5 -6
  60. package/dist/client/createInternalComponents.d.ts +14 -17
  61. package/dist/client/createInternalComponents.js +25 -30
  62. package/dist/client/createModelProxy.d.ts +130 -120
  63. package/dist/client/createModelProxy.js +152 -122
  64. package/dist/client/credentialEndpoint.d.ts +40 -42
  65. package/dist/client/credentialEndpoint.js +35 -36
  66. package/dist/client/functionalUpdate.d.ts +29 -27
  67. package/dist/client/functionalUpdate.js +21 -21
  68. package/dist/client/hostedEndpoints.d.ts +9 -12
  69. package/dist/client/hostedEndpoints.js +9 -12
  70. package/dist/client/httpClient.d.ts +57 -53
  71. package/dist/client/httpClient.js +29 -31
  72. package/dist/client/identity.d.ts +15 -20
  73. package/dist/client/identity.js +47 -58
  74. package/dist/client/modelRegistration.d.ts +5 -9
  75. package/dist/client/modelRegistration.js +67 -87
  76. package/dist/client/options.d.ts +134 -157
  77. package/dist/client/options.js +3 -7
  78. package/dist/client/registerDataSource.d.ts +9 -9
  79. package/dist/client/registerDataSource.js +15 -16
  80. package/dist/client/resourceTypes.d.ts +64 -75
  81. package/dist/client/resourceTypes.js +4 -10
  82. package/dist/client/schemaConfig.d.ts +31 -43
  83. package/dist/client/schemaConfig.js +38 -50
  84. package/dist/client/sessionMint.d.ts +16 -12
  85. package/dist/client/sessionMint.js +26 -31
  86. package/dist/client/validateAbloOptions.d.ts +12 -14
  87. package/dist/client/validateAbloOptions.js +8 -9
  88. package/dist/client/writeOptionsSchema.d.ts +18 -16
  89. package/dist/client/writeOptionsSchema.js +23 -20
  90. package/dist/client/wsMutationExecutor.d.ts +15 -20
  91. package/dist/client/wsMutationExecutor.js +17 -23
  92. package/dist/context.d.ts +6 -4
  93. package/dist/context.js +6 -4
  94. package/dist/coordination/index.d.ts +10 -8
  95. package/dist/coordination/index.js +14 -12
  96. package/dist/coordination/schema.d.ts +176 -128
  97. package/dist/coordination/schema.js +197 -133
  98. package/dist/coordination/trace.d.ts +9 -10
  99. package/dist/coordination/trace.js +13 -14
  100. package/dist/core/DatabaseManager.d.ts +5 -7
  101. package/dist/core/DatabaseManager.js +15 -19
  102. package/dist/core/QueryProcessor.d.ts +7 -9
  103. package/dist/core/QueryProcessor.js +22 -28
  104. package/dist/core/QueryView.d.ts +8 -8
  105. package/dist/core/QueryView.js +2 -2
  106. package/dist/core/StoreManager.d.ts +12 -14
  107. package/dist/core/StoreManager.js +21 -24
  108. package/dist/core/ViewRegistry.d.ts +5 -5
  109. package/dist/core/ViewRegistry.js +4 -4
  110. package/dist/core/index.d.ts +17 -12
  111. package/dist/core/index.js +32 -26
  112. package/dist/core/openIDBWithTimeout.d.ts +38 -36
  113. package/dist/core/openIDBWithTimeout.js +42 -43
  114. package/dist/core/queryUtils.d.ts +45 -0
  115. package/dist/core/queryUtils.js +69 -0
  116. package/dist/core/storeContract.d.ts +63 -61
  117. package/dist/core/storeContract.js +8 -12
  118. package/dist/environment.d.ts +28 -0
  119. package/dist/environment.js +21 -0
  120. package/dist/errorCodes.d.ts +107 -99
  121. package/dist/errorCodes.js +131 -132
  122. package/dist/errors.d.ts +160 -166
  123. package/dist/errors.js +155 -158
  124. package/dist/index.d.ts +30 -27
  125. package/dist/index.js +89 -86
  126. package/dist/interfaces/index.d.ts +102 -113
  127. package/dist/interfaces/index.js +5 -4
  128. package/dist/keys/index.d.ts +27 -29
  129. package/dist/keys/index.js +41 -40
  130. package/dist/mutators/RecordingTransaction.d.ts +16 -16
  131. package/dist/mutators/RecordingTransaction.js +31 -37
  132. package/dist/mutators/Transaction.d.ts +18 -26
  133. package/dist/mutators/Transaction.js +14 -20
  134. package/dist/mutators/UndoManager.d.ts +122 -131
  135. package/dist/mutators/UndoManager.js +145 -156
  136. package/dist/mutators/defineMutators.d.ts +23 -34
  137. package/dist/mutators/defineMutators.js +14 -20
  138. package/dist/mutators/inverseOp.d.ts +12 -15
  139. package/dist/mutators/inverseOp.js +12 -15
  140. package/dist/mutators/mutateActions.d.ts +10 -9
  141. package/dist/mutators/mutateActions.js +1 -1
  142. package/dist/mutators/readerActions.d.ts +9 -8
  143. package/dist/mutators/readerActions.js +2 -2
  144. package/dist/mutators/undoApply.d.ts +31 -27
  145. package/dist/mutators/undoApply.js +26 -24
  146. package/dist/policy/index.d.ts +5 -3
  147. package/dist/policy/index.js +5 -3
  148. package/dist/policy/types.d.ts +104 -100
  149. package/dist/policy/types.js +67 -66
  150. package/dist/query/client.d.ts +28 -23
  151. package/dist/query/client.js +45 -43
  152. package/dist/query/types.d.ts +37 -60
  153. package/dist/query/types.js +13 -33
  154. package/dist/react/AbloProvider.d.ts +1 -1
  155. package/dist/react/AbloProvider.js +2 -2
  156. package/dist/react/context.d.ts +25 -28
  157. package/dist/react/context.js +9 -10
  158. package/dist/react/index.d.ts +41 -42
  159. package/dist/react/index.js +37 -38
  160. package/dist/react/internalContext.d.ts +17 -19
  161. package/dist/react/useAblo.d.ts +23 -22
  162. package/dist/react/useAblo.js +16 -14
  163. package/dist/react/useCurrentUserId.d.ts +8 -7
  164. package/dist/react/useCurrentUserId.js +8 -7
  165. package/dist/react/useErrorListener.d.ts +7 -7
  166. package/dist/react/useErrorListener.js +10 -11
  167. package/dist/react/useMutationFailureListener.d.ts +8 -8
  168. package/dist/react/useMutationFailureListener.js +8 -8
  169. package/dist/react/useMutators.d.ts +11 -11
  170. package/dist/react/useMutators.js +3 -3
  171. package/dist/react/useReactive.js +2 -2
  172. package/dist/react/useSyncStatus.d.ts +4 -6
  173. package/dist/react/useUndoScope.d.ts +7 -9
  174. package/dist/react/useUndoScope.js +1 -1
  175. package/dist/schema/coordination.d.ts +21 -25
  176. package/dist/schema/coordination.js +21 -25
  177. package/dist/schema/ddl.d.ts +43 -39
  178. package/dist/schema/ddl.js +75 -68
  179. package/dist/schema/ddlLock.d.ts +20 -24
  180. package/dist/schema/ddlLock.js +18 -23
  181. package/dist/schema/diff.d.ts +99 -61
  182. package/dist/schema/diff.js +43 -34
  183. package/dist/schema/field.d.ts +37 -42
  184. package/dist/schema/field.js +35 -48
  185. package/dist/schema/generate.d.ts +12 -12
  186. package/dist/schema/generate.js +12 -12
  187. package/dist/schema/index.d.ts +2 -2
  188. package/dist/schema/index.js +21 -23
  189. package/dist/schema/model.d.ts +118 -143
  190. package/dist/schema/model.js +22 -33
  191. package/dist/schema/openapi.d.ts +10 -9
  192. package/dist/schema/openapi.js +5 -3
  193. package/dist/schema/queries.d.ts +29 -31
  194. package/dist/schema/queries.js +23 -25
  195. package/dist/schema/relation.d.ts +89 -99
  196. package/dist/schema/relation.js +13 -13
  197. package/dist/schema/residency.d.ts +16 -13
  198. package/dist/schema/residency.js +16 -13
  199. package/dist/schema/roles.d.ts +36 -43
  200. package/dist/schema/roles.js +31 -37
  201. package/dist/schema/schema.d.ts +33 -42
  202. package/dist/schema/schema.js +31 -32
  203. package/dist/schema/select.d.ts +13 -13
  204. package/dist/schema/select.js +13 -13
  205. package/dist/schema/serialize.d.ts +28 -31
  206. package/dist/schema/serialize.js +27 -31
  207. package/dist/schema/sugar.d.ts +17 -32
  208. package/dist/schema/sugar.js +14 -29
  209. package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +26 -49
  210. package/dist/schema/syncDeltaRow.js +89 -0
  211. package/dist/schema/tenancy.d.ts +44 -46
  212. package/dist/schema/tenancy.js +46 -48
  213. package/dist/server/adapter.d.ts +58 -58
  214. package/dist/server/adapter.js +13 -14
  215. package/dist/server/commit.d.ts +60 -64
  216. package/dist/server/index.d.ts +9 -10
  217. package/dist/server/index.js +1 -1
  218. package/dist/server/readConfig.d.ts +70 -0
  219. package/dist/server/readConfig.js +8 -0
  220. package/dist/server/storageMode.d.ts +23 -0
  221. package/dist/server/storageMode.js +17 -0
  222. package/dist/source/adapter.d.ts +30 -25
  223. package/dist/source/adapter.js +10 -10
  224. package/dist/source/adapters/drizzle.d.ts +28 -23
  225. package/dist/source/adapters/drizzle.js +30 -25
  226. package/dist/source/adapters/kysely.d.ts +27 -25
  227. package/dist/source/adapters/kysely.js +24 -23
  228. package/dist/source/adapters/memory.d.ts +8 -7
  229. package/dist/source/adapters/memory.js +9 -8
  230. package/dist/source/adapters/prisma.d.ts +13 -12
  231. package/dist/source/adapters/prisma.js +22 -25
  232. package/dist/source/conformance.d.ts +18 -11
  233. package/dist/source/conformance.js +17 -11
  234. package/dist/source/connector.d.ts +31 -32
  235. package/dist/source/connector.js +28 -28
  236. package/dist/source/connectorProtocol.d.ts +160 -0
  237. package/dist/source/connectorProtocol.js +162 -0
  238. package/dist/source/contract.d.ts +26 -27
  239. package/dist/source/contract.js +28 -29
  240. package/dist/source/factory.d.ts +46 -58
  241. package/dist/source/factory.js +22 -27
  242. package/dist/source/index.d.ts +7 -9
  243. package/dist/source/index.js +12 -14
  244. package/dist/source/migrations.d.ts +9 -9
  245. package/dist/source/migrations.js +9 -9
  246. package/dist/source/next.d.ts +9 -10
  247. package/dist/source/next.js +6 -7
  248. package/dist/source/pushQueue.d.ts +69 -47
  249. package/dist/source/pushQueue.js +32 -28
  250. package/dist/source/signing.d.ts +46 -17
  251. package/dist/source/signing.js +28 -11
  252. package/dist/source/types.d.ts +121 -104
  253. package/dist/source/types.js +13 -14
  254. package/dist/stores/ObjectStore.d.ts +10 -11
  255. package/dist/stores/ObjectStore.js +11 -12
  256. package/dist/stores/ObjectStoreContract.d.ts +12 -15
  257. package/dist/stores/SyncActionStore.d.ts +7 -11
  258. package/dist/stores/SyncActionStore.js +13 -17
  259. package/dist/surface.d.ts +27 -20
  260. package/dist/surface.js +27 -20
  261. package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
  262. package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
  263. package/dist/sync/ConnectionManager.d.ts +39 -50
  264. package/dist/sync/ConnectionManager.js +55 -66
  265. package/dist/sync/NetworkProbe.d.ts +24 -29
  266. package/dist/sync/NetworkProbe.js +63 -69
  267. package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
  268. package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
  269. package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
  270. package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
  271. package/dist/sync/SyncWebSocket.d.ts +139 -165
  272. package/dist/sync/SyncWebSocket.js +191 -223
  273. package/dist/sync/awaitClaimGrant.d.ts +18 -18
  274. package/dist/sync/awaitClaimGrant.js +11 -11
  275. package/dist/sync/bootstrapApply.d.ts +34 -24
  276. package/dist/sync/bootstrapApply.js +27 -19
  277. package/dist/sync/commitFrames.d.ts +21 -20
  278. package/dist/sync/commitFrames.js +18 -18
  279. package/dist/sync/createClaimStream.d.ts +23 -22
  280. package/dist/sync/createClaimStream.js +105 -23
  281. package/dist/sync/createPresenceStream.d.ts +19 -18
  282. package/dist/sync/createPresenceStream.js +25 -26
  283. package/dist/sync/createSnapshot.d.ts +12 -14
  284. package/dist/sync/createSnapshot.js +20 -26
  285. package/dist/sync/credentialLifecycle.d.ts +104 -104
  286. package/dist/sync/credentialLifecycle.js +140 -147
  287. package/dist/sync/deltaPipeline.d.ts +36 -34
  288. package/dist/sync/deltaPipeline.js +64 -65
  289. package/dist/sync/groupChange.d.ts +63 -61
  290. package/dist/sync/groupChange.js +74 -78
  291. package/dist/sync/heartbeat.d.ts +34 -33
  292. package/dist/sync/heartbeat.js +31 -31
  293. package/dist/sync/participants.d.ts +19 -19
  294. package/dist/sync/schemas.d.ts +3 -2
  295. package/dist/sync/schemas.js +14 -10
  296. package/dist/sync/syncCursor.d.ts +17 -21
  297. package/dist/sync/syncCursor.js +17 -21
  298. package/dist/sync/syncPlan.d.ts +28 -36
  299. package/dist/sync/syncPlan.js +18 -19
  300. package/dist/sync/syncPosition.d.ts +54 -49
  301. package/dist/sync/syncPosition.js +57 -52
  302. package/dist/sync/wsFrameHandlers.d.ts +35 -36
  303. package/dist/sync/wsFrameHandlers.js +63 -67
  304. package/dist/testing/fixtures/bootstrap.d.ts +12 -6
  305. package/dist/testing/fixtures/bootstrap.js +12 -6
  306. package/dist/testing/fixtures/deltas.d.ts +30 -33
  307. package/dist/testing/fixtures/deltas.js +30 -33
  308. package/dist/testing/fixtures/models.d.ts +11 -10
  309. package/dist/testing/fixtures/models.js +11 -10
  310. package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
  311. package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
  312. package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -15
  313. package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
  314. package/dist/testing/helpers/wait.d.ts +13 -8
  315. package/dist/testing/helpers/wait.js +13 -8
  316. package/dist/testing/index.d.ts +3 -3
  317. package/dist/testing/index.js +2 -2
  318. package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
  319. package/dist/testing/mocks/MockMutationExecutor.js +15 -14
  320. package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
  321. package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
  322. package/dist/testing/mocks/MockSyncContext.d.ts +20 -17
  323. package/dist/testing/mocks/MockSyncContext.js +15 -13
  324. package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
  325. package/dist/testing/mocks/MockSyncStore.js +11 -11
  326. package/dist/testing/mocks/MockWebSocket.d.ts +26 -22
  327. package/dist/testing/mocks/MockWebSocket.js +22 -21
  328. package/dist/transactions/TransactionQueue.d.ts +181 -176
  329. package/dist/transactions/TransactionQueue.js +338 -350
  330. package/dist/transactions/TransactionStore.d.ts +6 -4
  331. package/dist/transactions/TransactionStore.js +6 -4
  332. package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
  333. package/dist/transactions/UnconfirmedWrites.js +104 -0
  334. package/dist/transactions/coalesceRules.d.ts +41 -17
  335. package/dist/transactions/coalesceRules.js +40 -17
  336. package/dist/transactions/commitPayload.d.ts +48 -52
  337. package/dist/transactions/commitPayload.js +48 -57
  338. package/dist/transactions/deltaConfirmation.d.ts +20 -22
  339. package/dist/transactions/deltaConfirmation.js +37 -45
  340. package/dist/transactions/optimisticApply.d.ts +49 -0
  341. package/dist/transactions/optimisticApply.js +65 -0
  342. package/dist/transactions/{persistedReplay.d.ts → replayValidation.d.ts} +28 -22
  343. package/dist/transactions/{persistedReplay.js → replayValidation.js} +33 -27
  344. package/dist/types/global.d.ts +46 -41
  345. package/dist/types/global.js +20 -19
  346. package/dist/types/index.d.ts +71 -77
  347. package/dist/types/index.js +22 -22
  348. package/dist/types/modelData.d.ts +6 -8
  349. package/dist/types/modelData.js +5 -7
  350. package/dist/types/participant.d.ts +10 -11
  351. package/dist/types/participant.js +6 -8
  352. package/dist/types/streams.d.ts +208 -195
  353. package/dist/types/streams.js +7 -7
  354. package/dist/utils/asyncIterator.d.ts +25 -32
  355. package/dist/utils/asyncIterator.js +25 -32
  356. package/dist/utils/duration.d.ts +12 -15
  357. package/dist/utils/duration.js +12 -15
  358. package/dist/utils/mobxSetup.d.ts +53 -0
  359. package/dist/utils/{mobx-setup.js → mobxSetup.js} +42 -98
  360. package/dist/webhooks/events.d.ts +21 -16
  361. package/dist/webhooks/events.js +10 -8
  362. package/dist/webhooks/index.d.ts +5 -7
  363. package/dist/webhooks/index.js +5 -7
  364. package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
  365. package/dist/wire/delta.js +114 -0
  366. package/dist/wire/errorEnvelope.d.ts +30 -31
  367. package/dist/wire/errorEnvelope.js +34 -40
  368. package/dist/wire/frames.d.ts +79 -86
  369. package/dist/wire/frames.js +26 -33
  370. package/dist/wire/index.d.ts +14 -12
  371. package/dist/wire/index.js +30 -26
  372. package/dist/wire/listEnvelope.d.ts +16 -23
  373. package/dist/wire/listEnvelope.js +7 -6
  374. package/dist/wire/protocol.d.ts +25 -32
  375. package/dist/wire/protocol.js +25 -32
  376. package/dist/wire/protocolVersion.d.ts +44 -40
  377. package/dist/wire/protocolVersion.js +44 -40
  378. package/docs/coordination.md +59 -0
  379. package/package.json +11 -10
  380. package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
  381. package/dist/ai-sdk/coordination-context.d.ts +0 -52
  382. package/dist/core/query-utils.d.ts +0 -34
  383. package/dist/core/query-utils.js +0 -59
  384. package/dist/schema/sync-delta-row.js +0 -103
  385. package/dist/schema/sync-delta-wire.js +0 -102
  386. package/dist/server/read-config.d.ts +0 -67
  387. package/dist/server/read-config.js +0 -8
  388. package/dist/server/storage-mode.d.ts +0 -8
  389. package/dist/server/storage-mode.js +0 -28
  390. package/dist/source/connector-protocol.d.ts +0 -159
  391. package/dist/source/connector-protocol.js +0 -161
  392. package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
  393. package/dist/transactions/OptimisticEchoTracker.js +0 -104
  394. package/dist/transactions/mutation-error-handler.d.ts +0 -5
  395. package/dist/transactions/mutation-error-handler.js +0 -39
  396. package/dist/transactions/optimistic.d.ts +0 -24
  397. package/dist/transactions/optimistic.js +0 -45
  398. package/dist/utils/mobx-setup.d.ts +0 -42
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.27.0
4
+
5
+ ### Minor Changes
6
+
7
+ - **Claims can now be held for long-running work by heartbeating — on both transports.** A claim's TTL is crash cleanup, not a work estimate; work that outlives it (a 30-minute report, a long agent run) keeps its lease by beating. `claim({ heartbeat: true })` beats automatically until release; `held.heartbeat()` beats by hand. A lapsed lease answers the next beat with `AbloClaimedError` (`claim_lost`) — for a socketless worker, the failed beat _is_ the loss notification, and any write attempted under the old lease is independently rejected by its `readAt` guard.
8
+
9
+ - **Beats carry progress and pressure.** `heartbeat({ details })` stores lightweight progress as the claim's peer-visible `meta.progress` (last beat wins, via `claim.state`); every beat's answer reports `queueDepth` — how many participants wait in line behind the lease — observable per auto-beat with the new `onHeartbeat` claim option.
10
+
11
+ - **`ablo.claims.heartbeatAll({ ttl })`** extends every lease the credential holds in one request (`POST /v1/claims/heartbeat`) — the stateless twin of the WebSocket keepalive, for workers holding many rows.
12
+
13
+ - **Keepalive renewals extend but never shorten a lease**, so an explicit work-duration `ttl` now survives pings and brief reconnects instead of collapsing to the liveness window.
14
+
15
+ - **README.** The quick start leads with a runnable example, and a new _Background workers_ section shows the enqueue-on-your-own-queue / heartbeat-the-claim pattern end to end.
16
+
3
17
  ## 0.26.0
4
18
 
5
19
  ### Minor Changes
package/README.md CHANGED
@@ -39,10 +39,10 @@ Under the hood, you define your data once with a Zod schema and get the same
39
39
  typed model client for every actor — people, server actions, and agents:
40
40
 
41
41
  ```ts
42
- await ablo.task.create({ data }) // create
43
- await ablo.task.retrieve({ id }) // read
44
- await ablo.task.update({ id, data }) // update
45
- await using task = await ablo.task.claim({ id }) // claim for safe, slow agent work
42
+ await ablo.weatherReports.create({ data }) // create
43
+ await ablo.weatherReports.retrieve({ id }) // read
44
+ await ablo.weatherReports.update({ id, data }) // update
45
+ await using claim = await ablo.weatherReports.claim({ id }) // hold for slow agent work
46
46
  ```
47
47
 
48
48
  The schema is the public contract. It gives you typed model methods, realtime
@@ -63,8 +63,9 @@ yet? A **sandbox** `sk_test` key holds throwaway **test data** — like Stripe t
63
63
  mode — so you can explore before pointing it at your Postgres. Test-mode only; in
64
64
  production every row lives in your database.)
65
65
 
66
- **Built for** collaborative editors, AI agent workflows, and internal tools —
67
- anywhere people and agents change shared state and everyone has to see it live.
66
+ **Built for** collaborative editors, AI agent workflows, background workers on
67
+ your own infrastructure, and internal tools anywhere people and agents change
68
+ shared state and everyone has to see it live.
68
69
 
69
70
  ## Set up
70
71
 
@@ -111,62 +112,15 @@ instead of guessing:
111
112
 
112
113
  ## Quick Start
113
114
 
115
+ One schema, one client, one write path for humans and agents — this runs as-is
116
+ after `ablo push`:
117
+
114
118
  ```ts
115
119
  import Ablo from '@abloatai/ablo';
116
120
  import { defineSchema, model, z } from '@abloatai/ablo/schema';
117
- ```
118
-
119
- The schema is registered once (init scaffolds `ablo/register.ts` for you), and
120
- every type is one parameter away — no `typeof schema` re-stating, anywhere:
121
-
122
- ```ts
123
- // ablo/register.ts — scaffolded by `npx ablo init`, sits beside ablo/schema.ts
124
- import type { schema } from './schema';
125
- declare module '@abloatai/ablo' {
126
- interface Register { Schema: typeof schema }
127
- }
128
- export {};
129
- ```
130
-
131
- It's a regular `.ts` module, not a hand-authored `.d.ts`. The top-level
132
- `import type { schema }` makes the `declare module` block *merge* into (augment)
133
- the SDK's `Register` interface instead of colliding with it — the same shape
134
- [TanStack Router uses in `src/router.tsx`](https://tanstack.com/router/latest/docs/framework/react/guide/type-safety). Any `.ts` file in your
135
- `tsconfig` `include` works; it never needs to be imported.
136
-
137
- ```ts
138
- import type { Model } from '@abloatai/ablo/schema';
139
-
140
- type WeatherReport = Model<'weatherReports'>; // fully typed from YOUR schema
141
- ```
142
-
143
- (The same `Register` binding types every hook and client — it's the
144
- TanStack-Router pattern: declare the source of truth once, everything
145
- infers from it.)
146
121
 
147
- ### Naming the client type
148
-
149
- When you need to pass the client around (a function parameter, a context value),
150
- **infer the type from the value** — `type Sync = typeof sync`:
151
-
152
- ```ts
153
- export const sync = Ablo({ schema, apiKey: process.env.ABLO_API_KEY });
154
- export type Sync = typeof sync; // fully-typed, schema-aware
155
-
156
- function persist(client: Sync) { /* ... */ }
157
- ```
158
-
159
- This is the same idiom as tRPC's `type AppRouter = typeof appRouter` and
160
- Drizzle's `typeof db` — the factory resolves the typed overload at the call
161
- site, so `typeof sync` carries your schema. Do **not** write
162
- `ReturnType<typeof Ablo>`: that collapses to the untyped last overload and
163
- loses your model types. There is no bespoke client-type generic to import —
164
- `typeof` your client value is the type.
165
-
166
- ```ts
167
122
  const schema = defineSchema({
168
- // Reserved fields (id, createdAt, updatedAt, organizationId, createdBy) are
169
- // provided automatically — don't declare them.
123
+ // id, createdAt, updatedAt, organizationId, createdBy come free on every model
170
124
  weatherReports: model({
171
125
  location: z.string(),
172
126
  status: z.enum(['pending', 'ready']),
@@ -174,29 +128,21 @@ const schema = defineSchema({
174
128
  }),
175
129
  });
176
130
 
177
- const ablo = Ablo({
178
- schema,
179
- apiKey: process.env.ABLO_API_KEY, // written to .env.local by `npx ablo push`
180
- });
181
- // Your Postgres is connected once via `npx ablo connect` (logical replication) —
182
- // not passed here. Ablo tails its WAL; your rows never leave your database.
183
-
131
+ const ablo = Ablo({ schema, apiKey: process.env.ABLO_API_KEY });
184
132
  await ablo.ready();
185
133
 
186
134
  const created = await ablo.weatherReports.create({
187
- data: {
188
- location: 'Stockholm',
189
- status: 'pending',
190
- },
135
+ data: { location: 'Stockholm', status: 'pending' },
191
136
  });
192
137
 
193
- // An agent claims the row, does its slow work, then writes back. While the
194
- // claim is held nobody else can overwrite it; anyone else who tries waits in
195
- // line and re-reads the result. This is the whole point of Ablo.
138
+ // Claim the row before slow work — anyone else waits in line, then re-reads.
196
139
  await using claim = await ablo.weatherReports.claim({ id: created.id });
197
- const report = claim.data;
198
- const forecast = await fetchForecast(report.location); // slow: API or LLM call
199
- await ablo.weatherReports.update({ id: report.id, data: { status: 'ready', forecast } });
140
+ const forecast = await fetchForecast(claim.data.location); // slow: API or LLM call
141
+ await ablo.weatherReports.update({
142
+ id: created.id,
143
+ data: { status: 'ready', forecast },
144
+ claim, // the write completes the claimed work and releases the lease
145
+ });
200
146
 
201
147
  const ready = ablo.weatherReports.get(created.id);
202
148
  console.log({ id: ready?.id, status: ready?.status });
@@ -210,6 +156,38 @@ Expected output:
210
156
  { id: '...', status: 'ready' }
211
157
  ```
212
158
 
159
+ ### TypeScript setup (once, scaffolded for you)
160
+
161
+ `npx ablo init` writes `ablo/register.ts` next to your schema. It binds your
162
+ schema to the SDK's types once — the same declaration-merging shape
163
+ [TanStack Router uses](https://tanstack.com/router/latest/docs/framework/react/guide/type-safety) —
164
+ so every hook and client infers from it:
165
+
166
+ ```ts
167
+ // ablo/register.ts — scaffolded by `npx ablo init`
168
+ import type { schema } from './schema';
169
+ declare module '@abloatai/ablo' {
170
+ interface Register { Schema: typeof schema }
171
+ }
172
+ export {};
173
+ ```
174
+
175
+ ```ts
176
+ import type { Model } from '@abloatai/ablo/schema';
177
+
178
+ type WeatherReport = Model<'weatherReports'>; // fully typed from your schema
179
+ ```
180
+
181
+ To pass the client around, take the type from the value — the tRPC /
182
+ Drizzle idiom:
183
+
184
+ ```ts
185
+ export const sync = Ablo({ schema, apiKey: process.env.ABLO_API_KEY });
186
+ export type Sync = typeof sync;
187
+
188
+ function persist(client: Sync) { /* ... */ }
189
+ ```
190
+
213
191
  ## Reading
214
192
 
215
193
  Two ways to read, depending on whether you can wait. `get(id)` / `getAll({ where })`
@@ -262,7 +240,11 @@ meanwhile, or worse, acts on stale state. `claim` holds the row across that gap:
262
240
  await using claim = await ablo.weatherReports.claim({ id: 'report_stockholm' });
263
241
  const report = claim.data;
264
242
  const forecast = await weatherAgent.getWeather(report.location);
265
- await ablo.weatherReports.update({ id: report.id, data: { forecast, status: 'ready' } });
243
+ await ablo.weatherReports.update({
244
+ id: report.id,
245
+ data: { forecast, status: 'ready' },
246
+ claim, // attribute the write to the held claim
247
+ });
266
248
  ```
267
249
 
268
250
  If someone else holds the row, `claim()` waits in a fair queue, then re-reads —
@@ -311,6 +293,46 @@ try {
311
293
  See [Coordination](./docs/coordination.md) for the full `claim` / `claim.state` /
312
294
  `claim.queue` / `claim.release` reference.
313
295
 
296
+ ## Background workers — jobs that run for minutes, not seconds
297
+
298
+ Your API route enqueues a job on your own queue (SQS, EventBridge, anything);
299
+ a worker on your own infrastructure does the slow part. **Keep that queue —
300
+ Ablo is the worker's data layer.** It covers the two things every queue leaves
301
+ to you: keeping the row safe, and showing progress live.
302
+
303
+ Long work holds its claim by **heartbeating** — the same pattern as an SQS
304
+ visibility heartbeat or a Temporal activity heartbeat:
305
+
306
+ ```ts
307
+ // on your worker — stateless HTTP, no socket to hold
308
+ await using claim = await ablo.weatherReports.claim({
309
+ id: msg.reportId,
310
+ ttl: '10m',
311
+ heartbeat: true, // beats automatically until release
312
+ onHeartbeatLost: () => abort(), // the lease is gone → stop working
313
+ });
314
+
315
+ for (const step of steps) {
316
+ await runStep(step);
317
+ // write progress to the row — every subscribed UI updates live
318
+ await ablo.weatherReports.update({ id: msg.reportId, data: { progress: step.pct }, claim });
319
+ }
320
+ ```
321
+
322
+ - A worker that **crashes** stops beating; the row frees within one beat and
323
+ the next worker takes over.
324
+ - A worker that **wakes up late** learns it on its next beat
325
+ (`AbloClaimedError`), and the write path rejects its stale writes anyway.
326
+ - **Retries stay on your queue** — the redelivered job claims the now-free
327
+ row, reads its current state, and resumes.
328
+ - A worker holding **many rows** extends them all in one call:
329
+ `ablo.claims.heartbeatAll({ ttl: '5m' })`.
330
+
331
+ SQS's heartbeat protects the *message* from redelivery; Ablo's protects the
332
+ *row* from concurrent and stale writes. SQS is at-least-once, so two workers
333
+ will eventually get the same job — the claim is what keeps that from
334
+ corrupting data.
335
+
314
336
  ## React
315
337
 
316
338
  In a React app it's the **same `ablo.<model>` API** — just mounted through a
@@ -445,14 +467,8 @@ connects:
445
467
  | **Logical replication** (primary) | `npx ablo connect` prints the setup SQL (`wal_level=logical`, a publication, a `REPLICATION` role); `npx ablo connect --register` tells Ablo to replicate it. Ablo tails the WAL — it never runs DDL on, writes to, owns, or migrates your database. | Your database can grant a `REPLICATION` role (most can). |
446
468
  | **Signed endpoint** (fallback) | Your app exposes one route built from an ORM adapter (`prismaDataSource` / `drizzleDataSource`); Ablo sends signed requests and your app touches its own database. Needs no database configuration. | Your database **can't** grant a replication role (a locked-down managed DB). |
447
469
 
448
- (No database yet? A **sandbox** `sk_test` key lets you try Ablo's full API and
449
- coordination with throwaway **test data** — like Stripe test mode — before you
450
- connect your own Postgres. Test-mode only: in production your rows always live in
451
- your database and Ablo holds just the transaction log, never your data.)
452
-
453
- Your database is the system of record. The old `databaseUrl` dial-in (Ablo
454
- holding a read/write connection) is **deprecated and being removed** — connect
455
- via logical replication instead. See
470
+ Your database is the system of record Ablo holds the transaction log and
471
+ coordination, never your rows. See
456
472
  [Connect Your Database](./docs/data-sources.md).
457
473
 
458
474
  ## Configuration
@@ -466,7 +482,7 @@ Every other option has correct defaults:
466
482
  | --- | --- | --- | --- |
467
483
  | `schema` | `Schema` | — (required) | Typed model proxies (`ablo.<model>.*`) |
468
484
  | `apiKey` | `string \| ApiKeySetter \| null` | `process.env.ABLO_API_KEY` | Server key — a string, or an async function for rotation |
469
- | `databaseUrl` | `string \| null` | `—` | **Deprecated — being removed.** The old dial-in (Ablo holding a read/write connection to your DB). Connect via `npx ablo connect` (logical replication) instead; Ablo tails your WAL rather than dialing in. See [Connect Your Database](./docs/data-sources.md). |
485
+ | `databaseUrl` | `string \| null` | `—` | Deprecated. Connect via `npx ablo connect` instead see [Connect Your Database](./docs/data-sources.md). |
470
486
 
471
487
  Keep `apiKey` in trusted server runtimes. In the browser, `<AbloProvider>`
472
488
  authenticates with the signed-in user's session; the raw-key path is gated
@@ -519,7 +535,7 @@ contract; there are no retry or timeout knobs to tune.
519
535
  - [Guarantees](./docs/guarantees.md) — confirmed writes, stale-write protection, claim coordination, and agent lifecycle.
520
536
  - [Integration Guide](./docs/integration-guide.md) — integrate React, your database, multiplayer, and agents.
521
537
  - [React](./docs/react.md) — `<AbloProvider>`, `useAblo`, presence, status, and bootstrap gating.
522
- - [Coordination](./docs/coordination.md) — `claim` / `claim.state` / `claim.queue` / `claim.release` reference: hold a row across slow agent work, and observe the line waiting behind it.
538
+ - [Coordination](./docs/coordination.md) — `claim` / `claim.state` / `claim.queue` / `claim.release` / `heartbeat` reference: hold a row across slow agent work — minutes or hours, via heartbeats — and observe the line waiting behind it.
523
539
  - [Client Behavior](./docs/client-behavior.md) — options, errors, retries, timeouts, and public imports.
524
540
  - [Connect Your Database](./docs/data-sources.md) — connect your Postgres by logical replication (`npx ablo connect`) or, as a fallback, a signed endpoint; your database is the system of record either way.
525
541
  - [Existing Python Backend](./docs/examples/existing-python-backend.md) — migrate existing Python endpoints to multiplayer and agent-safe writes gradually.
@@ -1,28 +1,27 @@
1
1
  /**
2
- * BaseSyncedStore Generic sync store base class for the SDK.
2
+ * The base class that application-specific sync stores extend. It supplies the
3
+ * shared orchestration for reads, writes, delta processing, and bootstrap, and
4
+ * exports the core types those stores build on.
3
5
  *
4
- * Exports the core types, interfaces, and a base class that app-specific
5
- * stores extend. The base class provides query/mutation/delta/bootstrap
6
- * orchestration. Subclasses add domain-specific lazy-loading, collaboration
7
- * events, and model enrichment.
8
- *
9
- * Design: The app's SyncedStore extends this and adds its own methods.
10
- * This file only contains types and the abstract contract — the actual
11
- * implementation stays in the app's SyncedStore.ts until we incrementally
12
- * pull generic methods into this base class.
6
+ * A subclass adds its own domain behavior lazy-loaded relations,
7
+ * collaboration events, and model enrichment by overriding the protected
8
+ * extension points defined here. The heavy lifting is delegated to injected
9
+ * collaborators: {@link SyncClient} owns pool writes and the transaction
10
+ * queue, {@link Database} owns local persistence, {@link InstanceCache} holds the
11
+ * in-memory models, and {@link ModelRegistry} holds their metadata.
13
12
  */
14
13
  import type { RecoveryClass } from './errorCodes.js';
15
14
  import { ConnectionManager } from './sync/ConnectionManager.js';
16
- import { AreaOfInterestManager } from './sync/AreaOfInterestManager.js';
15
+ import { SubscriptionManager } from './sync/SubscriptionManager.js';
17
16
  import { type ParticipantScope } from './sync/participants.js';
18
17
  import type { SyncClient } from './SyncClient.js';
19
18
  import type { Database, BootstrapResult } from './Database.js';
20
- import type { ObjectPool } from './ObjectPool.js';
19
+ import type { InstanceCache } from './InstanceCache.js';
21
20
  import { ModelRegistry } from './ModelRegistry.js';
22
21
  import { SyncWebSocket, type SyncDelta, type SyncGroupChangePayload, type GroupAddedPayload, type GroupRemovedPayload, type BootstrapHint, type BootstrapDataEvent, type PresenceUpdateEvent, type EventMap, type DefaultCollaborationEvents } from './sync/SyncWebSocket.js';
23
22
  import { QueryProcessor } from './core/QueryProcessor.js';
24
23
  import { Model } from './Model.js';
25
- import { ModelScope } from './ObjectPool.js';
24
+ import { ModelScope } from './InstanceCache.js';
26
25
  import type { Schema } from './schema/schema.js';
27
26
  import type { SyncStatus, LocalMutation } from './core/storeContract.js';
28
27
  import type { AuthCredentialSource } from './auth/credentialSource.js';
@@ -56,7 +55,7 @@ export interface SyncedStoreConfig {
56
55
  */
57
56
  enrichmentPlan?: readonly EnrichmentPlanEntry[];
58
57
  /**
59
- * Foreign-key indexes to register on the ObjectPool at construction
58
+ * Foreign-key indexes to register on the InstanceCache at construction
60
59
  * time. Replaces the subclass override of `registerForeignKeys` for
61
60
  * per-model FK registration. Merged with schema-derived entries
62
61
  * (relations marked `{ index: true }` on `belongsTo`). Both sets
@@ -79,8 +78,7 @@ export interface UserContext {
79
78
  kind?: 'user' | 'agent' | 'system';
80
79
  /** Restricted (`rk_`) API key for `kind: 'agent'` — the agent's
81
80
  * bearer credential. Sent in the `ablo.bearer.<token>` WebSocket
82
- * subprotocol, never in the URL. (Field name predates the
83
- * Biscuit→opaque-key migration.) */
81
+ * subprotocol, never in the URL. */
84
82
  capabilityToken?: string;
85
83
  /** Server-authoritative sync groups, supplied by auth/capability
86
84
  * exchange. The SDK does not invent org/user/default groups; app
@@ -119,16 +117,15 @@ export { ModelScope };
119
117
  export type { SyncDelta, SyncGroupChangePayload, GroupAddedPayload, GroupRemovedPayload, BootstrapHint, BootstrapDataEvent, PresenceUpdateEvent, };
120
118
  export { deriveSyncPlanFromSchema } from './sync/syncPlan.js';
121
119
  /**
122
- * BaseSyncedStore abstract base for app-specific sync stores.
123
- *
124
- * Provides the dependency structure, observable status, and protected
125
- * accessors that subclasses use. The actual sync orchestration (initialize,
126
- * delta processing, bootstrap, query, save, delete, etc.) lives in the
127
- * app's concrete subclass for now — methods will be pulled up into this
128
- * base class incrementally as they are genericized.
120
+ * The abstract base class that application-specific sync stores extend. It
121
+ * carries the injected collaborators, the observable sync status, and the
122
+ * orchestration for initialization, delta processing, bootstrap, and the
123
+ * read and write API. A subclass supplies its own domain behavior by
124
+ * overriding the protected extension points defined here and by typing its
125
+ * collaboration events through the generic parameter.
129
126
  *
130
- * Subclasses MUST call `super(dependencies, config)` and then set up
131
- * their own MobX observables.
127
+ * A subclass must call `super(dependencies, config)` and then set up its own
128
+ * MobX observables.
132
129
  *
133
130
  * Generic over `TCollaboration` — an app-defined event map for real-time
134
131
  * collaboration events (cursors, selections, presence beyond the core set).
@@ -150,7 +147,7 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
150
147
  syncStatus: SyncStatus;
151
148
  protected readonly syncClient: SyncClient;
152
149
  protected readonly database: Database;
153
- protected readonly objectPool: ObjectPool;
150
+ protected readonly objectPool: InstanceCache;
154
151
  protected readonly modelRegistry: ModelRegistry;
155
152
  protected readonly auth?: AuthCredentialSource;
156
153
  /**
@@ -166,7 +163,7 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
166
163
  * to whichever instance is current, so callers (the React participant
167
164
  * hook) never hold a stale reference. Null until `setupWebSocketSync`.
168
165
  */
169
- protected areaOfInterest: AreaOfInterestManager | null;
166
+ protected areaOfInterest: SubscriptionManager | null;
170
167
  /** Sync groups whose current state has been backfilled into the pool
171
168
  * (hydrate-on-enter). Cleared when the pool is reset on (re)bootstrap. */
172
169
  private readonly hydratedGroups;
@@ -185,22 +182,22 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
185
182
  getSyncWebSocket(): SyncWebSocket<TCollaboration> | null;
186
183
  private scopeToGroups;
187
184
  /**
188
- * Bring a scope into view subscribe to its groups. With
189
- * `{ hydrate: true }`, ALSO backfill the groups' current state into the pool
190
- * after the subscription is active (the game "spawn snapshot + delta stream"
191
- * pattern): subscribe-first so no live delta is missed in the gap, then
192
- * snapshot. Hydration is soft — a failed backfill never rejects `enterScope`
193
- * and the live tail still flows.
185
+ * Bring a scope into view and subscribe to its sync groups. With
186
+ * `{ hydrate: true }`, also backfill the groups' current state into the pool
187
+ * once the subscription is active. The order matters: subscribing first
188
+ * guarantees no live delta is missed in the gap before the snapshot lands.
189
+ * Hydration is best-effort — a failed backfill never rejects `enterScope`,
190
+ * and the live delta stream keeps flowing regardless.
194
191
  */
195
192
  enterScope(scope: ParticipantScope, opts?: {
196
193
  hydrate?: boolean;
197
194
  }): Promise<void>;
198
195
  /**
199
- * Backfill the current state of `syncGroups` into the pool via a PURE scoped
200
- * snapshot fetch + the version-guarded, ghost-free scoped apply. Idempotent
201
- * (skips groups already hydrated) and single-flight (concurrent enters of the
202
- * same group share one fetch). Soft-fails: on error the groups are NOT marked
203
- * hydrated, so a later re-enter retries.
196
+ * Backfill the current state of `syncGroups` into the pool with a side-effect-free
197
+ * scoped snapshot fetch followed by the version-guarded scoped apply. The call
198
+ * is idempotent (it skips groups already hydrated) and single-flight (concurrent
199
+ * enters of the same group share one fetch). On error the groups are left
200
+ * unmarked, so a later re-enter retries.
204
201
  */
205
202
  protected hydrateGroups(syncGroups: readonly string[]): Promise<void>;
206
203
  /** Leave a scope → its groups go warm (hysteresis), then drop on sweep. */
@@ -246,15 +243,14 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
246
243
  constructor(dependencies: {
247
244
  syncClient: SyncClient;
248
245
  database: Database;
249
- objectPool: ObjectPool;
246
+ objectPool: InstanceCache;
250
247
  modelRegistry: ModelRegistry;
251
248
  /**
252
- * Optional schema. When provided, `deriveSyncPlanFromSchema` walks
253
- * the schema's models + relations to auto-populate FK indexes and
254
- * the enrichment plan from declarative annotations. Class-based
255
- * subclass users (like Ablo's legacy SyncedStore) typically pass
256
- * explicit `config.foreignKeyIndexes` / `config.enrichmentPlan`
257
- * instead.
249
+ * Optional schema. When provided, {@link deriveSyncPlanFromSchema} walks
250
+ * the schema's models and relations to auto-populate foreign-key indexes
251
+ * and the enrichment plan from their declarative annotations. Subclasses
252
+ * that register model classes directly can instead pass explicit
253
+ * `config.foreignKeyIndexes` / `config.enrichmentPlan`.
258
254
  */
259
255
  schema?: TSchema;
260
256
  /** Sync server URL for WebSocket connection. Converted to wss:// automatically. */
@@ -263,17 +259,17 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
263
259
  auth?: AuthCredentialSource;
264
260
  }, config?: SyncedStoreConfig);
265
261
  /**
266
- * Register foreign key indexes for O(1) lookups.
262
+ * Register foreign-key indexes for constant-time lookups.
267
263
  *
268
- * Legacy override hook in Phase 2 the preferred way to declare FK
269
- * indexes is via `config.foreignKeyIndexes` at construction time, or
270
- * by marking the `belongsTo` relation with `{ index: true }` in the
271
- * schema. This hook still fires AFTER the schema-derived + config
272
- * registrations, so subclasses can layer additional FKs on top.
264
+ * This is an override hook. The preferred way to declare a foreign-key
265
+ * index is `config.foreignKeyIndexes` at construction time, or marking the
266
+ * `belongsTo` relation with `{ index: true }` in the schema. The hook fires
267
+ * after the schema-derived and config registrations, so a subclass can
268
+ * layer additional indexes on top.
273
269
  */
274
270
  protected registerForeignKeys(): void;
275
271
  /**
276
- * Enrich delta data with related models from the ObjectPool.
272
+ * Enrich delta data with related models from the InstanceCache.
277
273
  *
278
274
  * Base implementation walks `this.enrichmentPlan` — entries populated
279
275
  * from the schema's `{ enrich: true }` relations and from
@@ -390,11 +386,12 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
390
386
  */
391
387
  performCredentialRefresh(): Promise<'refreshed' | 'session_error' | 'network_error'>;
392
388
  /**
393
- * THE auth-recovery backbone for HTTP transports (lazy query lane etc.):
394
- * classify-driven single-flight re-mint with the same FSM outcome routing
395
- * the WS probe and proactive pre-roll use. `'retry'` ⇒ a fresh credential
396
- * is in the credential source, replay the request ONCE. Full contract on
397
- * {@link CredentialLifecycle.recoverFromAuthRejection}.
389
+ * The authentication-recovery path for HTTP transports, such as the lazy
390
+ * query lane. It runs a single-flight credential re-mint driven by the
391
+ * rejection's recovery class, routing outcomes through the same state
392
+ * machine the WebSocket probe uses. `'retry'` means a fresh credential is
393
+ * now in the credential source and the request should be replayed once.
394
+ * Full contract on {@link CredentialLifecycle.recoverFromAuthRejection}.
398
395
  */
399
396
  recoverFromAuthRejection(recovery: RecoveryClass): Promise<'retry' | 'stop'>;
400
397
  /**
@@ -406,11 +403,11 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
406
403
  */
407
404
  nudgeReconnect(): void;
408
405
  /**
409
- * Install the access-credential lifecycle the CLIENT owns: register
410
- * `getToken` as the reactive re-mint hook AND arm the browser-only
411
- * proactive pre-roll (refresh timer + OS-wake re-mint). Idempotent
412
- * (a second call replaces the first); torn down on {@link disconnect}.
413
- * Full rationale on {@link CredentialLifecycle.start}.
406
+ * Install the client-owned access-credential lifecycle: register `getToken`
407
+ * as the reactive re-mint hook and arm the browser-only proactive refresh
408
+ * (a refresh timer plus an OS-wake re-mint). Idempotent — a second call
409
+ * replaces the first — and torn down on {@link disconnect}. Full rationale
410
+ * on {@link CredentialLifecycle.start}.
414
411
  */
415
412
  startCredentialLifecycle(getToken: CredentialRefresher, opts?: {
416
413
  proactiveInNode?: boolean;
@@ -431,8 +428,9 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
431
428
  */
432
429
  protected handleGroupAdded(payload: GroupAddedPayload, syncId: number): Promise<void>;
433
430
  /**
434
- * Handle an actionType 'S' (GroupRemoved) delta SECURITY clear of local
435
- * state + full re-bootstrap. See {@link groupChange.handleGroupRemoved}.
431
+ * Handle an actionType 'S' (GroupRemoved) delta: for safety, clear the
432
+ * revoked local state and trigger a full re-bootstrap. See
433
+ * {@link groupChange.handleGroupRemoved}.
436
434
  */
437
435
  protected handleGroupRemoved(delta: SyncDelta): Promise<void>;
438
436
  /** Compute new sync groups after applying additions and removals */
@@ -453,8 +451,7 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
453
451
  protected checkSyncGroupShrinkage(): Promise<void>;
454
452
  /** Narrow context the bootstrap-apply leaf talks back through. */
455
453
  private poolContext;
456
- /** Apply bootstrap data to the ObjectPool with ghost removal */
457
- /** Apply bootstrap data to the ObjectPool. Delegates pool writes to SyncClient. */
454
+ /** Apply bootstrap data to the {@link InstanceCache}, removing entities that are no longer present (ghost removal). Pool writes are delegated to {@link SyncClient}. */
458
455
  protected applyBootstrapToPool(bootstrapResult: BootstrapResult, protectedIds?: ReadonlySet<string>): RehydrationStats;
459
456
  /**
460
457
  * Initialize the sync engine with user context.
@@ -553,23 +550,24 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
553
550
  /**
554
551
  * Apply a complete, server-delivered delta frame atomically.
555
552
  *
556
- * A `delta_batch` WS event (reconnect/catch-up replay) already carries
557
- * the FULL set of missed deltas. Routing it through the per-delta
558
- * `processDeltaWithBatching` path re-chunks it via the live-traffic
559
- * debounce timer + `maxBatchSize` force-flush, so a 300-delta catch-up
560
- * fans out into ~6 separate `flushPendingDeltas` cycles — each its own
561
- * IDB write, pool mutation, `models:changed` emit, and React re-render.
562
- * The decks gallery visibly re-sorts and "pops in" once per chunk.
553
+ * A `delta_batch` WebSocket event (a reconnect or catch-up replay) already
554
+ * carries the full set of missed deltas. Routing it through the per-delta
555
+ * `processDeltaWithBatching` path would re-chunk it via the live-traffic
556
+ * debounce timer and `maxBatchSize` force-flush, so a 300-delta catch-up
557
+ * would fan out into several separate `flushPendingDeltas` cycles — each its
558
+ * own local write, pool mutation, `models:changed` emit, and re-render, so
559
+ * the UI visibly repaints once per chunk.
563
560
  *
564
- * Here we run the per-delta bookkeeping (dedup, ack, version vector,
565
- * watermark, G/S routing, D cascade) for every delta WITHOUT scheduling
566
- * a flush, then flush ONCE — collapsing the whole frame into a single
567
- * IDB write + pool mutation + `models:changed` + re-render. Same code
568
- * for the post-bootstrap replay of deltas queued during bootstrap.
561
+ * Instead, this runs the per-delta bookkeeping (deduplication, ack, version
562
+ * vector, watermark, group-change routing, delete cascade) for every delta
563
+ * without scheduling a flush, then flushes once — collapsing the whole frame
564
+ * into a single local write, pool mutation, `models:changed` emit, and
565
+ * re-render. The post-bootstrap replay of deltas queued during bootstrap
566
+ * uses the same path.
569
567
  *
570
- * (Named `applyDeltaFrame`, not `processDeltaBatch`, to avoid confusion
571
- * with `Database.processDeltaBatch` — the lower-level IDB write this
572
- * eventually drives through `flushPendingDeltas`.)
568
+ * It is named `applyDeltaFrame`, not `processDeltaBatch`, to avoid confusion
569
+ * with {@link Database.processDeltaBatch} — the lower-level local write this
570
+ * eventually drives through `flushPendingDeltas`.
573
571
  */
574
572
  protected applyDeltaFrame(deltas: SyncDelta[]): void;
575
573
  /**
@@ -597,8 +595,7 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
597
595
  * skips both the scan AND the allocation.
598
596
  */
599
597
  protected cascadeCancelTransactionsForDeletedParent(parentModelName: string, parentId: string): void;
600
- /** Flush pending deltas with deduplication and batched ObjectPool mutations */
601
- /** Flush pending deltas with deduplication. Delegates pool writes to SyncClient. */
598
+ /** Flush pending deltas with deduplication. Pool writes are delegated to {@link SyncClient}. */
602
599
  protected flushPendingDeltas(): Promise<void>;
603
600
  /** Check if a model type is local-only (no sync). Override for domain-specific models. */
604
601
  protected isLocalOnlyModel(_modelName: string): boolean;
@@ -663,10 +660,10 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
663
660
  */
664
661
  create<K extends keyof TSchema['models'] & string>(typename: K, data: Record<string, unknown>): import('./schema/schema.js').InferModel<TSchema, K> | null;
665
662
  /**
666
- * Legacy class-based query entry point — kept for callers that still pass
667
- * a Model constructor + options object. New code should use the typed
668
- * `store.query.<modelKey>` namespace instead, which returns properly
669
- * inferred schema types without needing a class value or cast.
663
+ * Query entry point for callers that hold a {@link Model} constructor and an
664
+ * options object. It filters, orders, and paginates the matching models from
665
+ * the pool. Prefer the schema-typed read surface (`ablo.<model>.list`) where
666
+ * you can, since it infers concrete row types without a class value or cast.
670
667
  */
671
668
  queryByClass(modelClass: ModelConstructor<Model>, options?: {
672
669
  predicate?: (model: Model) => boolean;
@@ -695,7 +692,7 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
695
692
  protected incrementPendingChanges(): void;
696
693
  protected decrementPendingChanges(): void;
697
694
  protected updateSyncStatus(updates: Partial<SyncStatus>): void;
698
- get pool(): ObjectPool;
695
+ get pool(): InstanceCache;
699
696
  get lastSyncId(): number;
700
697
  get isReady(): boolean;
701
698
  get isSyncing(): boolean;