@abloatai/ablo 0.34.1 → 0.36.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 (536) hide show
  1. package/AGENTS.md +2 -1
  2. package/CHANGELOG.md +758 -5
  3. package/README.md +56 -502
  4. package/bin/ablo.cjs +39 -0
  5. package/dist/BaseSyncedStore.d.ts +176 -48
  6. package/dist/BaseSyncedStore.js +346 -214
  7. package/dist/Database.d.ts +17 -44
  8. package/dist/Database.js +96 -79
  9. package/dist/InstanceCache.d.ts +31 -6
  10. package/dist/InstanceCache.js +65 -30
  11. package/dist/LazyReferenceCollection.d.ts +3 -3
  12. package/dist/LazyReferenceCollection.js +4 -4
  13. package/dist/Model.d.ts +23 -13
  14. package/dist/Model.js +27 -17
  15. package/dist/ModelRegistry.d.ts +8 -4
  16. package/dist/ModelRegistry.js +20 -18
  17. package/dist/NetworkMonitor.d.ts +3 -1
  18. package/dist/NetworkMonitor.js +7 -5
  19. package/dist/{SyncEngineContext.d.ts → RuntimeContext.d.ts} +20 -13
  20. package/dist/{SyncEngineContext.js → RuntimeContext.js} +11 -12
  21. package/dist/SyncClient.d.ts +47 -47
  22. package/dist/SyncClient.js +215 -156
  23. package/dist/ai-sdk/coordinatedTool.d.ts +2 -2
  24. package/dist/ai-sdk/coordinatedTool.js +1 -1
  25. package/dist/ai-sdk/coordinationContext.d.ts +2 -2
  26. package/dist/ai-sdk/coordinationContext.js +1 -1
  27. package/dist/ai-sdk/wrap.d.ts +3 -3
  28. package/dist/ai-sdk/wrap.js +2 -2
  29. package/dist/auth/index.d.ts +1 -156
  30. package/dist/auth/index.js +8 -301
  31. package/dist/client/Ablo.d.ts +42 -287
  32. package/dist/client/Ablo.js +129 -963
  33. package/dist/client/abloClient.d.ts +309 -0
  34. package/dist/client/abloClient.js +13 -0
  35. package/dist/client/clientPrelude.d.ts +52 -0
  36. package/dist/client/clientPrelude.js +60 -0
  37. package/dist/client/consoleLogger.d.ts +2 -2
  38. package/dist/client/coreClient.d.ts +60 -0
  39. package/dist/client/coreClient.js +118 -0
  40. package/dist/client/createInternalComponents.d.ts +8 -4
  41. package/dist/client/createInternalComponents.js +17 -10
  42. package/dist/client/createModelProxy.d.ts +98 -373
  43. package/dist/client/createModelProxy.js +233 -139
  44. package/dist/client/humans.d.ts +69 -0
  45. package/dist/client/humans.js +78 -0
  46. package/dist/client/modelRegistration.d.ts +1 -1
  47. package/dist/client/modelRegistration.js +9 -9
  48. package/dist/client/options.d.ts +73 -17
  49. package/dist/client/reactiveEngine.d.ts +53 -0
  50. package/dist/client/reactiveEngine.js +688 -0
  51. package/dist/client/resourceTypes.d.ts +9 -250
  52. package/dist/client/resourceTypes.js +8 -5
  53. package/dist/client/schemaConfig.d.ts +4 -4
  54. package/dist/client/schemaConfig.js +6 -2
  55. package/dist/client/storeCluster.d.ts +47 -0
  56. package/dist/client/storeCluster.js +118 -0
  57. package/dist/client/storeLifecycle.d.ts +61 -0
  58. package/dist/client/storeLifecycle.js +231 -0
  59. package/dist/client/validateAbloOptions.d.ts +3 -2
  60. package/dist/client/validateAbloOptions.js +1 -1
  61. package/dist/client/wsMutationExecutor.d.ts +3 -3
  62. package/dist/client/wsMutationExecutor.js +3 -3
  63. package/dist/context.d.ts +22 -9
  64. package/dist/context.js +33 -9
  65. package/dist/coordination/ClaimLog.d.ts +26 -0
  66. package/dist/coordination/ClaimLog.js +32 -0
  67. package/dist/coordination/index.d.ts +1 -15
  68. package/dist/coordination/index.js +8 -31
  69. package/dist/core/index.d.ts +3 -3
  70. package/dist/core/index.js +2 -2
  71. package/dist/docs/catalog.d.ts +72 -0
  72. package/dist/docs/catalog.js +230 -0
  73. package/dist/docs/index.d.ts +10 -0
  74. package/dist/docs/index.js +10 -0
  75. package/dist/environment.d.ts +1 -40
  76. package/dist/environment.js +8 -37
  77. package/dist/index.d.ts +44 -36
  78. package/dist/index.js +30 -22
  79. package/dist/interfaces/index.d.ts +44 -134
  80. package/dist/keys/index.d.ts +1 -77
  81. package/dist/keys/index.js +8 -190
  82. package/dist/mutators/{RecordingTransaction.d.ts → RecordingMutation.d.ts} +4 -4
  83. package/dist/mutators/{RecordingTransaction.js → RecordingMutation.js} +2 -2
  84. package/dist/mutators/Transaction.d.ts +1 -1
  85. package/dist/mutators/Transaction.js +1 -1
  86. package/dist/mutators/UndoManager.d.ts +6 -6
  87. package/dist/mutators/UndoManager.js +5 -5
  88. package/dist/mutators/defineMutators.d.ts +3 -3
  89. package/dist/mutators/defineMutators.js +1 -1
  90. package/dist/mutators/inverseOp.js +2 -2
  91. package/dist/mutators/mutateActions.d.ts +3 -3
  92. package/dist/mutators/mutateActions.js +1 -1
  93. package/dist/mutators/readerActions.d.ts +1 -1
  94. package/dist/mutators/undoApply.d.ts +1 -1
  95. package/dist/mutators/undoApply.js +1 -1
  96. package/dist/policy/index.d.ts +2 -2
  97. package/dist/policy/index.js +1 -1
  98. package/dist/query/client.d.ts +5 -2
  99. package/dist/query/client.js +10 -9
  100. package/dist/query/types.d.ts +6 -41
  101. package/dist/query/types.js +2 -2
  102. package/dist/react/AbloProvider.d.ts +18 -8
  103. package/dist/react/AbloProvider.js +10 -9
  104. package/dist/react/context.d.ts +3 -3
  105. package/dist/react/context.js +1 -1
  106. package/dist/react/createAbloReact.d.ts +56 -0
  107. package/dist/react/createAbloReact.js +51 -0
  108. package/dist/react/index.d.ts +6 -5
  109. package/dist/react/index.js +6 -3
  110. package/dist/react/internalContext.d.ts +1 -1
  111. package/dist/react/useAblo.d.ts +12 -5
  112. package/dist/react/useAblo.js +26 -8
  113. package/dist/react/useCurrentUserId.js +1 -1
  114. package/dist/react/useErrorListener.js +1 -1
  115. package/dist/react/useMutationFailureListener.d.ts +2 -2
  116. package/dist/react/useMutationFailureListener.js +1 -1
  117. package/dist/react/useMutators.d.ts +3 -3
  118. package/dist/react/useMutators.js +3 -3
  119. package/dist/react/useUndoScope.d.ts +5 -5
  120. package/dist/react/useUndoScope.js +1 -1
  121. package/dist/schema/coordination.d.ts +69 -10
  122. package/dist/schema/coordination.js +90 -9
  123. package/dist/schema/ddl.js +2 -2
  124. package/dist/schema/diff.d.ts +1 -1
  125. package/dist/schema/generate.js +1 -1
  126. package/dist/schema/index.d.ts +11 -10
  127. package/dist/schema/index.js +22 -18
  128. package/dist/schema/queries.d.ts +27 -27
  129. package/dist/schema/queries.js +23 -23
  130. package/dist/schema/select.d.ts +3 -3
  131. package/dist/schema/select.js +6 -3
  132. package/dist/schema/serialize.d.ts +15 -6
  133. package/dist/schema/serialize.js +20 -3
  134. package/dist/schema/sugar.d.ts +6 -7
  135. package/dist/schema/sugar.js +9 -12
  136. package/dist/schema/syncDeltaRow.d.ts +4 -152
  137. package/dist/schema/syncDeltaRow.js +4 -105
  138. package/dist/server/adapter.d.ts +18 -1
  139. package/dist/server/commit.d.ts +10 -16
  140. package/dist/server/index.d.ts +1 -1
  141. package/dist/server/index.js +1 -1
  142. package/dist/server/readConfig.d.ts +1 -1
  143. package/dist/source/adapter.d.ts +7 -5
  144. package/dist/source/adapter.js +7 -5
  145. package/dist/source/adapters/drizzle.d.ts +1 -1
  146. package/dist/source/adapters/drizzle.js +2 -2
  147. package/dist/source/adapters/kysely.d.ts +1 -1
  148. package/dist/source/adapters/kysely.js +1 -1
  149. package/dist/source/adapters/kyselyMutationCore.d.ts +1 -1
  150. package/dist/source/adapters/kyselyMutationCore.js +2 -2
  151. package/dist/source/adapters/memory.js +1 -1
  152. package/dist/source/adapters/prisma.d.ts +8 -3
  153. package/dist/source/adapters/prisma.js +1 -1
  154. package/dist/source/connector.js +1 -1
  155. package/dist/source/connectorProtocol.d.ts +2 -8
  156. package/dist/source/connectorProtocol.js +3 -2
  157. package/dist/source/contract.d.ts +29 -17
  158. package/dist/source/contract.js +27 -22
  159. package/dist/source/factory.d.ts +1 -1
  160. package/dist/source/idempotency.js +2 -2
  161. package/dist/source/index.d.ts +1 -0
  162. package/dist/source/index.js +3 -0
  163. package/dist/source/next.d.ts +1 -1
  164. package/dist/source/signing.d.ts +9 -2
  165. package/dist/source/signing.js +4 -1
  166. package/dist/source/types.d.ts +6 -4
  167. package/dist/source/types.js +1 -1
  168. package/dist/{core/storeContract.d.ts → storeContract.d.ts} +6 -6
  169. package/dist/{core → stores}/DatabaseManager.d.ts +3 -1
  170. package/dist/{core → stores}/DatabaseManager.js +14 -13
  171. package/dist/stores/ObjectStore.d.ts +1 -1
  172. package/dist/{core → stores}/StoreManager.d.ts +9 -26
  173. package/dist/{core → stores}/StoreManager.js +29 -77
  174. package/dist/stores/SyncActionStore.d.ts +4 -2
  175. package/dist/stores/SyncActionStore.js +11 -17
  176. package/dist/stores/syncAction.d.ts +26 -0
  177. package/dist/stores/syncAction.js +16 -0
  178. package/dist/surface.d.ts +3 -3
  179. package/dist/surface.js +6 -4
  180. package/dist/sync/BootstrapFetcher.d.ts +127 -6
  181. package/dist/sync/BootstrapFetcher.js +511 -83
  182. package/dist/sync/ConnectionManager.d.ts +6 -198
  183. package/dist/sync/ConnectionManager.js +6 -677
  184. package/dist/sync/OnDemandLoader.d.ts +5 -2
  185. package/dist/sync/OnDemandLoader.js +61 -21
  186. package/dist/sync/SubscriptionManager.d.ts +13 -2
  187. package/dist/sync/SubscriptionManager.js +23 -5
  188. package/dist/sync/SyncWebSocket.d.ts +27 -510
  189. package/dist/sync/SyncWebSocket.js +76 -954
  190. package/dist/sync/awaitClaimGrant.d.ts +4 -44
  191. package/dist/sync/awaitClaimGrant.js +4 -109
  192. package/dist/sync/bootstrapApply.d.ts +3 -0
  193. package/dist/sync/bootstrapApply.js +2 -2
  194. package/dist/sync/commitFrames.d.ts +6 -40
  195. package/dist/sync/commitFrames.js +6 -97
  196. package/dist/sync/contextPorts.d.ts +18 -0
  197. package/dist/sync/contextPorts.js +31 -0
  198. package/dist/sync/createClaimStream.d.ts +5 -49
  199. package/dist/sync/createClaimStream.js +5 -469
  200. package/dist/sync/createPresenceStream.d.ts +26 -4
  201. package/dist/sync/createPresenceStream.js +28 -20
  202. package/dist/sync/createSnapshot.d.ts +2 -2
  203. package/dist/sync/createSnapshot.js +1 -1
  204. package/dist/sync/credentialLifecycle.d.ts +5 -173
  205. package/dist/sync/credentialLifecycle.js +5 -320
  206. package/dist/sync/deltaPipeline.d.ts +13 -12
  207. package/dist/sync/deltaPipeline.js +21 -4
  208. package/dist/sync/groupChange.d.ts +3 -0
  209. package/dist/sync/groupChange.js +16 -14
  210. package/dist/sync/participants.d.ts +24 -6
  211. package/dist/sync/participants.js +32 -23
  212. package/dist/sync/schemaDrift.d.ts +55 -0
  213. package/dist/sync/schemaDrift.js +53 -0
  214. package/dist/sync/schemas.d.ts +23 -33
  215. package/dist/sync/schemas.js +29 -20
  216. package/dist/sync/syncPlan.d.ts +3 -3
  217. package/dist/sync/wsFrameHandlers.d.ts +6 -114
  218. package/dist/sync/wsFrameHandlers.js +6 -392
  219. package/dist/syncLog/contract.d.ts +20 -0
  220. package/dist/syncLog/contract.js +19 -0
  221. package/dist/syncLog/index.d.ts +1 -0
  222. package/dist/syncLog/index.js +1 -0
  223. package/dist/transaction/ablo.d.ts +88 -0
  224. package/dist/transaction/ablo.js +33 -0
  225. package/dist/{client/auth.d.ts → transaction/auth/apiKey.d.ts} +43 -8
  226. package/dist/{client/auth.js → transaction/auth/apiKey.js} +19 -0
  227. package/dist/transaction/auth/bootstrapScope.d.ts +15 -0
  228. package/dist/transaction/auth/bootstrapScope.js +1 -0
  229. package/dist/transaction/auth/capability.d.ts +212 -0
  230. package/dist/transaction/auth/capability.js +224 -0
  231. package/dist/{auth → transaction/auth}/credentialSource.d.ts +8 -1
  232. package/dist/{client → transaction/auth}/identity.d.ts +8 -7
  233. package/dist/{client → transaction/auth}/identity.js +1 -1
  234. package/dist/transaction/auth/index.d.ts +162 -0
  235. package/dist/transaction/auth/index.js +304 -0
  236. package/dist/{auth → transaction/auth}/schemas.d.ts +1 -1
  237. package/dist/{auth → transaction/auth}/schemas.js +13 -13
  238. package/dist/{client → transaction/auth}/sessionMint.d.ts +8 -8
  239. package/dist/{client → transaction/auth}/sessionMint.js +4 -7
  240. package/dist/transaction/coordination/awaitClaimGrant.d.ts +56 -0
  241. package/dist/transaction/coordination/awaitClaimGrant.js +124 -0
  242. package/dist/{client → transaction/coordination}/claimHeartbeatLoop.d.ts +34 -0
  243. package/dist/{client → transaction/coordination}/claimHeartbeatLoop.js +20 -0
  244. package/dist/transaction/coordination/claimMeta.d.ts +49 -0
  245. package/dist/transaction/coordination/claimMeta.js +52 -0
  246. package/dist/transaction/coordination/createClaimStream.d.ts +64 -0
  247. package/dist/transaction/coordination/createClaimStream.js +475 -0
  248. package/dist/transaction/coordination/events.d.ts +74 -0
  249. package/dist/transaction/coordination/events.js +7 -0
  250. package/dist/transaction/coordination/index.d.ts +19 -0
  251. package/dist/transaction/coordination/index.js +45 -0
  252. package/dist/transaction/coordination/locator.d.ts +104 -0
  253. package/dist/transaction/coordination/locator.js +102 -0
  254. package/dist/transaction/coordination/schema.d.ts +1536 -0
  255. package/dist/transaction/coordination/schema.js +1177 -0
  256. package/dist/transaction/coordination/targetConflict.d.ts +2 -0
  257. package/dist/transaction/coordination/targetConflict.js +107 -0
  258. package/dist/{coordination → transaction/coordination}/trace.d.ts +7 -18
  259. package/dist/{coordination → transaction/coordination}/trace.js +18 -25
  260. package/dist/transaction/durableWrites.d.ts +62 -0
  261. package/dist/{client → transaction}/durableWrites.js +28 -3
  262. package/dist/transaction/environment.d.ts +105 -0
  263. package/dist/transaction/environment.js +108 -0
  264. package/dist/{errorCodes.d.ts → transaction/errorCodes.d.ts} +12 -12
  265. package/dist/{errorCodes.js → transaction/errorCodes.js} +45 -18
  266. package/dist/{errors.d.ts → transaction/errors.d.ts} +37 -13
  267. package/dist/{errors.js → transaction/errors.js} +85 -16
  268. package/dist/transaction/footprint.d.ts +111 -0
  269. package/dist/transaction/footprint.js +0 -0
  270. package/dist/transaction/index.d.ts +20 -0
  271. package/dist/transaction/index.js +20 -0
  272. package/dist/transaction/keys/index.d.ts +87 -0
  273. package/dist/transaction/keys/index.js +207 -0
  274. package/dist/transaction/log/syncDeltaRow.d.ts +158 -0
  275. package/dist/transaction/log/syncDeltaRow.js +95 -0
  276. package/dist/{sync/syncPosition.d.ts → transaction/logPosition.d.ts} +22 -8
  277. package/dist/{sync/syncPosition.js → transaction/logPosition.js} +15 -6
  278. package/dist/transaction/logger.d.ts +16 -0
  279. package/dist/transaction/logger.js +7 -0
  280. package/dist/transaction/observability.d.ts +53 -0
  281. package/dist/transaction/observability.js +19 -0
  282. package/dist/transaction/plugin.d.ts +285 -0
  283. package/dist/transaction/plugin.js +106 -0
  284. package/dist/{policy → transaction/policy}/types.d.ts +3 -3
  285. package/dist/{policy → transaction/policy}/types.js +2 -0
  286. package/dist/transaction/resources/httpResources.d.ts +321 -0
  287. package/dist/transaction/resources/httpResources.js +7 -0
  288. package/dist/transaction/resources/modelOperations.d.ts +427 -0
  289. package/dist/transaction/resources/modelOperations.js +12 -0
  290. package/dist/transaction/resources/mutationOptions.d.ts +66 -0
  291. package/dist/transaction/resources/mutationOptions.js +9 -0
  292. package/dist/transaction/resources/where.d.ts +101 -0
  293. package/dist/transaction/resources/where.js +115 -0
  294. package/dist/{client → transaction/resources}/writeOptionsSchema.d.ts +2 -6
  295. package/dist/{client → transaction/resources}/writeOptionsSchema.js +9 -5
  296. package/dist/{schema → transaction/schema}/field.d.ts +17 -23
  297. package/dist/{schema → transaction/schema}/field.js +5 -5
  298. package/dist/transaction/schema/fieldRef.d.ts +38 -0
  299. package/dist/transaction/schema/fieldRef.js +11 -0
  300. package/dist/transaction/schema/loadStrategy.d.ts +45 -0
  301. package/dist/transaction/schema/loadStrategy.js +46 -0
  302. package/dist/{schema → transaction/schema}/model.d.ts +50 -35
  303. package/dist/{schema → transaction/schema}/model.js +30 -20
  304. package/dist/transaction/schema/openapi.d.ts +58 -0
  305. package/dist/transaction/schema/openapi.js +501 -0
  306. package/dist/{schema → transaction/schema}/relation.d.ts +21 -16
  307. package/dist/{schema → transaction/schema}/relation.js +7 -7
  308. package/dist/{schema → transaction/schema}/residency.d.ts +0 -9
  309. package/dist/{schema → transaction/schema}/residency.js +0 -5
  310. package/dist/{schema → transaction/schema}/roles.d.ts +5 -5
  311. package/dist/{schema → transaction/schema}/roles.js +5 -5
  312. package/dist/{schema → transaction/schema}/schema.d.ts +39 -10
  313. package/dist/{schema → transaction/schema}/schema.js +24 -3
  314. package/dist/{schema → transaction/schema}/tenancy.d.ts +1 -1
  315. package/dist/{schema → transaction/schema}/tenancy.js +7 -4
  316. package/dist/transaction/transactionLayer.d.ts +82 -0
  317. package/dist/transaction/transactionLayer.js +24 -0
  318. package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.d.ts +5 -6
  319. package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.js +9 -13
  320. package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.d.ts +9 -2
  321. package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.js +5 -9
  322. package/dist/{transactions/durableWriteStore.d.ts → transaction/transactions/settlement/pendingWrite.d.ts} +11 -37
  323. package/dist/transaction/transactions/settlement/pendingWrite.js +20 -0
  324. package/dist/transaction/transport/commitFrames.d.ts +90 -0
  325. package/dist/transaction/transport/commitFrames.js +134 -0
  326. package/dist/transaction/transport/connectionManager.d.ts +215 -0
  327. package/dist/transaction/transport/connectionManager.js +673 -0
  328. package/dist/transaction/transport/credentialLifecycle.d.ts +177 -0
  329. package/dist/transaction/transport/credentialLifecycle.js +324 -0
  330. package/dist/{sync → transaction/transport}/heartbeat.d.ts +3 -1
  331. package/dist/{sync → transaction/transport}/heartbeat.js +6 -4
  332. package/dist/transaction/transport/httpClient.d.ts +131 -0
  333. package/dist/{client → transaction/transport}/httpClient.js +6 -5
  334. package/dist/transaction/transport/httpOptions.d.ts +33 -0
  335. package/dist/transaction/transport/httpOptions.js +12 -0
  336. package/dist/{client → transaction/transport}/httpTransport.js +295 -97
  337. package/dist/{sync/NetworkProbe.d.ts → transaction/transport/networkProbe.d.ts} +7 -4
  338. package/dist/{sync/NetworkProbe.js → transaction/transport/networkProbe.js} +14 -13
  339. package/dist/transaction/transport/wsFrameHandlers.d.ts +128 -0
  340. package/dist/transaction/transport/wsFrameHandlers.js +429 -0
  341. package/dist/transaction/transport/wsTransport.d.ts +574 -0
  342. package/dist/transaction/transport/wsTransport.js +1023 -0
  343. package/dist/transaction/types/assertExact.d.ts +17 -0
  344. package/dist/transaction/types/assertExact.js +1 -0
  345. package/dist/{types → transaction/types}/global.d.ts +17 -2
  346. package/dist/{types → transaction/types}/global.js +2 -1
  347. package/dist/{types → transaction/types}/index.d.ts +14 -46
  348. package/dist/{types → transaction/types}/index.js +7 -16
  349. package/dist/{types → transaction/types}/streams.d.ts +73 -45
  350. package/dist/transaction/utils/duration.d.ts +50 -0
  351. package/dist/{utils → transaction/utils}/duration.js +32 -0
  352. package/dist/{utils → transaction/utils}/json.d.ts +18 -0
  353. package/dist/transaction/utils/json.js +276 -0
  354. package/dist/transaction/wire/accountResponses.d.ts +420 -0
  355. package/dist/transaction/wire/accountResponses.js +290 -0
  356. package/dist/transaction/wire/auth.d.ts +56 -0
  357. package/dist/transaction/wire/auth.js +63 -0
  358. package/dist/transaction/wire/claimEvent.d.ts +76 -0
  359. package/dist/transaction/wire/claimEvent.js +73 -0
  360. package/dist/transaction/wire/claims.d.ts +530 -0
  361. package/dist/transaction/wire/claims.js +327 -0
  362. package/dist/{wire → transaction/wire}/commit.d.ts +125 -193
  363. package/dist/{wire → transaction/wire}/commit.js +68 -47
  364. package/dist/{wire → transaction/wire}/delta.d.ts +66 -17
  365. package/dist/{wire → transaction/wire}/delta.js +37 -13
  366. package/dist/transaction/wire/errorEnvelope.d.ts +72 -0
  367. package/dist/{wire → transaction/wire}/errorEnvelope.js +36 -5
  368. package/dist/transaction/wire/feedCursor.d.ts +60 -0
  369. package/dist/transaction/wire/feedCursor.js +82 -0
  370. package/dist/transaction/wire/feedEvent.d.ts +204 -0
  371. package/dist/transaction/wire/feedEvent.js +65 -0
  372. package/dist/transaction/wire/frames.d.ts +194 -0
  373. package/dist/transaction/wire/frames.js +50 -0
  374. package/dist/transaction/wire/inboundFrames.d.ts +562 -0
  375. package/dist/transaction/wire/inboundFrames.js +116 -0
  376. package/dist/transaction/wire/index.d.ts +54 -0
  377. package/dist/transaction/wire/index.js +83 -0
  378. package/dist/{wire → transaction/wire}/listEnvelope.d.ts +13 -14
  379. package/dist/transaction/wire/listEnvelope.js +42 -0
  380. package/dist/transaction/wire/modelMutations.d.ts +31 -0
  381. package/dist/transaction/wire/modelMutations.js +52 -0
  382. package/dist/transaction/wire/modelResponses.d.ts +85 -0
  383. package/dist/transaction/wire/modelResponses.js +43 -0
  384. package/dist/transaction/wire/modelShape.d.ts +78 -0
  385. package/dist/transaction/wire/modelShape.js +74 -0
  386. package/dist/transactions/{TransactionQueue.d.ts → mutations/MutationQueue.d.ts} +85 -38
  387. package/dist/transactions/{TransactionQueue.js → mutations/MutationQueue.js} +141 -80
  388. package/dist/transactions/{TransactionStore.d.ts → mutations/MutationStore.d.ts} +8 -8
  389. package/dist/transactions/{TransactionStore.js → mutations/MutationStore.js} +2 -2
  390. package/dist/transactions/{coalesceRules.d.ts → mutations/coalesceRules.d.ts} +10 -10
  391. package/dist/transactions/{coalesceRules.js → mutations/coalesceRules.js} +1 -1
  392. package/dist/transactions/mutations/commitLatency.d.ts +52 -0
  393. package/dist/transactions/mutations/commitLatency.js +130 -0
  394. package/dist/transactions/{commitOutboxStore.d.ts → mutations/commitOutboxStore.d.ts} +1 -5
  395. package/dist/transactions/{commitOutboxStore.js → mutations/commitOutboxStore.js} +1 -1
  396. package/dist/transactions/{commitPayload.d.ts → mutations/commitPayload.d.ts} +18 -16
  397. package/dist/transactions/{commitPayload.js → mutations/commitPayload.js} +15 -15
  398. package/dist/transactions/{deltaConfirmation.d.ts → mutations/deltaConfirmation.d.ts} +15 -11
  399. package/dist/transactions/{deltaConfirmation.js → mutations/deltaConfirmation.js} +14 -12
  400. package/dist/transactions/mutations/durableWriteStore.d.ts +14 -0
  401. package/dist/transactions/mutations/durableWriteStore.js +12 -0
  402. package/dist/transactions/{optimisticApply.d.ts → mutations/optimisticApply.d.ts} +7 -7
  403. package/dist/transactions/{replayValidation.d.ts → mutations/replayValidation.d.ts} +4 -3
  404. package/dist/transactions/{replayValidation.js → mutations/replayValidation.js} +7 -5
  405. package/dist/utils/mobxSetup.d.ts +1 -1
  406. package/dist/utils/mobxSetup.js +5 -2
  407. package/dist/{core → views}/QueryView.d.ts +2 -2
  408. package/dist/{core → views}/QueryView.js +2 -2
  409. package/dist/{core → views}/ViewRegistry.d.ts +1 -1
  410. package/dist/{core/queryUtils.d.ts → views/incrementalView.d.ts} +6 -6
  411. package/dist/{core/queryUtils.js → views/incrementalView.js} +6 -6
  412. package/dist/webhooks/events.d.ts +2 -2
  413. package/dist/wire/index.d.ts +1 -34
  414. package/dist/wire/index.js +8 -49
  415. package/docs/agent-messaging.md +3 -3
  416. package/docs/agents.md +20 -13
  417. package/docs/api-keys.md +14 -10
  418. package/docs/api.md +27 -61
  419. package/docs/audit.md +6 -3
  420. package/docs/cli.md +41 -13
  421. package/docs/client-behavior.md +11 -9
  422. package/docs/concurrency-convention.md +49 -57
  423. package/docs/coordination.md +283 -121
  424. package/docs/data-sources.md +7 -5
  425. package/docs/debugging.md +39 -15
  426. package/docs/deployment.md +267 -0
  427. package/docs/examples/agent-human.md +49 -42
  428. package/docs/examples/ai-sdk-tool.md +69 -44
  429. package/docs/examples/existing-python-backend.md +8 -6
  430. package/docs/examples/nextjs.md +129 -47
  431. package/docs/examples/scoped-agent.md +46 -45
  432. package/docs/examples/server-agent.md +46 -26
  433. package/docs/groups.md +87 -30
  434. package/docs/guarantees.md +41 -12
  435. package/docs/how-it-works.md +38 -12
  436. package/docs/idempotency.md +126 -0
  437. package/docs/identity.md +77 -74
  438. package/docs/index.md +172 -86
  439. package/docs/integration-guide.md +31 -19
  440. package/docs/mcp.md +46 -21
  441. package/docs/migration.md +95 -18
  442. package/docs/operating-on-your-database.md +3 -1
  443. package/docs/projects.md +3 -1
  444. package/docs/quickstart.md +22 -5
  445. package/docs/react.md +31 -18
  446. package/docs/schema-contract.md +5 -3
  447. package/docs/session-settings.md +108 -0
  448. package/docs/sessions.md +4 -2
  449. package/docs/webhooks.md +12 -10
  450. package/llms.txt +48 -18
  451. package/package.json +21 -26
  452. package/dist/agent/Agent.d.ts +0 -366
  453. package/dist/agent/Agent.js +0 -514
  454. package/dist/agent/index.d.ts +0 -115
  455. package/dist/agent/index.js +0 -128
  456. package/dist/agent/session.d.ts +0 -93
  457. package/dist/agent/session.js +0 -149
  458. package/dist/agent/types.d.ts +0 -68
  459. package/dist/agent/types.js +0 -9
  460. package/dist/cli.cjs +0 -286329
  461. package/dist/client/durableWrites.d.ts +0 -21
  462. package/dist/client/httpClient.d.ts +0 -80
  463. package/dist/coordination/schema.d.ts +0 -722
  464. package/dist/coordination/schema.js +0 -578
  465. package/dist/schema/openapi.d.ts +0 -29
  466. package/dist/schema/openapi.js +0 -124
  467. package/dist/testing/fixtures/bootstrap.d.ts +0 -49
  468. package/dist/testing/fixtures/bootstrap.js +0 -59
  469. package/dist/testing/fixtures/deltas.d.ts +0 -83
  470. package/dist/testing/fixtures/deltas.js +0 -136
  471. package/dist/testing/fixtures/models.d.ts +0 -83
  472. package/dist/testing/fixtures/models.js +0 -272
  473. package/dist/testing/helpers/reactWrapper.d.ts +0 -69
  474. package/dist/testing/helpers/reactWrapper.js +0 -67
  475. package/dist/testing/helpers/syncEngineHarness.d.ts +0 -54
  476. package/dist/testing/helpers/syncEngineHarness.js +0 -73
  477. package/dist/testing/helpers/wait.d.ts +0 -30
  478. package/dist/testing/helpers/wait.js +0 -49
  479. package/dist/testing/index.d.ts +0 -23
  480. package/dist/testing/index.js +0 -33
  481. package/dist/testing/mocks/FakeDatabase.d.ts +0 -18
  482. package/dist/testing/mocks/FakeDatabase.js +0 -10
  483. package/dist/testing/mocks/MockMutationExecutor.d.ts +0 -87
  484. package/dist/testing/mocks/MockMutationExecutor.js +0 -192
  485. package/dist/testing/mocks/MockNetworkMonitor.d.ts +0 -20
  486. package/dist/testing/mocks/MockNetworkMonitor.js +0 -46
  487. package/dist/testing/mocks/MockSyncContext.d.ts +0 -51
  488. package/dist/testing/mocks/MockSyncContext.js +0 -71
  489. package/dist/testing/mocks/MockSyncStore.d.ts +0 -88
  490. package/dist/testing/mocks/MockSyncStore.js +0 -171
  491. package/dist/testing/mocks/MockWebSocket.d.ts +0 -71
  492. package/dist/testing/mocks/MockWebSocket.js +0 -118
  493. package/dist/transactions/durableWriteStore.js +0 -30
  494. package/dist/utils/duration.d.ts +0 -25
  495. package/dist/utils/json.js +0 -88
  496. package/dist/wire/errorEnvelope.d.ts +0 -55
  497. package/dist/wire/frames.d.ts +0 -197
  498. package/dist/wire/frames.js +0 -49
  499. package/dist/wire/listEnvelope.js +0 -18
  500. package/docs/interaction-model.md +0 -97
  501. /package/dist/{core → query}/QueryProcessor.d.ts +0 -0
  502. /package/dist/{core → query}/QueryProcessor.js +0 -0
  503. /package/dist/{core/storeContract.js → storeContract.js} +0 -0
  504. /package/dist/{core → stores}/openIDBWithTimeout.d.ts +0 -0
  505. /package/dist/{core → stores}/openIDBWithTimeout.js +0 -0
  506. /package/dist/{client → transaction/auth}/credentialEndpoint.d.ts +0 -0
  507. /package/dist/{client → transaction/auth}/credentialEndpoint.js +0 -0
  508. /package/dist/{auth → transaction/auth}/credentialPolicy.d.ts +0 -0
  509. /package/dist/{auth → transaction/auth}/credentialPolicy.js +0 -0
  510. /package/dist/{auth → transaction/auth}/credentialSource.js +0 -0
  511. /package/dist/{client → transaction/auth}/hostedEndpoints.d.ts +0 -0
  512. /package/dist/{client → transaction/auth}/hostedEndpoints.js +0 -0
  513. /package/dist/{client → transaction}/persistence.d.ts +0 -0
  514. /package/dist/{client → transaction}/persistence.js +0 -0
  515. /package/dist/{client → transaction/resources}/functionalUpdate.d.ts +0 -0
  516. /package/dist/{client → transaction/resources}/functionalUpdate.js +0 -0
  517. /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.d.ts +0 -0
  518. /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.js +0 -0
  519. /package/dist/{client → transaction/transport}/httpTransport.d.ts +0 -0
  520. /package/dist/{types → transaction/types}/modelData.d.ts +0 -0
  521. /package/dist/{types → transaction/types}/modelData.js +0 -0
  522. /package/dist/{types → transaction/types}/participant.d.ts +0 -0
  523. /package/dist/{types → transaction/types}/participant.js +0 -0
  524. /package/dist/{types → transaction/types}/streams.js +0 -0
  525. /package/dist/{utils → transaction/utils}/asyncIterator.d.ts +0 -0
  526. /package/dist/{utils → transaction/utils}/asyncIterator.js +0 -0
  527. /package/dist/{wire → transaction/wire}/bootstrapReason.d.ts +0 -0
  528. /package/dist/{wire → transaction/wire}/bootstrapReason.js +0 -0
  529. /package/dist/{wire → transaction/wire}/protocol.d.ts +0 -0
  530. /package/dist/{wire → transaction/wire}/protocol.js +0 -0
  531. /package/dist/{wire → transaction/wire}/protocolVersion.d.ts +0 -0
  532. /package/dist/{wire → transaction/wire}/protocolVersion.js +0 -0
  533. /package/dist/transactions/{UnconfirmedWrites.d.ts → mutations/UnconfirmedWrites.d.ts} +0 -0
  534. /package/dist/transactions/{UnconfirmedWrites.js → mutations/UnconfirmedWrites.js} +0 -0
  535. /package/dist/transactions/{optimisticApply.js → mutations/optimisticApply.js} +0 -0
  536. /package/dist/{core → views}/ViewRegistry.js +0 -0
