@abloatai/ablo 0.26.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 (398) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +101 -85
  3. package/dist/BaseSyncedStore.d.ts +85 -88
  4. package/dist/BaseSyncedStore.js +131 -147
  5. package/dist/Database.d.ts +54 -68
  6. package/dist/Database.js +97 -113
  7. package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
  8. package/dist/{ObjectPool.js → InstanceCache.js} +85 -83
  9. package/dist/LazyReferenceCollection.d.ts +11 -15
  10. package/dist/LazyReferenceCollection.js +12 -16
  11. package/dist/Model.d.ts +37 -52
  12. package/dist/Model.js +46 -61
  13. package/dist/ModelRegistry.d.ts +21 -19
  14. package/dist/ModelRegistry.js +23 -27
  15. package/dist/NetworkMonitor.d.ts +5 -6
  16. package/dist/NetworkMonitor.js +5 -6
  17. package/dist/SyncClient.d.ts +112 -112
  18. package/dist/SyncClient.js +165 -172
  19. package/dist/adapters/alwaysOnline.d.ts +6 -8
  20. package/dist/adapters/alwaysOnline.js +6 -8
  21. package/dist/adapters/inMemoryStorage.d.ts +9 -9
  22. package/dist/adapters/inMemoryStorage.js +9 -9
  23. package/dist/agent/Agent.d.ts +27 -32
  24. package/dist/agent/Agent.js +18 -19
  25. package/dist/agent/index.d.ts +4 -4
  26. package/dist/agent/index.js +5 -5
  27. package/dist/agent/session.d.ts +47 -44
  28. package/dist/agent/session.js +37 -48
  29. package/dist/agent/types.d.ts +26 -31
  30. package/dist/agent/types.js +6 -7
  31. package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
  32. package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
  33. package/dist/ai-sdk/coordinationContext.d.ts +46 -0
  34. package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +26 -33
  35. package/dist/ai-sdk/index.d.ts +25 -22
  36. package/dist/ai-sdk/index.js +25 -22
  37. package/dist/ai-sdk/wrap.d.ts +6 -7
  38. package/dist/ai-sdk/wrap.js +1 -1
  39. package/dist/auth/credentialPolicy.d.ts +69 -74
  40. package/dist/auth/credentialPolicy.js +51 -56
  41. package/dist/auth/credentialSource.d.ts +6 -5
  42. package/dist/auth/credentialSource.js +9 -10
  43. package/dist/auth/index.d.ts +59 -58
  44. package/dist/auth/index.js +31 -37
  45. package/dist/auth/schemas.d.ts +5 -4
  46. package/dist/auth/schemas.js +5 -4
  47. package/dist/batching/index.d.ts +19 -21
  48. package/dist/batching/index.js +14 -17
  49. package/dist/cli.cjs +167 -119
  50. package/dist/client/Ablo.d.ts +73 -73
  51. package/dist/client/Ablo.js +125 -160
  52. package/dist/client/ApiClient.d.ts +30 -19
  53. package/dist/client/ApiClient.js +133 -38
  54. package/dist/client/auth.d.ts +47 -47
  55. package/dist/client/auth.js +108 -117
  56. package/dist/client/claimHeartbeatLoop.d.ts +50 -0
  57. package/dist/client/claimHeartbeatLoop.js +88 -0
  58. package/dist/client/consoleLogger.d.ts +5 -6
  59. package/dist/client/consoleLogger.js +5 -6
  60. package/dist/client/createInternalComponents.d.ts +14 -17
  61. package/dist/client/createInternalComponents.js +25 -30
  62. package/dist/client/createModelProxy.d.ts +130 -120
  63. package/dist/client/createModelProxy.js +152 -122
  64. package/dist/client/credentialEndpoint.d.ts +40 -42
  65. package/dist/client/credentialEndpoint.js +35 -36
  66. package/dist/client/functionalUpdate.d.ts +29 -27
  67. package/dist/client/functionalUpdate.js +21 -21
  68. package/dist/client/hostedEndpoints.d.ts +9 -12
  69. package/dist/client/hostedEndpoints.js +9 -12
  70. package/dist/client/httpClient.d.ts +57 -53
  71. package/dist/client/httpClient.js +29 -31
  72. package/dist/client/identity.d.ts +15 -20
  73. package/dist/client/identity.js +47 -58
  74. package/dist/client/modelRegistration.d.ts +5 -9
  75. package/dist/client/modelRegistration.js +67 -87
  76. package/dist/client/options.d.ts +134 -157
  77. package/dist/client/options.js +3 -7
  78. package/dist/client/registerDataSource.d.ts +9 -9
  79. package/dist/client/registerDataSource.js +15 -16
  80. package/dist/client/resourceTypes.d.ts +64 -75
  81. package/dist/client/resourceTypes.js +4 -10
  82. package/dist/client/schemaConfig.d.ts +31 -43
  83. package/dist/client/schemaConfig.js +38 -50
  84. package/dist/client/sessionMint.d.ts +16 -12
  85. package/dist/client/sessionMint.js +26 -31
  86. package/dist/client/validateAbloOptions.d.ts +12 -14
  87. package/dist/client/validateAbloOptions.js +8 -9
  88. package/dist/client/writeOptionsSchema.d.ts +18 -16
  89. package/dist/client/writeOptionsSchema.js +23 -20
  90. package/dist/client/wsMutationExecutor.d.ts +15 -20
  91. package/dist/client/wsMutationExecutor.js +17 -23
  92. package/dist/context.d.ts +6 -4
  93. package/dist/context.js +6 -4
  94. package/dist/coordination/index.d.ts +10 -8
  95. package/dist/coordination/index.js +14 -12
  96. package/dist/coordination/schema.d.ts +176 -128
  97. package/dist/coordination/schema.js +197 -133
  98. package/dist/coordination/trace.d.ts +9 -10
  99. package/dist/coordination/trace.js +13 -14
  100. package/dist/core/DatabaseManager.d.ts +5 -7
  101. package/dist/core/DatabaseManager.js +15 -19
  102. package/dist/core/QueryProcessor.d.ts +7 -9
  103. package/dist/core/QueryProcessor.js +22 -28
  104. package/dist/core/QueryView.d.ts +8 -8
  105. package/dist/core/QueryView.js +2 -2
  106. package/dist/core/StoreManager.d.ts +12 -14
  107. package/dist/core/StoreManager.js +21 -24
  108. package/dist/core/ViewRegistry.d.ts +5 -5
  109. package/dist/core/ViewRegistry.js +4 -4
  110. package/dist/core/index.d.ts +17 -12
  111. package/dist/core/index.js +32 -26
  112. package/dist/core/openIDBWithTimeout.d.ts +38 -36
  113. package/dist/core/openIDBWithTimeout.js +42 -43
  114. package/dist/core/queryUtils.d.ts +45 -0
  115. package/dist/core/queryUtils.js +69 -0
  116. package/dist/core/storeContract.d.ts +63 -61
  117. package/dist/core/storeContract.js +8 -12
  118. package/dist/environment.d.ts +28 -0
  119. package/dist/environment.js +21 -0
  120. package/dist/errorCodes.d.ts +107 -99
  121. package/dist/errorCodes.js +131 -132
  122. package/dist/errors.d.ts +160 -166
  123. package/dist/errors.js +155 -158
  124. package/dist/index.d.ts +30 -27
  125. package/dist/index.js +89 -86
  126. package/dist/interfaces/index.d.ts +102 -113
  127. package/dist/interfaces/index.js +5 -4
  128. package/dist/keys/index.d.ts +27 -29
  129. package/dist/keys/index.js +41 -40
  130. package/dist/mutators/RecordingTransaction.d.ts +16 -16
  131. package/dist/mutators/RecordingTransaction.js +31 -37
  132. package/dist/mutators/Transaction.d.ts +18 -26
  133. package/dist/mutators/Transaction.js +14 -20
  134. package/dist/mutators/UndoManager.d.ts +122 -131
  135. package/dist/mutators/UndoManager.js +145 -156
  136. package/dist/mutators/defineMutators.d.ts +23 -34
  137. package/dist/mutators/defineMutators.js +14 -20
  138. package/dist/mutators/inverseOp.d.ts +12 -15
  139. package/dist/mutators/inverseOp.js +12 -15
  140. package/dist/mutators/mutateActions.d.ts +10 -9
  141. package/dist/mutators/mutateActions.js +1 -1
  142. package/dist/mutators/readerActions.d.ts +9 -8
  143. package/dist/mutators/readerActions.js +2 -2
  144. package/dist/mutators/undoApply.d.ts +31 -27
  145. package/dist/mutators/undoApply.js +26 -24
  146. package/dist/policy/index.d.ts +5 -3
  147. package/dist/policy/index.js +5 -3
  148. package/dist/policy/types.d.ts +104 -100
  149. package/dist/policy/types.js +67 -66
  150. package/dist/query/client.d.ts +28 -23
  151. package/dist/query/client.js +45 -43
  152. package/dist/query/types.d.ts +37 -60
  153. package/dist/query/types.js +13 -33
  154. package/dist/react/AbloProvider.d.ts +1 -1
  155. package/dist/react/AbloProvider.js +2 -2
  156. package/dist/react/context.d.ts +25 -28
  157. package/dist/react/context.js +9 -10
  158. package/dist/react/index.d.ts +41 -42
  159. package/dist/react/index.js +37 -38
  160. package/dist/react/internalContext.d.ts +17 -19
  161. package/dist/react/useAblo.d.ts +23 -22
  162. package/dist/react/useAblo.js +16 -14
  163. package/dist/react/useCurrentUserId.d.ts +8 -7
  164. package/dist/react/useCurrentUserId.js +8 -7
  165. package/dist/react/useErrorListener.d.ts +7 -7
  166. package/dist/react/useErrorListener.js +10 -11
  167. package/dist/react/useMutationFailureListener.d.ts +8 -8
  168. package/dist/react/useMutationFailureListener.js +8 -8
  169. package/dist/react/useMutators.d.ts +11 -11
  170. package/dist/react/useMutators.js +3 -3
  171. package/dist/react/useReactive.js +2 -2
  172. package/dist/react/useSyncStatus.d.ts +4 -6
  173. package/dist/react/useUndoScope.d.ts +7 -9
  174. package/dist/react/useUndoScope.js +1 -1
  175. package/dist/schema/coordination.d.ts +21 -25
  176. package/dist/schema/coordination.js +21 -25
  177. package/dist/schema/ddl.d.ts +43 -39
  178. package/dist/schema/ddl.js +75 -68
  179. package/dist/schema/ddlLock.d.ts +20 -24
  180. package/dist/schema/ddlLock.js +18 -23
  181. package/dist/schema/diff.d.ts +99 -61
  182. package/dist/schema/diff.js +43 -34
  183. package/dist/schema/field.d.ts +37 -42
  184. package/dist/schema/field.js +35 -48
  185. package/dist/schema/generate.d.ts +12 -12
  186. package/dist/schema/generate.js +12 -12
  187. package/dist/schema/index.d.ts +2 -2
  188. package/dist/schema/index.js +21 -23
  189. package/dist/schema/model.d.ts +118 -143
  190. package/dist/schema/model.js +22 -33
  191. package/dist/schema/openapi.d.ts +10 -9
  192. package/dist/schema/openapi.js +5 -3
  193. package/dist/schema/queries.d.ts +29 -31
  194. package/dist/schema/queries.js +23 -25
  195. package/dist/schema/relation.d.ts +89 -99
  196. package/dist/schema/relation.js +13 -13
  197. package/dist/schema/residency.d.ts +16 -13
  198. package/dist/schema/residency.js +16 -13
  199. package/dist/schema/roles.d.ts +36 -43
  200. package/dist/schema/roles.js +31 -37
  201. package/dist/schema/schema.d.ts +33 -42
  202. package/dist/schema/schema.js +31 -32
  203. package/dist/schema/select.d.ts +13 -13
  204. package/dist/schema/select.js +13 -13
  205. package/dist/schema/serialize.d.ts +28 -31
  206. package/dist/schema/serialize.js +27 -31
  207. package/dist/schema/sugar.d.ts +17 -32
  208. package/dist/schema/sugar.js +14 -29
  209. package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +26 -49
  210. package/dist/schema/syncDeltaRow.js +89 -0
  211. package/dist/schema/tenancy.d.ts +44 -46
  212. package/dist/schema/tenancy.js +46 -48
  213. package/dist/server/adapter.d.ts +58 -58
  214. package/dist/server/adapter.js +13 -14
  215. package/dist/server/commit.d.ts +60 -64
  216. package/dist/server/index.d.ts +9 -10
  217. package/dist/server/index.js +1 -1
  218. package/dist/server/readConfig.d.ts +70 -0
  219. package/dist/server/readConfig.js +8 -0
  220. package/dist/server/storageMode.d.ts +23 -0
  221. package/dist/server/storageMode.js +17 -0
  222. package/dist/source/adapter.d.ts +30 -25
  223. package/dist/source/adapter.js +10 -10
  224. package/dist/source/adapters/drizzle.d.ts +28 -23
  225. package/dist/source/adapters/drizzle.js +30 -25
  226. package/dist/source/adapters/kysely.d.ts +27 -25
  227. package/dist/source/adapters/kysely.js +24 -23
  228. package/dist/source/adapters/memory.d.ts +8 -7
  229. package/dist/source/adapters/memory.js +9 -8
  230. package/dist/source/adapters/prisma.d.ts +13 -12
  231. package/dist/source/adapters/prisma.js +22 -25
  232. package/dist/source/conformance.d.ts +18 -11
  233. package/dist/source/conformance.js +17 -11
  234. package/dist/source/connector.d.ts +31 -32
  235. package/dist/source/connector.js +28 -28
  236. package/dist/source/connectorProtocol.d.ts +160 -0
  237. package/dist/source/connectorProtocol.js +162 -0
  238. package/dist/source/contract.d.ts +26 -27
  239. package/dist/source/contract.js +28 -29
  240. package/dist/source/factory.d.ts +46 -58
  241. package/dist/source/factory.js +22 -27
  242. package/dist/source/index.d.ts +7 -9
  243. package/dist/source/index.js +12 -14
  244. package/dist/source/migrations.d.ts +9 -9
  245. package/dist/source/migrations.js +9 -9
  246. package/dist/source/next.d.ts +9 -10
  247. package/dist/source/next.js +6 -7
  248. package/dist/source/pushQueue.d.ts +69 -47
  249. package/dist/source/pushQueue.js +32 -28
  250. package/dist/source/signing.d.ts +46 -17
  251. package/dist/source/signing.js +28 -11
  252. package/dist/source/types.d.ts +121 -104
  253. package/dist/source/types.js +13 -14
  254. package/dist/stores/ObjectStore.d.ts +10 -11
  255. package/dist/stores/ObjectStore.js +11 -12
  256. package/dist/stores/ObjectStoreContract.d.ts +12 -15
  257. package/dist/stores/SyncActionStore.d.ts +7 -11
  258. package/dist/stores/SyncActionStore.js +13 -17
  259. package/dist/surface.d.ts +27 -20
  260. package/dist/surface.js +27 -20
  261. package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
  262. package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
  263. package/dist/sync/ConnectionManager.d.ts +39 -50
  264. package/dist/sync/ConnectionManager.js +55 -66
  265. package/dist/sync/NetworkProbe.d.ts +24 -29
  266. package/dist/sync/NetworkProbe.js +63 -69
  267. package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
  268. package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
  269. package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
  270. package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
  271. package/dist/sync/SyncWebSocket.d.ts +139 -165
  272. package/dist/sync/SyncWebSocket.js +191 -223
  273. package/dist/sync/awaitClaimGrant.d.ts +18 -18
  274. package/dist/sync/awaitClaimGrant.js +11 -11
  275. package/dist/sync/bootstrapApply.d.ts +34 -24
  276. package/dist/sync/bootstrapApply.js +27 -19
  277. package/dist/sync/commitFrames.d.ts +21 -20
  278. package/dist/sync/commitFrames.js +18 -18
  279. package/dist/sync/createClaimStream.d.ts +23 -22
  280. package/dist/sync/createClaimStream.js +105 -23
  281. package/dist/sync/createPresenceStream.d.ts +19 -18
  282. package/dist/sync/createPresenceStream.js +25 -26
  283. package/dist/sync/createSnapshot.d.ts +12 -14
  284. package/dist/sync/createSnapshot.js +20 -26
  285. package/dist/sync/credentialLifecycle.d.ts +104 -104
  286. package/dist/sync/credentialLifecycle.js +140 -147
  287. package/dist/sync/deltaPipeline.d.ts +36 -34
  288. package/dist/sync/deltaPipeline.js +64 -65
  289. package/dist/sync/groupChange.d.ts +63 -61
  290. package/dist/sync/groupChange.js +74 -78
  291. package/dist/sync/heartbeat.d.ts +34 -33
  292. package/dist/sync/heartbeat.js +31 -31
  293. package/dist/sync/participants.d.ts +19 -19
  294. package/dist/sync/schemas.d.ts +3 -2
  295. package/dist/sync/schemas.js +14 -10
  296. package/dist/sync/syncCursor.d.ts +17 -21
  297. package/dist/sync/syncCursor.js +17 -21
  298. package/dist/sync/syncPlan.d.ts +28 -36
  299. package/dist/sync/syncPlan.js +18 -19
  300. package/dist/sync/syncPosition.d.ts +54 -49
  301. package/dist/sync/syncPosition.js +57 -52
  302. package/dist/sync/wsFrameHandlers.d.ts +35 -36
  303. package/dist/sync/wsFrameHandlers.js +63 -67
  304. package/dist/testing/fixtures/bootstrap.d.ts +12 -6
  305. package/dist/testing/fixtures/bootstrap.js +12 -6
  306. package/dist/testing/fixtures/deltas.d.ts +30 -33
  307. package/dist/testing/fixtures/deltas.js +30 -33
  308. package/dist/testing/fixtures/models.d.ts +11 -10
  309. package/dist/testing/fixtures/models.js +11 -10
  310. package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
  311. package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
  312. package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -15
  313. package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
  314. package/dist/testing/helpers/wait.d.ts +13 -8
  315. package/dist/testing/helpers/wait.js +13 -8
  316. package/dist/testing/index.d.ts +3 -3
  317. package/dist/testing/index.js +2 -2
  318. package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
  319. package/dist/testing/mocks/MockMutationExecutor.js +15 -14
  320. package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
  321. package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
  322. package/dist/testing/mocks/MockSyncContext.d.ts +20 -17
  323. package/dist/testing/mocks/MockSyncContext.js +15 -13
  324. package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
  325. package/dist/testing/mocks/MockSyncStore.js +11 -11
  326. package/dist/testing/mocks/MockWebSocket.d.ts +26 -22
  327. package/dist/testing/mocks/MockWebSocket.js +22 -21
  328. package/dist/transactions/TransactionQueue.d.ts +181 -176
  329. package/dist/transactions/TransactionQueue.js +338 -350
  330. package/dist/transactions/TransactionStore.d.ts +6 -4
  331. package/dist/transactions/TransactionStore.js +6 -4
  332. package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
  333. package/dist/transactions/UnconfirmedWrites.js +104 -0
  334. package/dist/transactions/coalesceRules.d.ts +41 -17
  335. package/dist/transactions/coalesceRules.js +40 -17
  336. package/dist/transactions/commitPayload.d.ts +48 -52
  337. package/dist/transactions/commitPayload.js +48 -57
  338. package/dist/transactions/deltaConfirmation.d.ts +20 -22
  339. package/dist/transactions/deltaConfirmation.js +37 -45
  340. package/dist/transactions/optimisticApply.d.ts +49 -0
  341. package/dist/transactions/optimisticApply.js +65 -0
  342. package/dist/transactions/{persistedReplay.d.ts → replayValidation.d.ts} +28 -22
  343. package/dist/transactions/{persistedReplay.js → replayValidation.js} +33 -27
  344. package/dist/types/global.d.ts +46 -41
  345. package/dist/types/global.js +20 -19
  346. package/dist/types/index.d.ts +71 -77
  347. package/dist/types/index.js +22 -22
  348. package/dist/types/modelData.d.ts +6 -8
  349. package/dist/types/modelData.js +5 -7
  350. package/dist/types/participant.d.ts +10 -11
  351. package/dist/types/participant.js +6 -8
  352. package/dist/types/streams.d.ts +208 -195
  353. package/dist/types/streams.js +7 -7
  354. package/dist/utils/asyncIterator.d.ts +25 -32
  355. package/dist/utils/asyncIterator.js +25 -32
  356. package/dist/utils/duration.d.ts +12 -15
  357. package/dist/utils/duration.js +12 -15
  358. package/dist/utils/mobxSetup.d.ts +53 -0
  359. package/dist/utils/{mobx-setup.js → mobxSetup.js} +42 -98
  360. package/dist/webhooks/events.d.ts +21 -16
  361. package/dist/webhooks/events.js +10 -8
  362. package/dist/webhooks/index.d.ts +5 -7
  363. package/dist/webhooks/index.js +5 -7
  364. package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
  365. package/dist/wire/delta.js +114 -0
  366. package/dist/wire/errorEnvelope.d.ts +30 -31
  367. package/dist/wire/errorEnvelope.js +34 -40
  368. package/dist/wire/frames.d.ts +79 -86
  369. package/dist/wire/frames.js +26 -33
  370. package/dist/wire/index.d.ts +14 -12
  371. package/dist/wire/index.js +30 -26
  372. package/dist/wire/listEnvelope.d.ts +16 -23
  373. package/dist/wire/listEnvelope.js +7 -6
  374. package/dist/wire/protocol.d.ts +25 -32
  375. package/dist/wire/protocol.js +25 -32
  376. package/dist/wire/protocolVersion.d.ts +44 -40
  377. package/dist/wire/protocolVersion.js +44 -40
  378. package/docs/coordination.md +59 -0
  379. package/package.json +11 -10
  380. package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
  381. package/dist/ai-sdk/coordination-context.d.ts +0 -52
  382. package/dist/core/query-utils.d.ts +0 -34
  383. package/dist/core/query-utils.js +0 -59
  384. package/dist/schema/sync-delta-row.js +0 -103
  385. package/dist/schema/sync-delta-wire.js +0 -102
  386. package/dist/server/read-config.d.ts +0 -67
  387. package/dist/server/read-config.js +0 -8
  388. package/dist/server/storage-mode.d.ts +0 -8
  389. package/dist/server/storage-mode.js +0 -28
  390. package/dist/source/connector-protocol.d.ts +0 -159
  391. package/dist/source/connector-protocol.js +0 -161
  392. package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
  393. package/dist/transactions/OptimisticEchoTracker.js +0 -104
  394. package/dist/transactions/mutation-error-handler.d.ts +0 -5
  395. package/dist/transactions/mutation-error-handler.js +0 -39
  396. package/dist/transactions/optimistic.d.ts +0 -24
  397. package/dist/transactions/optimistic.js +0 -45
  398. package/dist/utils/mobx-setup.d.ts +0 -42
