@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,24 +1,18 @@
1
1
  /**
2
- * ConnectionManager single source of truth for the sync engine's
3
- * connection lifecycle. Absorbs the FSM every SDK consumer used to
4
- * rebuild by hand (apps/web's `ConnectionStore` was the reference
5
- * implementation 605 LOC of FSM + watchdog + backoff).
2
+ * Owns the sync engine's connection lifecycle: the state machine that carries a
3
+ * client from a healthy connection, through a dropout, and back to live. It
4
+ * watches the browser's online/offline and visibility events, probes real
5
+ * connectivity and session validity with {@link probeNetwork}, applies retry
6
+ * backoff with a ceiling and jitter, and runs a watchdog for the cases where
7
+ * the browser never fires an event (VPN flips, captive portals). When it
8
+ * decides to recover, it drives the reconnect sequence — bootstrap, then
9
+ * WebSocket connect — through the {@link ConnectionCallbacks.onReconnect}
10
+ * callback and reacts to the outcome.
6
11
  *
7
- * What it owns:
8
- * - Browser online/offline + visibility events
9
- * - Network probe orchestration (via `probeNetwork`)
10
- * - Session-validity checks (HEAD /api/auth/check)
11
- * - Retry backoff with ceiling, jitter, and offline-aware parking
12
- * - Watchdog for browser events that never fire (VPN, captive portal)
13
- * - The reconnect → bootstrap → WebSocket connect sequence
14
- *
15
- * What it DOES NOT own:
16
- * - The actual bootstrap / IndexedDB / ObjectPool work — that lives in
17
- * `BaseSyncedStore.performReconnect()`. This class calls it via the
18
- * `onReconnect` callback and reacts to the outcome.
19
- *
20
- * Designed to be embedded by `BaseSyncedStore`: one instance per store,
21
- * started on first successful connect, disposed on teardown.
12
+ * It deliberately does not perform the bootstrap, local-storage, or object-pool
13
+ * work itself; that lives in the embedding store, which the manager reaches
14
+ * only through its callbacks. One manager is created per store, started on the
15
+ * first successful connect and disposed on teardown.
22
16
  *
23
17
  * CONNECTED ──(socket drop)──► PROBING_NETWORK ──► RECONNECTING ──► CONNECTED
24
18
  * │ │ │
@@ -29,20 +23,15 @@
29
23
  * ▼
30
24
  * WAITING_FOR_NETWORK
31
25
  *
32
- * Includes three fixes over the original app-side FSM:
33
- * 1. `backoff` accepts `NETWORK_ONLINE` / `TAB_VISIBLE` jumps to
34
- * probing immediately when the network comes back, without
35
- * waiting for the backoff timer to elapse.
36
- * 2. `scheduleBackoff` parks in `waiting_for_network` (resetting
37
- * `attempt`) when `navigator.onLine === false` at max retries,
38
- * instead of hard-reloading an already-offline browser.
39
- * 3. A socket drop (`WS_DISCONNECTED`, typically code 1006) goes
40
- * STRAIGHT to `probing_network`, not the passive `offline` state.
41
- * 1006 is browser-local and carries no connectivity signal, so on a
42
- * healthy machine no `online`/`offline` event ever fires — parking in
43
- * `offline` stranded recovery until the 30s watchdog, long enough for
44
- * queued commits to roll back. Only a genuine OS-level `NETWORK_LOST`
45
- * parks in `offline` and waits for the `online` event.
26
+ * Three behaviors are worth calling out. A network return or tab focus during a
27
+ * backoff delay jumps straight to probing instead of waiting out the full
28
+ * interval. Reaching the retry ceiling while the browser reports offline parks
29
+ * in `waiting_for_network` rather than hard-reloading a browser that has no
30
+ * network. And a socket drop (close code 1006) goes straight to probing rather
31
+ * than the passive `offline` state 1006 is generated locally and carries no
32
+ * connectivity signal, so on a healthy machine no online/offline event ever
33
+ * fires; only a genuine operating-system network loss parks in `offline` to
34
+ * wait for the `online` event.
46
35
  */