@@ -9,7 +9,9 @@
9
9
  * Every handler takes a {@link GroupChangeContext}, the narrow facade through
10
10
  * which it reaches the client's local storage and connection lifecycle hooks.
11
11
  */
12
- import { getContext } from '../context.js';
12
+ import { globalRuntime } from '../context.js';
13
+ /** The context's runtime, falling back to the module-global bridge. */
14
+ const runtimeOf = (ctx) => ctx.runtime ?? globalRuntime;
13
15
  /**
14
16
  * Marker returned when a group-change payload cannot be parsed, kept distinct
15
17
  * from a valid null or absent payload, which the handlers accept normally.
@@ -22,14 +24,14 @@ const MALFORMED_PAYLOAD = Symbol('malformed-group-change-payload');
22
24
  * would leave the delta pipeline after the watermark has already advanced. The
23
25
  * delta is never re-delivered, so the security clear it carried would be lost.
24
26
  */
25
- function parseGroupChangePayload(delta) {
27
+ function parseGroupChangePayload(delta, runtime) {
26
28
  if (typeof delta.data !== 'string')
27
29
  return delta.data;
28
30
  try {
29
31
  return JSON.parse(delta.data);
30
32
  }
31
33
  catch (error) {
32
- getContext().logger.debug('[BaseSyncedStore] Malformed group-change payload', {
34
+ runtime.logger.debug('[BaseSyncedStore] Malformed group-change payload', {
33
35
  syncId: delta.id,
34
36
  actionType: delta.actionType,
35
37
  error: error instanceof Error ? error.message : String(error),
@@ -44,7 +46,7 @@ function parseGroupChangePayload(delta) {
44
46
  * re-bootstrap from the server.
45
47
  */
46
48
  async function clearForUnknownGroupChange(ctx, delta, kind) {
47
- getContext().logger.debug(`[BaseSyncedStore] Unreadable ${kind} payload — clearing cached data and re-bootstrapping`, { syncId: delta.id });
49
+ runtimeOf(ctx).logger.debug(`[BaseSyncedStore] Unreadable ${kind} payload — clearing cached data and re-bootstrapping`, { syncId: delta.id });
48
50
  // Revoked data must not persist if the device goes offline before the
49
51
  // re-bootstrap, the same reasoning as the explicit removed-groups path.
50
52
  await ctx.database.clear();
@@ -64,7 +66,7 @@ async function clearForUnknownGroupChange(ctx, delta, kind) {
64
66
  * and refetch), clearing cached data first if any group was removed.
65
67
  */
66
68
  export async function handleSyncGroupChange(ctx, delta) {
67
- const raw = parseGroupChangePayload(delta);
69
+ const raw = parseGroupChangePayload(delta, runtimeOf(ctx));
68
70
  if (raw === MALFORMED_PAYLOAD) {
69
71
  // The payload is unreadable, so we cannot tell which groups changed, and
70
72
  // this delta will never be re-delivered because the watermark has already
@@ -88,7 +90,7 @@ export async function handleSyncGroupChange(ctx, delta) {
88
90
  removedGroups: rawObj.removedGroups ?? [],
89
91
  addedGroups: rawObj.addedGroups ?? [],
90
92
  };
91
- getContext().logger.info('[BaseSyncedStore] Sync group change received (legacy)', {
93
+ runtimeOf(ctx).logger.info('[BaseSyncedStore] Sync group change received (legacy)', {
92
94
  removedGroups: payload.removedGroups,
93
95
  addedGroups: payload.addedGroups,
94
96
  syncId: delta.id,
@@ -99,7 +101,7 @@ export async function handleSyncGroupChange(ctx, delta) {
99
101
  if (payload.removedGroups.length > 0) {
100
102
  await ctx.database.clear();
101
103
  ctx.objectPool.clear();
102
- getContext().logger.info('[BaseSyncedStore] Cleared cached data due to revoked sync groups', {
104
+ runtimeOf(ctx).logger.info('[BaseSyncedStore] Cleared cached data due to revoked sync groups', {
103
105
  removedGroups: payload.removedGroups,
104
106
  });
105
107
  }
@@ -114,7 +116,7 @@ export async function handleSyncGroupChange(ctx, delta) {
114
116
  * through the normal insert path.
115
117
  */
116
118
  export async function handleGroupAdded(ctx, payload, syncId) {
117
- getContext().logger.info('[BaseSyncedStore] Group added (incremental)', {
119
+ runtimeOf(ctx).logger.info('[BaseSyncedStore] Group added (incremental)', {
118
120
  group: payload.group,
119
121
  syncId,
120
122
  });
@@ -130,7 +132,7 @@ export async function handleGroupAdded(ctx, payload, syncId) {
130
132
  * local state and forces a re-bootstrap with the updated group list.
131
133
  */
132
134
  export async function handleGroupRemoved(ctx, delta) {
133
- const raw = parseGroupChangePayload(delta);
135
+ const raw = parseGroupChangePayload(delta, runtimeOf(ctx));
134
136
  if (raw === MALFORMED_PAYLOAD) {
135
137
  // The payload is unreadable: access was revoked but we cannot tell which
136
138
  // group. Fall back to a full clear, the safe direction for an
@@ -141,12 +143,12 @@ export async function handleGroupRemoved(ctx, delta) {
141
143
  const rawObj = (raw ?? {});
142
144
  const groupKey = typeof rawObj.group === 'string' ? rawObj.group : undefined;
143
145
  if (!groupKey) {
144
- getContext().logger.debug('[BaseSyncedStore] Group removed delta missing group key', {
146
+ runtimeOf(ctx).logger.debug('[BaseSyncedStore] Group removed delta missing group key', {
145
147
  syncId: delta.id,
146
148
  });
147
149
  return;
148
150
  }
149
- getContext().logger.info('[BaseSyncedStore] Group removed', {
151
+ runtimeOf(ctx).logger.info('[BaseSyncedStore] Group removed', {
150
152
  group: groupKey,
151
153
  syncId: delta.id,
152
154
  });
@@ -181,7 +183,7 @@ export function computeUpdatedSyncGroups(ctx, payload) {
181
183
  */
182
184
  export function forceFullRebootstrap(ctx) {
183
185
  if (ctx.getBootstrapMode() === 'none') {
184
- getContext().logger.info('[BaseSyncedStore] forceFullRebootstrap skipped (bootstrapMode=none)');
186
+ runtimeOf(ctx).logger.info('[BaseSyncedStore] forceFullRebootstrap skipped (bootstrapMode=none)');
185
187
  return;
186
188
  }
187
189
  ctx.database.markRequiresFullBootstrap();
@@ -219,7 +221,7 @@ export async function checkSyncGroupShrinkage(ctx) {
219
221
  const currentGroups = new Set(currentSyncGroups);
220
222
  const removedGroups = stored.filter((g) => !currentGroups.has(g));
221
223
  if (removedGroups.length > 0) {
222
- getContext().logger.info('[BaseSyncedStore] Sync groups shrank — forcing full bootstrap', {
224
+ runtimeOf(ctx).logger.info('[BaseSyncedStore] Sync groups shrank — forcing full bootstrap', {
223
225
  removedGroups,
224
226
  storedCount: stored.length,
225
227
  currentCount: currentGroups.size,
@@ -235,7 +237,7 @@ export async function checkSyncGroupShrinkage(ctx) {
235
237
  });
236
238
  }
237
239
  catch (error) {
238
- getContext().logger.debug('[BaseSyncedStore] Failed to check sync group shrinkage', {
240
+ runtimeOf(ctx).logger.debug('[BaseSyncedStore] Failed to check sync group shrinkage', {
239
241
  error: error instanceof Error ? error.message : String(error),
240
242
  });
241
243
  }
@@ -1,6 +1,7 @@
1
+ import type { JoinOptions } from '../transaction/resources/modelOperations.js';
1
2
  import type { SyncWebSocket } from './SyncWebSocket.js';
2
- import type { Schema } from '../schema/schema.js';
3
- import type { Claim, Activity, ClaimTarget, ClaimStream, Peer, PresenceStream, PresenceTarget } from '../types/streams.js';
3
+ import type { Schema } from '../transaction/schema/schema.js';
4
+ import type { Claim, Activity, ClaimTarget, ClaimStream, Peer, PresenceStream, PresenceTarget } from '../transaction/types/streams.js';
4
5
  import type { AttachableClaimStream } from './createClaimStream.js';
5
6
  /**
6
7
  * The scope a participant can be joined to. The usual form is an entity target
@@ -17,7 +18,13 @@ export interface EngineParticipant {
17
18
  readonly presence: PresenceStream;
18
19
  readonly claims: ClaimStream;
19
20
  }
20
- export interface ParticipantJoinOptions {
21
+ /**
22
+ * The options for a participant join. It extends the public per-model
23
+ * {@link JoinOptions} rather than restating its members, so the lease dial is
24
+ * declared once, in the core, and this surface adds only what a lower-level
25
+ * join can additionally say.
26
+ */
27
+ export interface ParticipantJoinOptions extends JoinOptions {
21
28
  /**
22
29
  * The initial focus target, named in your schema's vocabulary and optionally
23
30
  * narrowed to a path, field, or range. When `scope` is omitted, this target
@@ -34,7 +41,17 @@ export interface ParticipantJoinOptions {
34
41
  readonly scope?: ParticipantScope;
35
42
  /** Present a narrower capability for this logical participant. */
36
43
  readonly capabilityToken?: string;
37
- /** How long the claim lives, in seconds or a compact duration string (`30s`, `5m`). */
44
+ /**
45
+ * @deprecated Use `ttl`. Removed in 0.37.0.
46
+ *
47
+ * One lease, spelled two ways, and the seconds spelling was the one that
48
+ * misled: it accepted a duration string, so `ablo.<model>.join(ids, { ttl:
49
+ * '5m' })` reached this surface as `ttlSeconds: '5m'` — a field whose name
50
+ * asserts a unit its value did not carry. `ttl` takes the same values and is
51
+ * the spelling every other lease in the SDK already uses (`claim`'s `ttl`,
52
+ * `ClaimLeaseOptions.ttl`). The wire is unchanged: it has always carried
53
+ * seconds, and still does.
54
+ */
38
55
  readonly ttlSeconds?: number | string | null;
39
56
  /**
40
57
  * The activity to announce as soon as the claim is acknowledged. Defaults to
@@ -64,7 +81,7 @@ export interface ScopedClaimOptions {
64
81
  /** Peer-visible description of the work. Defaults to `'editing'`. */
65
82
  readonly description?: string;
66
83
  /** How long the claim lives; the server expires it automatically after this. */
67
- readonly ttl?: import('../types/streams.js').Duration;
84
+ readonly ttl?: import('../transaction/types/streams.js').Duration;
68
85
  }
69
86
  export interface ScopedClaims {
70
87
  readonly focus: ClaimTarget | null;
@@ -102,7 +119,8 @@ export interface ParticipantManager {
102
119
  }
103
120
  export interface ParticipantManagerConfig {
104
121
  readonly ready: () => Promise<void>;
105
- readonly getTransport: () => SyncWebSocket | null;
122
+ /** The connection, host-built and stable for the client's lifetime. */
123
+ readonly transport: SyncWebSocket;
106
124
  readonly presence: PresenceStream;
107
125
  readonly claims: AttachableClaimStream;
108
126
  readonly schema?: Schema;
@@ -1,5 +1,6 @@
1
- import { scopeKindOf } from '../schema/model.js';
2
- import { AbloConnectionError, AbloValidationError } from '../errors.js';
1
+ import { scopeKindOf } from '../transaction/schema/model.js';
2
+ import { AbloValidationError } from '../transaction/errors.js';
3
+ import { subTarget, streamTarget, wireTarget, } from '../transaction/coordination/index.js';
3
4
  export function createParticipantManager(config) {
4
5
  return {
5
6
  async join(input, overrides) {
@@ -9,15 +10,16 @@ export function createParticipantManager(config) {
9
10
  : null;
10
11
  const syncGroups = unique(resolveParticipantSyncGroups(options.scope ?? target ?? undefined, config.schema));
11
12
  await config.ready();
12
- const transport = config.getTransport();
13
- if (!transport) {
14
- throw new AbloConnectionError('Ablo participant join failed: WebSocket is not connected', { code: 'ws_not_ready' });
15
- }
13
+ // Not-connected joins surface through `sendClaim`'s diagnosed
14
+ // rejection below; a scopeless join needs no wire send at all.
15
+ const transport = config.transport;
16
16
  const claimId = createParticipantClaimId();
17
17
  if (syncGroups.length > 0) {
18
18
  await transport.sendClaim(claimId, syncGroups, {
19
19
  capabilityToken: options.capabilityToken,
20
- ttlSeconds: parseParticipantTtlSeconds(options.ttlSeconds),
20
+ // `ttl` is the spelling; `ttlSeconds` is the deprecated one, read
21
+ // second so a caller passing both gets the current name honored.
22
+ ttlSeconds: parseParticipantTtlSeconds(options.ttl ?? options.ttlSeconds),
21
23
  });
22
24
  }
23
25
  const participant = createJoinedParticipant({
@@ -74,15 +76,30 @@ export function resolveParticipantSyncGroups(scope, schema) {
74
76
  }
75
77
  return out;
76
78
  }
79
+ /**
80
+ * The group kind for a model, in the wire dialect every plane shares: a
81
+ * declared scope root wins; otherwise the lowercased typename — the same
82
+ * token the commit plane and claim targets use (`wireModel`). Never the
83
+ * camelCase schema key: the server validates inbound subscription groups
84
+ * against a lowercase-only grammar, so a key like `reportBlocks` would be
85
+ * rejected as malformed on subscribe — and even a lowercase key would put
86
+ * this client in a different group than a peer who resolved the same row
87
+ * through an entity ref, so the two would never see each other's claims.
88
+ */
89
+ function groupKindForModel(def, key) {
90
+ return scopeKindOf(def, key) ?? (def.typename ?? key).toLowerCase();
91
+ }
77
92
  export function syncGroupFromEntityRef(ref, schema) {
78
93
  const match = findModelForEntityRef(ref, schema);
79
- const kind = match ? scopeKindOf(match.def, match.key) : undefined;
80
- return `${kind ?? ref.type.toLowerCase()}:${ref.id}`;
94
+ const kind = match
95
+ ? groupKindForModel(match.def, match.key)
96
+ : ref.type.toLowerCase();
97
+ return `${kind}:${ref.id}`;
81
98
  }
82
99
  function syncGroupFromSchemaKey(schemaKey, id, schema) {
83
100
  const def = schema?.models?.[schemaKey];
84
- const kind = def ? scopeKindOf(def, schemaKey) : undefined;
85
- return `${kind ?? schemaKey}:${id}`;
101
+ const kind = def ? groupKindForModel(def, schemaKey) : schemaKey.toLowerCase();
102
+ return `${kind}:${id}`;
86
103
  }
87
104
  function findModelForEntityRef(ref, schema) {
88
105
  if (!schema?.models)
@@ -296,12 +313,8 @@ function createJoinedParticipant(args) {
296
313
  }
297
314
  function activityFromTarget(target) {
298
315
  return {
299
- entityType: target.type,
300
- entityId: target.id,
301
- path: target.path,
302
- range: target.range,
303
- field: target.field,
304
- meta: target.meta,
316
+ ...wireTarget(target),
317
+ ...subTarget(target),
305
318
  };
306
319
  }
307
320
  function presenceMatchesParticipant(entry, target, syncGroups) {
@@ -310,12 +323,8 @@ function presenceMatchesParticipant(entry, target, syncGroups) {
310
323
  if (!target)
311
324
  return true;
312
325
  return targetsOverlap({
313
- type: entry.activity.entityType,
314
- id: entry.activity.entityId,
315
- path: entry.activity.path,
316
- range: entry.activity.range,
317
- field: entry.activity.field,
318
- meta: entry.activity.meta,
326
+ ...streamTarget(entry.activity),
327
+ ...subTarget(entry.activity),
319
328
  }, target);
320
329
  }
321
330
  function targetsOverlap(a, b) {
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The semantic schema-drift classifier — the question that matters is not
3
+ * "did the schema change at all?" (one whole-schema hash answers that, and
4
+ * welds every client to every push) but "does THIS client use anything that
5
+ * changed?". This module compares only the models the client declares against
6
+ * the server's per-model surface (`GET /api/schema`), so:
7
+ *
8
+ * - a purely additive server change (models this build never references) is
9
+ * SILENCE — deployed clients don't care what they don't use;
10
+ * - a model this build declares that the server doesn't have is named, with
11
+ * the push as the fix;
12
+ * - a shared model whose content differs is named, so "which field moved"
13
+ * is one `ablo status` away instead of a hash-guessing game.
14
+ *
15
+ * Pure and transport-free; the BootstrapFetcher owns fetching the surface.
16
+ */
17
+ /** One model as the server's schema read-back reports it. */
18
+ export interface ServerSchemaModel {
19
+ readonly key: string;
20
+ /** Per-model content hash; absent on servers older than this check. */
21
+ readonly hash?: string;
22
+ }
23
+ export type SchemaDriftFinding =
24
+ /** Every model this client declares exists server-side with matching content
25
+ * (the server may know more — that's an additive lead, not drift). */
26
+ {
27
+ readonly kind: 'aligned';
28
+ }
29
+ /** Models this build declares that the server has no idea about — writes to
30
+ * them will be declined until the schema is pushed. */
31
+ | {
32
+ readonly kind: 'unpushed';
33
+ readonly models: readonly string[];
34
+ }
35
+ /** Shared models whose content differs between this build and the server
36
+ * (may also carry unpushed models found alongside). */
37
+ | {
38
+ readonly kind: 'changed';
39
+ readonly models: readonly string[];
40
+ readonly unpushed: readonly string[];
41
+ }
42
+ /** The server surface carries no per-model hashes (older server) — the
43
+ * caller falls back to the whole-hash comparison. */
44
+ | {
45
+ readonly kind: 'unknown';
46
+ };
47
+ export declare function classifySchemaDrift(clientModels: Readonly<Record<string, string>>, serverModels: readonly ServerSchemaModel[]): SchemaDriftFinding;
48
+ /**
49
+ * The warning for a real, named divergence. Calm and specific: which models,
50
+ * what that means for this client, and the one next step. Never speaks about
51
+ * hashes — the point of the semantic check is that nobody has to compare hex.
52
+ */
53
+ export declare function describeSchemaDrift(finding: Extract<SchemaDriftFinding, {
54
+ kind: 'unpushed' | 'changed';
55
+ }>, serverLabel: string): string;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The semantic schema-drift classifier — the question that matters is not
3
+ * "did the schema change at all?" (one whole-schema hash answers that, and
4
+ * welds every client to every push) but "does THIS client use anything that
5
+ * changed?". This module compares only the models the client declares against
6
+ * the server's per-model surface (`GET /api/schema`), so:
7
+ *
8
+ * - a purely additive server change (models this build never references) is
9
+ * SILENCE — deployed clients don't care what they don't use;
10
+ * - a model this build declares that the server doesn't have is named, with
11
+ * the push as the fix;
12
+ * - a shared model whose content differs is named, so "which field moved"
13
+ * is one `ablo status` away instead of a hash-guessing game.
14
+ *
15
+ * Pure and transport-free; the BootstrapFetcher owns fetching the surface.
16
+ */
17
+ export function classifySchemaDrift(clientModels, serverModels) {
18
+ if (serverModels.length > 0 && serverModels.every((m) => !m.hash)) {
19
+ return { kind: 'unknown' };
20
+ }
21
+ const server = new Map(serverModels.map((m) => [m.key, m.hash]));
22
+ const unpushed = [];
23
+ const changed = [];
24
+ for (const [key, hash] of Object.entries(clientModels)) {
25
+ const serverHash = server.get(key);
26
+ if (serverHash === undefined)
27
+ unpushed.push(key);
28
+ else if (serverHash !== hash)
29
+ changed.push(key);
30
+ }
31
+ if (changed.length > 0)
32
+ return { kind: 'changed', models: changed, unpushed };
33
+ if (unpushed.length > 0)
34
+ return { kind: 'unpushed', models: unpushed };
35
+ return { kind: 'aligned' };
36
+ }
37
+ /**
38
+ * The warning for a real, named divergence. Calm and specific: which models,
39
+ * what that means for this client, and the one next step. Never speaks about
40
+ * hashes — the point of the semantic check is that nobody has to compare hex.
41
+ */
42
+ export function describeSchemaDrift(finding, serverLabel) {
43
+ if (finding.kind === 'unpushed') {
44
+ return (`Ablo: This build declares models the server at ${serverLabel} doesn't have yet ` +
45
+ `(${finding.models.join(', ')}). Writes to them will be declined until the schema is ` +
46
+ `pushed — run \`ablo push\` (and \`ablo status\` to confirm it targets this server).`);
47
+ }
48
+ const alsoUnpushed = finding.unpushed.length > 0 ? ` (${finding.unpushed.join(', ')} not pushed yet)` : '';
49
+ return (`Ablo: These models differ between this build and the server at ${serverLabel}: ` +
50
+ `${finding.models.join(', ')}${alsoUnpushed}. Reads and writes touching what changed may be ` +
51
+ `declined — \`ablo status\` shows the deployed shape; pushing your schema or deploying a ` +
52
+ `current build aligns them.`);
53
+ }
@@ -2,22 +2,24 @@
2
2
  * Zod validation schemas for sync engine server responses.
3
3
  *
4
4
  * Validates data at the fetch boundary before it enters the sync engine.
5
- * Uses .passthrough() so the server can add fields without breaking clients.
5
+ * Unknown keys are kept, so a server that adds a field does not break a client
6
+ * that predates it.
6
7
  */
7
8
  import { z } from 'zod';
9
+ import type { RuntimeContext } from "../RuntimeContext.js";
10
+ /**
11
+ * A delta as it arrives in a bootstrap payload.
12
+ *
13
+ * The bootstrap routes return the same rows the broadcast path does, so the
14
+ * fields are taken from {@link syncDeltaWireCoreSchema} rather than restated
15
+ * here — a delta is one shape, and this is the reader for it, not a second
16
+ * definition of it. Unknown keys are kept, because the server sends its own
17
+ * wider projection (attribution, `projectId`) that later stages may read.
18
+ */
8
19
  export declare const ServerDeltaSchema: z.ZodObject<{
9
20
  id: z.ZodNumber;
10
- operation: z.ZodOptional<z.ZodEnum<{
11
- I: "I";
12
- U: "U";
13
- D: "D";
14
- A: "A";
15
- V: "V";
16
- C: "C";
17
- G: "G";
18
- S: "S";
19
- }>>;
20
- action: z.ZodOptional<z.ZodEnum<{
21
+ data: z.ZodNullable<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodString]>>;
22
+ actionType: z.ZodEnum<{
21
23
  I: "I";
22
24
  U: "U";
23
25
  D: "D";
@@ -26,33 +28,22 @@ export declare const ServerDeltaSchema: z.ZodObject<{
26
28
  C: "C";
27
29
  G: "G";
28
30
  S: "S";
29
- }>>;
31
+ }>;
30
32
  modelName: z.ZodString;
31
- entityId: z.ZodOptional<z.ZodString>;
32
- modelId: z.ZodOptional<z.ZodString>;
33
- data: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
33
+ modelId: z.ZodString;
34
34
  }, z.core.$loose>;
35
35
  export type ValidatedServerDelta = z.infer<typeof ServerDeltaSchema>;
36
36
  export declare const BootstrapResponseSchema: z.ZodObject<{
37
37
  type: z.ZodEnum<{
38
- partial: "partial";
39
38
  full: "full";
39
+ partial: "partial";
40
40
  }>;
41
41
  lastSyncId: z.ZodNumber;
42
42
  models: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodPipe<z.ZodUnion<readonly [z.ZodArray<z.ZodUnknown>, z.ZodString, z.ZodNull]>, z.ZodTransform<unknown[], string | unknown[] | null>>>>;
43
43
  deltas: z.ZodOptional<z.ZodArray<z.ZodObject<{
44
44
  id: z.ZodNumber;
45
- operation: z.ZodOptional<z.ZodEnum<{
46
- I: "I";
47
- U: "U";
48
- D: "D";
49
- A: "A";
50
- V: "V";
51
- C: "C";
52
- G: "G";
53
- S: "S";
54
- }>>;
55
- action: z.ZodOptional<z.ZodEnum<{
45
+ data: z.ZodNullable<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodString]>>;
46
+ actionType: z.ZodEnum<{
56
47
  I: "I";
57
48
  U: "U";
58
49
  D: "D";
@@ -61,16 +52,15 @@ export declare const BootstrapResponseSchema: z.ZodObject<{
61
52
  C: "C";
62
53
  G: "G";
63
54
  S: "S";
64
- }>>;
55
+ }>;
65
56
  modelName: z.ZodString;
66
- entityId: z.ZodOptional<z.ZodString>;
67
- modelId: z.ZodOptional<z.ZodString>;
68
- data: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
57
+ modelId: z.ZodString;
69
58
  }, z.core.$loose>>>;
70
59
  deltaCount: z.ZodOptional<z.ZodNumber>;
71
60
  failedModels: z.ZodOptional<z.ZodArray<z.ZodString>>;
72
61
  timestamp: z.ZodDefault<z.ZodNumber>;
73
62
  schemaHash: z.ZodOptional<z.ZodString>;
63
+ nextCursor: z.ZodOptional<z.ZodString>;
74
64
  }, z.core.$loose>;
75
65
  export type ValidatedBootstrapResponse = z.infer<typeof BootstrapResponseSchema>;
76
66
  /**
@@ -78,4 +68,4 @@ export type ValidatedBootstrapResponse = z.infer<typeof BootstrapResponseSchema>
78
68
  * result. On failure it records a diagnostic breadcrumb and throws an
79
69
  * {@link AbloValidationError} describing which fields were invalid.
80
70
  */
81
- export declare function parseBootstrapResponse(raw: unknown): ValidatedBootstrapResponse;
71
+ export declare function parseBootstrapResponse(raw: unknown, runtime?: RuntimeContext): ValidatedBootstrapResponse;
@@ -2,27 +2,32 @@
2
2
  * Zod validation schemas for sync engine server responses.
3
3
  *
4
4
  * Validates data at the fetch boundary before it enters the sync engine.
5
- * Uses .passthrough() so the server can add fields without breaking clients.
5
+ * Unknown keys are kept, so a server that adds a field does not break a client
6
+ * that predates it.
6
7
  */
7
8
  import { z } from 'zod';
8
- import { getContext } from "../context.js";
9
- import { AbloValidationError } from "../errors.js";
10
- // ─── Sync Action Types ───────────────────────────────────────────────────────
11
- // The action codes a server delta can carry, matching the wire protocol's
12
- // action-type set.
13
- const SYNC_ACTION_VALUES = ['I', 'U', 'D', 'A', 'C', 'G', 'S', 'V'];
9
+ import { globalRuntime } from "../context.js";
10
+ import { AbloValidationError } from "../transaction/errors.js";
11
+ import { syncDeltaWireCoreSchema } from '../transaction/wire/delta.js';
14
12
  // ─── Server Delta Schema ─────────────────────────────────────────────────────
15
- export const ServerDeltaSchema = z
16
- .object({
17
- id: z.number(),
18
- operation: z.enum(SYNC_ACTION_VALUES).optional(),
19
- action: z.enum(SYNC_ACTION_VALUES).optional(),
20
- modelName: z.string(),
21
- entityId: z.string().optional(),
22
- modelId: z.string().optional(),
23
- data: z.record(z.string(), z.unknown()).nullable().optional(),
13
+ /**
14
+ * A delta as it arrives in a bootstrap payload.
15
+ *
16
+ * The bootstrap routes return the same rows the broadcast path does, so the
17
+ * fields are taken from {@link syncDeltaWireCoreSchema} rather than restated
18
+ * here — a delta is one shape, and this is the reader for it, not a second
19
+ * definition of it. Unknown keys are kept, because the server sends its own
20
+ * wider projection (attribution, `projectId`) that later stages may read.
21
+ */
22
+ export const ServerDeltaSchema = syncDeltaWireCoreSchema
23
+ .pick({
24
+ id: true,
25
+ actionType: true,
26
+ modelName: true,
27
+ modelId: true,
28
+ data: true,
24
29
  })
25
- .passthrough();
30
+ .loose();
26
31
  // ─── Model Value Schema ─────────────────────────────────────────────────────
27
32
  // A model's values can arrive in more than one shape depending on how the
28
33
  // server serialized them:
@@ -60,19 +65,23 @@ export const BootstrapResponseSchema = z
60
65
  // absent when the server predates this field or the tenant has never
61
66
  // pushed a schema.
62
67
  schemaHash: z.string().optional(),
68
+ // Present when a paged single-model request stopped at its row limit
69
+ // with rows remaining: pass it back as the next page's cursor. Absent
70
+ // on the final page, on unpaged responses, and from older servers.
71
+ nextCursor: z.string().optional(),
63
72
  })
64
- .passthrough();
73
+ .loose();
65
74
  // ─── Parse Helpers ───────────────────────────────────────────────────────────
66
75
  /**
67
76
  * Validates a raw bootstrap response from the server and returns the typed
68
77
  * result. On failure it records a diagnostic breadcrumb and throws an
69
78
  * {@link AbloValidationError} describing which fields were invalid.
70
79
  */
71
- export function parseBootstrapResponse(raw) {
80
+ export function parseBootstrapResponse(raw, runtime = globalRuntime) {
72
81
  const result = BootstrapResponseSchema.safeParse(raw);
73
82
  if (!result.success) {
74
83
  const issues = result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');
75
- getContext().observability.breadcrumb('Bootstrap response validation failed', 'sync.bootstrap', 'error', {
84
+ runtime.observability.breadcrumb('Bootstrap response validation failed', 'sync.bootstrap', 'error', {
76
85
  issues,
77
86
  rawType: typeof raw,
78
87
  rawKeys: raw && typeof raw === 'object' ? Object.keys(raw).join(',') : 'n/a',
@@ -5,17 +5,17 @@
5
5
  * object pool, and the enrichment rules that attach related parents to
6
6
  * incoming rows. See {@link deriveSyncPlanFromSchema}.
7
7
  */
8
- import type { Schema } from '../schema/schema.js';
8
+ import type { Schema } from '../transaction/schema/schema.js';
9
9
  /** A foreign-key index to register on the in-memory object pool when the store is constructed. */
10
10
  export interface ForeignKeyIndexSpec {
11
11
  /**
12
12
  * The name of the child model, where the foreign-key field lives, and the
13
13
  * name the object pool indexes by. Use the wire type-name casing (for
14
- * example `'SlideLayer'`, not `'slideLayer'`), since that is the value
14
+ * example `'Block'`, not `'block'`), since that is the value
15
15
  * stamped onto reconstructed models and the key the pool looks up.
16
16
  */
17
17
  readonly modelName: string;
18
- /** The foreign-key field name on the child model, for example `'slideId'`. */
18
+ /** The foreign-key field name on the child model, for example `'sectionId'`. */
19
19
  readonly fieldName: string;
20
20
  }
21
21
  /**