@abloatai/ablo 0.25.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 (425) hide show
  1. package/AGENTS.md +5 -3
  2. package/CHANGELOG.md +34 -0
  3. package/README.md +104 -88
  4. package/dist/BaseSyncedStore.d.ts +140 -266
  5. package/dist/BaseSyncedStore.js +338 -739
  6. package/dist/Database.d.ts +62 -77
  7. package/dist/Database.js +106 -127
  8. package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
  9. package/dist/{ObjectPool.js → InstanceCache.js} +91 -83
  10. package/dist/LazyReferenceCollection.d.ts +11 -15
  11. package/dist/LazyReferenceCollection.js +16 -15
  12. package/dist/Model.d.ts +37 -52
  13. package/dist/Model.js +52 -69
  14. package/dist/ModelRegistry.d.ts +46 -25
  15. package/dist/ModelRegistry.js +32 -30
  16. package/dist/NetworkMonitor.d.ts +5 -6
  17. package/dist/NetworkMonitor.js +6 -7
  18. package/dist/SyncClient.d.ts +119 -109
  19. package/dist/SyncClient.js +303 -224
  20. package/dist/SyncEngineContext.d.ts +1 -3
  21. package/dist/SyncEngineContext.js +1 -2
  22. package/dist/adapters/alwaysOnline.d.ts +6 -8
  23. package/dist/adapters/alwaysOnline.js +6 -8
  24. package/dist/adapters/inMemoryStorage.d.ts +9 -9
  25. package/dist/adapters/inMemoryStorage.js +9 -9
  26. package/dist/agent/Agent.d.ts +39 -31
  27. package/dist/agent/Agent.js +35 -23
  28. package/dist/agent/index.d.ts +4 -4
  29. package/dist/agent/index.js +5 -5
  30. package/dist/agent/session.d.ts +47 -44
  31. package/dist/agent/session.js +37 -48
  32. package/dist/agent/types.d.ts +26 -31
  33. package/dist/agent/types.js +6 -7
  34. package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
  35. package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
  36. package/dist/ai-sdk/coordinationContext.d.ts +46 -0
  37. package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +30 -31
  38. package/dist/ai-sdk/index.d.ts +25 -22
  39. package/dist/ai-sdk/index.js +25 -22
  40. package/dist/ai-sdk/wrap.d.ts +7 -8
  41. package/dist/ai-sdk/wrap.js +2 -2
  42. package/dist/auth/credentialPolicy.d.ts +74 -71
  43. package/dist/auth/credentialPolicy.js +51 -56
  44. package/dist/auth/credentialSource.d.ts +7 -18
  45. package/dist/auth/credentialSource.js +10 -18
  46. package/dist/auth/index.d.ts +59 -58
  47. package/dist/auth/index.js +34 -40
  48. package/dist/auth/schemas.d.ts +5 -4
  49. package/dist/auth/schemas.js +5 -4
  50. package/dist/batching/index.d.ts +19 -21
  51. package/dist/batching/index.js +14 -17
  52. package/dist/cli.cjs +483 -369
  53. package/dist/client/Ablo.d.ts +107 -836
  54. package/dist/client/Ablo.js +174 -833
  55. package/dist/client/ApiClient.d.ts +44 -20
  56. package/dist/client/ApiClient.js +193 -44
  57. package/dist/client/auth.d.ts +51 -60
  58. package/dist/client/auth.js +137 -110
  59. package/dist/client/claimHeartbeatLoop.d.ts +50 -0
  60. package/dist/client/claimHeartbeatLoop.js +88 -0
  61. package/dist/client/consoleLogger.d.ts +35 -0
  62. package/dist/client/consoleLogger.js +44 -0
  63. package/dist/client/createInternalComponents.d.ts +14 -17
  64. package/dist/client/createInternalComponents.js +26 -31
  65. package/dist/client/createModelProxy.d.ts +130 -120
  66. package/dist/client/createModelProxy.js +158 -124
  67. package/dist/client/credentialEndpoint.d.ts +61 -0
  68. package/dist/client/credentialEndpoint.js +86 -0
  69. package/dist/client/functionalUpdate.d.ts +29 -27
  70. package/dist/client/functionalUpdate.js +21 -21
  71. package/dist/client/hostedEndpoints.d.ts +21 -0
  72. package/dist/client/hostedEndpoints.js +21 -0
  73. package/dist/client/httpClient.d.ts +58 -54
  74. package/dist/client/httpClient.js +29 -31
  75. package/dist/client/identity.d.ts +15 -20
  76. package/dist/client/identity.js +49 -59
  77. package/dist/client/modelRegistration.d.ts +10 -0
  78. package/dist/client/modelRegistration.js +301 -0
  79. package/dist/client/options.d.ts +373 -0
  80. package/dist/client/options.js +6 -0
  81. package/dist/client/registerDataSource.d.ts +9 -9
  82. package/dist/client/registerDataSource.js +15 -16
  83. package/dist/client/resourceTypes.d.ts +333 -0
  84. package/dist/client/resourceTypes.js +7 -0
  85. package/dist/client/schemaConfig.d.ts +44 -0
  86. package/dist/client/schemaConfig.js +176 -0
  87. package/dist/client/sessionMint.d.ts +17 -13
  88. package/dist/client/sessionMint.js +26 -31
  89. package/dist/client/validateAbloOptions.d.ts +12 -14
  90. package/dist/client/validateAbloOptions.js +9 -10
  91. package/dist/client/writeOptionsSchema.d.ts +18 -16
  92. package/dist/client/writeOptionsSchema.js +23 -20
  93. package/dist/client/wsMutationExecutor.d.ts +28 -0
  94. package/dist/client/wsMutationExecutor.js +71 -0
  95. package/dist/context.d.ts +6 -4
  96. package/dist/context.js +6 -7
  97. package/dist/coordination/index.d.ts +13 -4
  98. package/dist/coordination/index.js +29 -4
  99. package/dist/coordination/schema.d.ts +176 -128
  100. package/dist/coordination/schema.js +197 -133
  101. package/dist/coordination/trace.d.ts +9 -11
  102. package/dist/coordination/trace.js +13 -15
  103. package/dist/core/DatabaseManager.d.ts +5 -8
  104. package/dist/core/DatabaseManager.js +38 -40
  105. package/dist/core/QueryProcessor.d.ts +7 -9
  106. package/dist/core/QueryProcessor.js +27 -34
  107. package/dist/core/QueryView.d.ts +17 -5
  108. package/dist/core/QueryView.js +6 -7
  109. package/dist/core/StoreManager.d.ts +14 -16
  110. package/dist/core/StoreManager.js +26 -25
  111. package/dist/core/ViewRegistry.d.ts +5 -5
  112. package/dist/core/ViewRegistry.js +4 -4
  113. package/dist/core/index.d.ts +18 -13
  114. package/dist/core/index.js +32 -26
  115. package/dist/core/openIDBWithTimeout.d.ts +38 -36
  116. package/dist/core/openIDBWithTimeout.js +57 -54
  117. package/dist/core/queryUtils.d.ts +45 -0
  118. package/dist/core/queryUtils.js +69 -0
  119. package/dist/core/storeContract.d.ts +145 -0
  120. package/dist/core/storeContract.js +12 -0
  121. package/dist/environment.d.ts +28 -0
  122. package/dist/environment.js +21 -0
  123. package/dist/errorCodes.d.ts +118 -101
  124. package/dist/errorCodes.js +277 -260
  125. package/dist/errors.d.ts +170 -165
  126. package/dist/errors.js +161 -151
  127. package/dist/index.d.ts +30 -27
  128. package/dist/index.js +90 -82
  129. package/dist/interfaces/index.d.ts +108 -133
  130. package/dist/interfaces/index.js +5 -4
  131. package/dist/keys/index.d.ts +27 -29
  132. package/dist/keys/index.js +59 -49
  133. package/dist/mutators/RecordingTransaction.d.ts +16 -16
  134. package/dist/mutators/RecordingTransaction.js +31 -37
  135. package/dist/mutators/Transaction.d.ts +18 -26
  136. package/dist/mutators/Transaction.js +14 -20
  137. package/dist/mutators/UndoManager.d.ts +122 -131
  138. package/dist/mutators/UndoManager.js +149 -155
  139. package/dist/mutators/defineMutators.d.ts +24 -37
  140. package/dist/mutators/defineMutators.js +14 -20
  141. package/dist/mutators/inverseOp.d.ts +12 -15
  142. package/dist/mutators/inverseOp.js +12 -15
  143. package/dist/mutators/mutateActions.d.ts +10 -9
  144. package/dist/mutators/mutateActions.js +1 -1
  145. package/dist/mutators/readerActions.d.ts +9 -8
  146. package/dist/mutators/readerActions.js +2 -2
  147. package/dist/mutators/undoApply.d.ts +31 -27
  148. package/dist/mutators/undoApply.js +26 -24
  149. package/dist/policy/index.d.ts +5 -3
  150. package/dist/policy/index.js +5 -3
  151. package/dist/policy/types.d.ts +105 -101
  152. package/dist/policy/types.js +67 -66
  153. package/dist/query/client.d.ts +32 -16
  154. package/dist/query/client.js +103 -72
  155. package/dist/query/types.d.ts +37 -60
  156. package/dist/query/types.js +13 -33
  157. package/dist/react/AbloProvider.d.ts +7 -11
  158. package/dist/react/AbloProvider.js +24 -17
  159. package/dist/react/context.d.ts +27 -146
  160. package/dist/react/context.js +9 -10
  161. package/dist/react/index.d.ts +41 -42
  162. package/dist/react/index.js +37 -38
  163. package/dist/react/internalContext.d.ts +17 -19
  164. package/dist/react/useAblo.d.ts +23 -22
  165. package/dist/react/useAblo.js +17 -15
  166. package/dist/react/useCurrentUserId.d.ts +8 -7
  167. package/dist/react/useCurrentUserId.js +8 -7
  168. package/dist/react/useErrorListener.d.ts +7 -7
  169. package/dist/react/useErrorListener.js +11 -12
  170. package/dist/react/useMutationFailureListener.d.ts +8 -8
  171. package/dist/react/useMutationFailureListener.js +9 -9
  172. package/dist/react/useMutators.d.ts +11 -11
  173. package/dist/react/useMutators.js +10 -4
  174. package/dist/react/useReactive.js +2 -3
  175. package/dist/react/useSyncStatus.d.ts +4 -6
  176. package/dist/react/useUndoScope.d.ts +7 -9
  177. package/dist/react/useUndoScope.js +3 -3
  178. package/dist/schema/coordination.d.ts +21 -25
  179. package/dist/schema/coordination.js +21 -25
  180. package/dist/schema/ddl.d.ts +43 -39
  181. package/dist/schema/ddl.js +75 -68
  182. package/dist/schema/ddlLock.d.ts +35 -0
  183. package/dist/schema/ddlLock.js +46 -0
  184. package/dist/schema/diff.d.ts +99 -61
  185. package/dist/schema/diff.js +43 -34
  186. package/dist/schema/field.d.ts +37 -42
  187. package/dist/schema/field.js +36 -49
  188. package/dist/schema/generate.d.ts +12 -12
  189. package/dist/schema/generate.js +12 -12
  190. package/dist/schema/index.d.ts +5 -4
  191. package/dist/schema/index.js +29 -21
  192. package/dist/schema/model.d.ts +121 -146
  193. package/dist/schema/model.js +24 -35
  194. package/dist/schema/openapi.d.ts +10 -9
  195. package/dist/schema/openapi.js +7 -1
  196. package/dist/schema/queries.d.ts +30 -32
  197. package/dist/schema/queries.js +24 -25
  198. package/dist/schema/relation.d.ts +89 -99
  199. package/dist/schema/relation.js +13 -13
  200. package/dist/schema/residency.d.ts +38 -0
  201. package/dist/schema/residency.js +30 -0
  202. package/dist/schema/roles.d.ts +45 -27
  203. package/dist/schema/roles.js +52 -21
  204. package/dist/schema/schema.d.ts +36 -45
  205. package/dist/schema/schema.js +42 -39
  206. package/dist/schema/select.d.ts +13 -13
  207. package/dist/schema/select.js +13 -13
  208. package/dist/schema/serialize.d.ts +36 -39
  209. package/dist/schema/serialize.js +27 -31
  210. package/dist/schema/sugar.d.ts +17 -32
  211. package/dist/schema/sugar.js +14 -29
  212. package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +27 -50
  213. package/dist/schema/syncDeltaRow.js +89 -0
  214. package/dist/schema/tenancy.d.ts +44 -46
  215. package/dist/schema/tenancy.js +46 -48
  216. package/dist/server/adapter.d.ts +58 -58
  217. package/dist/server/adapter.js +13 -14
  218. package/dist/server/commit.d.ts +60 -64
  219. package/dist/server/index.d.ts +9 -10
  220. package/dist/server/index.js +1 -1
  221. package/dist/server/readConfig.d.ts +70 -0
  222. package/dist/server/readConfig.js +8 -0
  223. package/dist/server/storageMode.d.ts +23 -0
  224. package/dist/server/storageMode.js +17 -0
  225. package/dist/source/adapter.d.ts +31 -26
  226. package/dist/source/adapter.js +10 -10
  227. package/dist/source/adapters/drizzle.d.ts +28 -23
  228. package/dist/source/adapters/drizzle.js +34 -28
  229. package/dist/source/adapters/kysely.d.ts +27 -25
  230. package/dist/source/adapters/kysely.js +28 -26
  231. package/dist/source/adapters/memory.d.ts +8 -7
  232. package/dist/source/adapters/memory.js +10 -9
  233. package/dist/source/adapters/prisma.d.ts +13 -12
  234. package/dist/source/adapters/prisma.js +27 -29
  235. package/dist/source/conformance.d.ts +18 -11
  236. package/dist/source/conformance.js +27 -19
  237. package/dist/source/connector.d.ts +31 -32
  238. package/dist/source/connector.js +30 -28
  239. package/dist/source/connectorProtocol.d.ts +160 -0
  240. package/dist/source/connectorProtocol.js +162 -0
  241. package/dist/source/contract.d.ts +26 -27
  242. package/dist/source/contract.js +28 -29
  243. package/dist/source/factory.d.ts +94 -0
  244. package/dist/source/factory.js +268 -0
  245. package/dist/source/index.d.ts +10 -462
  246. package/dist/source/index.js +17 -421
  247. package/dist/source/migrations.d.ts +9 -9
  248. package/dist/source/migrations.js +9 -9
  249. package/dist/source/next.d.ts +10 -11
  250. package/dist/source/next.js +7 -8
  251. package/dist/source/pushQueue.d.ts +70 -48
  252. package/dist/source/pushQueue.js +36 -29
  253. package/dist/source/signing.d.ts +88 -0
  254. package/dist/source/signing.js +159 -0
  255. package/dist/source/types.d.ts +351 -0
  256. package/dist/source/types.js +43 -0
  257. package/dist/stores/ObjectStore.d.ts +11 -12
  258. package/dist/stores/ObjectStore.js +34 -35
  259. package/dist/stores/ObjectStoreContract.d.ts +12 -15
  260. package/dist/stores/SyncActionStore.d.ts +8 -12
  261. package/dist/stores/SyncActionStore.js +77 -46
  262. package/dist/surface.d.ts +28 -21
  263. package/dist/surface.js +28 -20
  264. package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +37 -45
  265. package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +101 -80
  266. package/dist/sync/ConnectionManager.d.ts +47 -50
  267. package/dist/sync/ConnectionManager.js +74 -70
  268. package/dist/sync/NetworkProbe.d.ts +27 -31
  269. package/dist/sync/NetworkProbe.js +67 -72
  270. package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +49 -36
  271. package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +79 -54
  272. package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +45 -59
  273. package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +44 -52
  274. package/dist/sync/SyncWebSocket.d.ts +175 -250
  275. package/dist/sync/SyncWebSocket.js +431 -769
  276. package/dist/sync/awaitClaimGrant.d.ts +18 -18
  277. package/dist/sync/awaitClaimGrant.js +38 -30
  278. package/dist/sync/bootstrapApply.d.ts +70 -0
  279. package/dist/sync/bootstrapApply.js +73 -0
  280. package/dist/sync/commitFrames.d.ts +44 -0
  281. package/dist/sync/commitFrames.js +94 -0
  282. package/dist/sync/createClaimStream.d.ts +23 -22
  283. package/dist/sync/createClaimStream.js +108 -25
  284. package/dist/sync/createPresenceStream.d.ts +19 -18
  285. package/dist/sync/createPresenceStream.js +25 -26
  286. package/dist/sync/createSnapshot.d.ts +13 -17
  287. package/dist/sync/createSnapshot.js +20 -26
  288. package/dist/sync/credentialLifecycle.d.ts +175 -0
  289. package/dist/sync/credentialLifecycle.js +322 -0
  290. package/dist/sync/deltaPipeline.d.ts +113 -0
  291. package/dist/sync/deltaPipeline.js +261 -0
  292. package/dist/sync/groupChange.d.ts +113 -0
  293. package/dist/sync/groupChange.js +242 -0
  294. package/dist/sync/heartbeat.d.ts +63 -0
  295. package/dist/sync/heartbeat.js +91 -0
  296. package/dist/sync/participants.d.ts +27 -27
  297. package/dist/sync/schemas.d.ts +3 -2
  298. package/dist/sync/schemas.js +14 -10
  299. package/dist/sync/syncCursor.d.ts +40 -0
  300. package/dist/sync/syncCursor.js +55 -0
  301. package/dist/sync/syncPlan.d.ts +54 -0
  302. package/dist/sync/syncPlan.js +50 -0
  303. package/dist/sync/syncPosition.d.ts +54 -49
  304. package/dist/sync/syncPosition.js +57 -52
  305. package/dist/sync/wsFrameHandlers.d.ts +116 -0
  306. package/dist/sync/wsFrameHandlers.js +374 -0
  307. package/dist/testing/fixtures/bootstrap.d.ts +21 -17
  308. package/dist/testing/fixtures/bootstrap.js +12 -6
  309. package/dist/testing/fixtures/deltas.d.ts +31 -34
  310. package/dist/testing/fixtures/deltas.js +30 -33
  311. package/dist/testing/fixtures/models.d.ts +11 -10
  312. package/dist/testing/fixtures/models.js +12 -10
  313. package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
  314. package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
  315. package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -18
  316. package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +14 -11
  317. package/dist/testing/helpers/wait.d.ts +13 -8
  318. package/dist/testing/helpers/wait.js +13 -8
  319. package/dist/testing/index.d.ts +4 -4
  320. package/dist/testing/index.js +3 -3
  321. package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
  322. package/dist/testing/mocks/MockMutationExecutor.js +15 -14
  323. package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
  324. package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
  325. package/dist/testing/mocks/MockSyncContext.d.ts +21 -34
  326. package/dist/testing/mocks/MockSyncContext.js +16 -45
  327. package/dist/testing/mocks/MockSyncStore.d.ts +14 -14
  328. package/dist/testing/mocks/MockSyncStore.js +11 -11
  329. package/dist/testing/mocks/MockWebSocket.d.ts +28 -24
  330. package/dist/testing/mocks/MockWebSocket.js +22 -21
  331. package/dist/transactions/TransactionQueue.d.ts +190 -221
  332. package/dist/transactions/TransactionQueue.js +424 -822
  333. package/dist/transactions/TransactionStore.d.ts +20 -0
  334. package/dist/transactions/TransactionStore.js +53 -0
  335. package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
  336. package/dist/transactions/UnconfirmedWrites.js +104 -0
  337. package/dist/transactions/coalesceRules.d.ts +58 -0
  338. package/dist/transactions/coalesceRules.js +140 -0
  339. package/dist/transactions/commitPayload.d.ts +130 -0
  340. package/dist/transactions/commitPayload.js +143 -0
  341. package/dist/transactions/deltaConfirmation.d.ts +58 -0
  342. package/dist/transactions/deltaConfirmation.js +215 -0
  343. package/dist/transactions/optimisticApply.d.ts +49 -0
  344. package/dist/transactions/optimisticApply.js +65 -0
  345. package/dist/transactions/replayValidation.d.ts +99 -0
  346. package/dist/transactions/replayValidation.js +111 -0
  347. package/dist/types/global.d.ts +46 -41
  348. package/dist/types/global.js +20 -19
  349. package/dist/types/index.d.ts +74 -80
  350. package/dist/types/index.js +22 -27
  351. package/dist/types/modelData.d.ts +10 -0
  352. package/dist/types/modelData.js +9 -0
  353. package/dist/types/participant.d.ts +20 -0
  354. package/dist/types/participant.js +10 -0
  355. package/dist/types/streams.d.ts +216 -209
  356. package/dist/types/streams.js +7 -7
  357. package/dist/utils/asyncIterator.d.ts +25 -32
  358. package/dist/utils/asyncIterator.js +25 -32
  359. package/dist/utils/duration.d.ts +12 -15
  360. package/dist/utils/duration.js +12 -15
  361. package/dist/utils/mobxSetup.d.ts +53 -0
  362. package/dist/utils/{mobx-setup.js → mobxSetup.js} +44 -100
  363. package/dist/webhooks/events.d.ts +21 -16
  364. package/dist/webhooks/events.js +10 -8
  365. package/dist/webhooks/index.d.ts +5 -7
  366. package/dist/webhooks/index.js +5 -7
  367. package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
  368. package/dist/wire/delta.js +114 -0
  369. package/dist/wire/errorEnvelope.d.ts +35 -27
  370. package/dist/wire/errorEnvelope.js +38 -32
  371. package/dist/wire/frames.d.ts +150 -67
  372. package/dist/wire/frames.js +48 -1
  373. package/dist/wire/index.d.ts +18 -13
  374. package/dist/wire/index.js +36 -13
  375. package/dist/wire/listEnvelope.d.ts +16 -23
  376. package/dist/wire/listEnvelope.js +7 -6
  377. package/dist/wire/protocol.d.ts +38 -0
  378. package/dist/wire/protocol.js +38 -0
  379. package/dist/wire/protocolVersion.d.ts +60 -0
  380. package/dist/wire/protocolVersion.js +67 -0
  381. package/docs/api-keys.md +4 -3
  382. package/docs/coordination.md +59 -0
  383. package/docs/examples/existing-python-backend.md +3 -3
  384. package/docs/identity.md +4 -4
  385. package/docs/integration-guide.md +1 -1
  386. package/docs/react.md +1 -1
  387. package/docs/sessions.md +5 -7
  388. package/package.json +24 -21
  389. package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
  390. package/dist/ai-sdk/coordination-context.d.ts +0 -52
  391. package/dist/client/index.d.ts +0 -36
  392. package/dist/client/index.js +0 -33
  393. package/dist/config/index.d.ts +0 -10
  394. package/dist/config/index.js +0 -12
  395. package/dist/core/query-utils.d.ts +0 -34
  396. package/dist/core/query-utils.js +0 -59
  397. package/dist/interfaces/headless.d.ts +0 -95
  398. package/dist/interfaces/headless.js +0 -41
  399. package/dist/query/index.d.ts +0 -6
  400. package/dist/query/index.js +0 -5
  401. package/dist/realtime/index.d.ts +0 -10
  402. package/dist/realtime/index.js +0 -9
  403. package/dist/schema/plane.d.ts +0 -23
  404. package/dist/schema/plane.js +0 -19
  405. package/dist/schema/sync-delta-row.js +0 -103
  406. package/dist/schema/sync-delta-wire.js +0 -102
  407. package/dist/server/next.d.ts +0 -51
  408. package/dist/server/next.js +0 -47
  409. package/dist/server/read-config.d.ts +0 -67
  410. package/dist/server/read-config.js +0 -8
  411. package/dist/server/storage-mode.d.ts +0 -1
  412. package/dist/server/storage-mode.js +0 -18
  413. package/dist/source/connector-protocol.d.ts +0 -159
  414. package/dist/source/connector-protocol.js +0 -161
  415. package/dist/sync/OfflineFlush.d.ts +0 -9
  416. package/dist/sync/OfflineFlush.js +0 -22
  417. package/dist/sync/OfflineTransactionStore.d.ts +0 -37
  418. package/dist/sync/OfflineTransactionStore.js +0 -263
  419. package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
  420. package/dist/transactions/OptimisticEchoTracker.js +0 -104
  421. package/dist/transactions/index.d.ts +0 -16
  422. package/dist/transactions/index.js +0 -7
  423. package/dist/transactions/mutation-error-handler.d.ts +0 -5
  424. package/dist/transactions/mutation-error-handler.js +0 -39
  425. package/dist/utils/mobx-setup.d.ts +0 -42
