@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,11 +1,11 @@
1
1
  /**
2
- * Ablo — The one-liner consumer API.
3
- *
4
- * Hides all internal wiring (ObjectPool, Database, SyncClient, WebSocket,
5
- * bootstrap, offline queue, DI adapters) behind a single function call.
2
+ * `Ablo`the one-call entry point to the sync engine client. It hides the
3
+ * internal wiring — the object pool, local database, sync client, WebSocket,
4
+ * bootstrap, and offline queue behind a single function that returns a typed
5
+ * client with one property per model in your schema.
6
6
  *
7
7
  * Usage:
8
- * import { Ablo } from '@abloatai/ablo/client';
8
+ * import { Ablo } from '@abloatai/ablo';
9
9
  * import { schema } from './schema';
10
10
  *
11
11
  * const sync = Ablo({ schema, apiKey: process.env.ABLO_API_KEY });
@@ -18,712 +18,22 @@
18
18
  * });
19
19
  * await sync.reports.delete({ id: reportId });
20
20
  */
21
- import type { StaleNotification, ReadDependency } from '../coordination/schema.js';
22
21
  import type { Schema, SchemaRecord, InferModel, InferCreate } from '../schema/schema.js';
23
- import type { SyncEngineConfig, SyncLogger, MutationExecutor, MutationDispatcher, SyncObservabilityProvider, SyncAnalytics, SessionErrorDetector, OnlineStatusProvider } from '../interfaces/index.js';
24
22
  import type { ModelTarget, ModelClaim } from '../coordination/schema.js';
25
23
  export type { ModelTarget, ModelClaim };
26
- import { ObjectPool } from '../ObjectPool.js';
24
+ import { InstanceCache } from '../InstanceCache.js';
27
25
  import type { SyncStoreContract } from '../react/context.js';
28
26
  import type { SyncWebSocket } from '../sync/SyncWebSocket.js';
29
- import type { SyncGroupInput } from '../schema/roles.js';
30
27
  import { type SyncStatus } from '../BaseSyncedStore.js';
31
- import type { ModelUpdater, ContentionOptions } from './functionalUpdate.js';
32
- import type { ClaimStream, ClaimWaitOptions, PresenceStream, Snapshot } from '../types/streams.js';
33
- import type { Claim, HeldClaim, Duration } from '../types/streams.js';
28
+ import type { PresenceStream, Snapshot } from '../types/streams.js';
34
29
  import { type AbloApi, type AbloApiClientOptions, type AbloApiClaims } from './ApiClient.js';
35
30
  import { type AbloHttpClient, type AbloHttpClientOptions } from './httpClient.js';
