@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,39 +1,33 @@
1
1
  /**
2
- * Auth + URL resolution for `Ablo()`.
2
+ * Authentication and URL resolution for the `Ablo()` client.
3
3
  *
4
- * Mirrors the small, focused helpers Anthropic ships in `client.ts`
5
- * (`apiKeyAuth`, `bearerAuth`, `validateHeaders`). Each function does
6
- * one thing resolve a value with the right precedence, or fail
7
- * with an actionable message — so the constructor reads as a
8
- * sequence of named decisions rather than a stream of `??`-chains.
4
+ * Each function here makes one decision: it resolves a configuration value with
5
+ * the right precedence, or fails with an actionable message. Together they let
6
+ * the client constructor read as a sequence of named steps rather than a chain
7
+ * of fallbacks.
9
8
  *
10
- * Customer-facing env surface is intentionally small: `ABLO_API_KEY`
11
- * is the only environment fallback. Other routing/auth overrides are
12
- * explicit options so generated apps do not accrete hidden env knobs.
9
+ * The environment surface is deliberately small: `ABLO_API_KEY` is the only
10
+ * value read from the environment. Every other routing or authentication
11
+ * override is an explicit option, so an app never picks up hidden behavior from
12
+ * a stray environment variable.
13
13
  */
14
14
  /**
15
- * Async callable that resolves the current credential. Mirrors the shape
16
- * Anthropic / OpenAI / Stripe ship — used for credential rotation
17
- * (e.g. AWS STS, GCP IAM, Vault) AND the short-lived per-user browser
18
- * path (mint a fresh `ek_`/`rk_` from the signed-in session). Re-exported
19
- * from `./Ablo` so existing import paths work; defined here so this module
20
- * has no circular dependency back to `Ablo.ts`.
21
- *
22
- * Contract: resolve a token; resolve `null` when the login itself is gone
23
- * (terminal → the credential lifecycle treats this as `session_expired` and
24
- * signs out); or THROW on a transient failure (→ back off and retry, never
25
- * sign out). A long-lived static `apiKey` string needs none of this — it is
26
- * used as-is. This is the single credential resolver the SDK supports.
15
+ * The credential-resolver callable type. It is defined alongside
16
+ * {@link createEndpointCredentialResolver} in `./credentialEndpoint` and
17
+ * re-exported here so importers of this module keep working. See that module
18
+ * for the full contract.
27
19
  */