@@ -1,30 +1,30 @@
1
1
  /**
2
- * `awaitClaimGrant` — the client side of the fair-queue handover.
2
+ * Waits for a queued claim to reach the head of the line — the client side of
3
+ * the fair-queue handover. When a claim is contended, the server puts it in a
4
+ * queue and replies that it is queued (HTTP 202 on `/v1/claims`, or a
5
+ * `claim_queued` frame over the WebSocket). The grant is delivered later, when
6
+ * the claim reaches the head, as a `claim_granted` frame. This resolves once
7
+ * that frame arrives for the given `claimId`, so the caller's `claim` promise
8
+ * stays pending — event-driven, with no polling — until it is actually the
9
+ * caller's turn. It rejects if the claim is lost (`claim_lost`: taken away by a
10
+ * TTL lapse on disconnect, or revoked) or if an optional timeout elapses.
3
11
  *
4
- * When a `claim` is contended, the server enqueues it and replies `queued`
5
- * (HTTP 202 on `/v1/claims`, or `claim_queued` over WS). The grant is then
6
- * PUSHED later over the WS as `claim_granted` when the claim reaches the head.
7
- * This resolves once that frame arrives for our `claimId` — so the caller's
8
- * `claim` promise stays pending (event-driven; no poll, no race) until it's
9
- * actually our turn. Rejects on `claim_lost` (surfaced as `claim_lost`: the claim was taken away — TTL
10
- * lapse on disconnect, revoke) or an optional timeout.
11
- *
12
- * Takes only a minimal `{ subscribe }` transport so it unit-tests against a
13
- * fake; `SyncWebSocket` satisfies it structurally.
12
+ * It needs only a minimal `{ subscribe }` transport, so it can be tested
13
+ * against a fake; {@link SyncWebSocket} satisfies it.
14
14
  */