36
- /**
37
- * Async function that resolves an apiKey at request time. Use for
38
- * credential rotation rotate from a vault, refresh from session
39
- * storage, or pull from a Better Auth session. Mirrors Anthropic's
40
- * `ApiKeySetter` exactly so any rotation pattern that works with
41
- * `@anthropic-ai/sdk` works here.
42
- *
43
- * Re-exported from `./auth` so existing import paths (`@abloatai/ablo`)
44
- * keep resolving; the canonical definition lives there alongside the
45
- * resolvers that consume it.
46
- */
47
- export type { ApiKeySetter } from './auth.js';
48
- import type { ApiKeySetter } from './auth.js';
49
- import { type AbloPersistence } from './persistence.js';
50
- /**
51
- * Options for `Ablo({...})`.
52
- *
53
- * The only required field is `schema`. The default path is one line:
54
- *
55
- * ```ts
56
- * const ablo = Ablo({ schema, apiKey: process.env.ABLO_API_KEY });
57
- * ```
58
- *
59
- * `apiKey` itself defaults to `process.env.ABLO_API_KEY`, so in most
60
- * server setups `Ablo({ schema })` is enough. Every other field is
61
- * optional tuning (timeouts, retries, custom fetch, persistence) —
62
- * if you're not sure whether you need one, you don't. Reach for them
63
- * the way you'd reach for the equivalent option on the Stripe / OpenAI
64
- * / Anthropic clients: rarely, and deliberately.
65
- *
66
- * @see https://docs.abloatai.com — full option reference
67
- */
68
- export interface AbloOptions<S extends SchemaRecord = SchemaRecord> {
69
- /**
70
- * TypeScript schema defined with `defineSchema()`. Required — it's what
71
- * makes `ablo.weatherReports.update(...)` typed. This is the one field you must
72
- * pass; start here.
73
- */
74
- schema: Schema<S>;
75
- /**
76
- * API key — **the one auth field most apps set.** Server-side this is your
77
- * secret `sk_` (and it defaults to `process.env['ABLO_API_KEY']`, so you
78
- * usually pass nothing). A long-lived key needs no refresh; the client uses
79
- * it as-is.
80
- *
81
- * Accepts a static string OR an async `() => Promise<string | null>` resolver
82
- * — the single credential path. Use the resolver form for two cases:
83
- *
84
- * - **Key rotation** (server): pull a fresh `sk_`/`pk_` from a vault on each
85
- * bootstrap (AWS STS, GCP IAM, Vault).
86
- * - **Short-lived per-user browser** auth: return the fresh `ek_`/`rk_` bearer
87
- * your backend minted for the signed-in user. The client mints once before
88
- * connect, then keeps it fresh for you — a refresh timer ahead of expiry
89
- * plus re-mint on OS-wake / network-online / tab-focus, and a reactive
90
- * re-mint when a probe finds the key stale. You never call a refresh method
91
- * (Supabase `autoRefreshToken` model).
92
- *
93
- * Resolver contract: resolve a token; resolve `null` when the login itself is
94
- * gone (terminal → the client signs out / fails `ready()` with `session_expired`);
95
- * or THROW on a transient failure (→ back off and retry, never sign out). A
96
- * static string never refreshes — it is used as-is.
97
- */
98
- apiKey?: string | ApiKeySetter | null | undefined;
99
- /**
100
- * @deprecated The direct connector lets Ablo dial INTO your Postgres and write to
101
- * it — the operate-their-database posture we are moving off. Ablo is Stripe-shaped:
102
- * it hosts only the transaction log (the ordered sync_deltas) + coordination, never
103
- * your data; your rows always live in your own database. Use the signed Data Source
104
- * endpoint instead — keep `DATABASE_URL` in your app, expose `dataSource(...)`, and
105
- * let your server own the write while Ablo coordinates the sync stream. To keep the
106
- * log in your infra too, self-host the engine. See
107
- * docs/plans/stripe-shaped-storage-posture.md.
108
- *
109
- * Still honored at runtime for back-compat. SERVER-ONLY: it carries credentials, so
110
- * it is never sent from the browser — constructing a client with `databaseUrl` and
111
- * `dangerouslyAllowBrowser` throws. If you use it, provide a NON-superuser,
112
- * non-`BYPASSRLS` role; the connector rejects privileged roles that cannot enforce RLS.
113
- */
114
- databaseUrl?: string | null | undefined;
115
- /**
116
- * Local persistence mode. Pass `indexeddb` only when you want offline
117
- * queueing and a reload-surviving browser cache.
118
- *
119
- * @default 'memory'
120
- */
121
- persistence?: AbloPersistence;
122
- /**
123
- * Transport selector. `'websocket'` (default) is the live client —
124
- * persistent socket, local synced pool, `onChange` subscriptions. `'http'`
125
- * returns the STATELESS client for server-side actors (agents, workers,
126
- * serverless): same `ablo.<model>` surface and coordination plane, but each
127
- * call is one HTTP round-trip, identity rides the Bearer credential, and no
128
- * socket is ever opened. With `'http'` the return type narrows to
129
- * `AbloHttpClient<S>`, so stateful-only capabilities (`get`/`getAll`,
130
- * `onChange`) are compile errors rather than latent runtime gaps.
131
- *
132
- * Note: session/credential minting (`sessions.create`) currently runs on the
133
- * stateful (default) client, not the http client.
134
- *
135
- * @default 'websocket'
136
- */
137
- transport?: 'websocket' | 'http' | undefined;
138
- /**
139
- * Turn Ablo's diagnostic logging on/off. `true` surfaces the `[Ablo]`
140
- * coordination trace — claims requested / queued / granted / released, agent
141
- * handovers, connection state — so you can SEE the human+agent coordination
142
- * you built while debugging. Omitted/`false` keeps the quiet default (only
143
- * warnings + errors). For a middle ground use {@link logLevel}. Env override:
144
- * `ABLO_LOG_LEVEL`. Ignored if a custom logger is supplied.
145
- */
146
- debug?: boolean | undefined;
147
- /**
148
- * Log threshold for the default `[Ablo]` logger (takes precedence over
149
- * {@link debug}). `'info'` = coordination + connection events without the
150
- * per-model registration firehose; `'debug'` = everything; `'warn'` (default)
151
- * = warnings + errors only; `'silent'` = nothing. Env override: `ABLO_LOG_LEVEL`.
152
- */
153
- logLevel?: 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined;
154
- /**
155
- * Bearer auth token. Hosted-cloud consumers pass `apiKey`; self-hosted
156
- * deployments may pass a bearer token minted by their own auth layer.
157
- */
158
- authToken?: string | null | undefined;
159
- /**
160
- * Override the Ablo API base URL. Defaults to hosted production.
161
- */
162
- baseURL?: string | null | undefined;
163
- /** Custom fetch implementation for tests, proxies, or non-standard runtimes. */
164
- fetch?: typeof fetch | undefined;
165
- /** Default headers sent with every API request. */
166
- defaultHeaders?: Record<string, string | null | undefined> | undefined;
167
- /** Default query parameters sent with every API request. */
168
- defaultQuery?: Record<string, string | undefined> | undefined;
169
- /**
170
- * Client-side use is disabled by default because private API keys should
171
- * not ship to browsers. Set this only when the browser holds a minted
172
- * session token (`ek_`/`rk_`) or you route through a controlled server proxy.
173
- */
174
- dangerouslyAllowBrowser?: boolean | undefined;
175
- }
176
- export interface InternalAbloOptions<S extends SchemaRecord = SchemaRecord> {
177
- /**
178
- * API key used for authentication.
179
- *
180
- * Accepts a static string (`sk_live_...`) or an async function that
181
- * resolves to one. Defaults to `process.env['ABLO_API_KEY']`.
182
- *
183
- * When a function is provided, it's invoked before each request so
184
- * you can rotate or refresh credentials at runtime. The function
185
- * must return a non-empty string; otherwise an `AbloAuthenticationError`
186
- * is thrown. If the function throws, the error is wrapped with the
187
- * original available as `cause`.
188
- *
189
- * Mirrors Anthropic / OpenAI / Stripe SDK shape exactly.
190
- */
191
- apiKey?: string | ApiKeySetter | null | undefined;
192
- /**
193
- * Bearer auth token. Sent as `Authorization: Bearer <token>` on
194
- * every request.
195
- *
196
- * Use this for self-hosted deployments where your auth layer mints
197
- * cap tokens directly. Hosted-cloud consumers pass `apiKey` instead;
198
- * the server handles cap-mint internally.
199
- */
200
- authToken?: string | null | undefined;
201
- /**
202
- * Override the default base URL. Defaults to
203
- * `wss://api.abloatai.com` for hosted production; pass an explicit
204
- * URL for self-hosted or private deployments.
205
- */
206
- baseURL?: string | null | undefined;
207
- /**
208
- * Custom `fetch` implementation. Defaults to `globalThis.fetch`.
209
- * Override for testing, custom transports, or runtime shims.
210
- */
211
- fetch?: typeof fetch | undefined;
212
- /**
213
- * Default headers to include with every request to the API.
214
- * Removed per-request by setting the header to `null` in request
215
- * options.
216
- */
217
- defaultHeaders?: Record<string, string | null | undefined> | undefined;
218
- /**
219
- * Default query parameters to include with every request.
220
- * Removed per-request by setting the param to `undefined`.
221
- */
222
- defaultQuery?: Record<string, string | undefined> | undefined;
223
- /**
224
- * Client-side use of this SDK is disabled by default — your apiKey
225
- * would ship to every visitor's network tab. Only set this to
226
- * `true` if you've understood the risk and have appropriate
227
- * mitigations (a minted session token, a server-side proxy, etc).
228
- */
229
- dangerouslyAllowBrowser?: boolean | undefined;
230
- /**
231
- * TypeScript schema defined with `defineSchema()`.
232
- *
233
- * The root `Ablo(...)` client is schema-first so consumers get typed
234
- * model clients such as `ablo.weatherReports.update(...)`. Omit `schema`
235
- * only for the advanced Model / Claim / Commit client.
236
- */
237
- schema: Schema<S>;
238
- /**
239
- * @deprecated Server derives participant kind from the apiKey's
240
- * scope. Pass apiKey only; this option will be removed once the
241
- * server-internal cap-mint flow lands.
242
- */
243
- kind?: 'user' | 'agent' | 'system';
244
- /**
245
- * @deprecated Server derives user identity from the apiKey's
246
- * scope (or from `Ablo-Acting-User` request header for B2B2C).
247
- * Removed once Phase 3 ships.
248
- */
249
- user?: {
250
- id: string;
251
- teamIds?: string[];
252
- };
253
- /**
254
- * @deprecated Server derives agent identity from the apiKey's
255
- * scope. Removed once Phase 3 ships.
256
- */
257
- agentId?: string;
258
- /**
259
- * @deprecated Cap-mint moves server-internal in Phase 3. Pass
260
- * `apiKey` only; the server handles capability issuance.
261
- */
262
- capabilityToken?: string;
263
- /** Custom logger (default: console). Supplying one bypasses {@link debug}/{@link logLevel}. */
264
- logger?: SyncLogger;
265
- /**
266
- * Turn Ablo's diagnostic logging on/off. `true` surfaces the `[Ablo]`
267
- * coordination trace — claims acquired / queued / granted / released, agent
268
- * handovers, connection state — plus internal lifecycle, so you can SEE the
269
- * human+agent coordination you built. Omitted/`false` keeps the quiet default
270
- * (only warnings + errors). For a middle ground use {@link logLevel}.
271
- * Env override: `ABLO_LOG_LEVEL`. Ignored if a custom {@link logger} is passed.
272
- */
273
- debug?: boolean;
274
- /**
275
- * Log threshold for the default `[Ablo]` logger (takes precedence over
276
- * {@link debug}). `'info'` = coordination + connection events without the
277
- * per-model registration firehose; `'debug'` = everything; `'warn'` (default)
278
- * = warnings + errors only; `'silent'` = nothing. Env override: `ABLO_LOG_LEVEL`.
279
- */
280
- logLevel?: 'debug' | 'info' | 'warn' | 'error' | 'silent';
281
- /** ObjectPool size limit (default: 10000) */
282
- maxPoolSize?: number;
283
- /**
284
- * Local persistence mode. Defaults to `memory` so Ablo behaves like a
285
- * point solution for shared state instead of silently bolting IndexedDB
286
- * durability onto every browser consumer.
287
- *
288
- * Pass `persistence: 'indexeddb'` only when you want offline queueing
289
- * and a reload-surviving local cache in a browser.
290
- */
291
- persistence?: AbloPersistence;
292
- /** @deprecated Use `persistence: 'indexeddb'` for durable browser storage. */
293
- offline?: boolean;
294
- /**
295
- * @deprecated Internal/testing escape hatch. Use `persistence` in
296
- * production code. `true` maps to `memory`; `false` maps to
297
- * `indexeddb` in browsers.
298
- */
299
- inMemory?: boolean;
300
- /**
301
- * If true, initialization starts immediately in the background so
302
- * `sync.reports.findMany()` works after `await sync.ready()`.
303
- *
304
- * If false (default), the consumer MUST call `await sync.ready()` before
305
- * using the engine — any query before that returns empty results.
306
- *
307
- * Default: false (explicit is better — prevents silent init failures).
308
- */
309
- autoStart?: boolean;
310
- /**
311
- * How aggressively this client should pull baseline state at
312
- * startup.
313
- *
314
- * - `'full'`: pull every delta in the configured sync groups before
315
- * `ready()` resolves. Default for `kind: 'user'`.
316
- * - `'none'`: open the WS and process live deltas only — no baseline
317
- * fetch. Reads round-trip via `model.retrieve()`; subscriptions
318
- * populate the pool lazily via covering deltas. Default for
319
- * `kind: 'agent'` because agent-worker / routine runners don't
320
- * need (or want) a local replica of the org's tenant plane.
321
- */
322
- bootstrapMode?: 'full' | 'none';
323
- /**
324
- * Custom observability provider (Sentry, Honeycomb, OTel, etc.).
325
- * Default: a noop implementation that drops all breadcrumbs and spans.
326
- */
327
- observability?: SyncObservabilityProvider;
328
- /**
329
- * Custom analytics provider (PostHog, Amplitude, Segment, etc.).
330
- * Default: a noop implementation that drops all events.
331
- */
332
- analytics?: SyncAnalytics;
333
- /**
334
- * Detect whether an error from a mutation/bootstrap response means the
335
- * user's session has expired. Used to surface re-auth prompts. Default:
336
- * heuristic that matches `401 Unauthorized` and a few common error shapes.
337
- */
338
- sessionErrorDetector?: SessionErrorDetector;
339
- /**
340
- * Detect whether the browser is currently online. Default: reads
341
- * `navigator.onLine` and listens to the `online`/`offline` events.
342
- */
343
- onlineStatus?: OnlineStatusProvider;
344
- /**
345
- * Replace the built-in `MutationExecutor` (which posts a hardcoded
346
- * `commit` method against `${url}/graphql`) with one that uses your own
347
- * GraphQL client, auth headers, retry policy, and observability hooks.
348
- *
349
- * Default: a fetch-based executor that targets `${url}/graphql` and sends
350
- * the configured bearer (`apiKey` / backend-minted token) as `Authorization`.
351
- */
352
- mutationExecutor?: MutationExecutor;
353
- /**
354
- * Replace the built-in `MutationDispatcher` (used by the offline queue
355
- * to replay mutations on reconnect). If you override `mutationExecutor`
356
- * you almost always want to override this too so the two paths share
357
- * the same auth/retry behavior.
358
- *
359
- * Default: a thin dispatcher that routes to the built-in executor.
360
- */
361
- mutationDispatcher?: MutationDispatcher;
362
- /**
363
- * Partial overrides for the auto-derived `SyncEngineConfig`. Merged on
364
- * top of `deriveConfigFromSchema(schema)`. Use this when you need
365
- * specific `modelCreatePriority`, `batchableModels`, or
366
- * `essentialFields` settings that the schema cannot express.
367
- */
368
- configOverrides?: Partial<SyncEngineConfig>;
369
- /**
370
- * Sync groups (entity scopes) this client subscribes to. **Provisional, not
371
- * deprecated** — pick the right lane: normally the server derives these from
372
- * the apiKey's scope, but passing them is still REQUIRED today in any config
373
- * where the key doesn't resolve them (omitting yields a `degenerate
374
- * syncGroups` warning and a zero-fan-out client). Keep passing it explicitly
375
- * until the server-derived path ships in Phase 3, at which point it becomes a
376
- * true no-op and is removed. Build values with `syncGroup(kind, id)` from
377
- * `@abloatai/ablo/schema`.
378
- */
379
- syncGroups?: string[];
380
- /**
381
- * Override the bootstrap endpoint base URL. Use this when your sync
382
- * server's HTTP API lives on a different host than the WebSocket URL.
383
- *
384
- * Must include the `/api` prefix — `BootstrapHelper` appends
385
- * `/sync/bootstrap` directly. Example:
386
- * `'http://api.example.com/api'` → `http://api.example.com/api/sync/bootstrap`.
387
- *
388
- * Default: `${url.replace(/^ws/, 'http')}/api`.
389
- */
390
- bootstrapBaseUrl?: string;
391
- /**
392
- * Ablo-owned account scope. Required for Branch 3 identity resolution
393
- * in `identity.ts` — without it the SDK falls through to the
394
- * `/api/identity` HTTP-derived path (Branch 2).
395
- */
396
- organizationId?: string;
397
- }
398
- /**
399
- * Operations available on each model in the sync engine.
400
- *
401
- * Naming aligns with Stripe / OpenAI / Anthropic conventions:
402
- * `retrieve({ id })` — async single-row server read
403
- * `list({ where })` — async collection server read
404
- * `get(id)` / `getAll(...)` / `getCount(...)` — local graph snapshots
405
- * `create({ data })` / `update({ id, data })` / `delete({ id })` — writes
406
- * `claim({ id })` — durable claim handle for coordinated writes
407
- */
408
- export type { LocalCountOptions, LocalReadOptions, ModelListScope, ServerReadOptions, ModelRetrieveParams, ModelCreateParams, ModelUpdateParams, ModelDeleteParams, ClaimOptions, ClaimParams, ClaimLookupParams, ClaimReorderParams, Claim, HeldClaim, ModelOperations, } from './createModelProxy.js';
409
- import type { ModelOperations, ClaimOptions, ClaimParams, ClaimReadApi, AwaitedClaimMethod, ServerReadOptions } from './createModelProxy.js';
410
- export type ModelOperationAction = 'create' | 'update' | 'delete' | 'archive' | 'unarchive';
411
- export type CommitWait = 'queued' | 'confirmed';
412
- export interface ModelRead<T = Record<string, unknown>> {
413
- /**
414
- * The row, or `undefined` when no row matched the id (or it's outside the
415
- * caller's scope). A miss is data-absence, not an error — `retrieve` never
416
- * throws "not found", mirroring the WebSocket client's `T | undefined`.
417
- * Branch on it: `const deal = (await ablo.deals.retrieve({ id })).data; if (!deal) …`.
418
- */
419
- readonly data: T | undefined;
420
- readonly stamp: number;
421
- readonly claims: readonly ModelClaim[];
422
- }
423
- export type IfClaimedPolicy = 'return' | 'fail';
424
- export interface ClaimedOptions {
425
- /**
426
- * What to do when another participant has claimed the target: `return`
427
- * includes active claim metadata in the response; `fail` throws
428
- * `AbloClaimedError`. Waiting for a claim to clear is a claim-side concern —
429
- * take `ablo.<model>.claim({ id })` (it queues fairly); reads never block.
430
- */
431
- readonly ifClaimed?: IfClaimedPolicy;
432
- }
433
- export type { ClaimWaitOptions } from '../types/streams.js';
434
- export interface ModelReadOptions extends ClaimedOptions {
435
- }
436
- export interface ClaimCreateOptions {
437
- readonly target: ModelTarget;
438
- /** Human-readable phase shown to peers — `'editing'`, `'writing'`. The same
439
- * word on every claim surface. */
440
- readonly reason: string;
441
- readonly ttl?: Duration;
442
- /**
443
- * Join the server's fair FIFO queue when the target is already claimed,
444
- * rather than failing immediately. `create` then resolves only once the
445
- * lease is actually ours (the server pushes `claim_acquired` if the target
446
- * was free, or `claim_granted` when we reach the head of the line). Without
447
- * this, a contended claim throws. Used by `ablo.<model>.claim` so writers
448
- * serialize instead of racing.
449
- */
450
- readonly queue?: boolean;
451
- /** Cap on how long to wait for a queued grant before rejecting. */
452
- readonly waitTimeoutMs?: number;
453
- /**
454
- * Backpressure: reject with `AbloClaimedError('queue_too_deep')` instead of
455
- * waiting if the queue is already `>= maxQueueDepth` when we join.
456
- */
457
- readonly maxQueueDepth?: number;
458
- }
459
- export interface CommitOperationInput {
460
- readonly action: ModelOperationAction;
461
- /** The model name — matches `ablo.<model>` and the schema's `model()`. */
462
- readonly model?: string;
463
- readonly target?: ModelTarget;
464
- readonly id?: string | null;
465
- readonly data?: Record<string, unknown> | null;
466
- readonly transactionId?: string | null;
467
- readonly readAt?: number | null;
468
- readonly onStale?: 'reject' | 'overwrite' | 'notify' | null;
469
- }
470
- export interface CommitCreateOptions {
471
- readonly claimRef?: string | {
472
- readonly id: string;
473
- } | null;
474
- readonly idempotencyKey?: string | null;
475
- readonly readAt?: number | null;
476
- readonly onStale?: 'reject' | 'overwrite' | 'notify' | null;
477
- /**
478
- * A claim handle from `ablo.<model>.claim({ id })` (or the HTTP claim
479
- * surface). Same vocabulary as the per-model writes: the handle's
480
- * snapshot watermark becomes the batch `readAt` default and `onStale`
481
- * defaults to `'reject'`, so a commit that follows a claim is guarded
482
- * against concurrent edits without re-stating the watermark by hand.
483
- * Explicit `readAt`/`onStale` on the options win.
484
- */
485
- readonly claim?: Claim<Record<string, unknown>> | null;
486
- readonly operation?: CommitOperationInput;
487
- readonly operations?: readonly CommitOperationInput[];
488
- readonly wait?: CommitWait;
489
- /**
490
- * Batch-level read dependencies (the STORM "did anything I looked at change?"
491
- * layer). Declare the rows (`{model,id,readAt,fields?}`) or sync groups
492
- * (`{group,readAt}`, e.g. `deck:abc`) this batch was premised on; the server
493
- * validates none moved since `readAt` and fires the entry's `onStale` over the
494
- * batch. Distinct from the write-target `readAt` — this guards what you READ,
495
- * not what you write.
496
- */
497
- readonly reads?: readonly ReadDependency[] | null;
498
- }
499
- export interface CommitReceipt {
500
- readonly id: string;
501
- readonly status: CommitWait;
502
- readonly lastSyncId?: number;
503
- /**
504
- * Stale-context notifications (notify-instead-of-abort, non-coercion). Present
505
- * only when this commit guarded a write with `onStale: 'notify' and
506
- * the premise moved concurrently — the conflicting field's current value,
507
- * handed back as data instead of a forced `AbloStaleContextError`. The engine
508
- * surfaces state; the intelligent actor (agent or human) decides how to
509
- * resolve. Also fires on `conflict:notified`.
510
- */
511
- readonly notifications?: readonly StaleNotification[];
512
- /**
513
- * Ids of UPDATE/DELETE targets in this commit that matched ZERO rows (the row
514
- * doesn't exist, or is outside the caller's org). Present (non-empty) only
515
- * when a write missed. Typed resource wrappers turn this into a loud
516
- * `AbloNotFoundError`; a raw `commits.create` caller can inspect it directly.
517
- */
518
- readonly missingIds?: readonly string[];
519
- }
520
- export interface CommitResource {
521
- create(options: CommitCreateOptions): Promise<CommitReceipt>;
522
- }
523
- export interface ClaimResource extends ClaimStream {
524
- create(options: ClaimCreateOptions): Promise<Claim>;
525
- list(target?: Partial<ModelTarget>): readonly ModelClaim[];
526
- waitFor(target: Partial<ModelTarget>, options?: ClaimWaitOptions): Promise<void>;
527
- }
528
- export interface ModelMutationOptions extends ClaimedOptions {
529
- readonly claimRef?: string | {
530
- readonly id: string;
531
- } | null;
532
- readonly idempotencyKey?: string | null;
533
- readonly readAt?: number | null;
534
- readonly onStale?: 'reject' | 'overwrite' | 'notify' | null;
535
- readonly wait?: CommitWait;
536
- readonly claim?: Claim | ClaimOptions | null;
537
- }
538
- /**
539
- * The HTTP/stateless claim surface. Normal tools usually put `claim` directly
540
- * on the write (`update({ id, data, claim })`) and let the SDK release it. Use
541
- * this namespace for multi-step handles and coordination screens.
542
- *
543
- * Same surface as the reactive {@link ClaimApi}, but every read is a server
544
- * round-trip, so `state`/`queue`/`reorder` are **awaited** here (the WebSocket
545
- * client resolves them synchronously from its local pool — which is what lets
546
- * `useAblo((ablo) => ablo.x.claim.state({ id }))` work inside a React render; a
547
- * stateless client has no pool to read, so the `Promise` is unavoidable).
548
- *
549
- * Mechanically DERIVED from `ClaimReadApi` via {@link AwaitedClaimMethod} so the
550
- * two transports can never drift: the ONLY difference is the uniform `Promise`
551
- * wrapper that statelessness forces. `claim({ id })` is identical (already async
552
- * on both); `state`/`queue`/`reorder`/`release` are the awaited form.
553
- */
554
- export type HttpClaimApi<T = Record<string, unknown>> = ((params: ClaimParams<T>) => Promise<HeldClaim<T>>) & {
555
- [K in keyof ClaimReadApi<T>]: AwaitedClaimMethod<ClaimReadApi<T>[K]>;
556
- };
557
- export interface ModelClient<T = Record<string, unknown>> {
558
- /**
559
- * Single-row read over HTTP. **Returns an envelope, not the bare row** — the
560
- * row is on `.data`, alongside the `.stamp` watermark (for stale-context
561
- * guards on the following write) and any active `.claims`. A stateless HTTP
562
- * client can't synthesize the watermark from a local snapshot, so the
563
- * envelope is load-bearing here (the WebSocket client's `retrieve` returns
564
- * `T | undefined` because it reads from the hydrated pool).
565
- *
566
- * ```ts
567
- * const deal = await ablo.deals.retrieve({ id });
568
- * deal.data?.recommendation; // ← the row is on .data
569
- * deal.stamp; // watermark — pass to the next write's readAt
570
- * ```
571
- */
572
- retrieve(params: ModelReadOptions & {
573
- readonly id: string;
574
- }): Promise<ModelRead<T>>;
575
- /**
576
- * Collection read over HTTP (server round-trip). Equality `where`, `orderBy`,
577
- * `limit`. Present on the stateless protocol client; the store-backed
578
- * `.model(name)` accessor omits it (use the typed `ablo.<model>.list` there).
579
- */
580
- list?(options?: ServerReadOptions<T>): Promise<T[]>;
581
- /**
582
- * Create a row and return it — the confirmed, authoritative server row (with
583
- * framework defaults like `createdAt`/`createdBy`), mirroring the WebSocket
584
- * client's `create`. A re-create of an existing caller-supplied id is
585
- * idempotent and returns the EXISTING row, not the input.
586
- */
587
- create(params: ModelMutationOptions & {
588
- readonly data: Record<string, unknown>;
589
- readonly id?: string | null;
590
- }): Promise<T>;
591
- update(params: ModelMutationOptions & {
592
- readonly id: string;
593
- readonly data: Record<string, unknown>;
594
- }): Promise<CommitReceipt>;
595
- /**
596
- * Update under contention with a function of the latest state —
597
- * `update(id, current => next)`, the `setState(prev => next)` of the data
598
- * layer. The SDK reads the freshest row, runs your updater, writes it as a
599
- * compare-and-swap against the row's watermark, and re-reads + re-runs on any
600
- * concurrent write. No claim, no identity, no conflict codes surface: the
601
- * write either lands or throws {@link AbloContentionError} once its reconcile
602
- * budget is spent. Return `null`/`undefined` from the updater to skip the
603
- * write (resolves to `undefined`).
604
- */
605
- update(id: string, updater: ModelUpdater<T>, options?: ContentionOptions): Promise<CommitReceipt | undefined>;
606
- delete(params: ModelMutationOptions & {
607
- readonly id: string;
608
- }): Promise<CommitReceipt>;
609
- /**
610
- * Durable lease + FIFO wait-line over HTTP — coordination without a socket.
611
- * Present on the stateless protocol client (`Ablo({ schema: null })` /
612
- * `createAbloHttpClient`); the store-backed `.model(name)` accessor omits it
613
- * (the typed `ablo.<model>.claim` proxy is the full reactive namespace there).
614
- */
615
- claim?: HttpClaimApi<T>;
616
- }
617
- /** A single data operation a scoped **agent** session may perform on a model. */
618
- export type SessionOperation = 'read' | 'create' | 'update' | 'delete';
619
- /** Mint params for an **end-user** session — full data authority within the
620
- * org (the Stripe `ephemeralKeys.create` / Supabase session shape). Mints an
621
- * `ek_` token. `user.id` is your end user's external IdP id (becomes the
622
- * session's `participantId`); Ablo does not model your users, so it's an
623
- * honest string at the trust boundary. */
624
- export interface CreateUserSessionParams {
625
- /** Your end user. `id` becomes the token's `participantId`. */
626
- user: {
627
- id: string;
628
- };
629
- /** Mint the session into THIS organization instead of the key's own org — the
630
- * Stripe Connect `Stripe-Account` pattern, for a platform serving many tenants
631
- * from one backend. Requires the `sk_` to carry the `ephemeral:mint-any-org`
632
- * scope; omit for the normal single-tenant case. */
633
- organizationId?: string;
634
- /** Sync groups this session may subscribe to — typed (`'default'` or
635
- * `<namespace>:<id>`; build with `syncGroup(kind, id)` from
636
- * `@abloatai/ablo/schema`). Omit for the server default:
637
- * `[org:<your org>, user:<user.id>]`. */
638
- syncGroups?: readonly SyncGroupInput[];
639
- /** Token lifetime in seconds. Defaults to 900 (15m, the Stripe ephemeral default). */
640
- ttlSeconds?: number;
641
- /** Opaque identity blob echoed back to the client as `ablo.user`. */
642
- userMeta?: Record<string, unknown>;
643
- agent?: never;
644
- can?: never;
645
- }
646
- /** Mint params for a scoped **agent** session — mints a restricted `rk_` token
647
- * gated to exactly the operations named in `can`. `can` is typed off your
648
- * schema (no magic `'task.update'` strings): `{ Task: ['update'], Deck: ['read'] }`
649
- * — the SDK serializes each entry to the wire allowlist (`task.update`). */
650
- export interface CreateAgentSessionParams<S extends SchemaRecord> {
651
- /** Your agent. `id` becomes the token's `participantId`. */
652
- agent: {
653
- id: string;
654
- };
655
- /** Per-model operation allowlist, typed against the schema's model names. */
656
- can: {
657
- [M in keyof S & string]?: readonly SessionOperation[];
658
- };
659
- /** Sync groups this session may subscribe to — typed (`'default'` or
660
- * `<namespace>:<id>`; build with `syncGroup(kind, id)` from
661
- * `@abloatai/ablo/schema`). Omit for the server default: the org
662
- * anchor (`org:<your org>`) + the agent's own anchor. */
663
- syncGroups?: readonly SyncGroupInput[];
664
- /** Token lifetime in seconds. Defaults to 900 (15m, the Stripe ephemeral default). */
665
- ttlSeconds?: number;
666
- /** Opaque identity blob echoed back to the client as `ablo.agent`. */
667
- userMeta?: Record<string, unknown>;
668
- user?: never;
669
- }
670
- /** Params for {@link Ablo.sessions}.create — a discriminated union: pass
671
- * `{ user }` for a full-authority end-user session (`ek_`) or `{ agent, can }`
672
- * for a scoped agent session (`rk_`). */
673
- export type CreateSessionParams<S extends SchemaRecord> = CreateUserSessionParams | CreateAgentSessionParams<S>;
674
- /** Params for {@link Ablo.agents}.create — a flattened agent descriptor (no
675
- * `{ agent }` discriminator: `agents.create` only ever mints an agent). Unlike
676
- * {@link CreateSessionParams} it resolves to a connected, scoped {@link Ablo}
677
- * client rather than a raw token. */
678
- export interface CreateAgentClientParams<S extends SchemaRecord> {
679
- /** Wire participant identity (`agent:<id>`) — what claim exclusion and the
680
- * FIFO queue gate on. OMIT to get a fresh `crypto.randomUUID()`: a distinct,
681
- * independent participant (the default, and what you want for concurrent
682
- * agents). Pass a STABLE string only when one logical agent must re-attach
683
- * to its own held claims across reconnects/restarts. */
684
- id?: string;
685
- /** Human-readable label for logs / attribution (carried in `userMeta.name`).
686
- * INDEPENDENT of `id`: two agents that share a `name` still receive distinct
687
- * ids and coordinate as SEPARATE participants — `name` never derives or
688
- * collapses identity. */
689
- name?: string;
690
- /** Per-model operation allowlist, typed against the schema's model names. */
691
- can: {
692
- [M in keyof S & string]?: readonly SessionOperation[];
693
- };
694
- /** Sync groups this agent may subscribe to — typed (`'default'` or
695
- * `<namespace>:<id>`). Omit for the server default (org anchor + the
696
- * agent's own anchor). */
697
- syncGroups?: readonly SyncGroupInput[];
698
- /** Token lifetime in seconds. Defaults to 900 (15m); the returned client
699
- * auto-re-mints before expiry, so a long-running agent never handles
700
- * rotation itself. */
701
- ttlSeconds?: number;
702
- /** Extra opaque identity blob echoed on the session scope. Merged with
703
- * `name` (the `name` param wins if you also set `userMeta.name`). */
704
- userMeta?: Record<string, unknown>;
705
- }
706
- /** A minted session token — the Stripe ephemeral-key / Supabase session
707
- * resource. `token` is the secret the holder presents as its bearer. */
708
- export interface AbloSession {
709
- object: 'session';
710
- /** Stable id of the minted credential (for revocation). */
711
- id: string;
712
- /** The short-lived session token — `ek_` for a `{ user }` session, `rk_`
713
- * for an `{ agent }` session. Hand this to the participant's runtime. */
714
- token: string;
715
- /** ISO-8601 expiry. */
716
- expiresAt: string;
717
- organizationId: string;
718
- scope: {
719
- organizationId: string;
720
- syncGroups: readonly string[];
721
- operations: readonly string[];
722
- participantKind: 'user' | 'agent' | 'system';
723
- participantId: string;
724
- };
725
- userMeta: Record<string, unknown>;
726
- }
31
+ import type { AbloOptions } from './options.js';
32
+ import type { AbloSession, CommitResource, CreateAgentClientParams, CreateSessionParams, ModelClient } from './resourceTypes.js';
33
+ export type { ApiKeySetter, AbloOptions, InternalAbloOptions } from './options.js';
34
+ export type { LocalCountOptions, LocalReadOptions, ModelListScope, ServerReadOptions, ModelRetrieveParams, ModelCreateParams, ModelUpdateParams, ModelDeleteParams, ClaimOptions, ClaimParams, ClaimLookupParams, ClaimReorderParams, Claim, ClaimHeartbeat, ClaimHeartbeatOptions, HeldClaim, ModelOperations, ModelOperationAction, CommitWait, ModelRead, IfClaimedPolicy, ClaimedOptions, ClaimWaitOptions, ModelReadOptions, ClaimCreateOptions, CommitOperationInput, CommitCreateOptions, CommitReceipt, CommitResource, ClaimResource, ModelMutationOptions, HttpClaimApi, ModelClient, SessionOperation, CreateUserSessionParams, CreateAgentSessionParams, CreateSessionParams, CreateAgentClientParams, AbloSession, } from './resourceTypes.js';
35
+ export { computeFKDepthPriority } from './schemaConfig.js';
36
+ import type { ModelOperations } from './createModelProxy.js';
727
37
  /** The typed sync engine client — one property per model in the schema */