47
36
  import { makeAutoObservable, runInAction } from 'mobx';
48
37
  import { getContext } from '../context.js';
@@ -158,13 +147,13 @@ export class ConnectionManager {
158
147
  // work.
159
148
  return 'offline';
160
149
  case 'WS_DISCONNECTED':
161
- // The socket died (typically code 1006) but the OS network is
162
- // almost certainly fine — 1006 is generated locally when the TCP
163
- // conn vanishes and carries NO connectivity signal, so the browser
164
- // fires no online/offline event. Probe IMMEDIATELY rather than
165
- // landing in the passive `offline` dead-end (which only escaped via
166
- // the 30s watchdog, long after queued commits rolled back). The
167
- // probe fast-fails if we genuinely ARE offline → waiting_for_network.
150
+ // The socket died (typically code 1006) but the operating-system
151
+ // network is almost certainly fine — 1006 is generated locally when
152
+ // the TCP connection vanishes and carries no connectivity signal, so
153
+ // the browser fires no online/offline event. Probe immediately rather
154
+ // than landing in the passive `offline` dead-end (which only escaped
155
+ // via the 30s watchdog, long after queued commits rolled back). The
156
+ // probe fast-fails if we genuinely are offline → waiting_for_network.
168
157
  return 'probing_network';
169
158
  case 'WS_SESSION_ERROR':
170
159
  case 'BOOTSTRAP_FAILED_SESSION':
@@ -233,15 +222,15 @@ export class ConnectionManager {
233
222
  return null;
234
223
  }
235
224
  case 'refreshing_credential':
236
- // Re-minting the short-lived access key (the Stripe-style `ek_`/`rk_`).
237
- // The login is presumed valid; this is NOT a sign-out state.
225
+ // Re-minting the short-lived access key (the `ek_`/`rk_`). The login is
226
+ // presumed valid; this is not a sign-out state.
238
227
  switch (event.type) {
239
228
  case 'CREDENTIAL_REFRESHED':
240
229
  // Fresh key in hand — re-probe so we reconnect with it.
241
230
  return 'probing_network';
242
231
  case 'BOOTSTRAP_FAILED_SESSION':
243
232
  // The re-mint hit a genuine 401/403: the long-lived login itself is
244
- // gone. THIS is the only path from here to sign-out.
233
+ // gone. This is the only path from here to sign-out.
245
234
  return 'session_expired';
246
235
  case 'RECONNECT_FAILED':
247
236
  // Couldn't reach the mint endpoint (offline/5xx/throw) — transient.
@@ -336,39 +325,40 @@ export class ConnectionManager {
336
325
  this.callbacks?.onDisconnectWebSocket();
337
326
  break;
338
327
  case 'probing_network':
339
- // A socket drop (`WS_DISCONNECTED`) now lands here directly so recovery
340
- // starts immediately. Tear the dead socket down FIRSTthis is what
328
+ // A socket drop (`WS_DISCONNECTED`) lands here directly so recovery
329
+ // starts immediately. Tear the dead socket down firstthat is what
341
330
  // sets SyncWebSocket's `isManualClose=true` and suppresses its own
342
- // scheduleReconnect, keeping the FSM the single reconnect authority on
343
- // the human path. The teardown runs synchronously inside the
344
- // `disconnected` emit, before `SyncWebSocket.onclose` checks the flag,
345
- // so the timing matches the previous `offline`-entry teardown. We gate
346
- // on the drop event specifically: the other paths into `probing_network`
347
- // (TAB_VISIBLE re-validation, handshake retry, backoff elapse) must NOT
331
+ // reconnect, keeping this machine the single reconnect authority on the
332
+ // human path. The teardown runs synchronously inside the `disconnected`
333
+ // emit, before `SyncWebSocket.onclose` checks the flag, so the timing
334
+ // matches the previous `offline`-entry teardown. We gate on the drop
335
+ // event specifically: the other paths into `probing_network`
336
+ // (tab-focus re-validation, handshake retry, backoff elapse) must not
348
337
  // tear down a socket that may still be live.
349
338
  if (event.type === 'WS_DISCONNECTED') {
350
339
  this.callbacks?.onDisconnectWebSocket();
351
340
  }
352
- this.runProbe();
341
+ void this.runProbe().catch(this.captureEffectFailure('probe'));
353
342
  break;
354
343
  case 'waiting_for_network':
355
344
  this.scheduleBackoff();
356
345
  break;
357
346
  case 'reconnecting':
358
- this.runReconnect();
347
+ void this.runReconnect().catch(this.captureEffectFailure('reconnect'));
359
348
  break;
360
349
  case 'refreshing_credential':
361
- this.runRefreshCredential();
350
+ void this.runRefreshCredential().catch(this.captureEffectFailure('refresh-credential'));
362
351
  break;
363
352
  case 'backoff':
364
353
  this.scheduleBackoff();
365
354
  break;
366
355
  case 'auth_blocked':
367
- // Stop — reachable but the credential was rejected (e.g.
368
- // api_key_required / jwt_issuer_untrusted from the data plane). Neither
369
- // reconnecting nor re-auth fixes it. Drop the socket and wait for a
370
- // manual retry / re-probe. Crucially NOT onSessionExpired (no sign-out)
371
- // and NOT a reconnect — that's the whole point of this state.
356
+ // Stop here the server is reachable but rejected the credential (for
357
+ // example api_key_required or jwt_issuer_untrusted from the data plane).
358
+ // Neither reconnecting nor re-authenticating fixes it. Drop the socket
359
+ // and wait for a manual retry or a re-probe. This deliberately does not
360
+ // call onSessionExpired (no sign-out) and does not reconnect — that is
361
+ // the whole point of the state.
372
362
  this.clearBackoffTimer();
373
363
  this.callbacks?.onDisconnectWebSocket();
374
364
  getContext().observability.breadcrumb('Auth blocked — reachable but credential rejected; not reconnecting or signing out', 'sync.offline', 'error');
@@ -382,6 +372,21 @@ export class ConnectionManager {
382
372
  }
383
373
  }
384
374
  // ── Async operations ─────────────────────────────────────────────────
375
+ /**
376
+ * FSM effects are fire-and-forget by design (`onEnterState` is sync). Each
377
+ * effect catches its own operational failures and maps them onto an FSM
378
+ * event, so a rejection here means the machine wedged mid-transition
379
+ * (`send()` or a transition listener threw) with no retry timer armed past
380
+ * it — capture it instead of losing the reconnect loop silently.
381
+ */
382
+ captureEffectFailure(effect) {
383
+ return (error) => {
384
+ getContext().observability.captureWebSocketError({
385
+ context: `connection-fsm-${effect}`,
386
+ error: error instanceof Error ? error.message : String(error),
387
+ });
388
+ };
389
+ }
385
390
  async runProbe() {
386
391
  try {
387
392
  const result = await probeNetwork({
@@ -587,16 +592,15 @@ export class ConnectionManager {
587
592
  this.watchdogTimer = setInterval(() => {
588
593
  if (this.disposed)
589
594
  return;
590
- // "Stuck" = parked in a non-active recovery state (offline,
591
- // waiting_for_network, backoff). We deliberately do NOT gate on
592
- // `navigator.onLine === true` here: per MDN, `navigator.onLine`
593
- // is only reliable when it returns false ("definitely offline"),
594
- // and even that lies after laptop wake / VPN flips. Gating the
595
- // watchdog on `onLine` was the actual "offline forever" bug
596
- // when the browser briefly reported offline and never re-fired
597
- // the `online` event, the FSM had no escape from `'offline'`.
598
- // The probe itself fast-fails when truly offline (NetworkProbe.ts),
599
- // so an unconditional retry costs nothing in the genuine case.
595
+ // "Stuck" means parked in a non-active recovery state (offline,
596
+ // waiting_for_network, backoff). This deliberately does not gate on
597
+ // `navigator.onLine === true`: per MDN, `navigator.onLine` is only
598
+ // reliable when it returns false ("definitely offline"), and even that
599
+ // lies after laptop wake or VPN flips. Gating the watchdog on `onLine`
600
+ // was what stranded the machine in `offline` forever when the browser
601
+ // briefly reported offline and never re-fired the `online` event, there
602
+ // was no escape. The probe itself fast-fails when truly offline, so an
603
+ // unconditional retry costs nothing in the genuine case.
600
604
  const isStuck = this.state !== 'connected' &&
601
605
  this.state !== 'session_expired' &&
602
606
  this.state !== 'probing_network' &&
@@ -609,7 +613,7 @@ export class ConnectionManager {
609
613
  // means definitely offline"), and reloading while truly offline
610
614
  // would either serve cached content forever or fail and leave
611
615
  // the user with a broken page.
612
- const browserOnline = typeof navigator === 'undefined' || navigator.onLine === true;
616
+ const browserOnline = typeof navigator === 'undefined' || navigator.onLine;
613
617
  if (this.stuckCycles >= MAX_STUCK_CYCLES_BEFORE_RELOAD && browserOnline) {
614
618
  getContext().logger.debug('[ConnectionManager] Watchdog: sustained stuck — hard reload');
615
619
  getContext().observability.breadcrumb('Watchdog hard reload', 'sync.offline', 'error');
@@ -1,36 +1,33 @@
1
1
  /**
2
- * NetworkProbe - Reliable network + session connectivity detection
2
+ * Detects real network and session connectivity for the sync engine. It exists
3
+ * because `navigator.onLine` is unreliable: it reports true whenever the device
4
+ * has a local network connection, even with no route to the internet, and after
5
+ * sleep/wake it can report true before Wi-Fi or DNS are working again.
3
6
  *
4
- * navigator.onLine is unreliable: it reports true whenever the device has a LAN
5
- * connection, even without actual internet access (MDN docs confirm this).
6
- * After laptop sleep/wake, it may report true before WiFi/DNS are functional.
7
- *
8
- * This module provides an authenticated probe against the sync server to verify
9
- * real connectivity + credential validity in a single round-trip. The probe
10
- * hits `/api/auth/check`, which runs the SAME auth middleware as the WebSocket
11
- * upgrade path, and classifies the response into a single {@link ProbeOutcome}
12
- * via the closed recovery taxonomy ({@link classifyRecovery}):
7
+ * The probe makes one authenticated request to the sync server's
8
+ * `/api/auth/check` endpoint which runs the same auth middleware as the
9
+ * WebSocket upgrade and classifies the response into a single
10
+ * {@link ProbeOutcome} through the recovery taxonomy ({@link classifyRecovery}):
13
11
  * 204 No Content → `reachable` (credential valid)
14
- * 401 `apikey_expired` (ephemeral key) → `credential_stale` (re-mint & retry, NO sign-out)
12
+ * 401 `apikey_expired` (ephemeral key) → `credential_stale` (re-mint and retry, no sign-out)
15
13
  * 401 `session_expired` / bare 401 → `session_expired` (sign out)
16
- * 401/403 credential-type/config/perm → `auth_blocked` (stop, no loop, no sign-out)
17
- * network fail / offline → `unreachable`
14
+ * 401/403 credential-type/config/perm → `auth_blocked` (stop; no loop, no sign-out)
15
+ * network failure / offline → `unreachable`
18
16
  *
19
- * This closes a real gap: the browser's WebSocket API hides HTTP status from
20
- * the handshake, so a 401 on the WS upgrade surfaces only as `close code
21
- * 1006`. Without this HTTP probe, the client cannot distinguish auth failure
22
- * from a network blip and loops reconnecting forever instead of redirecting
23
- * the user to sign-in.
17
+ * This closes a real gap. The browser's WebSocket API hides the HTTP status of
18
+ * a failed handshake, so a 401 on the upgrade surfaces only as close code 1006.
19
+ * Without this HTTP probe, the client cannot tell an auth failure from a network
20
+ * blip, and loops reconnecting forever instead of sending the user to sign in.
24
21
  *
25
22
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine
26
23
  */
27
24
  import { z } from 'zod';
28
25
  import { type AuthTokenGetter } from '../auth/credentialSource.js';
29
26
  /**
30
- * The closed set of probe outcomes one value carrying both reachability and
31
- * credential disposition, so the {@link ConnectionManager} branches on a single
32
- * exhaustive discriminant instead of reconstructing claim from a trio of
33
- * booleans. Mirrors the {@link RecoveryClass} taxonomy at the connectivity tier.
27
+ * The complete set of probe outcomes. Each value carries both reachability and
28
+ * credential state, so {@link ConnectionManager} can branch on one exhaustive
29
+ * discriminant instead of piecing the situation together from several booleans.
30
+ * It mirrors the {@link RecoveryClass} taxonomy at the connectivity layer.
34
31
  */
35
32
  export declare const PROBE_OUTCOMES: readonly ["reachable", "unreachable", "session_expired", "credential_stale", "auth_blocked"];
36
33
  /** Zod enum derived from {@link PROBE_OUTCOMES}. */
@@ -59,8 +56,9 @@ export declare const probeResultSchema: z.ZodObject<{
59
56
  export type ProbeResult = z.infer<typeof probeResultSchema>;
60
57
  export interface NetworkProbeOptions {
61
58
  /**
62
- * Sync-server base URL (HTTP or WS scheme accepted). If omitted, falls
63
- * back to the legacy `NEXT_PUBLIC_GO_SERVER_URL` default.
59
+ * Sync-server base URL (HTTP or WS scheme accepted). If omitted, the probe
60
+ * targets the canonical hosted endpoint ({@link ABLO_DEFAULT_BASE_URL}) —
61
+ * the same default `Ablo()` resolves.
64
62
  */
65
63
  baseUrl?: string;
66
64
  /**
@@ -73,13 +71,11 @@ export interface NetworkProbeOptions {
73
71
  authToken?: string | null;
74
72
  }
75
73
  /**
76
- * Probe the sync engine server with a lightweight HEAD request.
77
- *
78
- * Returns reachability AND session status in a single call, so the
79
- * ConnectionStore can make the right state transition without guessing.
74
+ * Probes the sync server with a lightweight HEAD request, returning both
75
+ * reachability and session status in a single call so {@link ConnectionManager}
76
+ * can pick the right state transition without guessing.
80
77
  *
81
- * @param input The sync-server base URL (HTTP or WS scheme accepted), or an
82
- * options bag with `authToken`. A bare string is still accepted
83
- * for backwards compatibility.
78
+ * @param input The sync-server base URL (an HTTP or WS scheme is accepted), or
79
+ * an options bag. A bare string is also accepted.
84
80
  */
85
81
  export declare function probeNetwork(input?: string | NetworkProbeOptions): Promise<ProbeResult>;
@@ -1,26 +1,23 @@
1
1
  /**
2
- * NetworkProbe - Reliable network + session connectivity detection
2
+ * Detects real network and session connectivity for the sync engine. It exists
3
+ * because `navigator.onLine` is unreliable: it reports true whenever the device
4
+ * has a local network connection, even with no route to the internet, and after
5
+ * sleep/wake it can report true before Wi-Fi or DNS are working again.
3
6
  *
4
- * navigator.onLine is unreliable: it reports true whenever the device has a LAN
5
- * connection, even without actual internet access (MDN docs confirm this).
6
- * After laptop sleep/wake, it may report true before WiFi/DNS are functional.
7
- *
8
- * This module provides an authenticated probe against the sync server to verify
9
- * real connectivity + credential validity in a single round-trip. The probe
10
- * hits `/api/auth/check`, which runs the SAME auth middleware as the WebSocket
11
- * upgrade path, and classifies the response into a single {@link ProbeOutcome}
12
- * via the closed recovery taxonomy ({@link classifyRecovery}):
7
+ * The probe makes one authenticated request to the sync server's
8
+ * `/api/auth/check` endpoint which runs the same auth middleware as the
9
+ * WebSocket upgrade and classifies the response into a single
10
+ * {@link ProbeOutcome} through the recovery taxonomy ({@link classifyRecovery}):
13
11
  * 204 No Content → `reachable` (credential valid)
14
- * 401 `apikey_expired` (ephemeral key) → `credential_stale` (re-mint & retry, NO sign-out)
12
+ * 401 `apikey_expired` (ephemeral key) → `credential_stale` (re-mint and retry, no sign-out)
15
13
  * 401 `session_expired` / bare 401 → `session_expired` (sign out)
16
- * 401/403 credential-type/config/perm → `auth_blocked` (stop, no loop, no sign-out)
17
- * network fail / offline → `unreachable`
14
+ * 401/403 credential-type/config/perm → `auth_blocked` (stop; no loop, no sign-out)
15
+ * network failure / offline → `unreachable`
18
16
  *
19
- * This closes a real gap: the browser's WebSocket API hides HTTP status from
20
- * the handshake, so a 401 on the WS upgrade surfaces only as `close code
21
- * 1006`. Without this HTTP probe, the client cannot distinguish auth failure
22
- * from a network blip and loops reconnecting forever instead of redirecting
23
- * the user to sign-in.
17
+ * This closes a real gap. The browser's WebSocket API hides the HTTP status of
18
+ * a failed handshake, so a 401 on the upgrade surfaces only as close code 1006.
19
+ * Without this HTTP probe, the client cannot tell an auth failure from a network
20
+ * blip, and loops reconnecting forever instead of sending the user to sign in.
24
21
  *
25
22
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine
26
23
  */
@@ -28,25 +25,26 @@ import { z } from 'zod';
28
25
  import { getContext } from '../context.js';
29
26
  import { classifyRecovery } from '../errors.js';
30
27
  import { withAuthHeaders } from '../auth/credentialSource.js';
28
+ import { ABLO_DEFAULT_BASE_URL } from '../client/hostedEndpoints.js';
31
29
  /**
32
- * The closed set of probe outcomes one value carrying both reachability and
33
- * credential disposition, so the {@link ConnectionManager} branches on a single
34
- * exhaustive discriminant instead of reconstructing claim from a trio of
35
- * booleans. Mirrors the {@link RecoveryClass} taxonomy at the connectivity tier.
30
+ * The complete set of probe outcomes. Each value carries both reachability and
31
+ * credential state, so {@link ConnectionManager} can branch on one exhaustive
32
+ * discriminant instead of piecing the situation together from several booleans.
33
+ * It mirrors the {@link RecoveryClass} taxonomy at the connectivity layer.
36
34
  */
37
35
  export const PROBE_OUTCOMES = [
38
36
  /** Server reachable and the access credential is currently valid. */
39
37
  'reachable',
40
- /** Could not reach the server (offline / DNS / TLS / timeout). */
38
+ /** Could not reach the server (offline, DNS, TLS, or timeout). */
41
39
  'unreachable',
42
- /** Reachable, but the long-lived login is gone terminal, sign out. */
40
+ /** Reachable, but the long-lived login is gone. Terminal: sign out. */
43
41
  'session_expired',
44
- /** Reachable, but the ephemeral access key (`ek_`/`rk_`) expired → silently
45
- * re-mint a fresh key from the still-valid login and retry. NOT a sign-out. */
42
+ /** Reachable, but the ephemeral access key (`ek_`/`rk_`) expired. Silently
43
+ * re-mint a fresh key from the still-valid login and retry; not a sign-out. */
46
44
  'credential_stale',
47
- /** Reachable, but the credential TYPE/config was rejected (wrong key kind,
48
- * untrusted issuer, no org, a 403) stop; neither reconnecting nor re-auth
49
- * helps. Distinct from a sign-out. */
45
+ /** Reachable, but the credential's type or configuration was rejected (wrong
46
+ * key kind, untrusted issuer, no organization, or a 403). Stop: neither
47
+ * reconnecting nor re-authenticating helps. Distinct from a sign-out. */
50
48
  'auth_blocked',
51
49
  ];
52
50
  /** Zod enum derived from {@link PROBE_OUTCOMES}. */
@@ -61,44 +59,40 @@ const PROBE_TIMEOUT_MS = 4000;
61
59
  /**
62
60
  * Derive the probe URL from a sync-server base URL. Accepts `ws://`,
63
61
  * `wss://`, `http://`, `https://`, or a bare host — mirrors the
64
- * normalisation in `BootstrapHelper` / `createSyncEngine`.
62
+ * normalisation in `BootstrapFetcher` / `createSyncEngine`.
65
63
  */
66
64
  function resolveProbeUrl(baseUrl) {
67
- // Fall back to the legacy env var so callers that haven't been migrated
68
- // to pass an explicit baseUrl keep working.
69
- const resolved = baseUrl ??
70
- (typeof process !== 'undefined' ? process.env?.NEXT_PUBLIC_GO_SERVER_URL : undefined) ??
71
- 'http://localhost:8080';
65
+ // No explicit baseUrl probe the canonical hosted endpoint, matching the
66
+ // `Ablo()` default.
67
+ const resolved = baseUrl ?? ABLO_DEFAULT_BASE_URL;
72
68
  // Normalize ws → http so fetch() accepts the URL. Strip any trailing slash
73
69
  // so we don't produce `//api/auth/check`.
74
70
  const httpBase = resolved.replace(/^ws/, 'http').replace(/\/+$/, '');
75
71
  return `${httpBase}/api/auth/check`;
76
72
  }
77
73
  /**
78
- * Probe the sync engine server with a lightweight HEAD request.
79
- *
80
- * Returns reachability AND session status in a single call, so the
81
- * ConnectionStore can make the right state transition without guessing.
74
+ * Probes the sync server with a lightweight HEAD request, returning both
75
+ * reachability and session status in a single call so {@link ConnectionManager}
76
+ * can pick the right state transition without guessing.
82
77
  *
83
- * @param input The sync-server base URL (HTTP or WS scheme accepted), or an
84
- * options bag with `authToken`. A bare string is still accepted
85
- * for backwards compatibility.
78
+ * @param input The sync-server base URL (an HTTP or WS scheme is accepted), or
79
+ * an options bag. A bare string is also accepted.
86
80
  */
87
81
  export async function probeNetwork(input) {
88
82
  const baseUrl = typeof input === 'string' ? input : input?.baseUrl;
89
83
  const getAuthToken = typeof input === 'string' ? undefined : input?.getAuthToken;
90
84
  const authToken = typeof input === 'string' ? undefined : input?.authToken;
91
85
  const url = resolveProbeUrl(baseUrl);
92
- // Fast-fail: if navigator.onLine is false, skip the probe entirely.
93
- // This is the ONE case where navigator.onLine is reliable (MDN: "false
94
- // means definitely offline"). Use `=== false` rather than `!onLine`
95
- // because Node 22+ exposes `navigator` with `onLine === undefined`,
96
- // and `!undefined === true` would short-circuit the probe server-side.
86
+ // Fast-fail: if navigator.onLine is false, skip the probe entirely. This is
87
+ // the one case where navigator.onLine is reliable (MDN: "false means
88
+ // definitely offline"). Use `=== false` rather than `!onLine` because Node
89
+ // 22+ exposes `navigator` with `onLine === undefined`, and `!undefined` is
90
+ // true, which would short-circuit the probe server-side.
97
91
  if (typeof navigator !== 'undefined' && navigator.onLine === false) {
98
92
  return { outcome: 'unreachable', latencyMs: null };
99
93
  }
100
94
  const controller = new AbortController();
101
- const timeout = setTimeout(() => controller.abort(), PROBE_TIMEOUT_MS);
95
+ const timeout = setTimeout(() => { controller.abort(); }, PROBE_TIMEOUT_MS);
102
96
  const start = performance.now();
103
97
  try {
104
98
  const headers = withAuthHeaders(getAuthToken, { 'Cache-Control': 'no-cache' }, authToken);
@@ -109,13 +103,13 @@ export async function probeNetwork(input) {
109
103
  headers,
110
104
  });
111
105
  const latencyMs = Math.round(performance.now() - start);
112
- // The probe is a HEAD (no body), but the sync-server sets `X-Auth-Failure:
113
- // <code>` on every auth rejection. Route the code through the closed
114
- // recovery taxonomy so each failure mode gets its correct outcome — the
115
- // whole reason this taxonomy exists: an expired ephemeral key
116
- // (`access_credential_expiry`) must re-mint, NOT sign the user out the way
117
- // a genuine login expiry (`session_expiry`) does, and NOT wedge the way a
118
- // credential-type/config rejection (`auth_blocked`) does.
106
+ // The probe is a HEAD request (no body), but the server sets
107
+ // `X-Auth-Failure: <code>` on every auth rejection. Route the code through
108
+ // the recovery taxonomy so each failure mode gets its correct outcome. That
109
+ // distinction is the whole point: an expired ephemeral key
110
+ // (`access_credential_expiry`) must re-mint, not sign the user out the way a
111
+ // genuine login expiry (`session_expiry`) does, and not wedge the way a
112
+ // credential type or configuration rejection (`auth_blocked`) does.
119
113
  const authFailure = response.headers.get('x-auth-failure');
120
114
  if (authFailure) {
121
115
  const recovery = classifyRecovery(authFailure);
@@ -137,10 +131,11 @@ export async function probeNetwork(input) {
137
131
  case 'auth_blocked':
138
132
  case 'permission':
139
133
  case 'none':
140
- // A non-expiry auth rejection — wrong credential type/config, a 403,
141
- // or an auth-tagged code this SDK doesn't recognise. Re-auth re-mints
142
- // the same rejected credential and retrying won't help, so STOP
143
- // rather than reconnect-loop or sign the user out.
134
+ // A non-expiry auth rejection — wrong credential type or config, a
135
+ // 403, or an auth-tagged code this SDK does not recognise.
136
+ // Re-authenticating re-mints the same rejected credential and
137
+ // retrying will not help, so stop rather than reconnect-loop or sign
138
+ // the user out.
144
139
  getContext().logger.debug('[NetworkProbe] Reachable but auth-blocked (non-retryable, non-expiry)', {
145
140
  status: response.status,
146
141
  code: authFailure,
@@ -159,20 +154,20 @@ export async function probeNetwork(input) {
159
154
  }
160
155
  }
161
156
  else if (response.status === 401) {
162
- // Bare 401 with no READABLE structured code. This is AMBIGUOUS and must
163
- // NOT sign the user out on its own — two common causes are both
157
+ // Bare 401 with no readable structured code. This is ambiguous and must
158
+ // not sign the user out on its own — two common causes are both
164
159
  // recoverable, and only one is a real logout:
165
- // 1. The server DID send `X-Auth-Failure: apikey_expired`, but it's a
166
- // custom header on a cross-origin response and the server didn't list
167
- // it in `Access-Control-Expose-Headers`, so the browser stripped it to
168
- // null (the network-change logout bug). The access key just needs a
169
- // re-mint.
170
- // 2. A genuinely expired access key on a non-Ablo proxy / cookie path.
171
- // So route to `credential_stale`: the FSM attempts a re-mint, and the ONLY
172
- // way to actually sign out is the re-mint resolving `null` (login truly
173
- // gone). If no refresher is wired, the bounded attempt counter falls
174
- // through to `auth_blocked` (stop) still never a spurious logout. This
175
- // upholds the invariant: null is the only terminal path, never a bare 401.
160
+ // 1. The server did send `X-Auth-Failure: apikey_expired`, but it is a
161
+ // custom header on a cross-origin response the server did not list in
162
+ // `Access-Control-Expose-Headers`, so the browser stripped it to
163
+ // null. The access key just needs a re-mint.
164
+ // 2. A genuinely expired access key on a non-Ablo proxy or cookie path.
165
+ // So route to `credential_stale`: the state machine attempts a re-mint,
166
+ // and the only way to actually sign out is that re-mint resolving `null`
167
+ // (the login is truly gone). If no refresher is wired, the bounded attempt
168
+ // counter falls through to `auth_blocked` (stop) still never a spurious
169
+ // logout. The invariant holds: null is the only terminal path, never a
170
+ // bare 401.
176
171
  getContext().logger.info('[NetworkProbe] Server reachable, bare 401 — re-mint (not sign-out)', {
177
172
  latencyMs,
178
173
  });