15
15
  export interface GrantTransport {
16
16
  subscribe(event: 'claim_acquired' | 'claim_granted' | 'claim_lost' | 'claim_queued' | 'claim_rejected', handler: (payload: Record<string, unknown>) => void): () => void;
17
17
  }
18
18
  export interface ClaimGrantInfo {
19
19
  /**
20
- * True when the grant arrived as `claim_granted` — i.e. the target was
21
- * HELD when we asked and we waited in the FIFO line behind the holder.
22
- * False for the immediate `claim_acquired` (target was free).
20
+ * True when the grant arrived as `claim_granted` — the target was held when
21
+ * the caller asked, and the caller waited in the FIFO line behind the holder.
22
+ * False for the immediate `claim_acquired`, where the target was free.
23
23
  *
24
- * Callers use this to know the row may have changed while we queued:
25
- * claim VISIBILITY is entity-scoped (org-wide subscriptions receive no
26
- * presence/claim fan-out — see Hub.broadcastPresenceChange), so the
27
- * local coordination snapshot cannot be trusted to detect "we waited".
24
+ * Callers read this to know the row may have changed while they queued. Claim
25
+ * visibility is scoped to the entity, so a broad, organization-wide
26
+ * subscription receives no presence or claim fan-out, and the local
27
+ * coordination snapshot cannot be trusted to tell whether the caller waited.
28
28
  * The grant frame itself is the authoritative signal.
29
29
  */
30
30
  readonly waited: boolean;
@@ -1,16 +1,16 @@
1
1
  /**
2
- * `awaitClaimGrant` — the client side of the fair-queue handover.
2
+ * Waits for a queued claim to reach the head of the line — the client side of
3
+ * the fair-queue handover. When a claim is contended, the server puts it in a
4
+ * queue and replies that it is queued (HTTP 202 on `/v1/claims`, or a
5
+ * `claim_queued` frame over the WebSocket). The grant is delivered later, when
6
+ * the claim reaches the head, as a `claim_granted` frame. This resolves once
7
+ * that frame arrives for the given `claimId`, so the caller's `claim` promise
8
+ * stays pending — event-driven, with no polling — until it is actually the
9
+ * caller's turn. It rejects if the claim is lost (`claim_lost`: taken away by a
10
+ * TTL lapse on disconnect, or revoked) or if an optional timeout elapses.
3
11
  *
4
- * When a `claim` is contended, the server enqueues it and replies `queued`
5
- * (HTTP 202 on `/v1/claims`, or `claim_queued` over WS). The grant is then
6
- * PUSHED later over the WS as `claim_granted` when the claim reaches the head.
7
- * This resolves once that frame arrives for our `claimId` — so the caller's
8
- * `claim` promise stays pending (event-driven; no poll, no race) until it's
9
- * actually our turn. Rejects on `claim_lost` (surfaced as `claim_lost`: the claim was taken away — TTL
10
- * lapse on disconnect, revoke) or an optional timeout.
11
- *
12
- * Takes only a minimal `{ subscribe }` transport so it unit-tests against a
13
- * fake; `SyncWebSocket` satisfies it structurally.
12
+ * It needs only a minimal `{ subscribe }` transport, so it can be tested
13
+ * against a fake; {@link SyncWebSocket} satisfies it.
14
14
  */
15
15
  import { AbloClaimedError, formatClaimedErrorMessage, claimTargetLabel, } from '../errors.js';
16
16
  import { getContext } from '../context.js';
@@ -31,7 +31,7 @@ export function awaitClaimGrant(transport, claimId, options) {
31
31
  unsubs.push(transport.subscribe('claim_acquired', (p) => {
32
32
  if (p?.claimId === claimId) {
33
33
  getContext().logger.debug(`claim: acquired ${claimId} (target was free)`);
34
- settle(() => resolve({ waited: false }));
34
+ settle(() => { resolve({ waited: false }); });
35
35
  }
36
36
  }));
37
37
  unsubs.push(transport.subscribe('claim_granted', (p) => {
@@ -39,7 +39,7 @@ export function awaitClaimGrant(transport, claimId, options) {
39
39
  // Promoted to the head of the line — the creator's "it's the agent's
40
40
  // turn now" moment after waiting behind a holder.
41
41
  getContext().logger.info(`claim: granted ${claimId} — your turn (waited in queue)`);
42
- settle(() => resolve({ waited: true }));
42
+ settle(() => { resolve({ waited: true }); });
43
43
  }
44
44
  }));
45
45
  if (options?.maxQueueDepth !== undefined) {
@@ -49,7 +49,9 @@ export function awaitClaimGrant(transport, claimId, options) {
49
49
  return;
50
50
  const position = typeof p.position === 'number' ? p.position : 0;
51
51
  if (position >= max) {
52
- settle(() => reject(new AbloClaimedError(`Claim queue for ${claimId} is ${position} deep (max ${max}).`, { code: 'queue_too_deep' })));
52
+ settle(() => {
53
+ reject(new AbloClaimedError(`Claim queue for ${claimId} is ${position} deep (max ${max}).`, { code: 'queue_too_deep' }));
54
+ });
53
55
  }
54
56
  }));
55
57
  }