728
38
  export type Ablo<S extends SchemaRecord> = {
729
39
  readonly [K in keyof S & string]: ModelOperations<InferModel<Schema<S>, K>, InferCreate<Schema<S>, K>>;
@@ -768,31 +78,32 @@ export type Ablo<S extends SchemaRecord> = {
768
78
  /** Disconnect and clean up */
769
79
  dispose(): Promise<void>;
770
80
  /**
771
- * Replace the bearer auth token used for the WebSocket upgrade and HTTP
772
- * requests, WITHOUT tearing down the engine. Use to push a refreshed
773
- * short-lived access key (the Stripe-style `ek_`/`rk_`) before it expires —
774
- * the client's `apiKey`-resolver refresh loop calls this. Reuses the same
775
- * rotation path as the internal capability-token refresh; safe to call before
776
- * `ready()`. Also nudges a parked connection to re-probe with the new token.
81
+ * Replace the bearer token used for the WebSocket upgrade and HTTP requests,
82
+ * without tearing down the engine. Use it to push a refreshed short-lived
83
+ * access key (an `ek_` or `rk_`) before it expires — the client's `apiKey`
84
+ * resolver refresh loop calls this for you. It reuses the same rotation path as
85
+ * the internal capability-token refresh and is safe to call before `ready()`.
86
+ * It also nudges a parked connection to re-probe with the new token.
777
87
  */
778
88
  setAuthToken(token: string): void;
779
89
  /**
780
90
  * Resolve the active bearer credential this engine authenticates with — the
781
- * live `ek_`/`rk_` the WebSocket and HTTP transports currently carry (kept
782
- * fresh by the `apiKey`-resolver refresh loop), falling back to a configured
91
+ * live `ek_` or `rk_` the WebSocket and HTTP transports currently carry (kept
92
+ * fresh by the `apiKey` resolver refresh loop), falling back to a configured
783
93
  * API key. Returns `null` when no credential is set yet. Use it to authenticate
784
- * a side-band request to the same server with the very token this client
785
- * already holds no extra mint round-trip.
94
+ * a side-band request to the same server with the token this client already
95
+ * holds, avoiding an extra mint round-trip.
786
96
  */
787
97
  getAuthToken(): Promise<string | null>;
788
98
  /**
789
- * Register a re-mint hook for the short-lived access key. The connection
790
- * layer calls it WHEN it finds the key stale (a `credential_stale` probe) or
791
- * on an external nudge; the hook mints a fresh `ek_`/`rk_` from the still-valid
792
- * login. Mirrors the `apiKey`-resolver contract: resolve a token, resolve
793
- * `null` when the login itself is gone ( sign out), or THROW on a transient
794
- * failure ( back off, never sign out). The client wires this automatically
795
- * from a function `apiKey`. Safe to call before `ready()`.
99
+ * Register a re-mint hook for the short-lived access key. The connection layer
100
+ * calls it when it finds the key stale (a `credential_stale` probe) or on an
101
+ * external nudge; the hook mints a fresh `ek_` or `rk_` from the still-valid
102
+ * login. It follows the same contract as the `apiKey` resolver: resolve a
103
+ * token, resolve `null` when the login itself is gone (which signs the user
104
+ * out), or throw on a transient failure (which backs off without signing out).
105
+ * The client wires this automatically from a function `apiKey`. Safe to call
106
+ * before `ready()`.
796
107
  */
797
108
  setCredentialRefresher(refresher: (() => Promise<string | null>) | null): void;
798
109
  /**
@@ -804,21 +115,19 @@ export type Ablo<S extends SchemaRecord> = {
804
115
  */
805
116
  nudgeReconnect(): void;
806
117
  /**
807
- * Mint a short-lived, scoped **session token** for one end user the
808
- * Stripe `ephemeralKeys.create` / Supabase session shape. Call this on YOUR
809
- * BACKEND (where the `sk_` secret key lives), then hand the returned
810
- * `token` to that user's browser (typically via a token route the browser's
811
- * `apiKey` resolver fetches). The browser presents it as the bearer; the sync-server verifies
812
- * it via `apiKeyProvider`.
813
- *
814
- * The browser must NEVER see the `sk_` key — only the per-user session token.
118
+ * Mint a short-lived, scoped session token for one end user. Call this on your
119
+ * backend, where the `sk_` secret key lives, then hand the returned `token` to
120
+ * that user's browser typically through a token route the browser's `apiKey`
121
+ * resolver fetches. The browser presents the token as its bearer, and the
122
+ * server verifies it. The browser must never see the `sk_` key, only the
123
+ * per-user session token.
815
124
  *
816
- * Pass `{ user: { id } }` for a full-authority end-user session (mints `ek_`,
817
- * `participantKind: 'user'` attribution, stored as `actor_kind` on the delta
818
- * row), or `{ agent: { id }, can: { tasks:
819
- * ['update'] } }` for a scoped agent session (mints `rk_`); `can` is typed
820
- * against your schema's model names. Always authenticates with the original
821
- * `sk_` — never the client's exchanged sync credential.
125
+ * Pass `{ user: { id } }` for a full-authority end-user session, which mints an
126
+ * `ek_` and attributes writes to a user (recorded as `actor_kind` on the delta
127
+ * row). Pass `{ agent: { id }, can: { tasks: ['update'] } }` for a scoped agent
128
+ * session, which mints an `rk_`; `can` is typed against your schema's model
129
+ * names. This always authenticates with the original `sk_`, never the client's
130
+ * exchanged sync credential.
822
131
  */
823
132
  sessions: {
824
133
  create(params: CreateSessionParams<S>): Promise<AbloSession>;
@@ -839,15 +148,16 @@ export type Ablo<S extends SchemaRecord> = {
839
148
  * await agent.dispose(); // when the agent is done
840
149
  * ```
841
150
  *
842
- * Server-side only (requires the `sk_` secret key, like `sessions.create`);
843
- * throws `AbloAuthenticationError` in the browser. The returned client holds
844
- * its own auto-refreshing `rk_`, so a long run never hits token expiry, and
845
- * the `sk_` never leaves this process. Each call is a DISTINCT participant by
846
- * default (omit `id` fresh uuid), so even two agents sharing a `name` queue
847
- * behind one another on a contended row — `name` is display only and never
848
- * collapses identity. Humans don't get a server-built client ship them a
849
- * token via `sessions.create({ user })`. Need the raw token for revocation,
850
- * or a stable re-attachable id? Use `sessions.create({ agent })` / pass `id`.
151
+ * Server-side only: it requires the `sk_` secret key (like `sessions.create`)
152
+ * and throws `AbloAuthenticationError` in the browser. The returned client
153
+ * holds its own auto-refreshing `rk_`, so a long run never hits token expiry,
154
+ * and the `sk_` never leaves this process. Each call is a distinct participant
155
+ * by default (omit `id` for a fresh uuid), so even two agents sharing a `name`
156
+ * queue behind one another on a contended row — `name` is display only and
157
+ * never collapses identity. Humans don't get a server-built client; ship them a
158
+ * token via `sessions.create({ user })`. If you need the raw token for
159
+ * revocation, or a stable re-attachable id, use `sessions.create({ agent })`
160
+ * or pass `id`.
851
161
  */
852
162
  agents: {
853
163
  create(params: CreateAgentClientParams<S>): Promise<Ablo<S>>;
@@ -935,14 +245,14 @@ export type Ablo<S extends SchemaRecord> = {
935
245
  /** The underlying schema */
936
246
  readonly schema: Schema<S>;
937
247
  /**
938
- * Real-time presence livestream — who else is connected on this
939
- * engine's sync groups, what they're doing, and a write surface for
940
- * announcing this user's own activity. Rides the engine's existing
941
- * WebSocket; opening a participant for presence does NOT open a
942
- * second socket. See `PresenceStream` in `types/streams.ts`.
248
+ * A real-time presence livestream — who else is connected on this engine's
249
+ * sync groups, what they're doing, and a write surface for announcing this
250
+ * user's own activity. It rides the engine's existing WebSocket; opening a
251
+ * participant for presence does not open a second socket. See
252
+ * {@link PresenceStream}.
943
253
  *
944
- * Stable reference for the engine's lifetime — the underlying
945
- * connection is rotated on `dispose()` but this object is the same.
254
+ * The reference is stable for the engine's lifetime — the underlying connection
255
+ * is rotated on `dispose()`, but this object stays the same.
946
256
  */
947
257
  readonly presence: PresenceStream;
948
258
  /**
@@ -960,7 +270,7 @@ export type Ablo<S extends SchemaRecord> = {
960
270
  * Capture a context-staleness watermark over a set of entities.
961
271
  * Returns a flat snapshot with `stamp` (thread into writes as
962
272
  * `readAt`), `signal` (aborts on any captured-entity delta), and
963
- * `onChange` (callback form). Reads from the engine's ObjectPool;
273
+ * `onChange` (callback form). Reads from the engine's InstanceCache;
964
274
  * subscription is on the engine's existing transport.
965
275
  *
966
276
  * Use before an LLM call to prevent the model from completing
@@ -970,68 +280,21 @@ export type Ablo<S extends SchemaRecord> = {
970
280
  * await streamText({ messages, signal: snap.signal });
971
281
  * ```
972
282
  */
973
- snapshot<ModelName extends keyof S & string>(entities: {
974
- readonly [M in ModelName]: string | readonly string[];
975
- }): Snapshot<Schema<S>, ModelName>;
283
+ snapshot<ModelName extends keyof S & string>(entities: Readonly<Record<ModelName, string | readonly string[]>>): Snapshot<Schema<S>, ModelName>;
976
284
  /**
977
- * The internal BaseSyncedStore. Implements SyncStoreContract — pass to
978
- * SyncContext.Provider so the SDK's useModel/useModels/useMutations hooks
979
- * can access it. Also satisfies useSyncStore() consumers during migration.
285
+ * The internal store. It implements {@link SyncStoreContract} — pass it to
286
+ * `SyncContext.Provider` so the SDK's `useModel` / `useModels` / `useMutations`
287
+ * hooks can reach it.
980
288
  */
981
289
  readonly _store: SyncStoreContract;
982
- /** The ObjectPool — for demand loaders and direct pool operations. */
983
- readonly _pool: ObjectPool;
290
+ /** The InstanceCache — for demand loaders and direct pool operations. */
291
+ readonly _pool: InstanceCache;
984
292
  /**
985
293
  * The SyncWebSocket handle — for collaboration events (slide selection,
986
294
  * cursor broadcast). Null until the engine connects.
987
295
  */
988
296
  readonly _ws: SyncWebSocket | null;
989
297
  };
990
- /**
991
- * Compute a create-priority map from schema `belongsTo` relations using
992
- * Tarjan's strongly-connected-components algorithm.
993
- *
994
- * The FK graph has an edge `child → parent` for every `belongsTo`. Tarjan
995
- * runs a single linear DFS that simultaneously (a) detects cycles by
996
- * grouping mutually-reachable nodes into SCCs and (b) emits those SCCs
997
- * in reverse topological order of the condensation graph. In this edge
998
- * convention a "sink" SCC has no outgoing edges — i.e. no parents — so
999
- * it is an *FK root* (`organizations`, `themes`, etc.). Tarjan emits
1000
- * roots first and leaves last, exactly the order in which rows must be
1001
- * inserted to satisfy FK constraints.
1002
- *
1003
- * Priorities are assigned by emit order: SCC #0 → 10, SCC #1 → 20, …
1004
- * Members of the same SCC share a priority, so insertion order wins the
1005
- * tiebreak inside a cycle (this matters for cyclic schemas like
1006
- * `slideDecks ↔ layouts`, where one direction is the user's chosen
1007
- * "soft" edge — only the consumer's mutator sequence knows which one).
1008
- *
1009
- * This algorithm is iteration-order-independent: starting the DFS from
1010
- * any node yields the same SCC partitioning, and SCCs always come out
1011
- * in valid topological order. The previous DFS-with-memoization
1012
- * heuristic broke under cycles by treating the back-edge as depth 0,
1013
- * which made priorities depend on which node the walk happened to
1014
- * enter the cycle at.
1015
- *
1016
- * Schema authors can mark one side of a cycle with
1017
- * `belongsTo(target, fk, { defer: true })`. Those edges are excluded
1018
- * from the dependency graph entirely, which deterministically breaks
1019
- * the cycle and turns the SCC into a chain — the marked child gets a
1020
- * strictly higher priority than its parent instead of being tied with
1021
- * it. Pair with a Postgres `DEFERRABLE INITIALLY DEFERRED` constraint
1022
- * if you want the database side of the cycle to also relax. See
1023
- * {@link BelongsToOptions.defer}.
1024
- *
1025
- * The returned map is keyed by {@link ModelDef.typename} (falling back
1026
- * to the schema key), because that is what `Model.getModelName()`
1027
- * returns at transaction time — keying by schema key would silently
1028
- * miss the lookup and every model would fall through to
1029
- * `defaultCreatePriority`.
1030
- *
1031
- * Reference: Tarjan, R. (1972), "Depth-first search and linear graph
1032
- * algorithms." Linear in V + E.
1033
- */
1034
- export declare function computeFKDepthPriority(schema: Schema): ReadonlyMap<string, number>;
1035
298
  /**
1036
299
  * Create a sync engine client in one call.
1037
300
  *
@@ -1042,6 +305,14 @@ export declare function computeFKDepthPriority(schema: Schema): ReadonlyMap<stri
1042
305
  * await sync.weatherReports.create({ location: 'Stockholm', status: 'pending' });
1043
306
  * ```
1044
307
  *
308
+ * In the browser (or any client that shouldn't hold a secret key), point
309
+ * `authEndpoint` at your session-mint route instead — the SDK fetches it, keeps the
310
+ * short-lived token fresh, and re-mints on expiry:
311
+ *
312
+ * ```ts
313
+ * const ablo = Ablo({ schema, authEndpoint: '/api/ablo-session' });
314
+ * ```
315
+ *
1045
316
  * Pass `transport: 'http'` for the stateless server-side client (agents,
1046
317
  * workers, serverless) — same `ablo.<model>` surface, no socket:
1047
318
  *
@@ -1063,22 +334,20 @@ import type * as _Tx from '../mutators/Transaction.js';
1063
334
  import type * as _Undo from '../mutators/UndoManager.js';
1064
335
  import type * as _SchemaTypes from '../schema/schema.js';
1065
336
  /**
1066
- * Canonical type namespace.
1067
- *
1068
- * Locked rules — apply uniformly to every future addition:
337
+ * The canonical type namespace.
1069
338
  *
1070
- * 1. Flat by default. `Ablo.X`. Fewest dots wins.
1071
- * 2. Sub-namespace ONLY when (a) 4+ types share a single conceptual
1072
- * prefix, AND (b) names read better with the prefix (`Conflict.Kind`
1073
- * over `ConflictKind`). If the cluster is heterogeneous (streams +
1074
- * data + handles), keep flat.
1075
- * 3. Only types a consumer would write `: Ablo.X` for. Inferred-only
1076
- * types stay un-exported.
1077
- * 4. Wire shapes never on `Ablo.*`. Engine vocabulary only.
1078
- * 5. Advanced / framework-integration types stay internal unless they
1079
- * graduate into one of the public subpaths.
339
+ * Rules applied uniformly to every addition:
1080
340
  *
1081
- * Anything not on this list stays internal.
341
+ * 1. Flat by default. `Ablo.X`. Fewest dots wins.
342
+ * 2. Sub-namespace only when (a) four or more types share a single conceptual
343
+ * prefix and (b) the names read better with it (`Conflict.Kind` over
344
+ * `ConflictKind`). If the cluster is heterogeneous (streams, data, handles),
345
+ * keep it flat.
346
+ * 3. Only types a consumer would write `: Ablo.X` for. Inferred-only types stay
347
+ * unexported.
348
+ * 4. Wire shapes never appear on `Ablo.*` — engine vocabulary only.
349
+ * 5. Advanced or framework-integration types stay internal unless they graduate
350
+ * into one of the public subpaths.
1082
351
  */
1083
352
  export declare namespace Ablo {
1084
353
  type Options<S extends SchemaRecord = SchemaRecord> = AbloOptions<S>;
@@ -1091,8 +360,8 @@ export declare namespace Ablo {
1091
360
  type CapabilityRevocation = import('./ApiClient.js').CapabilityRevocation;
1092
361
  type CapabilityRotateOptions = import('./ApiClient.js').CapabilityRotateOptions;
1093
362
  type RotatedCapability = import('./ApiClient.js').RotatedCapability;
1094
- type IfClaimedPolicy = import('./Ablo.js').IfClaimedPolicy;
1095
- type ClaimedOptions = import('./Ablo.js').ClaimedOptions;
363
+ type IfClaimedPolicy = import('./resourceTypes.js').IfClaimedPolicy;
364
+ type ClaimedOptions = import('./resourceTypes.js').ClaimedOptions;
1096
365
  type ClaimTarget = _Streams.ClaimTarget;
1097
366
  type PresenceTarget = _Streams.PresenceTarget;
1098
367
  type TargetRange = _Streams.TargetRange;
@@ -1104,6 +373,8 @@ export declare namespace Ablo {
1104
373
  type Claim = _Streams.Claim;
1105
374
  type ClaimRejection = _Streams.ClaimRejection;
1106
375
  type ClaimLost = _Streams.ClaimLost;
376
+ type ClaimHeartbeat = _Streams.ClaimHeartbeat;
377
+ type ClaimHeartbeatOptions = _Streams.ClaimHeartbeatOptions;
1107
378
  type Snapshot<TSchema extends _SchemaTypes.Schema = _SchemaTypes.Schema, K extends keyof TSchema['models'] = keyof TSchema['models']> = _Streams.Snapshot<TSchema, K>;
1108
379
  namespace Auth {
1109
380
  type Actor = _Streams.ParticipantRef;
@@ -1130,26 +401,26 @@ export declare namespace Ablo {
1130
401
  type Axis = _Policy.ConflictAxis;
1131
402
  }
1132
403
  namespace Commit {
1133
- type Wait = import('./Ablo.js').CommitWait;
1134
- type OperationAction = import('./Ablo.js').ModelOperationAction;
1135
- type OperationInput = import('./Ablo.js').CommitOperationInput;
1136
- type CreateOptions = import('./Ablo.js').CommitCreateOptions;
1137
- type Receipt = import('./Ablo.js').CommitReceipt;
1138
- type Client = import('./Ablo.js').CommitResource;
404
+ type Wait = import('./resourceTypes.js').CommitWait;
405
+ type OperationAction = import('./resourceTypes.js').ModelOperationAction;
406
+ type OperationInput = import('./resourceTypes.js').CommitOperationInput;
407
+ type CreateOptions = import('./resourceTypes.js').CommitCreateOptions;
408
+ type Receipt = import('./resourceTypes.js').CommitReceipt;
409
+ type Client = import('./resourceTypes.js').CommitResource;
1139
410
  }
1140
411
  namespace Claim {
1141
- type Handle = import('./Ablo.js').Claim;
1142
- type CreateOptions = import('./Ablo.js').ClaimCreateOptions;
1143
- type WaitOptions = import('./Ablo.js').ClaimWaitOptions;
1144
- type Client = import('./Ablo.js').ClaimResource;
412
+ type Handle = import('./resourceTypes.js').Claim;
413
+ type CreateOptions = import('./resourceTypes.js').ClaimCreateOptions;
414
+ type WaitOptions = import('./resourceTypes.js').ClaimWaitOptions;
415
+ type Client = import('./resourceTypes.js').ClaimResource;
1145
416
  }
1146
417
  namespace Model {
1147
- type Target = import('./Ablo.js').ModelTarget;
1148
- type Claim = import('./Ablo.js').ModelClaim;
1149
- type Read<T = Record<string, unknown>> = import('./Ablo.js').ModelRead<T>;
1150
- type Client<T = Record<string, unknown>> = import('./Ablo.js').ModelClient<T>;
1151
- type ReadOptions = import('./Ablo.js').ModelReadOptions;
1152
- type MutationOptions = import('./Ablo.js').ModelMutationOptions;
418
+ type Target = import('./resourceTypes.js').ModelTarget;
419
+ type Claim = import('./resourceTypes.js').ModelClaim;
420
+ type Read<T = Record<string, unknown>> = import('./resourceTypes.js').ModelRead<T>;
421
+ type Client<T = Record<string, unknown>> = import('./resourceTypes.js').ModelClient<T>;
422
+ type ReadOptions = import('./resourceTypes.js').ModelReadOptions;
423
+ type MutationOptions = import('./resourceTypes.js').ModelMutationOptions;
1153
424
  }
1154
425
  namespace Source {
1155
426
  type Operation = import('../source/index.js').SourceOperation;