@@ -1,48 +1,47 @@
1
1
  /**
2
- * @abloatai/ablo/react — React bindings (v0.3.0)
2
+ * React bindings for `@abloatai/ablo`.
3
3
  *
4
- * Umbrella provider:
5
- * const ablo = Ablo({ schema, apiKey }) // build once — module scope or useMemo
4
+ * # Provider
5
+ *
6
+ * Build a client once — at module scope or with `useMemo` — and wrap your tree:
7
+ *
8
+ * const ablo = Ablo({ schema, apiKey })
6
9
  * <AbloProvider client={ablo} fallback={<Skeleton/>}>
7
- * — `client` is the only required prop (construct it yourself; the provider
8
- * is the thin reactive binding, like `<Elements stripe={...}>`). `userId`
9
- * is optional + informational. Owns sync engine + multiplayer lifecycle;
10
- * the `fallback` prop
11
- * gates children on first bootstrap. Pass `fallback="passthrough"`
12
- * to disable the gate.
13
- * <ClientSideSuspense fallback={<Skeleton/>}> — NESTED gate inside an
14
- * already-ready provider. Use only when you need a separate gate
15
- * for a heavy subtree (e.g. a canvas) while app chrome renders
16
- * immediately. The provider-level `fallback` is the default path.
17
10
  *
18
- * Data hooks:
19
- * useAblo((ablo) => ablo.tasks.get(id)) — primary React read API (sync local snapshot)
20
- * useAblo() — typed client for callbacks/effects
21
- * (sync local reads: ablo.<model>.get/getAll;
22
- * async server reads: ablo.<model>.retrieve/list;
23
- * writes: ablo.<model>.create/update/delete)
24
- * useMutators(defs, opts?) — Zero-style custom mutators
25
- * useUndoScope(name) — per-surface undo/redo
11
+ * `client` is the only required prop; you construct it, and the provider is the
12
+ * thin reactive binding around it. The provider owns the sync-engine and
13
+ * multiplayer lifecycle. Its `fallback` gates children until the first sync
14
+ * bootstrap completes — pass `fallback="passthrough"` to render children
15
+ * immediately. `userId` is optional and informational.
16
+ *
17
+ * {@link ClientSideSuspense} adds a nested gate inside an already-ready
18
+ * provider. Reach for it only when a heavy subtree, such as a canvas, needs its
19
+ * own gate while the rest of the app renders right away; the provider-level
20
+ * `fallback` is the usual path.
21
+ *
22
+ * # Data hooks
23
+ *
24
+ * useAblo((ablo) => ablo.tasks.get(id)) — subscribe to a local snapshot (the main read API)
25
+ * useAblo() — the typed client, for callbacks and effects:
26
+ * synchronous local reads (`ablo.<model>.get`/`getAll`),
27
+ * async server reads (`retrieve`/`list`),
28
+ * and writes (`create`/`update`/`delete`)
29
+ * useMutators(defs, opts?) — define custom mutators
30
+ * useUndoScope(name) — per-surface undo and redo
31
+ *
32
+ * # Status and errors
33
+ *
34
+ * useSyncStatus() — a discriminated-union snapshot of the sync lifecycle
35
+ * useErrorListener(cb) — an imperative error callback, for telemetry or toasts
36
+ * useCurrentUserId() — the provider's `userId` prop
26
37
  *
27
- * Status + errors:
28
- * useSyncStatus() — tagged-union lifecycle snapshot
29
- * useErrorListener(cb) — imperative error callback (Sentry/Datadog)
30
- * useCurrentUserId() — the provider's userId prop
38
+ * # Multiplayer
31
39
  *
32
- * Multiplayer (always available `<AbloProvider>` always constructs a client):
33
- * useAblo((ablo) => ablo.<model>.claim.state(...)) — reactive coordination reads
34
- * useWatch({ scope }) — join multiplayer for a scope, get peers/claims
40
+ * Multiplayer is always available, because `<AbloProvider>` always constructs a
41
+ * client:
35
42
  *
36
- * ── Breaking changes from v0.2.x ───────────────────────────────────
37
- * Removed: <SyncProvider>, SyncContext, useSyncContext folded into
38
- * <AbloProvider>. Access the raw engine with `useSync()`.
39
- * Removed: createAbloContext() factory + its returned AbloProvider —
40
- * multiplayer is now always-on inside <AbloProvider>. Schema-typed
41
- * participant hooks ship in a follow-up release.
42
- * Removed: withSync (no-op alias of observer). Import observer
43
- * from mobx-react-lite directly if you still need it.
44
- * Changed: useSyncStatus() now returns a discriminated union. See the
45
- * migration notes in CHANGELOG.md.
43
+ * useAblo((ablo) => ablo.<model>.claim.state(...)) — reactive coordination reads
44
+ * useWatch({ scope }) — join a scope to get its peers and claims
46
45
  */