@@ -64,29 +66,35 @@ export function awaitClaimGrant(transport, claimId, options) {
64
66
  field: rejection.target.field,
65
67
  })
66
68
  : claimId;
67
- settle(() => reject(new AbloClaimedError(formatClaimedErrorMessage({
68
- targetLabel: target,
69
- heldBy: rejection.heldBy,
70
- claim: rejection.heldByClaim,
71
- policyReason: rejection.policyReason,
72
- fallback: `Claim rejected for ${target}.`,
73
- }), {
74
- code: rejection.reason === 'conflict'
75
- ? 'claim_conflict'
76
- : 'claim_lease_unavailable',
77
- claims: rejection.heldByClaim ? [rejection.heldByClaim] : undefined,
78
- })));
69
+ settle(() => {
70
+ reject(new AbloClaimedError(formatClaimedErrorMessage({
71
+ targetLabel: target,
72
+ heldBy: rejection.heldBy,
73
+ claim: rejection.heldByClaim,
74
+ policyReason: rejection.policyReason,
75
+ fallback: `Claim rejected for ${target}.`,
76
+ }), {
77
+ code: rejection.reason === 'conflict'
78
+ ? 'claim_conflict'
79
+ : 'claim_lease_unavailable',
80
+ claims: rejection.heldByClaim ? [rejection.heldByClaim] : undefined,
81
+ }));
82
+ });
79
83
  }));
