@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,762 @@
1
+ /**
2
+ * ModelRegistry is the source of truth for model metadata: which model classes
3
+ * exist, the properties and references declared on each, the back-references
4
+ * used for cascade handling, and a stable hash of the whole schema.
5
+ * {@link Model} instances resolve their metadata through the active registry,
6
+ * and {@link InstanceCache} uses it to map between model names and constructor
7
+ * classes. References resolve lazily, so a model may declare a reference to
8
+ * another model that is registered later.
9
+ */
10
+
11
+ // Removed Node.js crypto import for browser compatibility
12
+ import {
13
+ type ModelMetadata,
14
+ type PropertyMetadata,
15
+ type ReferenceMetadata,
16
+ PropertyType,
17
+ LoadStrategy,
18
+ } from '@abloatai/transaction/types';
19
+ import { globalRuntime } from './context.js';
20
+ import type { RuntimeContext } from './RuntimeContext.js';
21
+ import { AbloValidationError } from '@abloatai/transaction/errors';
22
+ // Type-only — erased at runtime, so no Model ↔ ModelRegistry module cycle.
23
+ import type { Model } from './Model.js';
24
+ import type { ConcreteModelConstructor } from './BaseSyncedStore.js';
25
+
26
+ /**
27
+ * What callers may hand to {@link ModelRegistry.registerModel}: any concrete
28
+ * `Model` subclass constructor. `never[]` params make every subclass
29
+ * constructor assignable (construct-signature params are contravariant).
30
+ */
31
+ export type ModelClassInput = new (...args: never[]) => Model;
32
+
33
+ /**
34
+ * What the registry hands BACK: a registered model class — concretely
35
+ * constructible with an optional data row (`ConcreteModelConstructor`, the
36
+ * SDK's existing Model-vs-row construction seam) and carrying `Model`'s
37
+ * statics (`fromJSON`, …). `Omit<typeof Model, never>` keeps the statics
38
+ * while stripping the ABSTRACT construct signature (mapped types drop
39
+ * construct signatures), so `new registry.getModelByName(n)!(...)` is legal.
40
+ * The one cast from {@link ModelClassInput} lives at the validated
41
+ * registration boundary below.
42
+ */
43
+ export type RegisteredModelClass = Omit<typeof Model, never> &
44
+ ConcreteModelConstructor<Model>;
45
+
46
+ /**
47
+ * {@link ReferenceMetadata} extended with cascade behavior: what happens to a
48
+ * referencing model when the referenced model is deleted or archived.
49
+ */
50
+ export interface ExtendedReferenceMetadata extends ReferenceMetadata {
51
+ onDelete?: 'cascade' | 'nullify' | 'restrict';
52
+ onArchive?: 'cascade' | 'nullify';
53
+ }
54
+
55
+ /**
56
+ * Reference metadata in its serialized form — `referencedModel` is
57
+ * resolved to the model NAME (string), not the lazy constructor
58
+ * thunk. Produced by `exportRegistryData()` and other debug-side
59
+ * paths. A class function would be unserializable JSON; the name is
60
+ * what consumers (devtools, schema-hash inputs) actually want.
61
+ */
62
+ export interface SerializedReferenceMetadata
63
+ extends Omit<ExtendedReferenceMetadata, 'referencedModel'> {
64
+ referencedModel: string;
65
+ }
66
+
67
+ /**
68
+ * Metadata that records a child model's foreign key to a parent model, used
69
+ * for cascade-aware transaction handling: when the parent is deleted, the
70
+ * child's pending transactions can be cancelled.
71
+ */
72
+ export interface BackReferenceMetadata {
73
+ /** The parent model name (e.g., 'Report') */
74
+ parentModel: string;
75
+ /** The foreign key property on this model (e.g., 'reportId') */
76
+ foreignKey: string;
77
+ /** Whether to cascade-cancel transactions when parent is deleted */
78
+ cascadeDelete: boolean;
79
+ }
80
+
81
+ interface PendingReference {
82
+ modelName: string;
83
+ propertyName: string;
84
+ metadata: ExtendedReferenceMetadata;
85
+ }
86
+
87
+ interface RegistryConfig {
88
+ validateOnRegister?: boolean;
89
+ allowLateReferences?: boolean;
90
+ /** The owning client's runtime. Defaults to the module-global bridge. */
91
+ runtime?: RuntimeContext;
92
+ }
93
+
94
+ /**
95
+ * Module-level active registry. Set by createSyncEngine so that Model instances
96
+ * (which don't receive DI) can look up metadata without static maps.
97
+ */
98
+ let _activeRegistry: ModelRegistry | null = null;
99
+
100
+ /** Set the active ModelRegistry instance (called by createSyncEngine) */
101
+ export function setActiveRegistry(registry: ModelRegistry): void {
102
+ _activeRegistry = registry;
103
+ }
104
+
105
+ /** Get the active ModelRegistry. Throws if none set. */
106
+ export function getActiveRegistry(): ModelRegistry {
107
+ if (!_activeRegistry) {
108
+ throw new AbloValidationError(
109
+ 'No active ModelRegistry — call createSyncEngine() first',
110
+ { code: 'registry_not_initialized' },
111
+ );
112
+ }
113
+ return _activeRegistry;
114
+ }
115
+
116
+ /** Whether an active ModelRegistry has been set. */
117
+ export function hasActiveRegistry(): boolean {
118
+ return _activeRegistry !== null;
119
+ }
120
+
121
+ /** Clear the active ModelRegistry (tests only). */
122
+ export function clearActiveRegistry(): void {
123
+ _activeRegistry = null;
124
+ }
125
+
126
+ export class ModelRegistry {
127
+ private models = new Map<string, RegisteredModelClass>();
128
+ private modelMetadata = new Map<string, ModelMetadata>();
129
+ private properties = new Map<string, Map<string, PropertyMetadata>>();
130
+ private references = new Map<string, Map<string, ExtendedReferenceMetadata>>();
131
+ private pendingReferences = new Map<string, PendingReference[]>();
132
+
133
+ // Maps a constructor back to its model name. Keyed as `unknown` on purpose:
134
+ // lookups arrive both as `this.constructor` (a Function) and as typed model
135
+ // classes, and both are accepted without a cast.
136
+ private constructorToModelName = new Map<unknown, string>();
137
+
138
+ // Back-references for cascade-aware transaction handling. Maps a child model
139
+ // name to the parent models it references. The inverse direction (parent to
140
+ // children) is derived on demand by `getChildModels`; it is populated here.
141
+ private backReferences = new Map<string, BackReferenceMetadata[]>();
142
+
143
+ private schemaHash?: string;
144
+ private config: Required<Omit<RegistryConfig, 'runtime'>>;
145
+ private readonly runtime: RuntimeContext;
146
+ private registeredModels = new Set<string>();
147
+
148
+ private pendingHashUpdate = false;
149
+
150
+ constructor(config: RegistryConfig = {}) {
151
+ this.config = {
152
+ validateOnRegister: config.validateOnRegister ?? true,
153
+ allowLateReferences: config.allowLateReferences ?? true,
154
+ };
155
+ this.runtime = config.runtime ?? globalRuntime;
156
+ }
157
+
158
+ private validateModelConstructor(name: string, constructor: unknown): void {
159
+ if (typeof constructor !== 'function') {
160
+ throw new AbloValidationError(
161
+ `Model ${name} constructor must be a function`,
162
+ { code: 'registry_invalid_constructor' },
163
+ );
164
+ }
165
+
166
+ const prototype: unknown = constructor.prototype;
167
+ if (!prototype || typeof prototype !== 'object') {
168
+ throw new AbloValidationError(
169
+ `Model ${name} constructor must have a prototype`,
170
+ { code: 'registry_invalid_constructor' },
171
+ );
172
+ }
173
+
174
+ // Check for required methods
175
+ const required = ['updateFromData', 'toJSON', 'getModelName'];
176
+ for (const method of required) {
177
+ if (typeof (prototype as Record<string, unknown>)[method] !== 'function') {
178
+ this.runtime.logger.debug('Model missing required method', name, { method });
179
+ }
180
+ }
181
+ }
182
+
183
+ private arePropertiesCompatible(existing: PropertyMetadata, incoming: PropertyMetadata): boolean {
184
+ // For reference-generated ID properties, be more lenient
185
+ // Only check core compatibility, not all metadata fields
186
+ return (
187
+ existing.type === incoming.type &&
188
+ // For indexed, treat undefined as false for comparison
189
+ (existing.indexed ?? false) === (incoming.indexed ?? false) &&
190
+ // For optional, treat undefined as false for comparison
191
+ (existing.optional ?? false) === (incoming.optional ?? false)
192
+ );
193
+ }
194
+
195
+ private addPendingReference(
196
+ modelName: string,
197
+ propertyName: string,
198
+ metadata: ExtendedReferenceMetadata
199
+ ): void {
200
+ // Get target model name
201
+ let targetName: string;
202
+ try {
203
+ targetName = metadata.referencedModel()?.name || 'Unknown';
204
+ } catch {
205
+ targetName = 'Unknown';
206
+ }
207
+
208
+ let pending = this.pendingReferences.get(targetName);
209
+ if (!pending) {
210
+ pending = [];
211
+ this.pendingReferences.set(targetName, pending);
212
+ }
213
+
214
+ pending.push({ modelName, propertyName, metadata });
215
+
216
+ this.runtime.logger.debug('Reference deferred', `${modelName}.${propertyName}`, { targetModel: targetName });
217
+ }
218
+
219
+ private resolvePendingReferences(targetModelName: string): void {
220
+ const pending = this.pendingReferences.get(targetModelName);
221
+ if (!pending) return;
222
+
223
+ for (const ref of pending) {
224
+ try {
225
+ this.completeReferenceRegistration(ref.modelName, ref.propertyName, ref.metadata);
226
+ this.runtime.logger.debug('Reference resolved', `${ref.modelName}.${ref.propertyName}`, {
227
+ targetModel: targetModelName,
228
+ });
229
+ } catch (error) {
230
+ this.runtime.observability.breadcrumb(
231
+ `Failed to resolve reference ${ref.modelName}.${ref.propertyName}`,
232
+ 'sync.database',
233
+ 'error',
234
+ {
235
+ error: error instanceof Error ? error.message : String(error),
236
+ }
237
+ );
238
+ }
239
+ }
240
+
241
+ this.pendingReferences.delete(targetModelName);
242
+ }
243
+
244
+ private completeReferenceRegistration(
245
+ modelName: string,
246
+ propertyName: string,
247
+ metadata: ExtendedReferenceMetadata
248
+ ): void {
249
+ // Store reference
250
+ let refs = this.references.get(modelName);
251
+ if (!refs) {
252
+ refs = new Map();
253
+ this.references.set(modelName, refs);
254
+ }
255
+ refs.set(propertyName, metadata);
256
+
257
+ // Register ID property (skip organizationId as it's handled by models themselves)
258
+ const idPropName = propertyName.endsWith('Id') ? propertyName : `${propertyName}Id`;
259
+ if (idPropName !== 'organizationId') {
260
+ this.registerProperty(modelName, idPropName, {
261
+ type: PropertyType.reference,
262
+ indexed: metadata.indexed || false,
263
+ optional: metadata.nullable || false,
264
+ });
265
+ }
266
+
267
+ // Register model property
268
+ this.registerProperty(modelName, propertyName, {
269
+ type: PropertyType.referenceModel,
270
+ optional: metadata.nullable || false,
271
+ });
272
+
273
+ this.schemaHash = undefined;
274
+ }
275
+
276
+ /**
277
+ * Register a model with validation
278
+ */
279
+ registerModel(
280
+ name: string,
281
+ constructor: ModelClassInput,
282
+ metadata: ModelMetadata = { loadStrategy: LoadStrategy.instant }
283
+ ): void {
284
+ // Validate
285
+ if (this.config.validateOnRegister) {
286
+ this.validateModelConstructor(name, constructor);
287
+ }
288
+
289
+ // Check for duplicate
290
+ if (this.models.has(name)) {
291
+ this.runtime.logger.debug('Model already registered, skipping', name);
292
+ return;
293
+ }
294
+
295
+ this.runtime.logger.debug('Registering model', name);
296
+
297
+ // Register. The one cast in this file: input is any Model-subclass
298
+ // constructor (validated above); registered classes are concrete
299
+ // subclasses constructible with `data?` and carrying Model's statics —
300
+ // the shape `RegisteredModelClass` names for every read site.
301
+ const modelClass = constructor as RegisteredModelClass;
302
+ this.models.set(name, modelClass);
303
+ this.modelMetadata.set(name, metadata);
304
+
305
+ // Record the reverse mapping from constructor to model name
306
+ this.constructorToModelName.set(constructor, name);
307
+
308
+ // Initialize property maps
309
+ if (!this.properties.has(name)) {
310
+ this.properties.set(name, new Map());
311
+ }
312
+ if (!this.references.has(name)) {
313
+ this.references.set(name, new Map());
314
+ }
315
+
316
+ // Mark as registered
317
+ this.registeredModels.add(name);
318
+
319
+ // Resolve pending references to this model
320
+ this.resolvePendingReferences(name);
321
+
322
+ // Invalidate schema hash
323
+ this.schemaHash = undefined;
324
+
325
+ this.runtime.logger.debug('Model registered', name, metadata);
326
+ }
327
+
328
+ /**
329
+ * Register property with validation
330
+ */
331
+ registerProperty(modelName: string, propertyName: string, metadata: PropertyMetadata): void {
332
+ // Validate model exists
333
+ if (!this.models.has(modelName) && this.config.validateOnRegister) {
334
+ throw new AbloValidationError(
335
+ `Cannot register property for unknown model: ${modelName}`,
336
+ { code: 'registry_unknown_model' },
337
+ );
338
+ }
339
+
340
+ // Get or create property map
341
+ let props = this.properties.get(modelName);
342
+ if (!props) {
343
+ props = new Map();
344
+ this.properties.set(modelName, props);
345
+ }
346
+
347
+ // Check for conflicts
348
+ const existing = props.get(propertyName);
349
+ if (existing) {
350
+ if (this.arePropertiesCompatible(existing, metadata)) {
351
+ // Properties are compatible, skip re-registration
352
+ this.runtime.logger.debug('Property already registered (compatible)', `${modelName}.${propertyName}`);
353
+ return;
354
+ } else {
355
+ throw new AbloValidationError(
356
+ `Property ${modelName}.${propertyName} already registered with incompatible metadata`,
357
+ { code: 'registry_property_conflict' },
358
+ );
359
+ }
360
+ }
361
+
362
+ props.set(propertyName, metadata);
363
+
364
+ this.schemaHash = undefined;
365
+
366
+ this.runtime.logger.debug('Property registered', `${modelName}.${propertyName}`, metadata);
367
+ }
368
+
369
+ /**
370
+ * Register reference with lazy resolution
371
+ */
372
+ registerReference(
373
+ modelName: string,
374
+ propertyName: string,
375
+ metadata: ExtendedReferenceMetadata
376
+ ): void {
377
+ // Try to resolve target model
378
+ let targetModelName: string;
379
+ try {
380
+ const targetModel = metadata.referencedModel();
381
+ targetModelName = targetModel?.name;
382
+ } catch {
383
+ // Defer resolution
384
+ if (this.config.allowLateReferences) {
385
+ this.addPendingReference(modelName, propertyName, metadata);
386
+ return;
387
+ }
388
+ throw new AbloValidationError(
389
+ `Cannot resolve reference ${modelName}.${propertyName}`,
390
+ { code: 'registry_reference_unresolved' },
391
+ );
392
+ }
393
+
394
+ // Validate target exists or defer
395
+ if (!this.models.has(targetModelName)) {
396
+ if (this.config.allowLateReferences) {
397
+ this.addPendingReference(modelName, propertyName, metadata);
398
+ return;
399
+ }
400
+ throw new AbloValidationError(
401
+ `Reference ${modelName}.${propertyName} points to unknown model ${targetModelName}`,
402
+ { code: 'registry_reference_unknown_target' },
403
+ );
404
+ }
405
+
406
+ // Complete registration
407
+ this.completeReferenceRegistration(modelName, propertyName, metadata);
408
+ }
409
+
410
+ /**
411
+ * Register a back-reference for cascade-aware transaction handling.
412
+ *
413
+ * When a parent model is deleted, the transaction queue cancels pending
414
+ * transactions for every child model that declares a back-reference to that
415
+ * parent.
416
+ *
417
+ * @param childModelName - The model that holds a foreign key to the parent (e.g., 'Section')
418
+ * @param metadata - The back-reference configuration
419
+ */
420
+ registerBackReference(childModelName: string, metadata: BackReferenceMetadata): void {
421
+ // Add to instance map
422
+ let refs = this.backReferences.get(childModelName);
423
+ if (!refs) {
424
+ refs = [];
425
+ this.backReferences.set(childModelName, refs);
426
+ }
427
+
428
+ // Avoid duplicates
429
+ const exists = refs.some(
430
+ (r) => r.parentModel === metadata.parentModel && r.foreignKey === metadata.foreignKey
431
+ );
432
+ if (!exists) {
433
+ refs.push(metadata);
434
+ }
435
+ // Reverse lookup (parent → children) is derived on demand by
436
+ // `getChildModels`, which scans this map.
437
+
438
+ this.runtime.logger.debug('BackReference registered', `${childModelName} -> ${metadata.parentModel}`, {
439
+ foreignKey: metadata.foreignKey,
440
+ cascadeDelete: metadata.cascadeDelete,
441
+ });
442
+ }
443
+
444
+ /** Get all models with specific load strategy. */
445
+ getModelsByLoadStrategy(strategy: LoadStrategy): string[] {
446
+ const models: string[] = [];
447
+ for (const [modelName, metadata] of this.modelMetadata) {
448
+ if (metadata.loadStrategy === strategy) {
449
+ models.push(modelName);
450
+ }
451
+ }
452
+ return models;
453
+ }
454
+
455
+ /** Get model name from constructor (production-safe). */
456
+ getModelNameFromConstructor(constructor: unknown): string | undefined {
457
+ return this.constructorToModelName.get(constructor);
458
+ }
459
+
460
+ /** Get properties for a model. */
461
+ getPropertiesForModel(modelName: string): Map<string, PropertyMetadata> {
462
+ return this.properties.get(modelName) || new Map();
463
+ }
464
+
465
+ /**
466
+ * Get all registered model names for this instance
467
+ */
468
+ getRegisteredModelNames(): string[] {
469
+ return Array.from(this.models.keys());
470
+ }
471
+
472
+ /** Get model constructor by name */
473
+ getModelByName(name: string): RegisteredModelClass | undefined {
474
+ return this.models.get(name);
475
+ }
476
+
477
+ /** Check if model is registered */
478
+ hasModel(name: string): boolean {
479
+ return this.models.has(name);
480
+ }
481
+
482
+ /** Get model metadata by name */
483
+ getMetadata(name: string): ModelMetadata | undefined {
484
+ return this.modelMetadata.get(name);
485
+ }
486
+
487
+ /** Get properties for a model */
488
+ getProperties(name: string): Map<string, PropertyMetadata> {
489
+ return this.properties.get(name) || new Map();
490
+ }
491
+
492
+ /** Get references for a model */
493
+ getReferences(name: string): Map<string, ExtendedReferenceMetadata> {
494
+ return this.references.get(name) || new Map();
495
+ }
496
+
497
+ /** Get indexed properties for a model */
498
+ getIndexedProperties(modelName: string): string[] {
499
+ const properties = this.getProperties(modelName);
500
+ const indexed: string[] = [];
501
+ for (const [propName, metadata] of properties) {
502
+ if (metadata.indexed) indexed.push(propName);
503
+ }
504
+ return indexed;
505
+ }
506
+
507
+ /** Get back-references for a child model */
508
+ getBackReferences(childModelName: string): BackReferenceMetadata[] {
509
+ return this.backReferences.get(childModelName) || [];
510
+ }
511
+
512
+ /** Get child models for a parent */
513
+ getChildModels(parentModelName: string): { childModel: string; foreignKey: string }[] {
514
+ // Derive from backReferences
515
+ const children: { childModel: string; foreignKey: string }[] = [];
516
+ for (const [childModel, refs] of this.backReferences) {
517
+ for (const ref of refs) {
518
+ if (ref.parentModel === parentModelName) {
519
+ children.push({ childModel, foreignKey: ref.foreignKey });
520
+ }
521
+ }
522
+ }
523
+ return children;
524
+ }
525
+
526
+ /**
527
+ * Compute a stable hash of the registered schema — model names, property
528
+ * types, and their indexed and optional flags. Memoized until the schema
529
+ * changes.
530
+ */
531
+ getSchemaHash(): string {
532
+ if (this.schemaHash) return this.schemaHash;
533
+
534
+ const schema: Record<
535
+ string,
536
+ Record<string, { type: PropertyType; indexed: boolean; optional: boolean }>
537
+ > = {};
538
+
539
+ // Build schema object
540
+ for (const [modelName, props] of this.properties) {
541
+ schema[modelName] = {};
542
+ for (const [propName, meta] of props) {
543
+ schema[modelName][propName] = {
544
+ type: meta.type,
545
+ indexed: meta.indexed || false,
546
+ optional: meta.optional || false,
547
+ };
548
+ }
549
+ }
550
+
551
+ // Sort and stringify
552
+ const sorted = JSON.stringify(schema, Object.keys(schema).sort());
553
+
554
+ // Create hash - browser-compatible simple hash
555
+ this.schemaHash = this.simpleHash(sorted);
556
+
557
+ this.runtime.logger.debug('Schema hash updated', this.schemaHash);
558
+
559
+ return this.schemaHash;
560
+ }
561
+
562
+ /**
563
+ * Browser-compatible hash function
564
+ */
565
+ private simpleHash(str: string): string {
566
+ let hash = 0;
567
+ for (let i = 0; i < str.length; i++) {
568
+ const char = str.charCodeAt(i);
569
+ hash = (hash << 5) - hash + char;
570
+ hash = hash & hash; // Convert to 32bit integer
571
+ }
572
+ return Math.abs(hash).toString(16).padStart(8, '0');
573
+ }
574
+
575
+ /**
576
+ * Static wrapper for backward compatibility
577
+ */
578
+
579
+ /**
580
+ * Validate all references
581
+ */
582
+ validateReferences(): { valid: boolean; errors: string[] } {
583
+ const errors: string[] = [];
584
+
585
+ // Check pending references
586
+ for (const [target, pending] of this.pendingReferences) {
587
+ for (const ref of pending) {
588
+ errors.push(`Unresolved reference: ${ref.modelName}.${ref.propertyName} -> ${target}`);
589
+ }
590
+ }
591
+
592
+ // Check resolved references
593
+ for (const [modelName, refs] of this.references) {
594
+ for (const [propName, meta] of refs) {
595
+ try {
596
+ const target = meta.referencedModel();
597
+ if (!this.models.has(target.name)) {
598
+ errors.push(`Invalid reference: ${modelName}.${propName} -> ${target.name}`);
599
+ }
600
+ } catch (error) {
601
+ errors.push(`Cannot resolve reference: ${modelName}.${propName}`);
602
+ }
603
+ }
604
+ }
605
+
606
+ const isValid = errors.length === 0;
607
+ if (isValid) {
608
+ this.runtime.logger.info('All model references are valid');
609
+ } else {
610
+ this.runtime.observability.breadcrumb('Reference validation failed', 'sync.database', 'error');
611
+ }
612
+
613
+ return {
614
+ valid: isValid,
615
+ errors,
616
+ };
617
+ }
618
+
619
+ /**
620
+ * Static wrapper for backward compatibility
621
+ */
622
+
623
+ /**
624
+ * Start batch registration mode to optimize performance
625
+ */
626
+ startBatch(): void {
627
+ this.pendingHashUpdate = false;
628
+ }
629
+
630
+ /**
631
+ * Static wrapper for backward compatibility
632
+ */
633
+
634
+ /**
635
+ * End batch registration mode and update schema hash if needed
636
+ */
637
+ endBatch(): void {
638
+ if (this.pendingHashUpdate) {
639
+ this.getSchemaHash(); // This will recalculate if needed
640
+ this.pendingHashUpdate = false;
641
+ }
642
+ }
643
+
644
+ /**
645
+ * Static wrapper for backward compatibility
646
+ */
647
+
648
+ /**
649
+ * Clear registry
650
+ */
651
+ clear(): void {
652
+ this.models.clear();
653
+ this.modelMetadata.clear();
654
+ this.properties.clear();
655
+ this.references.clear();
656
+ this.pendingReferences.clear();
657
+ this.registeredModels.clear();
658
+ this.backReferences.clear();
659
+ this.constructorToModelName.clear();
660
+ this.schemaHash = undefined;
661
+ this.pendingHashUpdate = false;
662
+
663
+ this.runtime.logger.info('ModelRegistry cleared');
664
+ }
665
+
666
+ /**
667
+ * Static wrapper for backward compatibility
668
+ */
669
+
670
+ /**
671
+ * Export for debugging
672
+ */
673
+ export() {
674
+ return {
675
+ models: Array.from(this.models.keys()),
676
+ metadata: Object.fromEntries(this.modelMetadata),
677
+ properties: Object.fromEntries(
678
+ Array.from(this.properties.entries()).map(([name, props]) => [
679
+ name,
680
+ Object.fromEntries(props),
681
+ ])
682
+ ),
683
+ references: Object.fromEntries(
684
+ Array.from(this.references.entries()).map(([name, refs]) => [
685
+ name,
686
+ Object.fromEntries(refs),
687
+ ])
688
+ ),
689
+ pending: Object.fromEntries(
690
+ Array.from(this.pendingReferences.entries()).map(([name, refs]) => [
691
+ name,
692
+ refs.map((r) => `${r.modelName}.${r.propertyName}`),
693
+ ])
694
+ ),
695
+ schemaHash: this.getSchemaHash(),
696
+ };
697
+ }
698
+
699
+ /**
700
+ * Export registry data for debugging (backward compatibility)
701
+ */
702
+ exportRegistryData(): {
703
+ models: Record<string, string>;
704
+ properties: Record<string, Record<string, PropertyMetadata>>;
705
+ references: Record<string, Record<string, SerializedReferenceMetadata>>;
706
+ metadata: Record<string, ModelMetadata>;
707
+ schemaHash: string;
708
+ } {
709
+ const models: Record<string, string> = {};
710
+ const properties: Record<string, Record<string, PropertyMetadata>> = {};
711
+ const references: Record<string, Record<string, SerializedReferenceMetadata>> = {};
712
+ const metadata: Record<string, ModelMetadata> = {};
713
+
714
+ // Export models
715
+ for (const [name, constructor] of this.models) {
716
+ models[name] = constructor.name;
717
+ }
718
+
719
+ // Export properties
720
+ for (const [modelName, propertyMap] of this.properties) {
721
+ properties[modelName] = {};
722
+ for (const [propName, propMetadata] of propertyMap) {
723
+ properties[modelName][propName] = propMetadata;
724
+ }
725
+ }
726
+
727
+ // Export references
728
+ for (const [modelName, referenceMap] of this.references) {
729
+ references[modelName] = {};
730
+ for (const [refName, refMetadata] of referenceMap) {
731
+ try {
732
+ references[modelName][refName] = {
733
+ ...refMetadata,
734
+ referencedModel: refMetadata.referencedModel().name,
735
+ };
736
+ } catch {
737
+ references[modelName][refName] = {
738
+ ...refMetadata,
739
+ referencedModel: 'Unresolved',
740
+ };
741
+ }
742
+ }
743
+ }
744
+
745
+ // Export metadata
746
+ for (const [modelName, modelMetadata] of this.modelMetadata) {
747
+ metadata[modelName] = modelMetadata;
748
+ }
749
+
750
+ return {
751
+ models,
752
+ properties,
753
+ references,
754
+ metadata,
755
+ schemaHash: this.getSchemaHash(),
756
+ };
757
+ }
758
+
759
+ /**
760
+ * Static wrapper for backward compatibility
761
+ */
762
+ }