47
46
  // ── Umbrella provider + lifecycle hooks ────────────────────────────
48
47
  export { AbloProvider, useWatch, usePeers, useSync, useSyncStore, } from './AbloProvider.js';
@@ -1,34 +1,32 @@
1
1
  import type { Ablo } from '../client/Ablo.js';
2
2
  import type { SchemaRecord } from '../schema/schema.js';
3
3
  /**
4
- * Internal context populated by `<AbloProvider>`. Separate from
5
- * `SyncContext` (which carries the store + schema for the data
6
- * hooks) because these fields are owned by the umbrella provider
7
- * and don't belong on the raw `SyncStoreContract`.
8
- *
9
- * Consumers should NOT use this directly — access the fields via
10
- * the typed hooks (`useCurrentUserId`, `useErrorListener`, etc.).
4
+ * The context that `<AbloProvider>` populates for its own hooks. It is kept
5
+ * separate from the data-hook context, which carries the store and schema,
6
+ * because these fields belong to the provider rather than to the store. Read
7
+ * them through the typed hooks such as `useCurrentUserId` and
8
+ * `useErrorListener` rather than reaching into this context directly.
11
9
  */
12
10
  export interface AbloInternalContextValue {
13
11
  /**
14
- * Optional app user id when the application passed one. Hosted Ablo
15
- * identity is server-derived, so this may be null.
12
+ * The application user id, when your app passed one to `<AbloProvider>`. Sync
13
+ * identity is derived on the server from the API key, so this is `null`
14
+ * unless you set it, and it is not required for sync to work.
16
15
  */
17
16
  currentUserId: string | null;
18
- /** Subscribe to provider-level errors (engine errors, bootstrap failures, session issues). */
17
+ /** Subscribe to provider-level errors: engine errors, bootstrap failures, and session issues. */
19
18
  subscribeError: (listener: (error: Error) => void) => () => void;
20
- /** Fire an error to all subscribed listeners. Called internally by the provider. */
19
+ /** Emit an error to every subscribed listener. The provider calls this for you. */
21
20
  emitError: (error: Error) => void;
22
21
  /**
23
- * The SyncEngine proxy for this provider. `null` before bootstrap
24
- * resolves. Exposed through the internal context so `useSync()`
25
- * can return it without having to reach into the store the two
26
- * are sibling objects constructed together by `createSyncEngine`
27
- * and shouldn't be coerced through each other.
22
+ * The typed `Ablo` client for this provider, or `null` until the first sync
23
+ * bootstrap resolves. It is held here so `useSync()` can return it without
24
+ * reaching into the store; the client and the store are sibling objects, and
25
+ * neither is derived from the other.
28
26
  *
29
- * Typed as `Ablo<SchemaRecord>` on the context because
30
- * generics don't flow through React context. `useSync<R>()` widens
31
- * via its own generic runtime value is the concrete engine.
27
+ * It is typed loosely as `Ablo<SchemaRecord>` because generics do not flow
28
+ * through React context. `useSync<R>()` restores the precise type through its
29
+ * own generic; the runtime value is the fully typed client.
32
30
  */
33
31
  engine: Ablo<SchemaRecord> | null;
34
32
  }
