@abloatai/humans 0.37.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 (404) hide show
  1. package/README.md +52 -0
  2. package/dist/Ablo.d.ts +208 -0
  3. package/dist/Ablo.js +120 -0
  4. package/dist/client.d.ts +317 -0
  5. package/dist/client.js +13 -0
  6. package/dist/core.d.ts +35 -0
  7. package/dist/core.js +48 -0
  8. package/dist/humans.d.ts +28 -0
  9. package/dist/humans.js +34 -0
  10. package/dist/index.d.ts +10 -0
  11. package/dist/index.js +6 -0
  12. package/dist/local/BaseSyncedStore.d.ts +807 -0
  13. package/dist/local/BaseSyncedStore.js +1516 -0
  14. package/dist/local/Database.d.ts +322 -0
  15. package/dist/local/Database.js +1589 -0
  16. package/dist/local/InstanceCache.d.ts +255 -0
  17. package/dist/local/InstanceCache.js +1263 -0
  18. package/dist/local/LazyReferenceCollection.d.ts +177 -0
  19. package/dist/local/LazyReferenceCollection.js +461 -0
  20. package/dist/local/Model.d.ts +475 -0
  21. package/dist/local/Model.js +950 -0
  22. package/dist/local/ModelRegistry.d.ts +225 -0
  23. package/dist/local/ModelRegistry.js +539 -0
  24. package/dist/local/NetworkMonitor.d.ts +28 -0
  25. package/dist/local/NetworkMonitor.js +79 -0
  26. package/dist/local/RuntimeContext.d.ts +52 -0
  27. package/dist/local/RuntimeContext.js +80 -0
  28. package/dist/local/SyncClient.d.ts +516 -0
  29. package/dist/local/SyncClient.js +1754 -0
  30. package/dist/local/adapters/alwaysOnline.d.ts +14 -0
  31. package/dist/local/adapters/alwaysOnline.js +17 -0
  32. package/dist/local/adapters/inMemoryStorage.d.ts +37 -0
  33. package/dist/local/adapters/inMemoryStorage.js +122 -0
  34. package/dist/local/client/clientPrelude.d.ts +52 -0
  35. package/dist/local/client/clientPrelude.js +60 -0
  36. package/dist/local/client/consoleLogger.d.ts +35 -0
  37. package/dist/local/client/consoleLogger.js +44 -0
  38. package/dist/local/client/createInternalComponents.d.ts +50 -0
  39. package/dist/local/client/createInternalComponents.js +98 -0
  40. package/dist/local/client/createModelProxy.d.ts +248 -0
  41. package/dist/local/client/createModelProxy.js +880 -0
  42. package/dist/local/client/modelRegistration.d.ts +10 -0
  43. package/dist/local/client/modelRegistration.js +316 -0
  44. package/dist/local/client/options.d.ts +440 -0
  45. package/dist/local/client/options.js +7 -0
  46. package/dist/local/client/reactiveEngine.d.ts +53 -0
  47. package/dist/local/client/reactiveEngine.js +705 -0
  48. package/dist/local/client/resourceTypes.d.ts +12 -0
  49. package/dist/local/client/resourceTypes.js +10 -0
  50. package/dist/local/client/schemaConfig.d.ts +44 -0
  51. package/dist/local/client/schemaConfig.js +185 -0
  52. package/dist/local/client/storeCluster.d.ts +46 -0
  53. package/dist/local/client/storeCluster.js +133 -0
  54. package/dist/local/client/storeLifecycle.d.ts +61 -0
  55. package/dist/local/client/storeLifecycle.js +236 -0
  56. package/dist/local/client/validateAbloOptions.d.ts +42 -0
  57. package/dist/local/client/validateAbloOptions.js +43 -0
  58. package/dist/local/client/wsMutationExecutor.d.ts +27 -0
  59. package/dist/local/client/wsMutationExecutor.js +72 -0
  60. package/dist/local/context.d.ts +42 -0
  61. package/dist/local/context.js +81 -0
  62. package/dist/local/coordination/ClaimLog.d.ts +26 -0
  63. package/dist/local/coordination/ClaimLog.js +32 -0
  64. package/dist/local/interfaces/index.d.ts +311 -0
  65. package/dist/local/interfaces/index.js +9 -0
  66. package/dist/local/localModelContract.d.ts +14 -0
  67. package/dist/local/localModelContract.js +1 -0
  68. package/dist/local/logPosition.d.ts +31 -0
  69. package/dist/local/logPosition.js +53 -0
  70. package/dist/local/mutationPersistence.d.ts +6 -0
  71. package/dist/local/mutationPersistence.js +1 -0
  72. package/dist/local/mutators/RecordingMutation.d.ts +36 -0
  73. package/dist/local/mutators/RecordingMutation.js +182 -0
  74. package/dist/local/mutators/Transaction.d.ts +40 -0
  75. package/dist/local/mutators/Transaction.js +58 -0
  76. package/dist/local/mutators/UndoManager.d.ts +258 -0
  77. package/dist/local/mutators/UndoManager.js +665 -0
  78. package/dist/local/mutators/defineMutators.d.ts +60 -0
  79. package/dist/local/mutators/defineMutators.js +18 -0
  80. package/dist/local/mutators/inverseOp.d.ts +126 -0
  81. package/dist/local/mutators/inverseOp.js +71 -0
  82. package/dist/local/mutators/mutateActions.d.ts +45 -0
  83. package/dist/local/mutators/mutateActions.js +105 -0
  84. package/dist/local/mutators/readerActions.d.ts +33 -0
  85. package/dist/local/mutators/readerActions.js +57 -0
  86. package/dist/local/mutators/undoApply.d.ts +51 -0
  87. package/dist/local/mutators/undoApply.js +117 -0
  88. package/dist/local/persistence.d.ts +7 -0
  89. package/dist/local/persistence.js +9 -0
  90. package/dist/local/query/QueryProcessor.d.ts +75 -0
  91. package/dist/local/query/QueryProcessor.js +255 -0
  92. package/dist/local/query/client.d.ts +64 -0
  93. package/dist/local/query/client.js +138 -0
  94. package/dist/local/query/types.d.ts +85 -0
  95. package/dist/local/query/types.js +16 -0
  96. package/dist/local/schema/serialize.d.ts +1 -0
  97. package/dist/local/schema/serialize.js +1 -0
  98. package/dist/local/store/queryApi.d.ts +13 -0
  99. package/dist/local/store/queryApi.js +35 -0
  100. package/dist/local/storeContract.d.ts +145 -0
  101. package/dist/local/storeContract.js +12 -0
  102. package/dist/local/stores/DatabaseManager.d.ts +112 -0
  103. package/dist/local/stores/DatabaseManager.js +400 -0
  104. package/dist/local/stores/ObjectStore.d.ts +115 -0
  105. package/dist/local/stores/ObjectStore.js +393 -0
  106. package/dist/local/stores/ObjectStoreContract.d.ts +38 -0
  107. package/dist/local/stores/ObjectStoreContract.js +1 -0
  108. package/dist/local/stores/StoreManager.d.ts +114 -0
  109. package/dist/local/stores/StoreManager.js +304 -0
  110. package/dist/local/stores/SyncActionStore.d.ts +99 -0
  111. package/dist/local/stores/SyncActionStore.js +506 -0
  112. package/dist/local/stores/openIDBWithTimeout.d.ts +65 -0
  113. package/dist/local/stores/openIDBWithTimeout.js +153 -0
  114. package/dist/local/stores/persistenceCleanup.d.ts +7 -0
  115. package/dist/local/stores/persistenceCleanup.js +26 -0
  116. package/dist/local/stores/persistenceIdentity.d.ts +27 -0
  117. package/dist/local/stores/persistenceIdentity.js +38 -0
  118. package/dist/local/stores/syncAction.d.ts +26 -0
  119. package/dist/local/stores/syncAction.js +16 -0
  120. package/dist/local/stores/v1PersistenceDeletion.d.ts +8 -0
  121. package/dist/local/stores/v1PersistenceDeletion.js +16 -0
  122. package/dist/local/sync/BootstrapFetcher.d.ts +284 -0
  123. package/dist/local/sync/BootstrapFetcher.js +964 -0
  124. package/dist/local/sync/ConnectionManager.d.ts +8 -0
  125. package/dist/local/sync/ConnectionManager.js +8 -0
  126. package/dist/local/sync/OnDemandLoader.d.ts +231 -0
  127. package/dist/local/sync/OnDemandLoader.js +743 -0
  128. package/dist/local/sync/SubscriptionManager.d.ts +159 -0
  129. package/dist/local/sync/SubscriptionManager.js +243 -0
  130. package/dist/local/sync/SyncWebSocket.d.ts +173 -0
  131. package/dist/local/sync/SyncWebSocket.js +438 -0
  132. package/dist/local/sync/bootstrapApply.d.ts +73 -0
  133. package/dist/local/sync/bootstrapApply.js +73 -0
  134. package/dist/local/sync/commitFrames.d.ts +8 -0
  135. package/dist/local/sync/commitFrames.js +8 -0
  136. package/dist/local/sync/connectionManagerLifecycle.d.ts +23 -0
  137. package/dist/local/sync/connectionManagerLifecycle.js +126 -0
  138. package/dist/local/sync/contextPorts.d.ts +18 -0
  139. package/dist/local/sync/contextPorts.js +31 -0
  140. package/dist/local/sync/createClaimStream.d.ts +64 -0
  141. package/dist/local/sync/createClaimStream.js +475 -0
  142. package/dist/local/sync/createSnapshot.d.ts +29 -0
  143. package/dist/local/sync/createSnapshot.js +116 -0
  144. package/dist/local/sync/credentialLifecycle.d.ts +7 -0
  145. package/dist/local/sync/credentialLifecycle.js +7 -0
  146. package/dist/local/sync/deltaPipeline.d.ts +116 -0
  147. package/dist/local/sync/deltaPipeline.js +357 -0
  148. package/dist/local/sync/groupChange.d.ts +116 -0
  149. package/dist/local/sync/groupChange.js +244 -0
  150. package/dist/local/sync/initialize.d.ts +27 -0
  151. package/dist/local/sync/initialize.js +137 -0
  152. package/dist/local/sync/participants.d.ts +132 -0
  153. package/dist/local/sync/participants.js +342 -0
  154. package/dist/local/sync/persistedPrefix.d.ts +12 -0
  155. package/dist/local/sync/persistedPrefix.js +22 -0
  156. package/dist/local/sync/reconnect.d.ts +23 -0
  157. package/dist/local/sync/reconnect.js +55 -0
  158. package/dist/local/sync/schemaDrift.d.ts +55 -0
  159. package/dist/local/sync/schemaDrift.js +53 -0
  160. package/dist/local/sync/schemas.d.ts +71 -0
  161. package/dist/local/sync/schemas.js +94 -0
  162. package/dist/local/sync/socketEventWiring.d.ts +31 -0
  163. package/dist/local/sync/socketEventWiring.js +130 -0
  164. package/dist/local/sync/syncCursor.d.ts +40 -0
  165. package/dist/local/sync/syncCursor.js +55 -0
  166. package/dist/local/sync/syncPlan.d.ts +54 -0
  167. package/dist/local/sync/syncPlan.js +50 -0
  168. package/dist/local/sync/terminalSessionLifecycle.d.ts +20 -0
  169. package/dist/local/sync/terminalSessionLifecycle.js +50 -0
  170. package/dist/local/sync/wsFrameHandlers.d.ts +8 -0
  171. package/dist/local/sync/wsFrameHandlers.js +8 -0
  172. package/dist/local/transactions/databaseCommitOutbox.d.ts +15 -0
  173. package/dist/local/transactions/databaseCommitOutbox.js +16 -0
  174. package/dist/local/transactions/localMutation.d.ts +10 -0
  175. package/dist/local/transactions/localMutation.js +37 -0
  176. package/dist/local/transactions/mutations/MutationQueue.d.ts +511 -0
  177. package/dist/local/transactions/mutations/MutationQueue.js +1498 -0
  178. package/dist/local/transactions/mutations/MutationStore.d.ts +20 -0
  179. package/dist/local/transactions/mutations/MutationStore.js +53 -0
  180. package/dist/local/transactions/mutations/UnconfirmedWrites.d.ts +82 -0
  181. package/dist/local/transactions/mutations/UnconfirmedWrites.js +104 -0
  182. package/dist/local/transactions/mutations/batchProcessing.d.ts +64 -0
  183. package/dist/local/transactions/mutations/batchProcessing.js +349 -0
  184. package/dist/local/transactions/mutations/coalesceRules.d.ts +58 -0
  185. package/dist/local/transactions/mutations/coalesceRules.js +140 -0
  186. package/dist/local/transactions/mutations/commitApi.d.ts +19 -0
  187. package/dist/local/transactions/mutations/commitApi.js +74 -0
  188. package/dist/local/transactions/mutations/commitLane.d.ts +70 -0
  189. package/dist/local/transactions/mutations/commitLane.js +140 -0
  190. package/dist/local/transactions/mutations/commitLatency.d.ts +52 -0
  191. package/dist/local/transactions/mutations/commitLatency.js +130 -0
  192. package/dist/local/transactions/mutations/commitPayload.d.ts +165 -0
  193. package/dist/local/transactions/mutations/commitPayload.js +152 -0
  194. package/dist/local/transactions/mutations/commitTransport.d.ts +36 -0
  195. package/dist/local/transactions/mutations/commitTransport.js +104 -0
  196. package/dist/local/transactions/mutations/deltaConfirmation.d.ts +63 -0
  197. package/dist/local/transactions/mutations/deltaConfirmation.js +235 -0
  198. package/dist/local/transactions/mutations/durableCommitRestore.d.ts +17 -0
  199. package/dist/local/transactions/mutations/durableCommitRestore.js +95 -0
  200. package/dist/local/transactions/mutations/durableWriteStore.d.ts +14 -0
  201. package/dist/local/transactions/mutations/durableWriteStore.js +12 -0
  202. package/dist/local/transactions/mutations/executionSelection.d.ts +6 -0
  203. package/dist/local/transactions/mutations/executionSelection.js +42 -0
  204. package/dist/local/transactions/mutations/failureHandling.d.ts +16 -0
  205. package/dist/local/transactions/mutations/failureHandling.js +130 -0
  206. package/dist/local/transactions/mutations/failurePolicy.d.ts +13 -0
  207. package/dist/local/transactions/mutations/failurePolicy.js +48 -0
  208. package/dist/local/transactions/mutations/localMutation.d.ts +58 -0
  209. package/dist/local/transactions/mutations/localMutation.js +75 -0
  210. package/dist/local/transactions/mutations/modelOperations.d.ts +44 -0
  211. package/dist/local/transactions/mutations/modelOperations.js +144 -0
  212. package/dist/local/transactions/mutations/mutationPersistence.d.ts +25 -0
  213. package/dist/local/transactions/mutations/mutationPersistence.js +188 -0
  214. package/dist/local/transactions/mutations/pendingDrain.d.ts +33 -0
  215. package/dist/local/transactions/mutations/pendingDrain.js +112 -0
  216. package/dist/local/transactions/mutations/processingScheduler.d.ts +14 -0
  217. package/dist/local/transactions/mutations/processingScheduler.js +24 -0
  218. package/dist/local/transactions/mutations/queueCoalescing.d.ts +13 -0
  219. package/dist/local/transactions/mutations/queueCoalescing.js +35 -0
  220. package/dist/local/transactions/mutations/replayValidation.d.ts +187 -0
  221. package/dist/local/transactions/mutations/replayValidation.js +164 -0
  222. package/dist/local/transactions/reconnectDrain.d.ts +11 -0
  223. package/dist/local/transactions/reconnectDrain.js +13 -0
  224. package/dist/local/utils/mobxSetup.d.ts +53 -0
  225. package/dist/local/utils/mobxSetup.js +330 -0
  226. package/dist/local/views/QueryView.d.ts +79 -0
  227. package/dist/local/views/QueryView.js +218 -0
  228. package/dist/local/views/ViewRegistry.d.ts +20 -0
  229. package/dist/local/views/ViewRegistry.js +57 -0
  230. package/dist/local/views/incrementalView.d.ts +45 -0
  231. package/dist/local/views/incrementalView.js +69 -0
  232. package/dist/plugin.d.ts +285 -0
  233. package/dist/plugin.js +106 -0
  234. package/dist/presenceStream.d.ts +69 -0
  235. package/dist/presenceStream.js +200 -0
  236. package/dist/react/AbloProvider.d.ts +242 -0
  237. package/dist/react/AbloProvider.js +456 -0
  238. package/dist/react/ClientSideSuspense.d.ts +36 -0
  239. package/dist/react/ClientSideSuspense.js +17 -0
  240. package/dist/react/DefaultFallback.d.ts +24 -0
  241. package/dist/react/DefaultFallback.js +43 -0
  242. package/dist/react/context.d.ts +55 -0
  243. package/dist/react/context.js +29 -0
  244. package/dist/react/createAbloReact.d.ts +50 -0
  245. package/dist/react/createAbloReact.js +48 -0
  246. package/dist/react/internalContext.d.ts +33 -0
  247. package/dist/react/internalContext.js +3 -0
  248. package/dist/react/useAblo.d.ts +96 -0
  249. package/dist/react/useAblo.js +120 -0
  250. package/dist/react/useCurrentUserId.d.ts +2 -0
  251. package/dist/react/useCurrentUserId.js +12 -0
  252. package/dist/react/useErrorListener.d.ts +2 -0
  253. package/dist/react/useErrorListener.js +14 -0
  254. package/dist/react/useMutationFailureListener.d.ts +8 -0
  255. package/dist/react/useMutationFailureListener.js +19 -0
  256. package/dist/react/useMutators.d.ts +56 -0
  257. package/dist/react/useMutators.js +84 -0
  258. package/dist/react/useSyncStatus.d.ts +19 -0
  259. package/dist/react/useSyncStatus.js +37 -0
  260. package/dist/react/useUndoScope.d.ts +34 -0
  261. package/dist/react/useUndoScope.js +73 -0
  262. package/dist/react.d.ts +18 -0
  263. package/dist/react.js +14 -0
  264. package/dist/reactRuntime.d.ts +4 -0
  265. package/dist/reactRuntime.js +2 -0
  266. package/dist/surface.d.ts +36 -0
  267. package/dist/surface.js +77 -0
  268. package/dist/useReactive.d.ts +6 -0
  269. package/dist/useReactive.js +43 -0
  270. package/package.json +119 -0
  271. package/src/Ablo.ts +456 -0
  272. package/src/client.ts +374 -0
  273. package/src/core.ts +104 -0
  274. package/src/humans.ts +61 -0
  275. package/src/index.ts +40 -0
  276. package/src/local/BaseSyncedStore.ts +1991 -0
  277. package/src/local/Database.ts +2052 -0
  278. package/src/local/InstanceCache.ts +1503 -0
  279. package/src/local/LazyReferenceCollection.ts +563 -0
  280. package/src/local/Model.ts +1124 -0
  281. package/src/local/ModelRegistry.ts +762 -0
  282. package/src/local/NetworkMonitor.ts +88 -0
  283. package/src/local/RuntimeContext.ts +141 -0
  284. package/src/local/SyncClient.ts +2131 -0
  285. package/src/local/adapters/alwaysOnline.ts +20 -0
  286. package/src/local/adapters/inMemoryStorage.ts +141 -0
  287. package/src/local/client/clientPrelude.ts +112 -0
  288. package/src/local/client/consoleLogger.ts +60 -0
  289. package/src/local/client/createInternalComponents.ts +163 -0
  290. package/src/local/client/createModelProxy.ts +1390 -0
  291. package/src/local/client/modelRegistration.ts +350 -0
  292. package/src/local/client/options.ts +526 -0
  293. package/src/local/client/reactiveEngine.ts +935 -0
  294. package/src/local/client/resourceTypes.ts +37 -0
  295. package/src/local/client/schemaConfig.ts +194 -0
  296. package/src/local/client/storeCluster.ts +172 -0
  297. package/src/local/client/storeLifecycle.ts +343 -0
  298. package/src/local/client/validateAbloOptions.ts +95 -0
  299. package/src/local/client/wsMutationExecutor.ts +110 -0
  300. package/src/local/context.ts +96 -0
  301. package/src/local/coordination/ClaimLog.ts +39 -0
  302. package/src/local/interfaces/index.ts +468 -0
  303. package/src/local/localModelContract.ts +15 -0
  304. package/src/local/logPosition.ts +84 -0
  305. package/src/local/mutationPersistence.ts +7 -0
  306. package/src/local/mutators/RecordingMutation.ts +222 -0
  307. package/src/local/mutators/Transaction.ts +97 -0
  308. package/src/local/mutators/UndoManager.ts +741 -0
  309. package/src/local/mutators/defineMutators.ts +76 -0
  310. package/src/local/mutators/inverseOp.ts +83 -0
  311. package/src/local/mutators/mutateActions.ts +167 -0
  312. package/src/local/mutators/readerActions.ts +99 -0
  313. package/src/local/mutators/undoApply.ts +141 -0
  314. package/src/local/persistence.ts +16 -0
  315. package/src/local/query/QueryProcessor.ts +347 -0
  316. package/src/local/query/client.ts +197 -0
  317. package/src/local/query/types.ts +102 -0
  318. package/src/local/schema/serialize.ts +1 -0
  319. package/src/local/store/queryApi.ts +56 -0
  320. package/src/local/storeContract.ts +146 -0
  321. package/src/local/stores/DatabaseManager.ts +507 -0
  322. package/src/local/stores/ObjectStore.ts +449 -0
  323. package/src/local/stores/ObjectStoreContract.ts +48 -0
  324. package/src/local/stores/StoreManager.ts +388 -0
  325. package/src/local/stores/SyncActionStore.ts +579 -0
  326. package/src/local/stores/openIDBWithTimeout.ts +195 -0
  327. package/src/local/stores/persistenceCleanup.ts +43 -0
  328. package/src/local/stores/persistenceIdentity.ts +83 -0
  329. package/src/local/stores/syncAction.ts +21 -0
  330. package/src/local/stores/v1PersistenceDeletion.ts +21 -0
  331. package/src/local/sync/BootstrapFetcher.ts +1224 -0
  332. package/src/local/sync/ConnectionManager.ts +15 -0
  333. package/src/local/sync/OnDemandLoader.ts +927 -0
  334. package/src/local/sync/SubscriptionManager.ts +300 -0
  335. package/src/local/sync/SyncWebSocket.ts +584 -0
  336. package/src/local/sync/bootstrapApply.ts +130 -0
  337. package/src/local/sync/commitFrames.ts +16 -0
  338. package/src/local/sync/connectionManagerLifecycle.ts +158 -0
  339. package/src/local/sync/contextPorts.ts +37 -0
  340. package/src/local/sync/createClaimStream.ts +668 -0
  341. package/src/local/sync/createSnapshot.ts +160 -0
  342. package/src/local/sync/credentialLifecycle.ts +18 -0
  343. package/src/local/sync/deltaPipeline.ts +473 -0
  344. package/src/local/sync/groupChange.ts +343 -0
  345. package/src/local/sync/initialize.ts +205 -0
  346. package/src/local/sync/participants.ts +564 -0
  347. package/src/local/sync/persistedPrefix.ts +27 -0
  348. package/src/local/sync/reconnect.ts +88 -0
  349. package/src/local/sync/schemaDrift.ts +86 -0
  350. package/src/local/sync/schemas.ts +118 -0
  351. package/src/local/sync/socketEventWiring.ts +196 -0
  352. package/src/local/sync/syncCursor.ts +62 -0
  353. package/src/local/sync/syncPlan.ts +89 -0
  354. package/src/local/sync/terminalSessionLifecycle.ts +66 -0
  355. package/src/local/sync/wsFrameHandlers.ts +20 -0
  356. package/src/local/transactions/databaseCommitOutbox.ts +33 -0
  357. package/src/local/transactions/localMutation.ts +58 -0
  358. package/src/local/transactions/mutations/MutationQueue.ts +1998 -0
  359. package/src/local/transactions/mutations/MutationStore.ts +65 -0
  360. package/src/local/transactions/mutations/UnconfirmedWrites.ts +133 -0
  361. package/src/local/transactions/mutations/batchProcessing.ts +469 -0
  362. package/src/local/transactions/mutations/coalesceRules.ts +192 -0
  363. package/src/local/transactions/mutations/commitApi.ts +97 -0
  364. package/src/local/transactions/mutations/commitLane.ts +191 -0
  365. package/src/local/transactions/mutations/commitLatency.ts +164 -0
  366. package/src/local/transactions/mutations/commitPayload.ts +281 -0
  367. package/src/local/transactions/mutations/commitTransport.ts +174 -0
  368. package/src/local/transactions/mutations/deltaConfirmation.ts +298 -0
  369. package/src/local/transactions/mutations/durableCommitRestore.ts +128 -0
  370. package/src/local/transactions/mutations/durableWriteStore.ts +21 -0
  371. package/src/local/transactions/mutations/executionSelection.ts +42 -0
  372. package/src/local/transactions/mutations/failureHandling.ts +154 -0
  373. package/src/local/transactions/mutations/failurePolicy.ts +61 -0
  374. package/src/local/transactions/mutations/localMutation.ts +135 -0
  375. package/src/local/transactions/mutations/modelOperations.ts +210 -0
  376. package/src/local/transactions/mutations/mutationPersistence.ts +231 -0
  377. package/src/local/transactions/mutations/pendingDrain.ts +160 -0
  378. package/src/local/transactions/mutations/processingScheduler.ts +35 -0
  379. package/src/local/transactions/mutations/queueCoalescing.ts +45 -0
  380. package/src/local/transactions/mutations/replayValidation.ts +192 -0
  381. package/src/local/transactions/reconnectDrain.ts +24 -0
  382. package/src/local/utils/mobxSetup.ts +388 -0
  383. package/src/local/views/QueryView.ts +311 -0
  384. package/src/local/views/ViewRegistry.ts +61 -0
  385. package/src/local/views/incrementalView.ts +92 -0
  386. package/src/plugin.ts +396 -0
  387. package/src/presenceStream.ts +279 -0
  388. package/src/react/AbloProvider.tsx +744 -0
  389. package/src/react/ClientSideSuspense.tsx +57 -0
  390. package/src/react/DefaultFallback.tsx +60 -0
  391. package/src/react/context.ts +89 -0
  392. package/src/react/createAbloReact.ts +116 -0
  393. package/src/react/internalContext.ts +38 -0
  394. package/src/react/useAblo.ts +280 -0
  395. package/src/react/useCurrentUserId.ts +17 -0
  396. package/src/react/useErrorListener.ts +22 -0
  397. package/src/react/useMutationFailureListener.ts +34 -0
  398. package/src/react/useMutators.ts +184 -0
  399. package/src/react/useSyncStatus.ts +42 -0
  400. package/src/react/useUndoScope.ts +143 -0
  401. package/src/react.ts +69 -0
  402. package/src/reactRuntime.ts +10 -0
  403. package/src/surface.ts +106 -0
  404. package/src/useReactive.ts +51 -0
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+
3
+ import { useContext, useEffect, useRef } from 'react';
4
+ import {
5
+ AbloInternalContext,
6
+ type QueuedMutation,
7
+ } from '../reactRuntime.js';
8
+ import { AbloValidationError } from '@abloatai/transaction/errors';
9
+
10
+ export interface MutationFailurePayload {
11
+ transaction: QueuedMutation;
12
+ error: Error;
13
+ permanent?: boolean;
14
+ }
15
+
16
+ /** Subscribe to optimistic mutation rollbacks and permanent write failures. */
17
+ export function useMutationFailureListener(
18
+ listener: (payload: MutationFailurePayload) => void,
19
+ ): void {
20
+ const context = useContext(AbloInternalContext);
21
+ if (!context) {
22
+ throw new AbloValidationError(
23
+ 'useMutationFailureListener: no <AbloProvider> mounted above this component.',
24
+ { code: 'no_ablo_provider' },
25
+ );
26
+ }
27
+ const listenerRef = useRef(listener);
28
+ listenerRef.current = listener;
29
+ useEffect(() => {
30
+ const engine = context.engine;
31
+ if (!engine) return;
32
+ return engine.onMutationFailure((payload) => listenerRef.current(payload));
33
+ }, [context, context.engine]);
34
+ }
@@ -0,0 +1,184 @@
1
+ 'use client';
2
+
3
+ import { useMemo } from 'react';
4
+ import type { Schema } from '@abloatai/transaction/schema/schema';
5
+ import type {
6
+ MutatorDefs,
7
+ MutatorFn,
8
+ } from '../local/mutators/defineMutators.js';
9
+ import { createTransaction } from '../local/mutators/Transaction.js';
10
+ import { createRecordingMutation } from '../local/mutators/RecordingMutation.js';
11
+ import type { UndoScope } from '../local/mutators/UndoManager.js';
12
+ import type { ResolveSchema } from '@abloatai/transaction/types/global';
13
+ import { useSyncContext } from './context.js';
14
+ import { AbloValidationError } from '@abloatai/transaction/errors';
15
+ import { getContext } from '../local/context.js';
16
+
17
+ /**
18
+ * Turns a mutator tree built with `defineMutators` into callable invokers. The
19
+ * returned object mirrors that tree one-to-one, but each leaf becomes an
20
+ * `(args) => Promise<TResult>` function.
21
+ *
22
+ * Each invocation builds a fresh `Transaction` bound to the current store and
23
+ * organization, calls your mutator with `{ tx, args }`, and returns whatever
24
+ * the mutator resolves to.
25
+ *
26
+ * If a mutator throws, the error propagates to the caller and any writes it
27
+ * already dispatched stay in place — there is no automatic rollback. Wrap the
28
+ * call in your own try/catch and issue compensating writes when you need to
29
+ * undo a partial change, or pass an `undoScope` (see {@link UseMutatorsOptions})
30
+ * to record inverses for undo and redo.
31
+ */
32
+
33
+ /**
34
+ * Map a `MutatorFn` onto its invoker form — strip `tx`, keep `args`/return.
35
+ *
36
+ * Uses nested `infer O` so the `args`/`result` types are extracted from the
37
+ * function signature without binding the `tx` parameter to a specific
38
+ * `Transaction<S>` variance. Function parameters are contravariant, so a
39
+ * match against `MutatorFn<Schema>` would reject mutators declared against
40
+ * a narrower schema (e.g. `Transaction<typeof appSchema>`). The two-step
41
+ * inference sidesteps that without resorting to `any`/`unknown` placeholders.
42
+ */
43
+ export type InvokerFor<F> = F extends (options: infer O) => Promise<infer R>
44
+ ? O extends { args: infer A }
45
+ ? (args: A) => Promise<R>
46
+ : never
47
+ : never;
48
+
49
+ /**
50
+ * The hook's return shape: same tree as the input `MutatorDefs`, every leaf
51
+ * rewritten to its invoker form.
52
+ */
53
+ export type MutatorInvokers<M> = {
54
+ [K in keyof M]: {
55
+ [N in keyof M[K]]: InvokerFor<M[K][N]>;
56
+ };
57
+ };
58
+
59
+ /**
60
+ * Options passed to `useMutators`. When `undoScope` is set, every mutator
61
+ * invocation is wrapped in a `RecordingMutation` and its inverses are
62
+ * pushed to the scope as one undo entry.
63
+ */
64
+ export interface UseMutatorsOptions<S extends Schema> {
65
+ /** Target undo scope for recording inverses. Omit to disable recording. */
66
+ undoScope?: UndoScope<S>;
67
+ }
68
+
69
+ /** Mutator invokers (explicit schema arg). */
70
+ export function useMutators<S extends Schema, M extends MutatorDefs<S>>(
71
+ schema: S,
72
+ mutators: M,
73
+ options?: UseMutatorsOptions<S>,
74
+ ): MutatorInvokers<M>;
75
+
76
+ /** Mutator invokers via the `Register` module augmentation. Schema comes
77
+ * from the `SyncProvider`'s context; the mutator tree is typed against
78
+ * `ResolveSchema` at the call site. */
79
+ export function useMutators<
80
+ M extends ResolveSchema extends Schema ? MutatorDefs<ResolveSchema> : MutatorDefs<Schema>,
81
+ >(
82
+ mutators: M,
83
+ options?: UseMutatorsOptions<ResolveSchema extends Schema ? ResolveSchema : Schema>,
84
+ ): MutatorInvokers<M>;
85
+
86
+ export function useMutators(
87
+ schemaOrMutators: Schema | MutatorDefs<Schema>,
88
+ mutatorsOrOptions?: MutatorDefs<Schema> | UseMutatorsOptions<Schema>,
89
+ maybeOptions?: UseMutatorsOptions<Schema>,
90
+ ): MutatorInvokers<MutatorDefs<Schema>> {
91
+ const { store, organizationId, schema: ctxSchema } = useSyncContext();
92
+
93
+ // Disambiguate: explicit-schema path has the schema object in first slot;
94
+ // the global-resolved path has the mutator tree there. A schema object
95
+ // has a `.models` property; a mutator tree doesn't.
96
+ const isExplicit =
97
+ typeof schemaOrMutators === 'object' &&
98
+ schemaOrMutators !== null &&
99
+ 'models' in schemaOrMutators;
100
+
101
+ const schema = isExplicit ? (schemaOrMutators as Schema) : ctxSchema;
102
+ const mutators = (isExplicit ? mutatorsOrOptions : schemaOrMutators) as MutatorDefs<Schema>;
103
+ const options = (isExplicit ? maybeOptions : mutatorsOrOptions) as
104
+ | UseMutatorsOptions<Schema>
105
+ | undefined;
106
+
107
+ if (!schema) {
108
+ throw new AbloValidationError(
109
+ 'useMutators: no schema available. Pass the schema as the first arg, ' +
110
+ 'or build the <AbloProvider> above with `Ablo({ schema })` so the ' +
111
+ 'zero-arg overload can read it from context.',
112
+ { code: 'mutators_schema_missing' },
113
+ );
114
+ }
115
+
116
+ const { undoScope } = options ?? {};
117
+
118
+ return useMemo<MutatorInvokers<MutatorDefs<Schema>>>(() => {
119
+ const out: Record<string, Record<string, (args: unknown) => Promise<unknown>>> = {};
120
+
121
+ for (const modelKey of Object.keys(mutators)) {
122
+ const group = (mutators as Record<string, Record<string, MutatorFn<Schema, unknown, unknown>>>)[modelKey];
123
+ if (!group) continue;
124
+
125
+ const invokers: Record<string, (args: unknown) => Promise<unknown>> = {};
126
+ for (const mutatorName of Object.keys(group)) {
127
+ const maybeFn = group[mutatorName];
128
+ if (!maybeFn) continue;
129
+ // Bind the narrowed value: `noUncheckedIndexedAccess` types the indexed
130
+ // read as `Fn | undefined`, and that narrowing doesn't survive into the
131
+ // deferred invoker closures below — a non-optional local does.
132
+ const fn = maybeFn;
133
+ const label = `${String(modelKey)}.${mutatorName}`;
134
+
135
+ invokers[mutatorName] = async (args: unknown) => {
136
+ // Recording path: wrap the transaction so each write snapshots its
137
+ // inverse. On success, push the captured entry to the scope.
138
+ //
139
+ // The whole snapshot → write → record sequence runs on the scope's
140
+ // serialization chain so concurrent invocations (a caller may fire
141
+ // writes without awaiting them) record in invocation order and never
142
+ // interleave their shared-model snapshots. See UndoScope.runRecorded.
143
+ if (undoScope) {
144
+ return undoScope.runRecorded(async () => {
145
+ const recording = createRecordingMutation(schema, store, organizationId);
146
+ try {
147
+ const result = await fn({ tx: recording.tx, args });
148
+ const entry = recording.getEntry(label);
149
+ if (entry) undoScope.record(entry);
150
+ return result;
151
+ } catch (err) {
152
+ // The error is re-thrown to the caller's await (the real
153
+ // consumer surface), so this is a forensic follow-on → debug.
154
+ getContext().logger.debug(
155
+ `[useMutators] mutator "${label}" threw`,
156
+ { error: err },
157
+ );
158
+ throw err;
159
+ }
160
+ });
161
+ }
162
+
163
+ // Non-recording path — plain transaction, no inverse capture.
164
+ const tx = createTransaction(schema, store, organizationId);
165
+ try {
166
+ return await fn({ tx, args });
167
+ } catch (err) {
168
+ // Re-thrown to the caller's await (the real consumer surface) →
169
+ // this duplicate is forensic, debug only.
170
+ getContext().logger.debug(
171
+ `[useMutators] mutator "${label}" threw`,
172
+ { error: err },
173
+ );
174
+ throw err;
175
+ }
176
+ };
177
+ }
178
+
179
+ out[modelKey] = invokers;
180
+ }
181
+
182
+ return out;
183
+ }, [schema, mutators, store, organizationId, undoScope]);
184
+ }
@@ -0,0 +1,42 @@
1
+ 'use client';
2
+
3
+ import { useCallback } from 'react';
4
+ import {
5
+ useSyncContext,
6
+ type SyncStoreContract,
7
+ } from './context.js';
8
+ import { useReactive } from '../useReactive.js';
9
+
10
+ export type SyncStatusSnapshot =
11
+ | { readonly name: 'initial' }
12
+ | { readonly name: 'connecting'; readonly progress: number }
13
+ | { readonly name: 'connected'; readonly hasUnsyncedChanges: boolean }
14
+ | { readonly name: 'reconnecting'; readonly reason?: string }
15
+ | { readonly name: 'disconnected'; readonly reason?: string }
16
+ | { readonly name: 'needs-auth' };
17
+
18
+ /** Reactively exposes the local store's connection and settlement status. */
19
+ export function useSyncStatus(): SyncStatusSnapshot {
20
+ const { store } = useSyncContext();
21
+ const compute = useCallback(() => deriveStatus(store), [store]);
22
+ return useReactive(compute, sameSnapshot);
23
+ }
24
+
25
+ function deriveStatus(store: SyncStoreContract): SyncStatusSnapshot {
26
+ const { state, progress, pendingChanges, isSessionError, error } = store.syncStatus;
27
+ if (isSessionError) return { name: 'needs-auth' };
28
+ if (state === 'reconnecting') return { name: 'reconnecting', reason: error?.message };
29
+ if (state === 'offline') return { name: 'disconnected', reason: 'offline' };
30
+ if (state === 'error') return { name: 'disconnected', reason: error?.message };
31
+ if (store.isReady) return { name: 'connected', hasUnsyncedChanges: pendingChanges > 0 };
32
+ if (state === 'idle' || state === 'syncing') return { name: 'connecting', progress };
33
+ return { name: 'initial' };
34
+ }
35
+
36
+ function sameSnapshot(a: SyncStatusSnapshot, b: SyncStatusSnapshot): boolean {
37
+ if (a.name !== b.name) return false;
38
+ if (a.name === 'initial' || a.name === 'needs-auth') return true;
39
+ if (a.name === 'connecting') return b.name === 'connecting' && a.progress === b.progress;
40
+ if (a.name === 'connected') return b.name === 'connected' && a.hasUnsyncedChanges === b.hasUnsyncedChanges;
41
+ return (b.name === 'reconnecting' || b.name === 'disconnected') && a.reason === b.reason;
42
+ }
@@ -0,0 +1,143 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useMemo, useState } from 'react';
4
+ import type { Schema } from '@abloatai/transaction/schema/schema';
5
+ import {
6
+ UndoManager,
7
+ type UndoScope,
8
+ type UndoScopeOptions,
9
+ } from '../local/mutators/UndoManager.js';
10
+ import type { ResolveSchema } from '@abloatai/transaction/types/global';
11
+ import { useSyncContext } from './context.js';
12
+ import { AbloValidationError } from '@abloatai/transaction/errors';
13
+
14
+ /**
15
+ * Provides per-surface undo and redo for mutator invocations. Each named scope
16
+ * owns an independent undo/redo stack, so different parts of your app — a main
17
+ * editor, a sidebar form — can undo separately without stepping on each other.
18
+ *
19
+ * Wire the returned `scope` into `useMutators(schema, mutators, { undoScope:
20
+ * scope })` and those invocations become recorded. `undo()` and `redo()` replay
21
+ * the captured inverses and forwards as new transactions that do not record
22
+ * themselves; the manager moves the entry between the two stacks explicitly.
23
+ *
24
+ * @example
25
+ * const { undo, redo, canUndo, canRedo, scope } = useUndoScope('report-editor');
26
+ * const mutate = useMutators(schema, reportMutators, { undoScope: scope });
27
+ *
28
+ * // Cmd+Z handler
29
+ * useHotkey('mod+z', () => { if (canUndo) void undo(); });
30
+ */
31
+
32
+ export interface UseUndoScopeResult<S extends Schema> {
33
+ /** Pass to `useMutators(..., { undoScope })` to enable recording. */
34
+ scope: UndoScope<S>;
35
+ undo: () => Promise<void>;
36
+ redo: () => Promise<void>;
37
+ canUndo: boolean;
38
+ canRedo: boolean;
39
+ /** Drop history. Use after sync errors / auth context changes. */
40
+ clear: () => void;
41
+ }
42
+
43
+ // Module-level weak registry: `SyncStoreContract` → `UndoManager`.
44
+ // A single app wiring through one SyncProvider shares one manager across
45
+ // every useUndoScope call, so scopes with the same name are identity-equal.
46
+ // The hook implementation already operates on the runtime-wide `Schema` type;
47
+ // its overloads restore the caller's precise schema type at the public boundary,
48
+ // so the registry can keep that same non-generic runtime representation.
49
+ const managers = new WeakMap<object, UndoManager<Schema>>();
50
+
51
+ function getManager(
52
+ key: object,
53
+ factory: () => UndoManager<Schema>,
54
+ ): UndoManager<Schema> {
55
+ let m = managers.get(key);
56
+ if (!m) {
57
+ const created = factory();
58
+ managers.set(key, created);
59
+ m = created;
60
+ }
61
+ return m;
62
+ }
63
+
64
+ /** Per-surface undo/redo (explicit schema arg). */
65
+ export function useUndoScope<S extends Schema>(
66
+ schema: S,
67
+ name: string,
68
+ options?: UndoScopeOptions,
69
+ ): UseUndoScopeResult<S>;
70
+
71
+ /** Per-surface undo/redo via the `Register` module augmentation. */
72
+ export function useUndoScope(
73
+ name: string,
74
+ options?: UndoScopeOptions,
75
+ ): UseUndoScopeResult<ResolveSchema extends Schema ? ResolveSchema : Schema>;
76
+
77
+ export function useUndoScope(
78
+ schemaOrName: Schema | string,
79
+ nameOrOptions?: string | UndoScopeOptions,
80
+ maybeOptions?: UndoScopeOptions,
81
+ ): UseUndoScopeResult<Schema> {
82
+ const { store, organizationId, schema: ctxSchema } = useSyncContext();
83
+
84
+ const isExplicit = typeof schemaOrName !== 'string';
85
+ const schema = isExplicit ? (schemaOrName) : ctxSchema;
86
+ const name = isExplicit ? (nameOrOptions as string) : schemaOrName;
87
+ const options = (isExplicit ? maybeOptions : nameOrOptions) as UndoScopeOptions | undefined;
88
+
89
+ if (!schema) {
90
+ throw new AbloValidationError(
91
+ 'useUndoScope: no schema available. Pass the schema as the first arg, ' +
92
+ 'or build the <AbloProvider> above with `Ablo({ schema })` so the ' +
93
+ 'zero-arg overload can read it from context.',
94
+ { code: 'undo_scope_schema_missing' },
95
+ );
96
+ }
97
+
98
+ const scope = useMemo(() => {
99
+ // Store is the identity for the manager — one per SyncProvider.
100
+ const manager = getManager(store, () => new UndoManager(schema, store, organizationId));
101
+ return manager.getScope(name, options);
102
+ // eslint-disable-next-line react-hooks/exhaustive-deps
103
+ }, [store, organizationId, name]);
104
+
105
+ // Local tick forces re-render after undo/redo/clear so canUndo/canRedo
106
+ // reflect the new stack sizes. The scope itself doesn't emit React-
107
+ // friendly notifications; callers that want cross-component reactivity
108
+ // can wire a mobx observable or custom event bus on top.
109
+ const [, setTick] = useState(0);
110
+
111
+ // Reset tick when scope identity changes (new store / new orgId).
112
+ useEffect(() => {
113
+ setTick(0);
114
+ }, [scope]);
115
+
116
+ // Re-render on any stack change — including entries recorded from the local-
117
+ // mutation stream, which don't otherwise trigger a React update. Without this
118
+ // `canUndo`/`canRedo` go stale in every consumer that didn't itself call
119
+ // undo/redo (e.g. a keyboard handler whose Cmd+Z gate then never fires).
120
+ useEffect(() => {
121
+ return scope.onChange(() => { setTick((t: number) => t + 1); });
122
+ }, [scope]);
123
+
124
+ const size = scope.size();
125
+
126
+ return {
127
+ scope,
128
+ undo: async () => {
129
+ await scope.undo();
130
+ setTick((t: number) => t + 1);
131
+ },
132
+ redo: async () => {
133
+ await scope.redo();
134
+ setTick((t: number) => t + 1);
135
+ },
136
+ canUndo: size.undo > 0,
137
+ canRedo: size.redo > 0,
138
+ clear: () => {
139
+ scope.clear();
140
+ setTick((t: number) => t + 1);
141
+ },
142
+ };
143
+ }
package/src/react.ts ADDED
@@ -0,0 +1,69 @@
1
+ /** React bindings for the optional human-facing local-state package. */
2
+ export { useReactive } from './useReactive.js';
3
+ export { useCurrentUserId } from './react/useCurrentUserId.js';
4
+ export { useErrorListener } from './react/useErrorListener.js';
5
+ export { useSyncStatus, type SyncStatusSnapshot } from './react/useSyncStatus.js';
6
+ export {
7
+ useMutationFailureListener,
8
+ type MutationFailurePayload,
9
+ } from './react/useMutationFailureListener.js';
10
+
11
+ export {
12
+ AbloProvider,
13
+ useJoin,
14
+ usePeers,
15
+ useSync,
16
+ useSyncStore,
17
+ type AbloProviderProps,
18
+ type ParticipantScope,
19
+ type ParticipantStatus,
20
+ type UseJoinOptions,
21
+ type UseJoinReturn,
22
+ } from './react/AbloProvider.js';
23
+
24
+ export {
25
+ ClientSideSuspense,
26
+ type ClientSideSuspenseProps,
27
+ } from './react/ClientSideSuspense.js';
28
+
29
+ export { DefaultFallback } from './react/DefaultFallback.js';
30
+
31
+ export {
32
+ createAbloReact,
33
+ type AbloReactBinding,
34
+ } from './react/createAbloReact.js';
35
+
36
+ export {
37
+ useAblo,
38
+ type UseAbloHydratedModelResult,
39
+ type UseAbloModelOptions,
40
+ type UseAbloModelResult,
41
+ } from './react/useAblo.js';
42
+
43
+ export {
44
+ useMutators,
45
+ type InvokerFor,
46
+ type MutatorInvokers,
47
+ type UseMutatorsOptions,
48
+ } from './react/useMutators.js';
49
+
50
+ export {
51
+ useUndoScope,
52
+ type UseUndoScopeResult,
53
+ } from './react/useUndoScope.js';
54
+
55
+ export type {
56
+ DefaultSyncShape,
57
+ ResolveSchema,
58
+ ResolveUserMeta,
59
+ ResolveClaimMeta,
60
+ ResolveModelKey,
61
+ } from '@abloatai/transaction/types/global';
62
+
63
+ export { ModelScope } from '@abloatai/transaction/types';
64
+ export type { SyncStoreContract } from './react/context.js';
65
+ export type { MutateActions } from './local/mutators/mutateActions.js';
66
+ export type {
67
+ ReaderActions,
68
+ ReaderFindOptions,
69
+ } from './local/mutators/readerActions.js';
@@ -0,0 +1,10 @@
1
+ export {
2
+ AbloInternalContext,
3
+ type AbloInternalContextValue,
4
+ } from './react/internalContext.js';
5
+ export {
6
+ useSyncContext,
7
+ type SyncReactContext,
8
+ } from './react/context.js';
9
+ export type { SyncStoreContract } from './local/storeContract.js';
10
+ export type { QueuedMutation } from './local/transactions/mutations/MutationQueue.js';
package/src/surface.ts ADDED
@@ -0,0 +1,106 @@
1
+ /**
2
+ * A machine-checked manifest of this package's public API surface. It lists,
3
+ * as string tuples, the method names on `ablo.<model>`, the keys accepted by
4
+ * the list-style read options, and the keys of the client constructor
5
+ * options. Each tuple is proven equal to the keys of its source interface at
6
+ * compile time, so the lists cannot drift from the real types: add or remove
7
+ * a name on either side without updating the matching tuple and this file
8
+ * fails to compile, in both directions — no name the interface lacks, and no
9
+ * interface key the tuple omits.
10
+ *
11
+ * Documentation tooling reads these tuples to describe the surface, which
12
+ * guarantees a generated summary never names a method or option that does
13
+ * not exist. The names are verified here; their prose descriptions are
14
+ * written by hand, since prose cannot be type-checked.
15
+ */
16
+
17
+ import type { ModelOperations, LocalReadOptions } from './local/client/createModelProxy.js';
18
+ import type { AbloOptions } from './Ablo.js';
19
+
20
+ // ── compile-time exact-equality (no runtime, no casts) ─────────────────────
21
+ // Standard invariant type-equality: true only when A and B are mutually assignable.
22
+ type Equal<A, B> =
23
+ (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false;
24
+ // `Expect<T extends true>` errors at the declaration when T is `false`.
25
+ type Expect<T extends true> = T;
26
+
27
+ // ── the per-`ablo.<model>` verb surface ────────────────────────────────────
28
+ /**
29
+ * The names of every method available on `ablo.<model>`, matching the keys of
30
+ * the {@link ModelOperations} interface. Documentation tooling reads this
31
+ * tuple, so it is the one list of model-verb names a generated summary can
32
+ * describe.
33
+ */
34
+ export const PUBLIC_MODEL_VERBS = [
35
+ 'get',
36
+ 'retrieve',
37
+ 'list',
38
+ 'local',
39
+ 'create',
40
+ 'update',
41
+ 'delete',
42
+ 'claim',
43
+ 'track',
44
+ 'join',
45
+ 'onChange',
46
+ ] as const;
47
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
48
+ type _ModelVerbsExact = Expect<
49
+ Equal<(typeof PUBLIC_MODEL_VERBS)[number], keyof ModelOperations<unknown, unknown> & string>
50
+ >;
51
+
52
+ // ── the read/list query option surface ─────────────────────────────────────
53
+ /**
54
+ * The option keys accepted by `local.list` and `onChange`, matching the
55
+ * keys of {@link LocalReadOptions}. Note that the lifecycle filter is named
56
+ * `state`, not `scope`.
57
+ */
58
+ export const PUBLIC_LIST_OPTION_KEYS = [
59
+ 'where',
60
+ 'filter',
61
+ 'orderBy',
62
+ 'limit',
63
+ 'offset',
64
+ 'state',
65
+ ] as const;
66
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
67
+ type _ListOptionKeysExact = Expect<
68
+ Equal<(typeof PUBLIC_LIST_OPTION_KEYS)[number], keyof LocalReadOptions<unknown> & string>
69
+ >;
70
+
71
+ // ── the `Ablo({ … })` constructor option surface ───────────────────────────
72
+ /**
73
+ * The keys of the client constructor options, {@link AbloOptions}. Only
74
+ * `schema` is required; every other key is optional.
75
+ */
76
+ export const PUBLIC_ABLO_OPTION_KEYS = [
77
+ 'schema',
78
+ 'apiKey',
79
+ 'authEndpoint',
80
+ 'authTimeoutMs',
81
+ 'allowCrossOriginAuthEndpoint',
82
+ 'persistence',
83
+ 'durableWrites',
84
+ 'commitOutbox',
85
+ 'commitOutboxScope',
86
+ 'debug',
87
+ 'logLevel',
88
+ 'logger',
89
+ 'authToken',
90
+ 'baseURL',
91
+ 'fetch',
92
+ 'defaultHeaders',
93
+ 'defaultQuery',
94
+ 'dangerouslyAllowBrowser',
95
+ 'collaborationEvents',
96
+ 'plugins',
97
+ 'wait',
98
+ ] as const;
99
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
100
+ type _AbloOptionKeysExact = Expect<
101
+ Equal<(typeof PUBLIC_ABLO_OPTION_KEYS)[number], keyof AbloOptions & string>
102
+ >;
103
+
104
+ export type ModelVerb = (typeof PUBLIC_MODEL_VERBS)[number];
105
+ export type ListOptionKey = (typeof PUBLIC_LIST_OPTION_KEYS)[number];
106
+ export type AbloOptionKey = (typeof PUBLIC_ABLO_OPTION_KEYS)[number];
@@ -0,0 +1,51 @@
1
+ 'use client';
2
+
3
+ import { useCallback, useRef } from 'react';
4
+ import { useSyncExternalStore } from 'react';
5
+ import { reaction } from 'mobx';
6
+
7
+ /**
8
+ * Subscribe a React component to a MobX computation with a cached snapshot.
9
+ * This is the framework-level reactive primitive owned by @abloatai/humans;
10
+ * store/model hooks are layered above it.
11
+ */
12
+ export function useReactive<T>(
13
+ compute: () => T,
14
+ equals: (a: T, b: T) => boolean = defaultEquals,
15
+ ): T {
16
+ const computeRef = useRef(compute);
17
+ const equalsRef = useRef(equals);
18
+ const snapshotRef = useRef<{ value: T } | null>(null);
19
+ const versionRef = useRef(0);
20
+
21
+ equalsRef.current = equals;
22
+ if (snapshotRef.current === null) {
23
+ snapshotRef.current = { value: compute() };
24
+ } else if (computeRef.current !== compute) {
25
+ const next = compute();
26
+ if (!equals(snapshotRef.current.value, next)) {
27
+ snapshotRef.current = { value: next };
28
+ versionRef.current++;
29
+ }
30
+ }
31
+ computeRef.current = compute;
32
+
33
+ const subscribe = useCallback((onChange: () => void) => reaction(
34
+ () => computeRef.current(),
35
+ (next) => {
36
+ const current = snapshotRef.current!.value;
37
+ if (!equalsRef.current(current, next)) {
38
+ snapshotRef.current = { value: next };
39
+ onChange();
40
+ }
41
+ },
42
+ ), [versionRef.current]);
43
+ const getSnapshot = useCallback(() => snapshotRef.current!.value, []);
44
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
45
+ }
46
+
47
+ function defaultEquals<T>(a: T, b: T): boolean {
48
+ if (Object.is(a, b)) return true;
49
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
50
+ return a.every((value, index) => Object.is(value, b[index]));
51
+ }