80
84
  unsubs.push(transport.subscribe('claim_lost', (p) => {
81
85
  if (p?.claimId === claimId) {
82
- settle(() => reject(new AbloClaimedError(`Claim lost while queued for ${claimId}.`, {
83
- code: 'claim_lost',
84
- })));
86
+ settle(() => {
87
+ reject(new AbloClaimedError(`Claim lost while queued for ${claimId}.`, {
88
+ code: 'claim_lost',
89
+ }));
90
+ });
85
91
  }
86
92
  }));
87
93
  if (options?.timeoutMs && options.timeoutMs > 0) {
88
94
  timer = setTimeout(() => {
89
- settle(() => reject(new AbloClaimedError(`Timed out waiting for the queue grant on claim ${claimId}.`, { code: 'grant_timeout' })));
95
+ settle(() => {
96
+ reject(new AbloClaimedError(`Timed out waiting for the queue grant on claim ${claimId}.`, { code: 'grant_timeout' }));
97
+ });
90
98
  }, options.timeoutMs);
91
99
  }
92
100
  });
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Applies a bootstrap result to the in-memory object pool. When a client
3
+ * connects, the server sends either a full snapshot of the models it can see or
4
+ * a partial catch-up of the deltas it missed. These functions route that result
5
+ * into the pool, protect entities that arrived mid-bootstrap from being swept
6
+ * away as stale, and replay any deltas that queued while the bootstrap was in
7
+ * flight.
8
+ *
9
+ * The functions here reach their host store only through the small
10
+ * {@link PoolContext} interface, not the store's concrete class, so the two can
11
+ * reference each other without forming an import cycle. The pool writes
12
+ * themselves — creating models, healing partial rows, upserting, and removing
13
+ * stale local copies the server no longer reports — are performed by the sync
14
+ * client behind that interface.
15
+ */
16
+ import type { BootstrapResult } from '../Database.js';
17
+ import type { SyncDelta } from './SyncWebSocket.js';
18
+ /** Counts describing what applying a bootstrap changed in the pool: entities
19
+ * added, updated, removed, skipped, and healed, plus the elapsed time. */
20
+ export interface RehydrationStats {
21
+ added: number;
22
+ updated: number;
23
+ removed: number;
24
+ skipped: number;
25
+ healed: number;
26
+ elapsedMs: number;
27
+ }
28
+ /**
29
+ * The methods the bootstrap-apply functions call back into on the host store.
30
+ * The two data-application methods arrive with relation enrichment already
31
+ * bound by the host, so a subclass override of how relations are enriched still
32
+ * takes effect through this interface.
33
+ */
34
+ export interface PoolContext {
35
+ /** Applies persisted delta results to the in-memory pool, with the host's relation enrichment bound. */
36
+ applyDeltaBatchToPool(results: NonNullable<BootstrapResult['deltaResults']>): void;
37
+ /** Writes bootstrap data into the pool: creates models, heals partial rows, upserts, and removes stale local copies the server no longer reports. */
38
+ applyBootstrapDataToPool(bootstrapData: {
39
+ models?: Record<string, unknown[]>;
40
+ failedModels?: string[];
41
+ }, protectedIds?: ReadonlySet<string>): {
42
+ added: number;
43
+ updated: number;
44
+ removed: number;
45
+ skipped: number;
46
+ healed: number;
47
+ };
48
+ /** Pool size — for the completion log line. */
49
+ getPoolSize(): number;
50
+ /** Every id currently in the pool, used to work out which entities must survive the stale-sweep (see {@link collectDeltaProtectedIds}). */
51
+ getAllPoolIds(): string[];
52
+ /** Deltas that queued while a bootstrap was in flight; null when no bootstrap
53
+ * is running. The host backs this with a field exposed through accessors. */
54
+ bootstrapDeltaQueue: SyncDelta[] | null;
55
+ /** Applies a complete set of deltas to the pool atomically — one write, one
56
+ * re-render. This entry point lives on the host, not in this module. */
57
+ applyDeltaFrame(deltas: SyncDelta[]): void;
58
+ }
59
+ /**
60
+ * Applies a bootstrap result to the in-memory pool and returns what changed.
61
+ * A full bootstrap creates, heals, and upserts models and removes stale local
62
+ * copies the server no longer reports; a partial bootstrap routes the missed
63
+ * deltas through the delta-apply path so deletions evict their entities. See
64
+ * {@link RehydrationStats} for the returned counts.
65
+ */
66
+ export declare function applyBootstrapToPool(ctx: PoolContext, bootstrapResult: BootstrapResult, protectedIds?: ReadonlySet<string>): RehydrationStats;
67
+ /** Collects the ids that must survive the post-bootstrap stale-sweep: entities added by deltas that arrived while the bootstrap was in flight. */
68
+ export declare function collectDeltaProtectedIds(ctx: PoolContext, preBootstrapIds: ReadonlySet<string>): Set<string>;
69
+ /** Replays the deltas that queued while a bootstrap was in flight, applying them as one atomic frame. */
70
+ export declare function replayQueuedDeltas(ctx: PoolContext): void;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Applies a bootstrap result to the in-memory object pool. When a client
3
+ * connects, the server sends either a full snapshot of the models it can see or
4
+ * a partial catch-up of the deltas it missed. These functions route that result
5
+ * into the pool, protect entities that arrived mid-bootstrap from being swept
6
+ * away as stale, and replay any deltas that queued while the bootstrap was in
7
+ * flight.
8
+ *
9
+ * The functions here reach their host store only through the small
10
+ * {@link PoolContext} interface, not the store's concrete class, so the two can
11
+ * reference each other without forming an import cycle. The pool writes
12
+ * themselves — creating models, healing partial rows, upserting, and removing
13
+ * stale local copies the server no longer reports — are performed by the sync
14
+ * client behind that interface.
15
+ */
16
+ import { getContext } from '../context.js';
17
+ /**
18
+ * Applies a bootstrap result to the in-memory pool and returns what changed.
19
+ * A full bootstrap creates, heals, and upserts models and removes stale local
20
+ * copies the server no longer reports; a partial bootstrap routes the missed
21
+ * deltas through the delta-apply path so deletions evict their entities. See
22
+ * {@link RehydrationStats} for the returned counts.
23
+ */
24
+ export function applyBootstrapToPool(ctx, bootstrapResult, protectedIds) {
25
+ const { bootstrapData } = bootstrapResult;
26
+ // Partial bootstrap: the missed deltas are already written to the local
27
+ // store. Route the same results through the delta-apply path so the
28
+ // in-memory pool also evicts deleted entities and updates modified ones.
29
+ // Without this, a reconnect delete persists locally but its stale copy
30
+ // lingers in the pool until a full reload.
31
+ if (bootstrapData.type === 'partial') {
32
+ const deltaResults = bootstrapResult.deltaResults;
33
+ if (deltaResults && deltaResults.length > 0) {
34
+ ctx.applyDeltaBatchToPool(deltaResults);
35
+ }
36
+ return { added: 0, updated: 0, removed: 0, skipped: 0, healed: 0, elapsedMs: 0 };
37
+ }
38
+ if (!bootstrapData.models) {
39
+ return { added: 0, updated: 0, removed: 0, skipped: 0, healed: 0, elapsedMs: 0 };
40
+ }
41
+ const start = typeof performance !== 'undefined' ? performance.now() : Date.now();
42
+ // Creates models, heals partial rows, upserts, and removes stale local copies.
43
+ const stats = ctx.applyBootstrapDataToPool(bootstrapData, protectedIds);
44
+ const elapsedMs = Math.round((typeof performance !== 'undefined' ? performance.now() : Date.now()) - start);
45
+ getContext().logger.info('[BaseSyncedStore] Bootstrap applied', {
46
+ ...stats, elapsedMs, poolSize: ctx.getPoolSize(),
47
+ });
48
+ return { ...stats, elapsedMs };
49
+ }
50
+ /** Collects the ids that must survive the post-bootstrap stale-sweep: entities added by deltas that arrived while the bootstrap was in flight. */
51
+ export function collectDeltaProtectedIds(ctx, preBootstrapIds) {
52
+ const protectedIds = new Set();
53
+ for (const id of ctx.getAllPoolIds()) {
54
+ if (!preBootstrapIds.has(id))
55
+ protectedIds.add(id);
56
+ }
57
+ for (const delta of ctx.bootstrapDeltaQueue ?? []) {
58
+ if (delta.actionType !== 'D' && delta.modelId)
59
+ protectedIds.add(delta.modelId);
60
+ }
61
+ return protectedIds;
62
+ }
63
+ /** Replays the deltas that queued while a bootstrap was in flight, applying them as one atomic frame. */
64
+ export function replayQueuedDeltas(ctx) {
65
+ const queue = ctx.bootstrapDeltaQueue;
66
+ ctx.bootstrapDeltaQueue = null;
67
+ if (!queue || queue.length === 0)
68
+ return;
69
+ // Deltas that landed during bootstrap are a complete frame — apply
70
+ // them atomically (one flush, one re-render) rather than dribbling
71
+ // each back through the live debounce path.
72
+ ctx.applyDeltaFrame(queue);
73
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Builds the outgoing frames the sync WebSocket sends on the commit path, and
3
+ * provides the single place claim events are traced. These are stateless
4
+ * helpers that hold no socket state, so both the transport and its frame
5
+ * dispatch can share them.
6
+ */
7
+ import type { CommitMessage } from '../wire/index.js';
8
+ import type { MutationOperation, ClaimEvent } from '../interfaces/index.js';
9
+ import type { StaleNotification, ReadDependency } from '../coordination/schema.js';
10
+ /**
11
+ * The value a commit acknowledgement resolves to. `notifications` is present
12
+ * only when a guarded write (`onStale: 'notify'`) met a concurrent change; it
13
+ * carries the advisory signal that lets the writer self-heal, and the same
14
+ * signal also arrives on the `conflict:notified` event.
15
+ */
16
+ export interface CommitAck {
17
+ lastSyncId: number;
18
+ notifications?: StaleNotification[];
19
+ }
20
+ /**
21
+ * Converts the client's list of {@link MutationOperation} values into the wire
22
+ * {@link CommitMessage} the server accepts. This is the one place the loosely
23
+ * typed operation — its `type` is a string, and it carries client-only
24
+ * `options` the server never reads — becomes the strict wire contract. Mapping
25
+ * each field by hand means a change to {@link CommitOperation} fails to compile
26
+ * here; the single `as` cast narrows the validated `type` to the wire union and
27
+ * is the only place that loosening happens.
28
+ */
29
+ export declare function buildCommitFrame(operations: readonly MutationOperation[], clientTxId: string, causedByTaskId?: string | null, reads?: readonly ReadDependency[] | null): CommitMessage;
30
+ /**
31
+ * Defensively validate the optional `notifications` array off a commit ack.
32
+ * Untrusted wire data — a malformed entry is dropped rather than throwing,
33
+ * so a bad notification never sinks an otherwise-successful commit.
34
+ */
35
+ export declare function parseNotifications(raw: unknown): StaleNotification[] | undefined;
36
+ /**
37
+ * The single place claim events are traced. Every `claim_*` frame passes
38
+ * through here, so a developer debugging a collision gets one consistent record
39
+ * — a console line and a structured capture — without each frame case
40
+ * re-deriving the row and holder shape. The wire payload is loosely typed
41
+ * (`Record<string, unknown>`), so this is the one place that narrows it into a
42
+ * {@link ClaimEvent}.
43
+ */
44
+ export declare function recordClaim(phase: ClaimEvent['phase'], payload: Record<string, unknown>): void;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Builds the outgoing frames the sync WebSocket sends on the commit path, and
3
+ * provides the single place claim events are traced. These are stateless
4
+ * helpers that hold no socket state, so both the transport and its frame
5
+ * dispatch can share them.
6
+ */
7
+ import { getContext } from '../context.js';
8
+ import { staleNotificationSchema, wireParticipantKindSchema, } from '../coordination/schema.js';
9
+ import { formatClaim } from '../coordination/trace.js';
10
+ /**
11
+ * Converts the client's list of {@link MutationOperation} values into the wire
12
+ * {@link CommitMessage} the server accepts. This is the one place the loosely
13
+ * typed operation — its `type` is a string, and it carries client-only
14
+ * `options` the server never reads — becomes the strict wire contract. Mapping
15
+ * each field by hand means a change to {@link CommitOperation} fails to compile
16
+ * here; the single `as` cast narrows the validated `type` to the wire union and
17
+ * is the only place that loosening happens.
18
+ */
19
+ export function buildCommitFrame(operations, clientTxId, causedByTaskId, reads) {
20
+ const payload = {
21
+ operations: operations.map((op) => ({
22
+ type: op.type,
23
+ model: op.model,
24
+ id: op.id,
25
+ input: op.input,
26
+ transactionId: op.transactionId,
27
+ readAt: op.readAt,
28
+ onStale: op.onStale,
29
+ })),
30
+ clientTxId,
31
+ };
32
+ if (causedByTaskId)
33
+ payload.causedByTaskId = causedByTaskId;
34
+ // The read set the batch was premised on: the rows or groups the writer read before committing.
35
+ if (reads && reads.length > 0)
36
+ payload.reads = [...reads];
37
+ return { type: 'commit', payload };
38
+ }
39
+ /**
40
+ * Defensively validate the optional `notifications` array off a commit ack.
41
+ * Untrusted wire data — a malformed entry is dropped rather than throwing,
42
+ * so a bad notification never sinks an otherwise-successful commit.
43
+ */
44
+ export function parseNotifications(raw) {
45
+ if (!Array.isArray(raw) || raw.length === 0)
46
+ return undefined;
47
+ const out = [];
48
+ for (const entry of raw) {
49
+ const parsed = staleNotificationSchema.safeParse(entry);
50
+ if (parsed.success)
51
+ out.push(parsed.data);
52
+ }
53
+ return out.length > 0 ? out : undefined;
54
+ }
55
+ /**
56
+ * The single place claim events are traced. Every `claim_*` frame passes
57
+ * through here, so a developer debugging a collision gets one consistent record
58
+ * — a console line and a structured capture — without each frame case
59
+ * re-deriving the row and holder shape. The wire payload is loosely typed
60
+ * (`Record<string, unknown>`), so this is the one place that narrows it into a
61
+ * {@link ClaimEvent}.
62
+ */
63
+ export function recordClaim(phase, payload) {
64
+ const str = (v) => typeof v === 'string' ? v : undefined;
65
+ // Targets arrive flat ({ entityType, entityId }) or nested under `target`.
66
+ const target = payload.target && typeof payload.target === 'object'
67
+ ? payload.target
68
+ : payload;
69
+ const kind = wireParticipantKindSchema.safeParse(payload.participantKind);
70
+ const event = {
71
+ phase,
72
+ claimId: str(payload.claimId),
73
+ model: str(target.entityType) ?? str(target.model),
74
+ id: str(target.entityId) ?? str(target.id),
75
+ field: str(target.field),
76
+ actor: str(payload.actor) ?? str(payload.heldBy),
77
+ participantKind: kind.success ? kind.data : undefined,
78
+ position: typeof payload.position === 'number' ? payload.position : undefined,
79
+ reason: str(payload.policyReason) ?? str(payload.reason),
80
+ };
81
+ const message = formatClaim(event);
82
+ // A rejection or lost lease is the collision a developer is actively
83
+ // debugging → warn (shows at the default log level). The routine events
84
+ // (acquired/queued/granted/expired) are debug-only so they never drown the
85
+ // console until you opt in with `new Ablo({ debug: true })`.
86
+ const isCollision = phase === 'rejected' || phase === 'lost';
87
+ const ctx = getContext();
88
+ if (isCollision)
89
+ ctx.logger.warn(message);
90
+ else
91
+ ctx.logger.debug(message);
92
+ ctx.observability.breadcrumb(message, 'sync.coordination', isCollision ? 'warning' : 'info');
93
+ ctx.observability.captureClaim(event);
94
+ }
@@ -1,25 +1,25 @@
1
1
  /**
2
- * Transport-driven ClaimStream factory.
2
+ * Creates a {@link ClaimStream} over a live sync connection. A claim is a
3
+ * short-lived, advisory lease a participant takes on an entity (or a field of
4
+ * one) to signal "I'm working on this"; the stream lets you take claims, see
5
+ * everyone else's, and watch the wait queue when a claim is contended.
3
6
  *
4
- * Mirrors `createPresenceStream` built directly on `SyncWebSocket`,
5
- * no SyncAgent wrapper. Claims derive their `others` view from the
6
- * same `presence_update` frames the presence stream consumes (the
7
- * Hub piggybacks `activeClaims` on every presence frame). Outbound
8
- * announce/revoke ride the same socket via `claim_begin` /
7
+ * The stream is built directly on the sync WebSocket and shares that one
8
+ * connection. It learns about other participants' claims from the same
9
+ * `presence_update` frames the {@link createPresenceStream} presence stream
10
+ * consumes — the server piggybacks each participant's `activeClaims` on every
11
+ * presence frame and sends its own claims as `claim_begin` and
9
12
  * `claim_abandon` frames.
10
13
  *
11
- * Wire contract (apps/sync-server/src/hub/types.ts):
12
- * • Outbound: `{ type: 'claim_begin', payload: { claimId,
13
- * entityType, entityId, reason, field?, estimatedMs? } }`
14
- * • Outbound: `{ type: 'claim_abandon', payload: { claimId,
15
- * entityType?, entityId? } }`
16
- * • Inbound (via presence): `event.activeClaims: Claim[]`
17
- * stamped with `declaredAt`, `expiresAt`.
18
- * • Inbound: `claim_rejected` event with conflict metadata.
19
- *
20
- * After the dual-engine collapse (step #36), this is the only
21
- * ClaimStream factory in the SDK; the older compatibility path
22
- * deletes.
14
+ * Wire frames:
15
+ * • Outbound `claim_begin` announce a claim: `{ claimId, entityType,
16
+ * entityId, reason, field?, estimatedMs? }`.
17
+ * • Outbound `claim_abandon` release it: `{ claimId, entityType?,
18
+ * entityId? }`.
19
+ * • Inbound, via presence `event.activeClaims`, each stamped with
20
+ * `declaredAt` and `expiresAt`.
21
+ * • Inbound `claim_rejected` the server refused the claim, with conflict
22
+ * metadata.
23
23
  */
24
24
  import type { SyncWebSocket } from './SyncWebSocket.js';
25
25
  import type { ClaimOptions, Claim, ClaimStream, PresenceTarget } from '../types/streams.js';
@@ -29,10 +29,11 @@ export interface ClaimStreamConfig {
29
29
  }
30
30
  export interface AttachableClaimStream extends ClaimStream {
31
31
  /**
32
- * INTERNAL lease mint sends the `claim_begin` frame and returns a held
33
- * {@link Claim} (no row `data`; the model door reads the row and stamps it).
34
- * Not part of the public `ClaimStream` surface: the only public way to take a
35
- * claim is `ablo.<model>.claim({ id })`, which builds on this.
32
+ * Mints a lease directly: sends the `claim_begin` frame and returns a held
33
+ * {@link Claim} that carries no row `data` (the resource layer reads the row
34
+ * and stamps it). This is an internal entry point, not part of the public
35
+ * {@link ClaimStream}; application code takes a claim through
36
+ * `ablo.<model>.claim({ id })`, which is built on this.
36
37
  */
37
38
  claim(target: PresenceTarget, opts?: ClaimOptions): Claim;
38
39
  attach(transport: SyncWebSocket): void;