28
- export type ApiKeySetter = () => Promise<string | null>;
20
+ import type { ApiKeySetter } from './credentialEndpoint.js';
21
+ export type { ApiKeySetter };
29
22
  export interface AuthResolveInput {
30
23
  /**
31
- * The full options bag the caller passed to `Ablo()`. Resolvers
32
- * read only the fields they care about; the wide shape avoids
33
- * passing N parameters into each helper.
24
+ * The full set of options the caller passed to the client constructor. Each
25
+ * resolver reads only the fields it needs; passing the whole object avoids
26
+ * threading many separate parameters through every helper.
34
27
  */
35
28
  readonly options: {
36
29
  readonly apiKey?: string | ApiKeySetter | null;
30
+ readonly authEndpoint?: string | ApiKeySetter | null;
37
31
  readonly authToken?: string | null;
38
32
  readonly baseURL?: string | null;
39
33
  readonly databaseUrl?: string | null;
@@ -69,40 +63,41 @@ export interface CliKeyMismatch {
69
63
  readonly kind: 'mode_mismatch' | 'key_override';
70
64
  readonly message: string;
71
65
  }
72
- /** Infer sandbox/production from Ablo key prefixes without importing CLI code. */
66
+ /** Infer the sandbox or production mode from an Ablo key's prefix. */
73
67
  export declare function modeFromApiKey(key: string): CliMode | undefined;
74
68
  export declare function describeCliKeyMismatch(configured: StaticApiKey, cli: CliCredentialSnapshot): CliKeyMismatch | null;
75
69
  /**
76
- * Resolve the direct-URL connector's Postgres connection string.
70
+ * Resolves the Postgres connection string for the direct-connection option, or
71
+ * `null` when none was given.
77
72
  *
78
- * `databaseUrl` is an EXPLICIT, opt-in option: Ablo registers a dedicated
79
- * tenant database only when the caller passes it to `Ablo(...)`. It is NOT
80
- * read from `process.env.DATABASE_URL` per this module's invariant
81
- * (`ABLO_API_KEY` is the only environment fallback), an app's `DATABASE_URL`
82
- * (commonly set for Prisma/Drizzle/docker) must never silently flip the client
83
- * into connection-string mode. The default Data Source path keeps `DATABASE_URL`
84
- * in the app and exposes `dataSource(...)`; that path leaves this null.
85
- * `warnIfDatabaseUrlEnvIgnored` nudges callers who set the env but omitted the option.
73
+ * `databaseUrl` is opt-in: the client registers a dedicated database only when
74
+ * the caller passes it explicitly. It is never read from
75
+ * `process.env.DATABASE_URL`, because this module treats `ABLO_API_KEY` as the
76
+ * one environment fallback an app's `DATABASE_URL`, commonly set for other
77
+ * tools, must not silently switch the client into connection-string mode. The
78
+ * default path leaves `DATABASE_URL` untouched and reads through `dataSource(...)`
79
+ * instead, so this returns `null`. {@link warnIfDatabaseUrlEnvIgnored} nudges a
80
+ * caller who set the environment variable but omitted the option.
86
81
  */
87
82
  export declare function resolveDatabaseUrl(input: AuthResolveInput): string | null;
88
83
  export declare function warnIfDatabaseUrlEnvIgnored(input: AuthResolveInput, warn?: (message: string) => void): void;
89
84
  export declare function warnIfDatabaseUrlDeprecated(input: AuthResolveInput, warn?: (message: string) => void): void;
90
85
  export declare function warnIfCliKeyMismatch(input: AuthResolveInput, warn?: (message: string) => void): Promise<void>;
91
- export declare const ABLO_HOSTED_API_DOMAIN = "api.abloatai.com";
92
- export declare const ABLO_HOSTED_HTTP_BASE_URL = "https://api.abloatai.com";
93
- export declare const ABLO_DEFAULT_BASE_URL = "https://api.abloatai.com";
86
+ export { ABLO_HOSTED_API_DOMAIN, ABLO_HOSTED_HTTP_BASE_URL, ABLO_DEFAULT_BASE_URL } from './hostedEndpoints.js';
94
87
  /**
95
- * Normalize old hosted aliases to the public API domain. Self-hosted/custom
96
- * URLs pass through unchanged; only first-party legacy hosts are rewritten.
88
+ * Normalizes older hosted host names to the current public API domain.
89
+ * Self-hosted or custom URLs pass through unchanged; only the retired
90
+ * first-party host names are rewritten.
97
91
  */
98
92
  export declare function normalizeAbloHostedBaseUrl(rawUrl: string): string;
99
93
  export declare function resolveBaseURL(input: AuthResolveInput): string;
100
94
  /**
101
- * Browser guard apiKey is server-side-only by default. Same check
102
- * Anthropic, OpenAI, and Stripe ship: shipping `sk_live_...` to a
103
- * browser exposes it in every visitor's network tab. Consumers opt
104
- * in explicitly when the browser holds a minted session token
105
- * (`ek_`/`rk_`) or routes through a server proxy.
95
+ * Guards against using a secret `apiKey` in a browser. A secret key is
96
+ * server-side only by default: shipping an `sk_live_...` key to a browser would
97
+ * expose it in every visitor's network tab. Callers opt in explicitly when the
98
+ * browser instead holds a minted session token (`ek_`/`rk_`) or routes through a
99
+ * server proxy. Throws {@link AbloAuthenticationError} when a secret key is
100
+ * detected in a browser without opt-in.
106
101
  */
107
102
  export declare function assertBrowserSafety(input: {
108
103
  apiKey: string | ApiKeySetter | null;
@@ -110,27 +105,23 @@ export declare function assertBrowserSafety(input: {
110
105
  dangerouslyAllowBrowser: boolean | undefined;
111
106
  }): void;
112
107
  /**
113
- * Resolve an `ApiKeySetter` callable to its current string value.
114
- * Used at request time so a rotating credential picks up rotations
115
- * between requests. Returns `null` when no key was configured.
116
- *
117
- * Mirrors Anthropic's pattern of supporting both a static string and
118
- * a callable for credential rotation.
108
+ * Resolves an {@link ApiKeySetter} callable to its current string value, or
109
+ * returns a plain string key as-is. Called at request time so a rotating
110
+ * credential picks up new values between requests. Returns `null` when no key
111
+ * was configured.
119
112
  */
120
113
  export declare function resolveApiKeyValue(apiKey: string | ApiKeySetter | null): Promise<string | null>;
121
114
  /**
122
- * Translate a sync-engine WebSocket URL to the matching HTTP API
123
- * base URL, defaulting to `${url}/api` when the caller hasn't
124
- * overridden `bootstrapBaseUrl`. Used by `BootstrapHelper`,
125
- * `HydrationCoordinator`, the apiKey-exchange flow, and the
126
- * self-derived identity flow — same derivation in all four spots,
127
- * so it lives here as a single source of truth.
115
+ * Translates a WebSocket URL into the matching HTTP API base URL, defaulting to
116
+ * `${url}/api` when the caller has not overridden `bootstrapBaseUrl`. The
117
+ * bootstrap helper, the hydration coordinator, the credential-exchange flow, and
118
+ * the identity flow all derive their base URL through this one function, so the
119
+ * derivation stays consistent across them.
128
120
  *
129
- * Note: when both `wss://` and `https://` are valid, `replace(/^ws/, 'http')`
130
- * preserves the protocol family (ws http, wss https).
121
+ * When both `wss://` and `https://` are valid, the ws-to-http rewrite preserves
122
+ * the protocol family: ws becomes http and wss becomes https.
131
123
  */
132
124
  export declare function resolveBootstrapBaseUrl(input: {
133
125
  readonly url: string;
134
126
  readonly bootstrapBaseUrl?: string;
135
127
  }): string;
136
- export {};
@@ -1,18 +1,20 @@
1
1
  /**
2
- * Auth + URL resolution for `Ablo()`.
2
+ * Authentication and URL resolution for the `Ablo()` client.
3
3
  *
4
- * Mirrors the small, focused helpers Anthropic ships in `client.ts`
5
- * (`apiKeyAuth`, `bearerAuth`, `validateHeaders`). Each function does
6
- * one thing resolve a value with the right precedence, or fail
7
- * with an actionable message — so the constructor reads as a
8
- * sequence of named decisions rather than a stream of `??`-chains.
4
+ * Each function here makes one decision: it resolves a configuration value with
5
+ * the right precedence, or fails with an actionable message. Together they let
6
+ * the client constructor read as a sequence of named steps rather than a chain
7
+ * of fallbacks.
9
8
  *
10
- * Customer-facing env surface is intentionally small: `ABLO_API_KEY`
11
- * is the only environment fallback. Other routing/auth overrides are
12
- * explicit options so generated apps do not accrete hidden env knobs.
9
+ * The environment surface is deliberately small: `ABLO_API_KEY` is the only
10
+ * value read from the environment. Every other routing or authentication
11
+ * override is an explicit option, so an app never picks up hidden behavior from
12
+ * a stray environment variable.
13
13
  */
14
- import { AbloAuthenticationError } from '../errors.js';
14
+ import { AbloAuthenticationError, AbloValidationError } from '../errors.js';
15
15
  import { classifyCredentialKind } from '../auth/credentialPolicy.js';
16
+ import { ABLO_HOSTED_API_DOMAIN, ABLO_DEFAULT_BASE_URL } from './hostedEndpoints.js';
17
+ import { isCredentialEndpoint, createEndpointCredentialResolver } from './credentialEndpoint.js';
16
18
  /**
17
19
  * Read `process.env` defensively. Works in browser (where `process`
18
20
  * is undefined), Node, and edge runtimes that expose a partial
@@ -23,7 +25,36 @@ export function readProcessEnv() {
23
25
  return maybeGlobal.process?.env ?? {};
24
26
  }
25
27
  export function resolveApiKey(input) {
26
- return input.options.apiKey ?? input.env.ABLO_API_KEY ?? null;
28
+ // `authEndpoint` is the option that names a session-mint route: a URL the
29
+ // client exchanges for a short-lived token, or an async resolver for custom
30
+ // exchanges. It is resolved into an `ApiKeySetter` here — the single point
31
+ // shared by every client variant (WebSocket, HTTP, and protocol clients) — so
32
+ // every downstream consumer sees the same resolver and the credential
33
+ // lifecycle drives renewal off it.
34
+ const endpoint = input.options.authEndpoint;
35
+ const configured = input.options.apiKey;
36
+ if (endpoint != null) {
37
+ if (configured != null) {
38
+ throw new AbloValidationError('Ablo: pass either `apiKey` (a key the process holds) or `authEndpoint` ' +
39
+ '(a route that mints the token) — not both; the client cannot know ' +
40
+ 'which credential to use.', { code: 'invalid_options', param: 'authEndpoint' });
41
+ }
42
+ if (typeof endpoint === 'function')
43
+ return endpoint;
44
+ if (!isCredentialEndpoint(endpoint)) {
45
+ throw new AbloValidationError('`authEndpoint` expects a URL or path (e.g. \'/api/ablo-session\') or an ' +
46
+ 'async resolver — a key string belongs in `apiKey`.', { code: 'invalid_options', param: 'authEndpoint' });
47
+ }
48
+ return createEndpointCredentialResolver(endpoint);
49
+ }
50
+ // `apiKey` also accepts the endpoint-string form directly, detected the same
51
+ // way — key strings are prefixed (`sk_`/`ek_`/`rk_`), so the two shapes never
52
+ // collide. Only the explicit option is treated this way: an `ABLO_API_KEY`
53
+ // environment value is always a literal key, never an endpoint.
54
+ if (typeof configured === 'string' && isCredentialEndpoint(configured)) {
55
+ return createEndpointCredentialResolver(configured);
56
+ }
57
+ return configured ?? input.env.ABLO_API_KEY ?? null;
27
58
  }
28
59
  export function resolveAuthToken(input) {
29
60
  return input.options.authToken ?? null;
@@ -31,7 +62,7 @@ export function resolveAuthToken(input) {
31
62
  function keyPrefix(key) {
32
63
  return `${key.slice(0, 12)}…`;
33
64
  }
34
- /** Infer sandbox/production from Ablo key prefixes without importing CLI code. */
65
+ /** Infer the sandbox or production mode from an Ablo key's prefix. */
35
66
  export function modeFromApiKey(key) {
36
67
  if (/^(sk|rk)_test_/.test(key))
37
68
  return 'sandbox';
@@ -41,6 +72,10 @@ export function modeFromApiKey(key) {
41
72
  }
42
73
  function resolveStaticApiKey(input) {
43
74
  if (typeof input.options.apiKey === 'string') {
75
+ // An endpoint-string `apiKey` is not a key — it never participates in
76
+ // CLI-mode mismatch checks (its minted tokens carry the mode instead).
77
+ if (isCredentialEndpoint(input.options.apiKey))
78
+ return null;
44
79
  return { key: input.options.apiKey, source: 'option' };
45
80
  }
46
81
  if (input.options.apiKey !== undefined && input.options.apiKey !== null) {
@@ -189,39 +224,38 @@ export function describeCliKeyMismatch(configured, cli) {
189
224
  return null;
190
225
  }
191
226
  /**
192
- * Resolve the direct-URL connector's Postgres connection string.
227
+ * Resolves the Postgres connection string for the direct-connection option, or
228
+ * `null` when none was given.
193
229
  *
194
- * `databaseUrl` is an EXPLICIT, opt-in option: Ablo registers a dedicated
195
- * tenant database only when the caller passes it to `Ablo(...)`. It is NOT
196
- * read from `process.env.DATABASE_URL` per this module's invariant
197
- * (`ABLO_API_KEY` is the only environment fallback), an app's `DATABASE_URL`
198
- * (commonly set for Prisma/Drizzle/docker) must never silently flip the client
199
- * into connection-string mode. The default Data Source path keeps `DATABASE_URL`
200
- * in the app and exposes `dataSource(...)`; that path leaves this null.
201
- * `warnIfDatabaseUrlEnvIgnored` nudges callers who set the env but omitted the option.
230
+ * `databaseUrl` is opt-in: the client registers a dedicated database only when
231
+ * the caller passes it explicitly. It is never read from
232
+ * `process.env.DATABASE_URL`, because this module treats `ABLO_API_KEY` as the
233
+ * one environment fallback an app's `DATABASE_URL`, commonly set for other
234
+ * tools, must not silently switch the client into connection-string mode. The
235
+ * default path leaves `DATABASE_URL` untouched and reads through `dataSource(...)`
236
+ * instead, so this returns `null`. {@link warnIfDatabaseUrlEnvIgnored} nudges a
237
+ * caller who set the environment variable but omitted the option.
202
238
  */
203
239
  export function resolveDatabaseUrl(input) {
204
240
  return input.options.databaseUrl ?? null;
205
241
  }
206
242
  /**
207
- * One-time migration nudge for the dropped `DATABASE_URL` env fallback.
243
+ * Warns once when `DATABASE_URL` is set in the environment but `databaseUrl` was
244
+ * not passed as an option.
208
245
  *
209
- * Earlier versions silently adopted `process.env.DATABASE_URL` when `databaseUrl`
210
- * was not passed, registering a direct connector behind the caller's back — which
211
- * surprised any app that keeps `DATABASE_URL` for another tool (Prisma, Drizzle,
212
- * docker-compose) and, on localhost, tried to register a database Ablo's cloud
213
- * cannot reach. The env value is now ignored; this points the developer at the
214
- * explicit option instead of flipping their mode for them. Warns once per process
215
- * so it never spams, and falls back to `console.warn` when no logger is supplied
216
- * (the `transport: 'api'` client has none).
246
+ * The client does not adopt `process.env.DATABASE_URL` on its own, because that
247
+ * value is commonly set for other tools and switching the client into
248
+ * connection-string mode behind the caller's back is surprising and on
249
+ * localhost it would try to register a database the hosted service cannot reach.
250
+ * This warning points the developer at the explicit option instead. It fires at
251
+ * most once per process and falls back to `console.warn` when no logger is
252
+ * supplied.
217
253
  *
218
- * Suppressed entirely on the hosted/token path: if an `apiKey` resolves (option
219
- * or `ABLO_API_KEY` env), the caller has chosen the hosted capability-token /
220
- * Data Source transport, which is mutually exclusive with direct `databaseUrl`
221
- * mode. A `DATABASE_URL` sitting in that environment is unrelated infra (Prisma,
222
- * Drizzle, the sync-server) — never an omitted option — so nudging would be a
223
- * false positive. This is the first-party hosted app's exact shape, where the
224
- * stray nudge otherwise reaches end-user desktop logs.
254
+ * The warning is skipped entirely when an `apiKey` resolves (from the option or
255
+ * `ABLO_API_KEY`): that caller has chosen the hosted, token-based transport,
256
+ * which is separate from the direct `databaseUrl` connection. A `DATABASE_URL`
257
+ * present in that environment belongs to unrelated infrastructure, not an omitted
258
+ * option, so warning would be a false positive.
225
259
  */
226
260
  let warnedDatabaseUrlEnvIgnored = false;
227
261
  export function warnIfDatabaseUrlEnvIgnored(input, warn) {
@@ -246,19 +280,18 @@ export function warnIfDatabaseUrlEnvIgnored(input, warn) {
246
280
  console.warn('[Ablo]', message);
247
281
  }
248
282
  /**
249
- * One-time deprecation nudge for the `databaseUrl` direct connector.
283
+ * Warns once when the deprecated `databaseUrl` option is used.
250
284
  *
251
- * `databaseUrl` registers the `dedicated` storage mode Ablo opens a pool INTO
252
- * the caller's Postgres and writes into it directly. That is the operate-their-
253
- * database posture we are moving off. Ablo is Stripe-shaped: it hosts only the
254
- * transaction log (the ordered sync_deltas) + coordination, never your data your
255
- * rows always live in your own database. The supported path is the signed Data
256
- * Source endpoint (`dataSource(...)`), where your app owns the write and your
257
- * credentials never leave it. See docs/plans/stripe-shaped-storage-posture.md.
285
+ * Passing `databaseUrl` opens a connection pool directly into your Postgres and
286
+ * writes to it. That option is deprecated. Ablo is designed to host only the
287
+ * ordered transaction log (the `sync_deltas` table) and coordination state,
288
+ * never your rows your data stays in your own database. The supported path is
289
+ * a signed data-source endpoint (`dataSource(...)`), where your app owns the
290
+ * write and your database credentials never leave it.
258
291
  *
259
- * Still honored at runtime so existing integrations keep working; this only warns
260
- * once per process (so it never spams) and falls back to `console.warn` when no
261
- * logger is supplied (the `transport: 'http'`/`'api'` client has none).
292
+ * The option still works at runtime so existing integrations keep running. This
293
+ * warning fires at most once per process and falls back to `console.warn` when
294
+ * no logger is supplied.
262
295
  */
263
296
  let warnedDatabaseUrlDeprecated = false;
264
297
  export function warnIfDatabaseUrlDeprecated(input, warn) {
@@ -299,9 +332,9 @@ export async function warnIfCliKeyMismatch(input, warn) {
299
332
  else if (typeof console !== 'undefined')
300
333
  console.warn('[Ablo]', mismatch.message);
301
334
  }
302
- export const ABLO_HOSTED_API_DOMAIN = 'api.abloatai.com';
303
- export const ABLO_HOSTED_HTTP_BASE_URL = `https://${ABLO_HOSTED_API_DOMAIN}`;
304
- export const ABLO_DEFAULT_BASE_URL = `https://${ABLO_HOSTED_API_DOMAIN}`;
335
+ // Declared in `./hostedEndpoints`, the single source of the hosted domain, and
336
+ // re-exported here so existing import paths keep working.
337
+ export { ABLO_HOSTED_API_DOMAIN, ABLO_HOSTED_HTTP_BASE_URL, ABLO_DEFAULT_BASE_URL } from './hostedEndpoints.js';
305
338
  const LEGACY_HOSTED_API_HOSTS = new Set([
306
339
  'mesh.ablo.finance',
307
340
  'mesh-staging.ablo.finance',
@@ -309,29 +342,29 @@ const LEGACY_HOSTED_API_HOSTS = new Set([
309
342
  'sync-staging.ablo.finance',
310
343
  ]);
311
344
  /**
312
- * Normalize old hosted aliases to the public API domain. Self-hosted/custom
313
- * URLs pass through unchanged; only first-party legacy hosts are rewritten.
345
+ * Normalizes older hosted host names to the current public API domain.
346
+ * Self-hosted or custom URLs pass through unchanged; only the retired
347
+ * first-party host names are rewritten.
314
348
  */
315
349
  export function normalizeAbloHostedBaseUrl(rawUrl) {
316
350
  const trimmed = rawUrl.trim();
317
351
  if (!trimmed)
318
352
  return trimmed;
319
- // A scheme-less value (e.g. `api-staging.abloatai.com`) is a RELATIVE URL:
320
- // `new URL()` throws on it, and downstream `fetch` then resolves it against
321
- // the current page — producing `https://<app-host>/<route>/api-staging…/api/
322
- // auth/identity`, a 404 from the app's own origin. Prepend a scheme so the
323
- // base is absolute. `https` mirrors `ABLO_HOSTED_HTTP_BASE_URL`; the socket
324
- // layer derives `wss` from it. An existing scheme (ws/wss/http/https) is
325
- // preserved untouched.
353
+ // A scheme-less value (e.g. `api-staging.abloatai.com`) is treated as a
354
+ // relative URL: `new URL()` throws on it, and a later `fetch` would resolve it
355
+ // against the current page — producing a 404 from the app's own origin.
356
+ // Prepending a scheme makes the base absolute. `https` matches
357
+ // {@link ABLO_HOSTED_HTTP_BASE_URL}; the socket layer derives `wss` from it.
358
+ // An existing scheme (ws, wss, http, or https) is preserved untouched.
326
359
  const schemed = /^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
327
360
  try {
328
361
  const url = new URL(schemed);
329
- // Canonicalize the scheme to the HTTP family the WHATWG WebSocket
330
- // model: accept all four schemes (`http`/`https`/`ws`/`wss`), normalize
331
- // ONCE at the entry point, and let each layer derive its own protocol
332
- // (the socket layer maps http→ws / https→wss; fetch uses it as-is).
333
- // Before this, a `ws://` baseURL reached HTTP consumers un-normalized
334
- // and the client wedged at startup instead of connecting.
362
+ // Canonicalize the scheme to the HTTP family: accept all four schemes
363
+ // (http, https, ws, wss), normalize at this single entry point, and let
364
+ // each layer derive its own protocol (the socket layer maps http to ws and
365
+ // https to wss; fetch uses the URL as-is). Without this, a `ws://` base URL
366
+ // reaches HTTP consumers un-normalized and the client fails at startup
367
+ // instead of connecting.
335
368
  if (url.protocol === 'ws:')
336
369
  url.protocol = 'http:';
337
370
  if (url.protocol === 'wss:')
@@ -352,11 +385,12 @@ export function resolveBaseURL(input) {
352
385
  return normalizeAbloHostedBaseUrl(input.options.baseURL ?? ABLO_DEFAULT_BASE_URL);
353
386
  }
354
387
  /**
355
- * Browser guard apiKey is server-side-only by default. Same check
356
- * Anthropic, OpenAI, and Stripe ship: shipping `sk_live_...` to a
357
- * browser exposes it in every visitor's network tab. Consumers opt
358
- * in explicitly when the browser holds a minted session token
359
- * (`ek_`/`rk_`) or routes through a server proxy.
388
+ * Guards against using a secret `apiKey` in a browser. A secret key is
389
+ * server-side only by default: shipping an `sk_live_...` key to a browser would
390
+ * expose it in every visitor's network tab. Callers opt in explicitly when the
391
+ * browser instead holds a minted session token (`ek_`/`rk_`) or routes through a
392
+ * server proxy. Throws {@link AbloAuthenticationError} when a secret key is
393
+ * detected in a browser without opt-in.
360
394
  */
361
395
  export function assertBrowserSafety(input) {
362
396
  const inBrowser = typeof window !== 'undefined';
@@ -371,9 +405,9 @@ export function assertBrowserSafety(input) {
371
405
  '`dangerouslyAllowBrowser` option to `true`, e.g.,\n\n' +
372
406
  ' Ablo({ schema, apiKey, dangerouslyAllowBrowser: true });\n', { code: 'browser_apikey_blocked' });
373
407
  }
374
- // `databaseUrl` carries DB credentials and is NEVER browser-safe, so
375
- // `dangerouslyAllowBrowser` does not override it. Register your database from
376
- // a server-side runtime.
408
+ // `databaseUrl` carries database credentials and is never browser-safe, so
409
+ // `dangerouslyAllowBrowser` does not override this check. Register your
410
+ // database from a server-side runtime.
377
411
  if (inBrowser && typeof input.databaseUrl === 'string' && input.databaseUrl.length > 0) {
378
412
  throw new AbloAuthenticationError('Ablo `databaseUrl` cannot be used in a browser-like environment — it ' +
379
413
  'carries your database credentials. Initialize the client with ' +
@@ -381,12 +415,10 @@ export function assertBrowserSafety(input) {
381
415
  }
382
416
  }
383
417
  /**
384
- * Resolve an `ApiKeySetter` callable to its current string value.
385
- * Used at request time so a rotating credential picks up rotations
386
- * between requests. Returns `null` when no key was configured.
387
- *
388
- * Mirrors Anthropic's pattern of supporting both a static string and
389
- * a callable for credential rotation.
418
+ * Resolves an {@link ApiKeySetter} callable to its current string value, or
419
+ * returns a plain string key as-is. Called at request time so a rotating
420
+ * credential picks up new values between requests. Returns `null` when no key
421
+ * was configured.
390
422
  */
391
423
  export async function resolveApiKeyValue(apiKey) {
392
424
  if (apiKey == null)
@@ -396,44 +428,39 @@ export async function resolveApiKeyValue(apiKey) {
396
428
  return apiKey;
397
429
  }
398
430
  /**
399
- * Translate a sync-engine WebSocket URL to the matching HTTP API
400
- * base URL, defaulting to `${url}/api` when the caller hasn't
401
- * overridden `bootstrapBaseUrl`. Used by `BootstrapHelper`,
402
- * `HydrationCoordinator`, the apiKey-exchange flow, and the
403
- * self-derived identity flow — same derivation in all four spots,
404
- * so it lives here as a single source of truth.
431
+ * Translates a WebSocket URL into the matching HTTP API base URL, defaulting to
432
+ * `${url}/api` when the caller has not overridden `bootstrapBaseUrl`. The
433
+ * bootstrap helper, the hydration coordinator, the credential-exchange flow, and
434
+ * the identity flow all derive their base URL through this one function, so the
435
+ * derivation stays consistent across them.
405
436
  *
406
- * Note: when both `wss://` and `https://` are valid, `replace(/^ws/, 'http')`
407
- * preserves the protocol family (ws http, wss https).
437
+ * When both `wss://` and `https://` are valid, the ws-to-http rewrite preserves
438
+ * the protocol family: ws becomes http and wss becomes https.
408
439
  */
409
440
  export function resolveBootstrapBaseUrl(input) {
410
441
  if (input.bootstrapBaseUrl) {
411
- // Coerce ws/wss http/https on the override path too. This base URL is
412
- // used for HTTP fetches (identity resolve, apiKey exchange, bootstrap) and
413
- // the browser `fetch` rejects ws/wss schemes outright ("URL scheme \"wss\"
414
- // is not supported"). apps/web derives this override as `${baseUrl}/api`
415
- // where `baseUrl` may carry a WebSocket scheme, so the override can
416
- // legitimately arrive as `wss://…` normalize it here rather than
417
- // faceplanting at fetch time. The derive branch below already does this;
418
- // the override branch silently skipped it.
442
+ // Coerce ws/wss to http/https on the override path as well. This base URL is
443
+ // used for HTTP fetches (identity resolution, credential exchange, and
444
+ // bootstrap), and the browser `fetch` rejects ws and wss schemes outright.
445
+ // The override can legitimately arrive with a WebSocket scheme when a caller
446
+ // derives it as `${baseUrl}/api` from a WebSocket base URL, so normalize it
447
+ // here rather than failing at fetch time.
419
448
  return ensureApiSuffix(normalizeAbloHostedBaseUrl(input.bootstrapBaseUrl).replace(/^ws/, 'http'));
420
449
  }
421
450
  const url = normalizeAbloHostedBaseUrl(input.url);
422
451
  return ensureApiSuffix(url.replace(/^ws/, 'http'));
423
452
  }
424
453
  /**
425
- * Guarantee the HTTP base ends in the `/api` route segment the sync-server
426
- * mounts every endpoint under (`apps/sync-server/src/index.ts` — `app.route('/api', …)`).
454
+ * Ensures the HTTP base ends in the `/api` route segment that every endpoint is
455
+ * mounted under.
427
456
  *
428
- * The derive branch always appended `/api`; the override branch did NOT,
429
- * trusting the caller (apps/web passes `${baseUrl}/api`). But a hosted
430
- * customer setting a custom `baseURL`/`bootstrapBaseUrl` (their own subdomain,
431
- * staging, etc.) without the suffix sent every credential exchange to
432
- * `…/auth/capability` instead of `…/api/auth/capability` a 404 surfaced as
433
- * `exchange_failed`. Since the SDK hardcodes routes relative to this base and
434
- * there is no valid Ablo deployment that serves them off the root, normalizing
435
- * to a single trailing `/api` here is always correct — and idempotent for
436
- * callers who already include it.
457
+ * A hosted deployment that sets a custom `baseURL` or `bootstrapBaseUrl` (a
458
+ * custom subdomain, a staging host, and so on) without the `/api` suffix would
459
+ * send every credential exchange to `…/auth/capability` instead of
460
+ * `…/api/auth/capability`, producing a 404 that surfaces as `exchange_failed`.
461
+ * Since the client builds routes relative to this base and no valid deployment
462
+ * serves them from the root, appending a single trailing `/api` here is always
463
+ * correct, and it is idempotent for callers who already include it.
437
464
  */
438
465
  function ensureApiSuffix(httpBase) {
439
466
  const trimmed = httpBase.replace(/\/+$/, '');
@@ -446,8 +473,8 @@ function ensureApiSuffix(httpBase) {
446
473
  return u.toString().replace(/\/+$/, '');
447
474
  }
448
475
  catch {
449
- // Should be unreachable post-`normalizeAbloHostedBaseUrl` (which yields an
450
- // absolute URL), but fall back to a string check rather than throwing.
451
- return /\/api$/.test(trimmed) ? trimmed : `${trimmed}/api`;
476
+ // Should be unreachable after `normalizeAbloHostedBaseUrl`, which yields an
477
+ // absolute URL, but fall back to a string check rather than throwing.
478
+ return trimmed.endsWith("/api") ? trimmed : `${trimmed}/api`;
452
479
  }
453
480
  }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * The auto-heartbeat loop behind `claim({ id, heartbeat: true })` — one
3
+ * implementation shared by both transports (the WebSocket claim stream and the
4
+ * HTTP `ApiClient`), so the cadence and failure semantics cannot drift.
5
+ *
6
+ * A beat is the "still working" signal that keeps a lease alive for the
7
+ * duration of real work. The loop's failure handling follows the lease-system
8
+ * convention (SQS visibility heartbeats, Kubernetes leases): a beat that fails
9
+ * for a transient reason — the network blipped, the server was briefly
10
+ * unavailable — is simply retried on the next tick, because the lease has
11
+ * runway to spare by construction (the default cadence is a third of the TTL,
12
+ * so two consecutive beats can fail before the lease is even at risk). Only a
13
+ * definitive answer from the server — the lease lapsed and may have been
14
+ * granted to the next in line ({@link AbloClaimedError}) — stops the loop and
15
+ * surfaces the loss, because for a caller with no push channel the failed beat
16
+ * IS the loss notification.
17
+ */
18
+ import { AbloClaimedError } from '../errors.js';
19
+ import type { ClaimHeartbeat, ClaimHeartbeatOptions, Duration } from '../types/streams.js';
20
+ /**
21
+ * Normalize the public `heartbeat(options?)` argument — a bare Duration is
22
+ * shorthand for `{ ttl }`. Shared by both transports' handle assembly so the
23
+ * shorthand cannot drift.
24
+ */
25
+ export declare function resolveHeartbeatOptions(input: Duration | ClaimHeartbeatOptions | undefined): ClaimHeartbeatOptions;
26
+ /**
27
+ * The beat cadence for a lease of `ttlMs`: an explicit duration when the
28
+ * caller set one, otherwise a third of the TTL (floored at 1s) — the
29
+ * DynamoDB-lock-client rule, leaving two missed beats of runway before the
30
+ * lease is at risk while keeping crash recovery within one beat window.
31
+ */
32
+ export declare function heartbeatCadenceMs(ttlMs: number, heartbeat: true | Duration): number;
33
+ export interface ClaimHeartbeatLoopOptions {
34
+ /** Send one beat; resolves while the lease is still ours. */
35
+ beat(): Promise<ClaimHeartbeat>;
36
+ /** Cadence between beats. Callers default this to a third of the TTL. */
37
+ intervalMs: number;
38
+ /**
39
+ * Called once when a beat comes back with a definitive loss — the lease
40
+ * expired or was taken. The loop has already stopped by the time this runs.
41
+ */
42
+ onLost?(error: AbloClaimedError): void;
43
+ }
44
+ /**
45
+ * Start beating. Returns a stop function; callers stop the loop when the
46
+ * claim is released (all held-claim assembly sites tie this to `release`).
47
+ * Beats never overlap: a tick that fires while the previous beat is still
48
+ * in flight is skipped rather than stacked.
49
+ */
50
+ export declare function startClaimHeartbeatLoop(options: ClaimHeartbeatLoopOptions): () => void;