@@ -3,11 +3,10 @@ import type { ModelOperations } from '../client/createModelProxy.js';
3
3
  import type { SchemaRecord } from '../schema/schema.js';
4
4
  import type { ResolveSchema } from '../types/global.js';
5
5
  /**
6
- * Resolved schema-record type for the consumer's app. Reads the
7
- * `Register` module augmentation if declared, falls back to the
8
- * loose `SchemaRecord` if not. This lets `useAblo()` produce a
9
- * fully typed engine handle without the consumer having to pass
10
- * `<(typeof schema)['models']>` at every call site.
6
+ * The app's resolved schema-record type. It reads your `Register` module
7
+ * augmentation when you declare one and falls back to the loose
8
+ * {@link SchemaRecord} otherwise, so `useAblo()` returns a fully typed client
9
+ * without you passing `<(typeof schema)['models']>` at every call site.
11
10
  */
12
11
  type DefaultModels = ResolveSchema extends {
13
12
  models: infer M;
@@ -16,48 +15,50 @@ type ModelClientSelector<R extends SchemaRecord, T, C> = (ablo: Ablo<R>) => Mode
16
15
  type AbloSelector<R extends SchemaRecord, T> = (ablo: Ablo<R>) => T;
17
16
  export interface UseAbloModelOptions<T> {
18
17
  /**
19
- * Initial row, usually from a Server Component or loader. The hook returns it
20
- * until the model client has a newer row in the local pool.
18
+ * An initial row, usually from a server component or a route loader. The hook
19
+ * returns it until sync delivers a newer row for the same id.
21
20
  */
22
21
  readonly initial?: T;
23
22
  }
24
23
  export interface UseAbloModelResult<T> {
25
- /** Current row for the id, or `initial` until the row has hydrated. */
24
+ /** The current row for the id, or `initial` until the row has synced. */
26
25
  readonly data: T | undefined;
27
- /** Active work claims on this model row. */
26
+ /** The work claims currently held on this row by any participant. */
28
27
  readonly claims: readonly ModelClaim[];
29
- /** Convenience flag for disabling UI while another participant is active. */
28
+ /** True while another participant holds a claim handy for disabling UI. */
30
29
  readonly claimed: boolean;
31
30
  }
32
31
  export type UseAbloHydratedModelResult<T> = Omit<UseAbloModelResult<T>, 'data'> & {
33
32
  readonly data: T;
34
33
  };
35
34
  /**
36
- * useAblo access the typed engine instance, or subscribe to a specific
37
- * `ablo.<model>` row from inside an `<AbloProvider>` subtree.
35
+ * Reads Ablo from inside an `<AbloProvider>` subtree. Called with no arguments
36
+ * it returns the typed client for use in callbacks and effects; called with a
37
+ * selector it subscribes the component to a reactive read — such as one
38
+ * `ablo.<model>` row — and re-renders when that read changes.
38
39
  *
39
- * Zero-arg when the consumer declares the `Register` global
40
- * augmentation (`declare module '@abloatai/ablo' { interface Register { Schema:
41
- * typeof schema } }`). The default generic resolves through
42
- * `ResolveSchema['models']` so call sites stay clean:
40
+ * You can call it with no type arguments once you declare the `Register` module
41
+ * augmentation (`declare module '@abloatai/ablo' { interface Register {
42
+ * Schema: typeof schema } }`); the default type then resolves through your
43
+ * schema's models, so call sites stay clean:
43
44
  *
44
45
  * ```ts
45
- * // With Register augmentation (recommended):
46
+ * // With the Register augmentation (recommended):
46
47
  * const ablo = useAblo();
47
48
  * if (!ablo) return <Loading />;
48
49
  * const doc = await ablo.documents.retrieve({ id }); // async server read
49
50
  *
50
- * // Reactive selector (sync local-graph snapshot):
51
+ * // Reactive selector (a synchronous local snapshot):
51
52
  * const doc = useAblo((ablo) => ablo.documents.get(id)) ?? serverDoc;
52
53
  * const active = useAblo((ablo) => ablo.documents.claim.state({ id }));
53
54
  *
54
- * // Without augmentation, pass the schema generic:
55
+ * // Without the augmentation, pass the schema as a type argument:
55
56
  * const ablo = useAblo<(typeof schema)['models']>();
56
57
  * ```
57
58
  *
58
- * Returns `null` while the engine is bootstrapping. Branch on null
59
- * and render a loading state (or use `useSyncStatus()` to gate on
60
- * `'connected'`) before reaching for model methods.
59
+ * The no-argument form returns `null` while the engine is still bootstrapping.
60
+ * Branch on `null` and render a loading state or gate on `useSyncStatus()`
61
+ * reaching `'connected'` before calling model methods.
61
62
  */
62
63
  export declare function useAblo<R extends SchemaRecord = DefaultModels>(): Ablo<R> | null;
63
64
  export declare function useAblo<R extends SchemaRecord = DefaultModels, T = unknown>(select: AbloSelector<R, T>): T | undefined;
@@ -17,14 +17,15 @@ function readModelResult(engine, modelClient, id, initial) {
17
17
  return { data, claims, claimed: claims.length > 0 };
18
18
  }
19
19
  /**
20
- * Project a reactive read into the value `useReactive` caches and returns.
20
+ * Projects a reactive read into the value that `useReactive` caches and
21
+ * returns.
21
22
  *
22
- * For a `Model`, this MUST read the row's fields (via `toReactiveSnapshot`),
23
- * not return the bare instance: MobX tracks property access, so reading the
24
- * fields inside this tracked function is what subscribes the reaction to them
25
- * and the fresh object identity lets `useReactive`'s equality detect an
26
- * in-place delta update. Returning `modelAsRow(value)` (the live instance, no
27
- * field read) is why `useAblo(a => a.x.get(id))` used to ignore remote edits.
23
+ * For a `Model`, this reads the row's fields through `toReactiveSnapshot`
24
+ * rather than returning the instance itself. Property access is what subscribes
25
+ * the reaction to those fields, so the read has to happen inside this tracked
26
+ * function; returning the live instance without reading its fields would leave
27
+ * the component blind to later edits. The fresh object it produces also lets
28
+ * `useReactive`'s equality check detect an in-place update.
28
29
  */
29
30
  function snapshotValue(value) {
30
31
  if (value instanceof Model) {
@@ -47,13 +48,14 @@ export function useAblo(modelOrSelect, id, options) {
47
48
  : typeof modelOrSelect === 'function'
48
49
  ? undefined
49
50
  : modelOrSelect;
50
- // Claims live on a non-MobX event emitter (engine.claims), so the useReactive
51
- // reactions below cannot track them we bridge changes through a setState bump.
52
- // ONLY the model-row form (`id !== undefined`) actually reads claims, so gate the
53
- // subscription on `id`. The selector-only form (`useAblo((a) => a.x.get/getAll)`)
54
- // never reads claims; subscribing it to the workspace-global claim stream would
55
- // re-render + double-compute it on every claim/presence delta anywhere (a real
56
- // storm during AI editing / live collaboration) for a value that can't change.
51
+ // Claims arrive through an event emitter (engine.claims), not through MobX, so
52
+ // the useReactive reactions below cannot track them; we bridge changes with a
53
+ // setState bump instead. Only the model-row form (`id !== undefined`) reads
54
+ // claims, so we subscribe only when `id` is set. The selector-only form never
55
+ // reads claims, and subscribing it to the workspace-wide claim stream would
56
+ // re-render and recompute it on every claim or presence change anywhere a
57
+ // real storm during AI editing or live collaboration for a value that cannot
58
+ // change.
57
59
  const [claimVersion, setClaimVersion] = useState(0);
58
60
  useEffect(() => {
59
61
  if (!engine || id === undefined)
@@ -1,13 +1,14 @@
1
1
  /**
2
- * Returns the app user ID passed to the nearest `<AbloProvider>`, when
3
- * the app chose to provide one.
2
+ * Returns the application user id passed to the nearest `<AbloProvider>`, or
3
+ * `null` when your app did not provide one.
4
4
  *
5
- * Hosted Ablo identity is resolved server-side from the API key, session,
6
- * or capability token. This hook is only for app-owned fields like
7
- * `assigneeId`; it is not required for Ablo sync to connect.
5
+ * Sync identity is resolved on the server from the API key or session, so this
6
+ * value is not required for sync to connect. It is here for your app's own
7
+ * fields an assignee id, a presence label, a permission check — where the
8
+ * current user matters to your data rather than to the sync layer. Reach for it
9
+ * in leaf components that need the id, for example to fill in a mutation
10
+ * payload.
8
11
  *
9
- * Use this in leaf components that need the current user ID for
10
- * mutation payloads, presence labels, permission checks, etc.
11
12
  * @example
12
13
  * function TaskRow({ id }) {
13
14
  * const userId = useCurrentUserId();
@@ -3,15 +3,16 @@ import { useContext } from 'react';
3
3
  import { AbloInternalContext } from './internalContext.js';
4
4
  import { AbloValidationError } from '../errors.js';
5
5
  /**
6
- * Returns the app user ID passed to the nearest `<AbloProvider>`, when
7
- * the app chose to provide one.
6
+ * Returns the application user id passed to the nearest `<AbloProvider>`, or
7
+ * `null` when your app did not provide one.
8
8
  *
9
- * Hosted Ablo identity is resolved server-side from the API key, session,
10
- * or capability token. This hook is only for app-owned fields like
11
- * `assigneeId`; it is not required for Ablo sync to connect.
9
+ * Sync identity is resolved on the server from the API key or session, so this
10
+ * value is not required for sync to connect. It is here for your app's own
11
+ * fields an assignee id, a presence label, a permission check — where the
12
+ * current user matters to your data rather than to the sync layer. Reach for it
13
+ * in leaf components that need the id, for example to fill in a mutation
14
+ * payload.
12
15
  *
13
- * Use this in leaf components that need the current user ID for
14
- * mutation payloads, presence labels, permission checks, etc.
15
16
  * @example
16
17
  * function TaskRow({ id }) {
17
18
  * const userId = useCurrentUserId();
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Register an imperative callback that fires whenever the provider
3
- * surfaces an error. Covers engine errors (bootstrap failures,
4
- * mutation rejections), WebSocket errors, and uncaught exceptions
5
- * inside `postBootstrap` hooks.
2
+ * Registers a callback that runs whenever the provider surfaces an error. This
3
+ * covers engine errors such as bootstrap failures and mutation rejections,
4
+ * WebSocket errors, and uncaught exceptions thrown inside `postBootstrap`
5
+ * hooks.
6
6
  *
7
- * Use this for telemetry (Sentry, Datadog), user-facing toasts, or
8
- * any side effect that should NOT trigger a re-render. The listener
9
- * is stored in a ref, so re-renders don't thrash the subscription.
7
+ * Use it for side effects that should not cause a re-render — telemetry,
8
+ * logging, or a toast. The callback is held in a ref, so a re-render does not
9
+ * resubscribe.
10
10
  *
11
11
  * @example
12
12
  * function ErrorToaster() {
@@ -3,14 +3,14 @@ import { useContext, useEffect, useRef } from 'react';
3
3
  import { AbloInternalContext } from './internalContext.js';
4
4
  import { AbloValidationError } from '../errors.js';
5
5
  /**
6
- * Register an imperative callback that fires whenever the provider
7
- * surfaces an error. Covers engine errors (bootstrap failures,
8
- * mutation rejections), WebSocket errors, and uncaught exceptions
9
- * inside `postBootstrap` hooks.
6
+ * Registers a callback that runs whenever the provider surfaces an error. This
7
+ * covers engine errors such as bootstrap failures and mutation rejections,
8
+ * WebSocket errors, and uncaught exceptions thrown inside `postBootstrap`
9
+ * hooks.
10
10
  *
11
- * Use this for telemetry (Sentry, Datadog), user-facing toasts, or
12
- * any side effect that should NOT trigger a re-render. The listener
13
- * is stored in a ref, so re-renders don't thrash the subscription.
11
+ * Use it for side effects that should not cause a re-render — telemetry,
12
+ * logging, or a toast. The callback is held in a ref, so a re-render does not
13
+ * resubscribe.
14
14
  *
15
15
  * @example
16
16
  * function ErrorToaster() {
@@ -27,10 +27,9 @@ export function useErrorListener(listener) {
27
27
  throw new AbloValidationError('useErrorListener: no <AbloProvider> mounted above this component. ' +
28
28
  'Wrap your tree with <AbloProvider ...> from @abloatai/ablo/react.', { code: 'no_ablo_provider' });
29
29
  }
30
- // Stash the latest callback in a ref so the effect subscription
31
- // stays stable across renders. Matches the `useEventCallback`
32
- // pattern: late-bind the listener so callers can pass inline
33
- // arrows without thrashing the subscription.
30
+ // Hold the latest callback in a ref so the subscription stays stable across
31
+ // renders. Late-binding the listener this way lets callers pass an inline
32
+ // arrow without resubscribing on every render.
34
33
  const ref = useRef(listener);
35
34
  ref.current = listener;
36
35
  useEffect(() => {
@@ -5,15 +5,15 @@ export interface MutationFailurePayload {
5
5
  permanent?: boolean;
6
6
  }
7
7
  /**
8
- * Register a side-effect listener for mutation failures. Fires whenever
9
- * the underlying transaction queue rolls back an optimistic write —
10
- * permanent rejections (validation, FK, auth) and exhausted-retry
11
- * rollbacks (connection lost mid-burst).
8
+ * Subscribes a listener to mutation failures. The callback fires whenever the
9
+ * transaction queue rolls back an optimistic write — both permanent rejections
10
+ * (a validation, foreign-key, or authorization error) and rollbacks after the
11
+ * retries are exhausted (for example, the connection drops mid-write).
12
12
  *
13
- * Use this to mount a single `<MutationFailureBoundary>` near the app
14
- * shell that turns silent pool rollbacks into toasts / banners. The
15
- * listener is stored in a ref so re-renders don't thrash the
16
- * subscription — matches `useErrorListener`.
13
+ * A single listener mounted near the top of your component tree can turn these
14
+ * otherwise-silent rollbacks into toasts or banners. The callback is held in a
15
+ * ref, so re-renders do not tear down and re-create the underlying
16
+ * subscription.
17
17
  *
18
18
  * @example
19
19
  * function MutationFailureBoundary() {
@@ -3,15 +3,15 @@ import { useContext, useEffect, useRef } from 'react';
3
3
  import { AbloInternalContext } from './internalContext.js';
4
4
  import { AbloValidationError } from '../errors.js';
5
5
  /**
6
- * Register a side-effect listener for mutation failures. Fires whenever
7
- * the underlying transaction queue rolls back an optimistic write —
8
- * permanent rejections (validation, FK, auth) and exhausted-retry
9
- * rollbacks (connection lost mid-burst).
6
+ * Subscribes a listener to mutation failures. The callback fires whenever the
7
+ * transaction queue rolls back an optimistic write — both permanent rejections
8
+ * (a validation, foreign-key, or authorization error) and rollbacks after the
9
+ * retries are exhausted (for example, the connection drops mid-write).
10
10
  *
11
- * Use this to mount a single `<MutationFailureBoundary>` near the app
12
- * shell that turns silent pool rollbacks into toasts / banners. The
13
- * listener is stored in a ref so re-renders don't thrash the
14
- * subscription — matches `useErrorListener`.
11
+ * A single listener mounted near the top of your component tree can turn these
12
+ * otherwise-silent rollbacks into toasts or banners. The callback is held in a
13
+ * ref, so re-renders do not tear down and re-create the underlying
14
+ * subscription.
15
15
  *
16
16
  * @example
17
17
  * function MutationFailureBoundary() {
@@ -3,19 +3,19 @@ import type { MutatorDefs } from '../mutators/defineMutators.js';
3
3
  import type { UndoScope } from '../mutators/UndoManager.js';
4
4
  import type { ResolveSchema } from '../types/global.js';
5
5
  /**
6
- * useMutators turn a `defineMutators` tree into callable invokers.
6
+ * Turns a mutator tree built with `defineMutators` into callable invokers. The
7
+ * returned object mirrors that tree one-to-one, but each leaf becomes an
8
+ * `(args) => Promise<TResult>` function.
7
9
  *
8
- * The returned object mirrors the mutator tree one-to-one, but each leaf is
9
- * now a `(args) => Promise<TResult>` function. Internally each invocation:
10
- * 1. Builds a fresh `Transaction` bound to the current store/org context.
11
- * 2. Calls the user's mutator with `{ tx, args }`.
12
- * 3. Returns the mutator's resolved value.
10
+ * Each invocation builds a fresh `Transaction` bound to the current store and
11
+ * organization, calls your mutator with `{ tx, args }`, and returns whatever
12
+ * the mutator resolves to.
13
13
  *
14
- * V1 error handling: if the mutator throws, we `console.error` + rethrow.
15
- * Any writes that already dispatched stay in place (no rollback). That
16
- * matches the existing behaviour of batch helpers like `saveManyOptimized`
17
- * and keeps the contract honest consumers can layer their own try/catch
18
- * + compensating writes until V2 adds atomicity.
14
+ * If a mutator throws, the error propagates to the caller and any writes it
15
+ * already dispatched stay in place — there is no automatic rollback. Wrap the
16
+ * call in your own try/catch and issue compensating writes when you need to
17
+ * undo a partial change, or pass an `undoScope` (see {@link UseMutatorsOptions})
18
+ * to record inverses for undo and redo.
19
19
  */
20
20
  /**
21
21
  * Map a `MutatorFn` onto its invoker form — strip `tx`, keep `args`/return.
@@ -43,8 +43,8 @@ export function useMutators(schemaOrMutators, mutatorsOrOptions, maybeOptions) {
43
43
  // inverse. On success, push the captured entry to the scope.
44
44
  //
45
45
  // The whole snapshot → write → record sequence runs on the scope's
46
- // serialization chain so concurrent invocations (the slides UI fires
47
- // writes un-awaited) record in *invocation* order and never
46
+ // serialization chain so concurrent invocations (a caller may fire
47
+ // writes without awaiting them) record in invocation order and never
48
48
  // interleave their shared-model snapshots. See UndoScope.runRecorded.
49
49
  if (undoScope) {
50
50
  return undoScope.runRecorded(async () => {
@@ -64,7 +64,7 @@ export function useMutators(schemaOrMutators, mutatorsOrOptions, maybeOptions) {
64
64
  }
65
65
  });
66
66
  }
67
- // Non-recording path — plain transaction, identical to pre-undo V1.
67
+ // Non-recording path — plain transaction, no inverse capture.
68
68
  const tx = createTransaction(schema, store, organizationId);
69
69
  try {
70
70
  return await fn({ tx, args });
@@ -48,7 +48,7 @@ export function useReactive(compute, equals = defaultEquals) {
48
48
  // When `compute` identity changes, its closed-over observable source
49
49
  // may have swapped (e.g. useQuery memoized a new QueryView because
50
50
  // the where clause changed). The MobX reaction subscribed in
51
- // `subscribe` only tracks the observables read on its FIRST run; if
51
+ // `subscribe` only tracks the observables read on its first run; if
52
52
  // the source swaps without a re-subscription, the reaction never
53
53
  // re-tracks the new observables and `getSnapshot` keeps returning
54
54
  // the stale value forever.
@@ -71,7 +71,7 @@ export function useReactive(compute, equals = defaultEquals) {
71
71
  // `compute` is a fresh inline arrow at virtually every call site, so this
72
72
  // branch runs on essentially every render. Reconcile the snapshot against
73
73
  // the latest closure, but only force a re-subscription when the value
74
- // ACTUALLY changed. For the dominant case (same observable source, new
74
+ // actually changed. For the dominant case (same observable source, new
75
75
  // arrow identity, unchanged value) this avoids tearing down + recreating
76
76
  // the MobX reaction — and its double-compute — on every render. A genuine
77
77
  // source swap (a memoized compute closing over a new observable source)
@@ -1,10 +1,8 @@
1
1
  /**
2
- * Reactive sync-status snapshot as a discriminated union. Impossible
3
- * states (e.g., "connected AND offline") are unrepresentableeach
4
- * variant carries only the fields that make sense in that state.
5
- *
6
- * Inspired by Liveblocks' `useStatus()` and Zero's `useConnectionState()`:
7
- * one hook, one switch, no six-boolean guessing games.
2
+ * A snapshot of the current sync status, modeled as a discriminated union so
3
+ * impossible states such as "connected and offline" at oncecannot be
4
+ * represented. Each variant carries only the fields that make sense in that
5
+ * state, so a single `switch` on `name` narrows to exactly what you can read.
8
6
  *
9
7
  * Variants:
10
8
  * - `initial` — the provider just mounted; no connection attempt yet.
@@ -2,16 +2,14 @@ import type { Schema } from '../schema/schema.js';
2
2
  import type { UndoScope, UndoScopeOptions } from '../mutators/UndoManager.js';
3
3
  import type { ResolveSchema } from '../types/global.js';
4
4
  /**
5
- * useUndoScope per-surface undo/redo for mutator invocations.
5
+ * Provides per-surface undo and redo for mutator invocations. Each named scope
6
+ * owns an independent undo/redo stack, so different parts of your app — a deck
7
+ * editor, a sidebar form — can undo separately without stepping on each other.
6
8
  *
7
- * Zero deliberately does NOT ship a built-in undo API; consumers build one
8
- * on top of mutation tracking. This is ours.
9
- *
10
- * Each named scope owns an independent undo/redo stack. Wire the returned
11
- * `scope` into `useMutators(schema, mutators, { undoScope: scope })` and the
12
- * invocations become recorded. `undo()` / `redo()` replay the inverses /
13
- * forwards as new transactions that do NOT re-record (the manager pushes
14
- * them between the two stacks explicitly).
9
+ * Wire the returned `scope` into `useMutators(schema, mutators, { undoScope:
10
+ * scope })` and those invocations become recorded. `undo()` and `redo()` replay
11
+ * the captured inverses and forwards as new transactions that do not record
12
+ * themselves; the manager moves the entry between the two stacks explicitly.
15
13
  *
16
14
  * @example
17
15
  * const { undo, redo, canUndo, canRedo, scope } = useUndoScope('deck-editor');
@@ -53,7 +53,7 @@ export function useUndoScope(schemaOrName, nameOrOptions, maybeOptions) {
53
53
  useEffect(() => {
54
54
  setTick(0);
55
55
  }, [scope]);
56
- // Re-render on ANY stack change — including entries recorded from the local-
56
+ // Re-render on any stack change — including entries recorded from the local-
57
57
  // mutation stream, which don't otherwise trigger a React update. Without this
58
58
  // `canUndo`/`canRedo` go stale in every consumer that didn't itself call
59
59
  // undo/redo (e.g. a keyboard handler whose Cmd+Z gate then never fires).