@abloatai/ablo 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (398) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +101 -85
  3. package/dist/BaseSyncedStore.d.ts +85 -88
  4. package/dist/BaseSyncedStore.js +131 -147
  5. package/dist/Database.d.ts +54 -68
  6. package/dist/Database.js +97 -113
  7. package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
  8. package/dist/{ObjectPool.js → InstanceCache.js} +85 -83
  9. package/dist/LazyReferenceCollection.d.ts +11 -15
  10. package/dist/LazyReferenceCollection.js +12 -16
  11. package/dist/Model.d.ts +37 -52
  12. package/dist/Model.js +46 -61
  13. package/dist/ModelRegistry.d.ts +21 -19
  14. package/dist/ModelRegistry.js +23 -27
  15. package/dist/NetworkMonitor.d.ts +5 -6
  16. package/dist/NetworkMonitor.js +5 -6
  17. package/dist/SyncClient.d.ts +112 -112
  18. package/dist/SyncClient.js +165 -172
  19. package/dist/adapters/alwaysOnline.d.ts +6 -8
  20. package/dist/adapters/alwaysOnline.js +6 -8
  21. package/dist/adapters/inMemoryStorage.d.ts +9 -9
  22. package/dist/adapters/inMemoryStorage.js +9 -9
  23. package/dist/agent/Agent.d.ts +27 -32
  24. package/dist/agent/Agent.js +18 -19
  25. package/dist/agent/index.d.ts +4 -4
  26. package/dist/agent/index.js +5 -5
  27. package/dist/agent/session.d.ts +47 -44
  28. package/dist/agent/session.js +37 -48
  29. package/dist/agent/types.d.ts +26 -31
  30. package/dist/agent/types.js +6 -7
  31. package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
  32. package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
  33. package/dist/ai-sdk/coordinationContext.d.ts +46 -0
  34. package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +26 -33
  35. package/dist/ai-sdk/index.d.ts +25 -22
  36. package/dist/ai-sdk/index.js +25 -22
  37. package/dist/ai-sdk/wrap.d.ts +6 -7
  38. package/dist/ai-sdk/wrap.js +1 -1
  39. package/dist/auth/credentialPolicy.d.ts +69 -74
  40. package/dist/auth/credentialPolicy.js +51 -56
  41. package/dist/auth/credentialSource.d.ts +6 -5
  42. package/dist/auth/credentialSource.js +9 -10
  43. package/dist/auth/index.d.ts +59 -58
  44. package/dist/auth/index.js +31 -37
  45. package/dist/auth/schemas.d.ts +5 -4
  46. package/dist/auth/schemas.js +5 -4
  47. package/dist/batching/index.d.ts +19 -21
  48. package/dist/batching/index.js +14 -17
  49. package/dist/cli.cjs +167 -119
  50. package/dist/client/Ablo.d.ts +73 -73
  51. package/dist/client/Ablo.js +125 -160
  52. package/dist/client/ApiClient.d.ts +30 -19
  53. package/dist/client/ApiClient.js +133 -38
  54. package/dist/client/auth.d.ts +47 -47
  55. package/dist/client/auth.js +108 -117
  56. package/dist/client/claimHeartbeatLoop.d.ts +50 -0
  57. package/dist/client/claimHeartbeatLoop.js +88 -0
  58. package/dist/client/consoleLogger.d.ts +5 -6
  59. package/dist/client/consoleLogger.js +5 -6
  60. package/dist/client/createInternalComponents.d.ts +14 -17
  61. package/dist/client/createInternalComponents.js +25 -30
  62. package/dist/client/createModelProxy.d.ts +130 -120
  63. package/dist/client/createModelProxy.js +152 -122
  64. package/dist/client/credentialEndpoint.d.ts +40 -42
  65. package/dist/client/credentialEndpoint.js +35 -36
  66. package/dist/client/functionalUpdate.d.ts +29 -27
  67. package/dist/client/functionalUpdate.js +21 -21
  68. package/dist/client/hostedEndpoints.d.ts +9 -12
  69. package/dist/client/hostedEndpoints.js +9 -12
  70. package/dist/client/httpClient.d.ts +57 -53
  71. package/dist/client/httpClient.js +29 -31
  72. package/dist/client/identity.d.ts +15 -20
  73. package/dist/client/identity.js +47 -58
  74. package/dist/client/modelRegistration.d.ts +5 -9
  75. package/dist/client/modelRegistration.js +67 -87
  76. package/dist/client/options.d.ts +134 -157
  77. package/dist/client/options.js +3 -7
  78. package/dist/client/registerDataSource.d.ts +9 -9
  79. package/dist/client/registerDataSource.js +15 -16
  80. package/dist/client/resourceTypes.d.ts +64 -75
  81. package/dist/client/resourceTypes.js +4 -10
  82. package/dist/client/schemaConfig.d.ts +31 -43
  83. package/dist/client/schemaConfig.js +38 -50
  84. package/dist/client/sessionMint.d.ts +16 -12
  85. package/dist/client/sessionMint.js +26 -31
  86. package/dist/client/validateAbloOptions.d.ts +12 -14
  87. package/dist/client/validateAbloOptions.js +8 -9
  88. package/dist/client/writeOptionsSchema.d.ts +18 -16
  89. package/dist/client/writeOptionsSchema.js +23 -20
  90. package/dist/client/wsMutationExecutor.d.ts +15 -20
  91. package/dist/client/wsMutationExecutor.js +17 -23
  92. package/dist/context.d.ts +6 -4
  93. package/dist/context.js +6 -4
  94. package/dist/coordination/index.d.ts +10 -8
  95. package/dist/coordination/index.js +14 -12
  96. package/dist/coordination/schema.d.ts +176 -128
  97. package/dist/coordination/schema.js +197 -133
  98. package/dist/coordination/trace.d.ts +9 -10
  99. package/dist/coordination/trace.js +13 -14
  100. package/dist/core/DatabaseManager.d.ts +5 -7
  101. package/dist/core/DatabaseManager.js +15 -19
  102. package/dist/core/QueryProcessor.d.ts +7 -9
  103. package/dist/core/QueryProcessor.js +22 -28
  104. package/dist/core/QueryView.d.ts +8 -8
  105. package/dist/core/QueryView.js +2 -2
  106. package/dist/core/StoreManager.d.ts +12 -14
  107. package/dist/core/StoreManager.js +21 -24
  108. package/dist/core/ViewRegistry.d.ts +5 -5
  109. package/dist/core/ViewRegistry.js +4 -4
  110. package/dist/core/index.d.ts +17 -12
  111. package/dist/core/index.js +32 -26
  112. package/dist/core/openIDBWithTimeout.d.ts +38 -36
  113. package/dist/core/openIDBWithTimeout.js +42 -43
  114. package/dist/core/queryUtils.d.ts +45 -0
  115. package/dist/core/queryUtils.js +69 -0
  116. package/dist/core/storeContract.d.ts +63 -61
  117. package/dist/core/storeContract.js +8 -12
  118. package/dist/environment.d.ts +28 -0
  119. package/dist/environment.js +21 -0
  120. package/dist/errorCodes.d.ts +107 -99
  121. package/dist/errorCodes.js +131 -132
  122. package/dist/errors.d.ts +160 -166
  123. package/dist/errors.js +155 -158
  124. package/dist/index.d.ts +30 -27
  125. package/dist/index.js +89 -86
  126. package/dist/interfaces/index.d.ts +102 -113
  127. package/dist/interfaces/index.js +5 -4
  128. package/dist/keys/index.d.ts +27 -29
  129. package/dist/keys/index.js +41 -40
  130. package/dist/mutators/RecordingTransaction.d.ts +16 -16
  131. package/dist/mutators/RecordingTransaction.js +31 -37
  132. package/dist/mutators/Transaction.d.ts +18 -26
  133. package/dist/mutators/Transaction.js +14 -20
  134. package/dist/mutators/UndoManager.d.ts +122 -131
  135. package/dist/mutators/UndoManager.js +145 -156
  136. package/dist/mutators/defineMutators.d.ts +23 -34
  137. package/dist/mutators/defineMutators.js +14 -20
  138. package/dist/mutators/inverseOp.d.ts +12 -15
  139. package/dist/mutators/inverseOp.js +12 -15
  140. package/dist/mutators/mutateActions.d.ts +10 -9
  141. package/dist/mutators/mutateActions.js +1 -1
  142. package/dist/mutators/readerActions.d.ts +9 -8
  143. package/dist/mutators/readerActions.js +2 -2
  144. package/dist/mutators/undoApply.d.ts +31 -27
  145. package/dist/mutators/undoApply.js +26 -24
  146. package/dist/policy/index.d.ts +5 -3
  147. package/dist/policy/index.js +5 -3
  148. package/dist/policy/types.d.ts +104 -100
  149. package/dist/policy/types.js +67 -66
  150. package/dist/query/client.d.ts +28 -23
  151. package/dist/query/client.js +45 -43
  152. package/dist/query/types.d.ts +37 -60
  153. package/dist/query/types.js +13 -33
  154. package/dist/react/AbloProvider.d.ts +1 -1
  155. package/dist/react/AbloProvider.js +2 -2
  156. package/dist/react/context.d.ts +25 -28
  157. package/dist/react/context.js +9 -10
  158. package/dist/react/index.d.ts +41 -42
  159. package/dist/react/index.js +37 -38
  160. package/dist/react/internalContext.d.ts +17 -19
  161. package/dist/react/useAblo.d.ts +23 -22
  162. package/dist/react/useAblo.js +16 -14
  163. package/dist/react/useCurrentUserId.d.ts +8 -7
  164. package/dist/react/useCurrentUserId.js +8 -7
  165. package/dist/react/useErrorListener.d.ts +7 -7
  166. package/dist/react/useErrorListener.js +10 -11
  167. package/dist/react/useMutationFailureListener.d.ts +8 -8
  168. package/dist/react/useMutationFailureListener.js +8 -8
  169. package/dist/react/useMutators.d.ts +11 -11
  170. package/dist/react/useMutators.js +3 -3
  171. package/dist/react/useReactive.js +2 -2
  172. package/dist/react/useSyncStatus.d.ts +4 -6
  173. package/dist/react/useUndoScope.d.ts +7 -9
  174. package/dist/react/useUndoScope.js +1 -1
  175. package/dist/schema/coordination.d.ts +21 -25
  176. package/dist/schema/coordination.js +21 -25
  177. package/dist/schema/ddl.d.ts +43 -39
  178. package/dist/schema/ddl.js +75 -68
  179. package/dist/schema/ddlLock.d.ts +20 -24
  180. package/dist/schema/ddlLock.js +18 -23
  181. package/dist/schema/diff.d.ts +99 -61
  182. package/dist/schema/diff.js +43 -34
  183. package/dist/schema/field.d.ts +37 -42
  184. package/dist/schema/field.js +35 -48
  185. package/dist/schema/generate.d.ts +12 -12
  186. package/dist/schema/generate.js +12 -12
  187. package/dist/schema/index.d.ts +2 -2
  188. package/dist/schema/index.js +21 -23
  189. package/dist/schema/model.d.ts +118 -143
  190. package/dist/schema/model.js +22 -33
  191. package/dist/schema/openapi.d.ts +10 -9
  192. package/dist/schema/openapi.js +5 -3
  193. package/dist/schema/queries.d.ts +29 -31
  194. package/dist/schema/queries.js +23 -25
  195. package/dist/schema/relation.d.ts +89 -99
  196. package/dist/schema/relation.js +13 -13
  197. package/dist/schema/residency.d.ts +16 -13
  198. package/dist/schema/residency.js +16 -13
  199. package/dist/schema/roles.d.ts +36 -43
  200. package/dist/schema/roles.js +31 -37
  201. package/dist/schema/schema.d.ts +33 -42
  202. package/dist/schema/schema.js +31 -32
  203. package/dist/schema/select.d.ts +13 -13
  204. package/dist/schema/select.js +13 -13
  205. package/dist/schema/serialize.d.ts +28 -31
  206. package/dist/schema/serialize.js +27 -31
  207. package/dist/schema/sugar.d.ts +17 -32
  208. package/dist/schema/sugar.js +14 -29
  209. package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +26 -49
  210. package/dist/schema/syncDeltaRow.js +89 -0
  211. package/dist/schema/tenancy.d.ts +44 -46
  212. package/dist/schema/tenancy.js +46 -48
  213. package/dist/server/adapter.d.ts +58 -58
  214. package/dist/server/adapter.js +13 -14
  215. package/dist/server/commit.d.ts +60 -64
  216. package/dist/server/index.d.ts +9 -10
  217. package/dist/server/index.js +1 -1
  218. package/dist/server/readConfig.d.ts +70 -0
  219. package/dist/server/readConfig.js +8 -0
  220. package/dist/server/storageMode.d.ts +23 -0
  221. package/dist/server/storageMode.js +17 -0
  222. package/dist/source/adapter.d.ts +30 -25
  223. package/dist/source/adapter.js +10 -10
  224. package/dist/source/adapters/drizzle.d.ts +28 -23
  225. package/dist/source/adapters/drizzle.js +30 -25
  226. package/dist/source/adapters/kysely.d.ts +27 -25
  227. package/dist/source/adapters/kysely.js +24 -23
  228. package/dist/source/adapters/memory.d.ts +8 -7
  229. package/dist/source/adapters/memory.js +9 -8
  230. package/dist/source/adapters/prisma.d.ts +13 -12
  231. package/dist/source/adapters/prisma.js +22 -25
  232. package/dist/source/conformance.d.ts +18 -11
  233. package/dist/source/conformance.js +17 -11
  234. package/dist/source/connector.d.ts +31 -32
  235. package/dist/source/connector.js +28 -28
  236. package/dist/source/connectorProtocol.d.ts +160 -0
  237. package/dist/source/connectorProtocol.js +162 -0
  238. package/dist/source/contract.d.ts +26 -27
  239. package/dist/source/contract.js +28 -29
  240. package/dist/source/factory.d.ts +46 -58
  241. package/dist/source/factory.js +22 -27
  242. package/dist/source/index.d.ts +7 -9
  243. package/dist/source/index.js +12 -14
  244. package/dist/source/migrations.d.ts +9 -9
  245. package/dist/source/migrations.js +9 -9
  246. package/dist/source/next.d.ts +9 -10
  247. package/dist/source/next.js +6 -7
  248. package/dist/source/pushQueue.d.ts +69 -47
  249. package/dist/source/pushQueue.js +32 -28
  250. package/dist/source/signing.d.ts +46 -17
  251. package/dist/source/signing.js +28 -11
  252. package/dist/source/types.d.ts +121 -104
  253. package/dist/source/types.js +13 -14
  254. package/dist/stores/ObjectStore.d.ts +10 -11
  255. package/dist/stores/ObjectStore.js +11 -12
  256. package/dist/stores/ObjectStoreContract.d.ts +12 -15
  257. package/dist/stores/SyncActionStore.d.ts +7 -11
  258. package/dist/stores/SyncActionStore.js +13 -17
  259. package/dist/surface.d.ts +27 -20
  260. package/dist/surface.js +27 -20
  261. package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
  262. package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
  263. package/dist/sync/ConnectionManager.d.ts +39 -50
  264. package/dist/sync/ConnectionManager.js +55 -66
  265. package/dist/sync/NetworkProbe.d.ts +24 -29
  266. package/dist/sync/NetworkProbe.js +63 -69
  267. package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
  268. package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
  269. package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
  270. package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
  271. package/dist/sync/SyncWebSocket.d.ts +139 -165
  272. package/dist/sync/SyncWebSocket.js +191 -223
  273. package/dist/sync/awaitClaimGrant.d.ts +18 -18
  274. package/dist/sync/awaitClaimGrant.js +11 -11
  275. package/dist/sync/bootstrapApply.d.ts +34 -24
  276. package/dist/sync/bootstrapApply.js +27 -19
  277. package/dist/sync/commitFrames.d.ts +21 -20
  278. package/dist/sync/commitFrames.js +18 -18
  279. package/dist/sync/createClaimStream.d.ts +23 -22
  280. package/dist/sync/createClaimStream.js +105 -23
  281. package/dist/sync/createPresenceStream.d.ts +19 -18
  282. package/dist/sync/createPresenceStream.js +25 -26
  283. package/dist/sync/createSnapshot.d.ts +12 -14
  284. package/dist/sync/createSnapshot.js +20 -26
  285. package/dist/sync/credentialLifecycle.d.ts +104 -104
  286. package/dist/sync/credentialLifecycle.js +140 -147
  287. package/dist/sync/deltaPipeline.d.ts +36 -34
  288. package/dist/sync/deltaPipeline.js +64 -65
  289. package/dist/sync/groupChange.d.ts +63 -61
  290. package/dist/sync/groupChange.js +74 -78
  291. package/dist/sync/heartbeat.d.ts +34 -33
  292. package/dist/sync/heartbeat.js +31 -31
  293. package/dist/sync/participants.d.ts +19 -19
  294. package/dist/sync/schemas.d.ts +3 -2
  295. package/dist/sync/schemas.js +14 -10
  296. package/dist/sync/syncCursor.d.ts +17 -21
  297. package/dist/sync/syncCursor.js +17 -21
  298. package/dist/sync/syncPlan.d.ts +28 -36
  299. package/dist/sync/syncPlan.js +18 -19
  300. package/dist/sync/syncPosition.d.ts +54 -49
  301. package/dist/sync/syncPosition.js +57 -52
  302. package/dist/sync/wsFrameHandlers.d.ts +35 -36
  303. package/dist/sync/wsFrameHandlers.js +63 -67
  304. package/dist/testing/fixtures/bootstrap.d.ts +12 -6
  305. package/dist/testing/fixtures/bootstrap.js +12 -6
  306. package/dist/testing/fixtures/deltas.d.ts +30 -33
  307. package/dist/testing/fixtures/deltas.js +30 -33
  308. package/dist/testing/fixtures/models.d.ts +11 -10
  309. package/dist/testing/fixtures/models.js +11 -10
  310. package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
  311. package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
  312. package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -15
  313. package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
  314. package/dist/testing/helpers/wait.d.ts +13 -8
  315. package/dist/testing/helpers/wait.js +13 -8
  316. package/dist/testing/index.d.ts +3 -3
  317. package/dist/testing/index.js +2 -2
  318. package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
  319. package/dist/testing/mocks/MockMutationExecutor.js +15 -14
  320. package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
  321. package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
  322. package/dist/testing/mocks/MockSyncContext.d.ts +20 -17
  323. package/dist/testing/mocks/MockSyncContext.js +15 -13
  324. package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
  325. package/dist/testing/mocks/MockSyncStore.js +11 -11
  326. package/dist/testing/mocks/MockWebSocket.d.ts +26 -22
  327. package/dist/testing/mocks/MockWebSocket.js +22 -21
  328. package/dist/transactions/TransactionQueue.d.ts +181 -176
  329. package/dist/transactions/TransactionQueue.js +338 -350
  330. package/dist/transactions/TransactionStore.d.ts +6 -4
  331. package/dist/transactions/TransactionStore.js +6 -4
  332. package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
  333. package/dist/transactions/UnconfirmedWrites.js +104 -0
  334. package/dist/transactions/coalesceRules.d.ts +41 -17
  335. package/dist/transactions/coalesceRules.js +40 -17
  336. package/dist/transactions/commitPayload.d.ts +48 -52
  337. package/dist/transactions/commitPayload.js +48 -57
  338. package/dist/transactions/deltaConfirmation.d.ts +20 -22
  339. package/dist/transactions/deltaConfirmation.js +37 -45
  340. package/dist/transactions/optimisticApply.d.ts +49 -0
  341. package/dist/transactions/optimisticApply.js +65 -0
  342. package/dist/transactions/{persistedReplay.d.ts → replayValidation.d.ts} +28 -22
  343. package/dist/transactions/{persistedReplay.js → replayValidation.js} +33 -27
  344. package/dist/types/global.d.ts +46 -41
  345. package/dist/types/global.js +20 -19
  346. package/dist/types/index.d.ts +71 -77
  347. package/dist/types/index.js +22 -22
  348. package/dist/types/modelData.d.ts +6 -8
  349. package/dist/types/modelData.js +5 -7
  350. package/dist/types/participant.d.ts +10 -11
  351. package/dist/types/participant.js +6 -8
  352. package/dist/types/streams.d.ts +208 -195
  353. package/dist/types/streams.js +7 -7
  354. package/dist/utils/asyncIterator.d.ts +25 -32
  355. package/dist/utils/asyncIterator.js +25 -32
  356. package/dist/utils/duration.d.ts +12 -15
  357. package/dist/utils/duration.js +12 -15
  358. package/dist/utils/mobxSetup.d.ts +53 -0
  359. package/dist/utils/{mobx-setup.js → mobxSetup.js} +42 -98
  360. package/dist/webhooks/events.d.ts +21 -16
  361. package/dist/webhooks/events.js +10 -8
  362. package/dist/webhooks/index.d.ts +5 -7
  363. package/dist/webhooks/index.js +5 -7
  364. package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
  365. package/dist/wire/delta.js +114 -0
  366. package/dist/wire/errorEnvelope.d.ts +30 -31
  367. package/dist/wire/errorEnvelope.js +34 -40
  368. package/dist/wire/frames.d.ts +79 -86
  369. package/dist/wire/frames.js +26 -33
  370. package/dist/wire/index.d.ts +14 -12
  371. package/dist/wire/index.js +30 -26
  372. package/dist/wire/listEnvelope.d.ts +16 -23
  373. package/dist/wire/listEnvelope.js +7 -6
  374. package/dist/wire/protocol.d.ts +25 -32
  375. package/dist/wire/protocol.js +25 -32
  376. package/dist/wire/protocolVersion.d.ts +44 -40
  377. package/dist/wire/protocolVersion.js +44 -40
  378. package/docs/coordination.md +59 -0
  379. package/package.json +11 -10
  380. package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
  381. package/dist/ai-sdk/coordination-context.d.ts +0 -52
  382. package/dist/core/query-utils.d.ts +0 -34
  383. package/dist/core/query-utils.js +0 -59
  384. package/dist/schema/sync-delta-row.js +0 -103
  385. package/dist/schema/sync-delta-wire.js +0 -102
  386. package/dist/server/read-config.d.ts +0 -67
  387. package/dist/server/read-config.js +0 -8
  388. package/dist/server/storage-mode.d.ts +0 -8
  389. package/dist/server/storage-mode.js +0 -28
  390. package/dist/source/connector-protocol.d.ts +0 -159
  391. package/dist/source/connector-protocol.js +0 -161
  392. package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
  393. package/dist/transactions/OptimisticEchoTracker.js +0 -104
  394. package/dist/transactions/mutation-error-handler.d.ts +0 -5
  395. package/dist/transactions/mutation-error-handler.js +0 -39
  396. package/dist/transactions/optimistic.d.ts +0 -24
  397. package/dist/transactions/optimistic.js +0 -45
  398. package/dist/utils/mobx-setup.d.ts +0 -42
@@ -1,11 +1,8 @@
1
1
  /**
2
- * Coordination authoring helpers for the model `conflict` axis.
3
- *
4
- * Composable disposition functions + a `cn`/`cx`-style combinator, so a model
5
- * declares conflict behaviour the way the rest of the DSL reads
6
- * (`relation.belongsTo()`, `field.string()`) — and the way modern libraries
7
- * compose config (Better Auth's `plugins: [admin(), twoFactor()]`, shadcn's
8
- * `cx(a, b)`) — instead of a raw disposition map:
2
+ * Authoring helpers for a model's `conflict` axis — the setting that decides
3
+ * what happens when two writers touch the same row. Instead of writing a raw
4
+ * disposition map, you compose small, named functions the way the rest of the
5
+ * schema DSL reads (`relation.belongsTo()`, `field.string()`):
9
6
  *
10
7
  * ```ts
11
8
  * import { coordination, humansOverwrite, agentsReject } from '@abloatai/ablo/schema';
@@ -14,12 +11,11 @@
14
11
  * // → { user: 'overwrite', agent: 'reject' } (a human's write wins, an agent's yields)
15
12
  * ```
16
13
  *
17
- * Each helper is named for the exact disposition it applies — the same
18
- * `overwrite | reject | notify` vocabulary used by write guards (`onStale`) —
19
- * and returns a partial {@link ConflictAxis}. {@link coordination} merges them
20
- * (later rules win on key collisions). The result is plain, serializable data —
21
- * the engine interpreter and schema round-trip are unchanged; this is only a
22
- * nicer authoring surface.
14
+ * Each helper is named for the disposition it applies — drawn from the same
15
+ * `overwrite | reject | notify` vocabulary the write guards use (`onStale`) —
16
+ * and returns a partial {@link ConflictAxis}. {@link coordination} merges the
17
+ * pieces, with later rules winning on key collisions. The result is plain,
18
+ * serializable data that the engine reads at commit time.
23
19
  */
24
20
  import type { ConflictAxis } from '../policy/types.js';
25
21
  /**
@@ -27,28 +23,28 @@ import type { ConflictAxis } from '../policy/types.js';
27
23
  * disposition helper below. Compose with {@link coordination}.
28
24
  */
29
25
  export type ConflictRule = ConflictAxis;
30
- /** A human's conflicting write OVERWRITES wins; never blocked (LWW among humans). */
26
+ /** A human's conflicting write wins and overwrites the other; it is never blocked. Among humans this gives last-write-wins. */
31
27
  export declare const humansOverwrite: () => ConflictRule;
32
- /** A human's conflicting write is REJECTED yields to a held claim / stale snapshot. */
28
+ /** A human's conflicting write is rejected, yielding to a held claim or a stale snapshot. */
33
29
  export declare const humansReject: () => ConflictRule;
34
- /** A human's stale write NOTIFIES re-reads & re-applies instead of clobbering. */
30
+ /** A human's stale write triggers a notification: it re-reads and re-applies rather than clobbering. */
35
31
  export declare const humansNotify: () => ConflictRule;
36
- /** An agent's conflicting write OVERWRITES wins (rarely wanted). */
32
+ /** An agent's conflicting write wins and overwrites the other (rarely what you want). */
37
33
  export declare const agentsOverwrite: () => ConflictRule;
38
- /** An agent's conflicting write is REJECTED yields to a held claim / stale snapshot. */
34
+ /** An agent's conflicting write is rejected, yielding to a held claim or a stale snapshot. */
39
35
  export declare const agentsReject: () => ConflictRule;
40
- /** An agent's stale write NOTIFIES re-reads & re-applies instead of clobbering. */
36
+ /** An agent's stale write triggers a notification: it re-reads and re-applies rather than clobbering. */
41
37
  export declare const agentsNotify: () => ConflictRule;
42
- /** A system/automation conflicting write OVERWRITES. */
38
+ /** A system or automation write wins and overwrites the other. */
43
39
  export declare const systemOverwrite: () => ConflictRule;
44
- /** A system/automation conflicting write is REJECTED. */
40
+ /** A system or automation write is rejected. */
45
41
  export declare const systemReject: () => ConflictRule;
46
- /** A system/automation stale write NOTIFIES (re-read & re-apply). */
42
+ /** A system or automation stale write triggers a notification: it re-reads and re-applies. */
47
43
  export declare const systemNotify: () => ConflictRule;
48
44
  /**
49
- * Merge coordination rules into one {@link ConflictAxis} the `cn`/`cx` of
50
- * conflict policy. Later rules win on key collisions; an omitted committer kind
51
- * falls through to the engine default at commit time.
45
+ * Merges coordination rules into a single {@link ConflictAxis}. Later rules win
46
+ * on key collisions, and a committer kind you leave out falls through to the
47
+ * engine's default at commit time.
52
48
  *
53
49
  * ```ts
54
50
  * coordination(humansOverwrite(), agentsReject()) // → { user: 'overwrite', agent: 'reject' }
@@ -1,11 +1,8 @@
1
1
  /**
2
- * Coordination authoring helpers for the model `conflict` axis.
3
- *
4
- * Composable disposition functions + a `cn`/`cx`-style combinator, so a model
5
- * declares conflict behaviour the way the rest of the DSL reads
6
- * (`relation.belongsTo()`, `field.string()`) — and the way modern libraries
7
- * compose config (Better Auth's `plugins: [admin(), twoFactor()]`, shadcn's
8
- * `cx(a, b)`) — instead of a raw disposition map:
2
+ * Authoring helpers for a model's `conflict` axis — the setting that decides
3
+ * what happens when two writers touch the same row. Instead of writing a raw
4
+ * disposition map, you compose small, named functions the way the rest of the
5
+ * schema DSL reads (`relation.belongsTo()`, `field.string()`):
9
6
  *
10
7
  * ```ts
11
8
  * import { coordination, humansOverwrite, agentsReject } from '@abloatai/ablo/schema';
@@ -14,38 +11,37 @@
14
11
  * // → { user: 'overwrite', agent: 'reject' } (a human's write wins, an agent's yields)
15
12
  * ```
16
13
  *
17
- * Each helper is named for the exact disposition it applies — the same
18
- * `overwrite | reject | notify` vocabulary used by write guards (`onStale`) —
19
- * and returns a partial {@link ConflictAxis}. {@link coordination} merges them
20
- * (later rules win on key collisions). The result is plain, serializable data —
21
- * the engine interpreter and schema round-trip are unchanged; this is only a
22
- * nicer authoring surface.
14
+ * Each helper is named for the disposition it applies — drawn from the same
15
+ * `overwrite | reject | notify` vocabulary the write guards use (`onStale`) —
16
+ * and returns a partial {@link ConflictAxis}. {@link coordination} merges the
17
+ * pieces, with later rules winning on key collisions. The result is plain,
18
+ * serializable data that the engine reads at commit time.
23
19
  */
24
20
  // ── Humans (user sessions) ──────────────────────────────────────────────
25
- /** A human's conflicting write OVERWRITES wins; never blocked (LWW among humans). */
21
+ /** A human's conflicting write wins and overwrites the other; it is never blocked. Among humans this gives last-write-wins. */
26
22
  export const humansOverwrite = () => ({ user: 'overwrite' });
27
- /** A human's conflicting write is REJECTED yields to a held claim / stale snapshot. */
23
+ /** A human's conflicting write is rejected, yielding to a held claim or a stale snapshot. */
28
24
  export const humansReject = () => ({ user: 'reject' });
29
- /** A human's stale write NOTIFIES re-reads & re-applies instead of clobbering. */
25
+ /** A human's stale write triggers a notification: it re-reads and re-applies rather than clobbering. */
30
26
  export const humansNotify = () => ({ user: 'notify' });
31
27
  // ── Agents (AI) ─────────────────────────────────────────────────────────
32
- /** An agent's conflicting write OVERWRITES wins (rarely wanted). */
28
+ /** An agent's conflicting write wins and overwrites the other (rarely what you want). */
33
29
  export const agentsOverwrite = () => ({ agent: 'overwrite' });
34
- /** An agent's conflicting write is REJECTED yields to a held claim / stale snapshot. */
30
+ /** An agent's conflicting write is rejected, yielding to a held claim or a stale snapshot. */
35
31
  export const agentsReject = () => ({ agent: 'reject' });
36
- /** An agent's stale write NOTIFIES re-reads & re-applies instead of clobbering. */
32
+ /** An agent's stale write triggers a notification: it re-reads and re-applies rather than clobbering. */
37
33
  export const agentsNotify = () => ({ agent: 'notify' });
38
34
  // ── System / automation ─────────────────────────────────────────────────
39
- /** A system/automation conflicting write OVERWRITES. */
35
+ /** A system or automation write wins and overwrites the other. */
40
36
  export const systemOverwrite = () => ({ system: 'overwrite' });
41
- /** A system/automation conflicting write is REJECTED. */
37
+ /** A system or automation write is rejected. */
42
38
  export const systemReject = () => ({ system: 'reject' });
43
- /** A system/automation stale write NOTIFIES (re-read & re-apply). */
39
+ /** A system or automation stale write triggers a notification: it re-reads and re-applies. */
44
40
  export const systemNotify = () => ({ system: 'notify' });
45
41
  /**
46
- * Merge coordination rules into one {@link ConflictAxis} the `cn`/`cx` of
47
- * conflict policy. Later rules win on key collisions; an omitted committer kind
48
- * falls through to the engine default at commit time.
42
+ * Merges coordination rules into a single {@link ConflictAxis}. Later rules win
43
+ * on key collisions, and a committer kind you leave out falls through to the
44
+ * engine's default at commit time.
49
45
  *
50
46
  * ```ts
51
47
  * coordination(humansOverwrite(), agentsReject()) // → { user: 'overwrite', agent: 'reject' }
@@ -1,21 +1,25 @@
1
1
  /**
2
- * Schema Postgres DDL the one pure SQL emitter shared by every consumer.
2
+ * Turns a schema definition into the ordered Postgres DDL that provisions and
3
+ * migrates its tables. A schema built with `defineSchema(...)` and serialized to
4
+ * {@link SchemaJSON} is the single source of truth, and this module lowers it to
5
+ * ordered SQL strings.
3
6
  *
4
- * `defineSchema(...)` (serialized to {@link SchemaJSON}) is the single source of
5
- * truth; this module lowers it to ordered DDL strings. Both the hosted server
6
- * (which applies it to Ablo-managed Postgres on `schema push`) and the
7
- * `ablo migrate` CLI (which applies it to a customer's own Postgres) call these
8
- * generators, so the SQL — column types, RLS, enum checks — is identical no
9
- * matter who runs it. There is no second type map.
7
+ * The same generators run wherever tables are created in a hosted server
8
+ * applying them to the Postgres it manages, and in the `ablo migrate` CLI
9
+ * applying them to a customer's own Postgres so the SQL, from column types to
10
+ * row-level security to enum checks, is identical no matter who runs it.
10
11
  *
11
- * Everything here is pure (returns strings; no DB, no I/O); the execution side
12
- * (transaction + advisory lock) lives with each consumer because it's coupled
13
- * to that consumer's Postgres client and error type.
12
+ * Everything here is pure: it returns strings and touches no database. The
13
+ * execution side — the transaction and advisory lock that actually run the
14
+ * statements lives with each caller, because it is coupled to that caller's
15
+ * Postgres client and error types.
14
16
  *
15
- * - `generateProvisionPlan` additive + idempotent (CREATE/ADD … IF NOT
16
- * EXISTS + RLS). Never loses data. The "create my tables" primitive.
17
- * - `generateMigrationPlan` — the destructive-aware counterpart driven by the
18
- * {@link diffSchema} step list (drops, renames, type casts, backfills).
17
+ * - {@link generateProvisionPlan} builds an additive, idempotent plan (CREATE
18
+ * and ADD … IF NOT EXISTS, plus row-level security) that never loses data
19
+ * the "create my tables" primitive.
20
+ * - {@link generateMigrationPlan} is its destructive-aware counterpart, driven
21
+ * by a {@link diffSchema} step list: drops, renames, type casts, and
22
+ * backfills.
19
23
  */
20
24
  import type { SchemaJSON, ModelJSON } from './serialize.js';
21
25
  import type { MigrationStep, BackfillValue } from './diff.js';
@@ -23,30 +27,30 @@ export interface ProvisionPlan {
23
27
  /** The Postgres schema the tables live in (`app_<id>` or `public`). */
24
28
  readonly appSchema: string;
25
29
  /** Ordered, idempotent DDL statements. Safe to run repeatedly. Executors run
26
- * these together in ONE transaction. */
30
+ * these together in one transaction. */
27
31
  readonly statements: readonly string[];
28
- /** Post-commit, NON-transactional DDL (`VALIDATE CONSTRAINT`, `CREATE INDEX
29
- * CONCURRENTLY`) — run AFTER {@link statements} commit, each outside any
30
- * transaction, best-effort. Keeps the lock-heavy / scan-heavy work off the
31
- * main transaction so adding a foreign key never freezes a large, live BYO
32
- * table. Optional + back-compat: absent = nothing to run. */
32
+ /** Post-commit, non-transactional DDL (`VALIDATE CONSTRAINT`, `CREATE INDEX
33
+ * CONCURRENTLY`) — run after {@link statements} commit, each outside any
34
+ * transaction, best-effort. Keeps the lock-heavy and scan-heavy work off the
35
+ * main transaction so adding a foreign key never freezes a large, live table.
36
+ * Optional: when absent, there is nothing to run. */
33
37
  readonly concurrent?: readonly string[];
34
38
  }
35
39
  export interface ProvisionOptions {
36
40
  /**
37
- * Emit `DEFERRABLE INITIALLY DEFERRED` FOREIGN KEY constraints for every
38
- * `parent: true` belongsTo relation (true ownership edges only see
39
- * {@link foreignKeyStatements}). Off by default: the soft-reference model keeps
40
- * out-of-order sync robust on Ablo-managed tables. Turn on for a customer's own
41
- * (BYO / dedicated) database, where a clean, navigable relational schema is
42
- * wanted and the DB starts empty (nothing for the constraint to fail against).
41
+ * Emit `DEFERRABLE INITIALLY DEFERRED` foreign-key constraints for the
42
+ * belongsTo relations that opt in; see {@link foreignKeyStatements} for exactly
43
+ * which relations qualify. Off by default, so soft references keep out-of-order
44
+ * sync robust. Turn it on for a customer's own database, where a clean,
45
+ * navigable relational schema is wanted and the database starts empty, so a
46
+ * constraint has nothing to fail against.
43
47
  */
44
48
  readonly foreignKeys?: boolean;
45
49
  }
46
50
  export interface MigrationPlan {
47
51
  /** The app Postgres schema the DDL targets (`app_<id>` or `public`). */
48
52
  readonly appSchema: string;
49
- /** Ordered DDL statements (expand → contract). Run in ONE transaction. */
53
+ /** Ordered DDL statements (expand → contract). Run in one transaction. */
50
54
  readonly statements: readonly string[];
51
55
  /** Post-commit, non-transactional DDL — see {@link ProvisionPlan.concurrent}. */
52
56
  readonly concurrent?: readonly string[];
@@ -55,10 +59,10 @@ export interface MigrationPlan {
55
59
  export declare function appSchemaName(organizationId: string): string;
56
60
  export declare function camelToSnake(identifier: string): string;
57
61
  /**
58
- * Pure snake_case camelCase — the inverse of {@link camelToSnake}, matching
59
- * `postgres.toCamel` semantics. Read-side translation: a column read back from a
60
- * BYO database (e.g. via `drizzleDataSource`) maps to the same JS field the SDK
61
- * wrote, so `camelToSnake('operatorId') === 'operator_id'` and
62
+ * Converts snake_case to camelCase — the inverse of {@link camelToSnake}. This
63
+ * is the read-side translation: a column read back from a customer's own
64
+ * database maps to the same JavaScript field the SDK wrote, so
65
+ * `camelToSnake('operatorId') === 'operator_id'` and
62
66
  * `snakeToCamel('operator_id') === 'operatorId'` round-trip.
63
67
  */
64
68
  export declare function snakeToCamel(identifier: string): string;
@@ -66,13 +70,13 @@ export declare function snakeToCamel(identifier: string): string;
66
70
  export declare function q(identifier: string): string;
67
71
  export declare function sqlType(fieldType: ModelJSON['fields'][string]['type']): string;
68
72
  /**
69
- * Build the additive, idempotent provisioning plan for an app. Pure — no DB
70
- * access.
73
+ * Builds the additive, idempotent provisioning plan for an app. Pure — it does
74
+ * not touch a database.
71
75
  *
72
- * `targetSchema` is where the tables live: the app's schema `app_<id>` on the
73
- * shared tier, or `public` on a dedicated tenant's own database (where the DB
74
- * itself is the isolation boundary). For `public` the `CREATE SCHEMA` is
75
- * skipped (it always exists).
76
+ * `targetSchema` is where the tables live: a per-app Postgres schema such as
77
+ * `app_<id>`, or `public` when the database itself is the isolation boundary
78
+ * (for example a customer's own database). For `public` the `CREATE SCHEMA`
79
+ * statement is skipped, since it always exists.
76
80
  */
77
81
  export declare function generateProvisionPlan(schema: SchemaJSON, targetSchema: string, opts?: ProvisionOptions): ProvisionPlan;
78
82
  /**
@@ -87,7 +91,7 @@ export declare function generateMigrationPlan(steps: readonly MigrationStep[], o
87
91
  /** Constant seed values that let a required-field add / made-required step
88
92
  * set NOT NULL on a non-empty table. Keyed by (model, field). */
89
93
  readonly backfills?: readonly BackfillValue[];
90
- /** Emit DEFERRABLE FK constraints for `parent: true` edges of newly-created
91
- * models. Off by default — see {@link ProvisionOptions.foreignKeys}. */
94
+ /** Emit deferrable foreign-key constraints for the relations that opt in.
95
+ * Off by default — see {@link ProvisionOptions.foreignKeys}. */
92
96
  readonly foreignKeys?: boolean;
93
97
  }): MigrationPlan;
@@ -1,21 +1,25 @@
1
1
  /**
2
- * Schema Postgres DDL the one pure SQL emitter shared by every consumer.
2
+ * Turns a schema definition into the ordered Postgres DDL that provisions and
3
+ * migrates its tables. A schema built with `defineSchema(...)` and serialized to
4
+ * {@link SchemaJSON} is the single source of truth, and this module lowers it to
5
+ * ordered SQL strings.
3
6
  *
4
- * `defineSchema(...)` (serialized to {@link SchemaJSON}) is the single source of
5
- * truth; this module lowers it to ordered DDL strings. Both the hosted server
6
- * (which applies it to Ablo-managed Postgres on `schema push`) and the
7
- * `ablo migrate` CLI (which applies it to a customer's own Postgres) call these
8
- * generators, so the SQL — column types, RLS, enum checks — is identical no
9
- * matter who runs it. There is no second type map.
7
+ * The same generators run wherever tables are created in a hosted server
8
+ * applying them to the Postgres it manages, and in the `ablo migrate` CLI
9
+ * applying them to a customer's own Postgres so the SQL, from column types to
10
+ * row-level security to enum checks, is identical no matter who runs it.
10
11
  *
11
- * Everything here is pure (returns strings; no DB, no I/O); the execution side
12
- * (transaction + advisory lock) lives with each consumer because it's coupled
13
- * to that consumer's Postgres client and error type.
12
+ * Everything here is pure: it returns strings and touches no database. The
13
+ * execution side — the transaction and advisory lock that actually run the
14
+ * statements lives with each caller, because it is coupled to that caller's
15
+ * Postgres client and error types.
14
16
  *
15
- * - `generateProvisionPlan` additive + idempotent (CREATE/ADD … IF NOT
16
- * EXISTS + RLS). Never loses data. The "create my tables" primitive.
17
- * - `generateMigrationPlan` — the destructive-aware counterpart driven by the
18
- * {@link diffSchema} step list (drops, renames, type casts, backfills).
17
+ * - {@link generateProvisionPlan} builds an additive, idempotent plan (CREATE
18
+ * and ADD … IF NOT EXISTS, plus row-level security) that never loses data
19
+ * the "create my tables" primitive.
20
+ * - {@link generateMigrationPlan} is its destructive-aware counterpart, driven
21
+ * by a {@link diffSchema} step list: drops, renames, type casts, and
22
+ * backfills.
19
23
  */
20
24
  import { AbloValidationError } from '../errors.js';
21
25
  import { resolveTenancy, tenancyColumn } from './tenancy.js';
@@ -33,10 +37,10 @@ export function camelToSnake(identifier) {
33
37
  return identifier.replace(/[A-Z]/g, (ch) => `_${ch.toLowerCase()}`);
34
38
  }
35
39
  /**
36
- * Pure snake_case camelCase — the inverse of {@link camelToSnake}, matching
37
- * `postgres.toCamel` semantics. Read-side translation: a column read back from a
38
- * BYO database (e.g. via `drizzleDataSource`) maps to the same JS field the SDK
39
- * wrote, so `camelToSnake('operatorId') === 'operator_id'` and
40
+ * Converts snake_case to camelCase — the inverse of {@link camelToSnake}. This
41
+ * is the read-side translation: a column read back from a customer's own
42
+ * database maps to the same JavaScript field the SDK wrote, so
43
+ * `camelToSnake('operatorId') === 'operator_id'` and
40
44
  * `snakeToCamel('operator_id') === 'operatorId'` round-trip.
41
45
  */
42
46
  export function snakeToCamel(identifier) {
@@ -70,7 +74,7 @@ const BASE_COLUMNS = new Set(['id', 'organization_id', 'created_by', 'created_at
70
74
  /**
71
75
  * A Postgres-identifier-safe constraint name ≤63 bytes. When the natural
72
76
  * `<table>_<col>_<suffix>` exceeds the limit, fall back to a deterministic
73
- * hashed form so the name stays stable AND matches what Postgres actually stores
77
+ * hashed form so the name stays stable and matches what Postgres actually stores
74
78
  * — a silently-truncated name would never match the DO-block existence guard,
75
79
  * breaking idempotency (re-adds every push) and risking prefix collisions.
76
80
  */
@@ -86,45 +90,47 @@ function constraintName(table, col, suffix) {
86
90
  return `${prefix}_${hash}_${suffix}`;
87
91
  }
88
92
  /**
89
- * Foreign-key constraints for a model's belongsTo relations marked `{ fk: true }`.
93
+ * Builds the foreign-key constraints for a model's belongsTo relations that opt
94
+ * in by setting `{ fk: true }`.
90
95
  *
91
- * Emission is driven by an explicit `fk` marker, DECOUPLED from `parent`
92
- * (`parent` = sync-group fan-out / visibility, control plane; `fk` = physical
93
- * referential integrity, data plane orthogonal axes, per Drizzle's
94
- * relations()-vs-references() split and the Zanzibar "parent is permission-only"
95
- * rule). A relation sets `fk` only when its target is co-located in the same DB
96
- * AND written in the same commit, and is a strong / contained entity. Soft
97
- * references (provenance / template pointers, e.g. `sourceSlideId`, `templateId`)
98
- * stay plain columns — a hard FK there would reject a write pointing cross-scope
99
- * or at an absent row and break sync.
96
+ * The `fk` marker is deliberately separate from `parent`: `parent` controls
97
+ * sync-group fan-out and visibility, while `fk` requests physical referential
98
+ * integrity in the database. A relation sets `fk` only when its target lives in
99
+ * the same database, is written in the same commit, and is a strong, contained
100
+ * entity. Soft references provenance or template pointers such as
101
+ * `sourceSlideId` or `templateId` stay plain columns; a hard foreign key there
102
+ * would reject a write that points across scopes or at an absent row and break
103
+ * sync.
100
104
  *
101
- * LIVE / POPULATED tables: a plain ADD CONSTRAINT takes SHARE ROW EXCLUSIVE on
102
- * both tables and scans the whole child table freezing writes on a customer's
103
- * production DB. So the constraint is added `NOT VALID` (instant, no scan, brief
104
- * lock) INSIDE the transaction, and the existing-row check (`VALIDATE
105
- * CONSTRAINT`, SHARE UPDATE EXCLUSIVE — allows writes) plus the child index
106
- * (`CREATE INDEX CONCURRENTLY`) are returned SEPARATELY in {@link
107
- * ForeignKeyDdl.concurrent}, run after commit, outside any transaction, and are
108
- * best-effort: if existing data violates a freshly-added FK the VALIDATE is
109
- * skipped (logged, never fatal), the constraint still enforces all new writes,
110
- * and nothing is destroyed.
105
+ * On a live, populated table a plain `ADD CONSTRAINT` takes a heavy lock and
106
+ * scans the whole child table, which would freeze writes on a customer's
107
+ * production database. To avoid that, the constraint is added `NOT VALID`
108
+ * (instant, no scan, brief lock) inside the transaction, and the existing-row
109
+ * check (`VALIDATE CONSTRAINT`, which allows concurrent writes) plus the child
110
+ * index (`CREATE INDEX CONCURRENTLY`) are returned separately in {@link
111
+ * ForeignKeyDdl.concurrent}, to run after commit, outside any transaction, and
112
+ * best-effort: if existing data violates a freshly added constraint the
113
+ * validation is skipped (logged, never fatal), the constraint still enforces
114
+ * every new write, and nothing is destroyed.
111
115
  *
112
- * The key is a pure `DEFERRABLE INITIALLY DEFERRED` **integrity guard** with
113
- * `ON DELETE NO ACTION`: it NEVER mutates a child row itself. (SET NULL / CASCADE
114
- * would change data server-side with NO sync_delta invisible to other clients
115
- * until re-bootstrap — and would override the app-layer ModelRegistry onDelete
116
- * contract.) The app layer owns deletes + nullification and emits the deltas; the
117
- * deferred check just verifies at COMMIT, so same-batch child-before-parent and
118
- * the app's own cascade both pass that integrity holds, failing loudly only if
119
- * the app left a dangling reference.
116
+ * The constraint is a `DEFERRABLE INITIALLY DEFERRED` integrity guard with `ON
117
+ * DELETE NO ACTION`; it never mutates a child row itself. A `SET NULL` or
118
+ * `CASCADE` action would change data in the database with no matching
119
+ * sync_delta — invisible to other clients until they re-bootstrap — and would
120
+ * override the application layer's own onDelete handling. The application layer
121
+ * owns deletes and nullification and emits the deltas; the deferred check only
122
+ * verifies, at commit time (so a same-batch child-before-parent write and the
123
+ * application's own cascade both pass), that integrity holds, failing loudly
124
+ * only when a dangling reference is left behind.
120
125
  *
121
- * Authoritative + idempotent: a same-named constraint that isn't deferrable or
122
- * carries the wrong delete action (a hand-added or legacy FK) is dropped and
123
- * recreated; an already-correct one is left untouched (no re-validation cost).
124
- * Emitted in a final pass, after every referenced table exists.
126
+ * Emission is idempotent and authoritative: a same-named constraint that is not
127
+ * deferrable or carries the wrong delete action (a hand-added or older foreign
128
+ * key) is dropped and recreated, while an already-correct one is left untouched
129
+ * with no revalidation cost. It runs in a final pass, after every referenced
130
+ * table exists.
125
131
  *
126
- * The FK column is resolved the SAME way the table loop names columns
127
- * (`fieldMeta.column ?? camelToSnake(field)`), not from `rel.foreignKeyColumn` —
132
+ * The foreign-key column is resolved the same way the table loop names columns
133
+ * (`fieldMeta.column ?? camelToSnake(field)`), not from `rel.foreignKeyColumn`:
128
134
  * the table loop ignores relation casing, so trusting `foreignKeyColumn` would
129
135
  * mismatch the real column whenever `casing` is unset.
130
136
  */
@@ -143,7 +149,7 @@ function foreignKeyStatements(table, model, models, qs) {
143
149
  const concurrent = [];
144
150
  for (const rel of Object.values(model.relations)) {
145
151
  if (rel.type !== 'belongsTo')
146
- continue; // only relations whose FK column lives on THIS table
152
+ continue; // only relations whose FK column lives on this table
147
153
  if (rel.options?.fk !== true)
148
154
  continue; // explicit `fk` marker — decoupled from `parent` (visibility)
149
155
  const targetModel = models[rel.target];
@@ -171,7 +177,7 @@ function foreignKeyStatements(table, model, models, qs) {
171
177
  `REFERENCES ${targetQt} (${q('id')}) ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED NOT VALID;\n` +
172
178
  ` END IF;\nEND $$;`);
173
179
  // Post-commit, non-blocking: validate existing rows (SHARE UPDATE EXCLUSIVE,
174
- // allows concurrent writes) then index the child column (Postgres does NOT
180
+ // allows concurrent writes) then index the child column (Postgres does not
175
181
  // auto-index the referencing column → parent deletes would seq-scan it).
176
182
  concurrent.push(`ALTER TABLE ${qt} VALIDATE CONSTRAINT ${q(cname)};`);
177
183
  concurrent.push(`CREATE INDEX CONCURRENTLY IF NOT EXISTS ${q(iname)} ON ${qt} (${q(col)});`);
@@ -180,13 +186,13 @@ function foreignKeyStatements(table, model, models, qs) {
180
186
  }
181
187
  // ── Provisioning (additive, idempotent) ─────────────────────────────────────
182
188
  /**
183
- * Build the additive, idempotent provisioning plan for an app. Pure — no DB
184
- * access.
189
+ * Builds the additive, idempotent provisioning plan for an app. Pure — it does
190
+ * not touch a database.
185
191
  *
186
- * `targetSchema` is where the tables live: the app's schema `app_<id>` on the
187
- * shared tier, or `public` on a dedicated tenant's own database (where the DB
188
- * itself is the isolation boundary). For `public` the `CREATE SCHEMA` is
189
- * skipped (it always exists).
192
+ * `targetSchema` is where the tables live: a per-app Postgres schema such as
193
+ * `app_<id>`, or `public` when the database itself is the isolation boundary
194
+ * (for example a customer's own database). For `public` the `CREATE SCHEMA`
195
+ * statement is skipped, since it always exists.
190
196
  */
191
197
  export function generateProvisionPlan(schema, targetSchema, opts = {}) {
192
198
  const appSchema = targetSchema;
@@ -194,10 +200,11 @@ export function generateProvisionPlan(schema, targetSchema, opts = {}) {
194
200
  const statements = appSchema === 'public' ? [] : [`CREATE SCHEMA IF NOT EXISTS ${qs};`];
195
201
  const concurrent = [];
196
202
  for (const [key, model] of Object.entries(schema.models)) {
197
- // Control-plane models (Ablo's own sync log / attribution / audit) are never
198
- // emitted into a tenant database — only `tenant`-plane models are. Absent
199
- // plane = `tenant` (back-compat). This declared boundary is what makes "what
200
- // a BYO customer DB gets" derivable instead of hand-coded.
203
+ // Control-plane models (the engine's own sync log, attribution, and audit
204
+ // tables) are never emitted into a tenant database — only `tenant`-plane
205
+ // models are. A model with no declared plane defaults to `tenant`. This
206
+ // declared boundary is what makes the set of tables a customer's own
207
+ // database receives derivable instead of hand-coded.
201
208
  if ((model.plane ?? 'tenant') === 'control')
202
209
  continue;
203
210
  // Default the physical table to the model key when `tableName` is omitted —
@@ -316,7 +323,7 @@ export function generateMigrationPlan(steps, opts) {
316
323
  const statements = [];
317
324
  const concurrent = [];
318
325
  // The app schema must exist before any statement targets it. On a fresh
319
- // org's FIRST push (`prev = null`) the migration plan IS the provisioning —
326
+ // org's first push (`prev = null`) the migration plan is the provisioning —
320
327
  // `app_<orgId>` has never been created, and skipping this line made every
321
328
  // first push die with `3F000 invalid_schema_name` at statement 0. Idempotent
322
329
  // (`IF NOT EXISTS`), so emitting it on every later migration is free.
@@ -464,8 +471,8 @@ export function generateMigrationPlan(steps, opts) {
464
471
  }
465
472
  }
466
473
  }
467
- // Foreign keys (opt-in). Reconcile against the FULL `next` schema, not just
468
- // create_model steps: a parent edge ADDED to an existing model surfaces only as
474
+ // Foreign keys (opt-in). Reconcile against the full `next` schema, not just
475
+ // create_model steps: a parent edge added to an existing model surfaces only as
469
476
  // an add_field (relation changes aren't diffed), so a create_model-only pass
470
477
  // would never materialize its FK. The DO-block is authoritative + idempotent
471
478
  // (a no-op when the constraint is already correct), so emitting the full set
@@ -1,32 +1,28 @@
1
1
  /**
2
- * Safe-DDL LOCKING knobs the ONE reader for how a schema change acquires
3
- * (and retries for) table locks, shared by BOTH executors of the provision
4
- * plan:
2
+ * Lock settings for schema-change (DDL) statements. When a schema push alters a
3
+ * table, these values control how quickly the change gives up on a contended
4
+ * lock and how many times it retries. The command-line `ablo migrate` and the
5
+ * host that applies a schema push both resolve their lock behavior through this
6
+ * module, so tuning the environment variables below changes both paths the same
7
+ * way.
5
8
  *
6
- * - `ablo migrate` (cli/migrate.ts) the customer runs the DDL themselves
7
- * - the hosted executor (`apps/sync-server/src/schema/ddlExec.ts`)
9
+ * The defaults follow the standard safe-migration recipe: a short `lock_timeout`
10
+ * so a blocked `ALTER` aborts quickly instead of parking an `ACCESS EXCLUSIVE`
11
+ * lock request at the head of the queue — which would freeze every other query
12
+ * on that table behind it — paired with a bounded retry-and-backoff on the
13
+ * resulting timeout.
8
14
  *
9
- * The two used to carry copy-pasted constants and had already drifted: the
10
- * server honored `ABLO_SCHEMA_LOCK_ATTEMPTS` while the CLI hardcoded 5, so an
11
- * operator tuning the knob got it applied by hosted push but silently ignored
12
- * by `ablo migrate`. Both now resolve through here.
13
- *
14
- * The settings themselves are the battle-tested ones every mature migration
15
- * tool uses (GitLab `with_lock_retries`, Strong Migrations, Doctolib
16
- * `safe-pg-migrations`): a LOW `lock_timeout` so a blocked ALTER aborts fast
17
- * instead of parking an ACCESS EXCLUSIVE request at the head of the lock
18
- * queue (which would freeze every query on that table behind it), plus a
19
- * bounded retry-with-backoff on the `55P03` abort.
20
- *
21
- * Env knobs (read at CALL time, not import time, so tests and long-lived
22
- * processes see updates): `ABLO_SCHEMA_LOCK_TIMEOUT` / `ABLO_SCHEMA_LOCK_ATTEMPTS`
23
- * — the older `ABLO_DDL_*` names are still honored so existing setups don't
24
- * break.
15
+ * The environment variables are read each time a resolver is called, not once
16
+ * at import, so a long-running process or a test that changes them sees the
17
+ * update: `ABLO_SCHEMA_LOCK_TIMEOUT` and `ABLO_SCHEMA_LOCK_ATTEMPTS`. The older
18
+ * `ABLO_DDL_*` names are also accepted.
25
19
  */
26
- /** Postgres SQLSTATE `lock_not_available` — a `lock_timeout` abort. The ONE
27
- * retryable DDL failure; everything else is a real error. */
20
+ /** The Postgres SQLSTATE `55P03` (`lock_not_available`), raised when a statement
21
+ * gives up waiting for a lock after `lock_timeout`. This is the one DDL failure
22
+ * worth retrying; any other error is a genuine problem. */
28
23
  export declare const PG_LOCK_NOT_AVAILABLE = "55P03";
29
- /** The env subset the resolvers read injectable for tests. */
24
+ /** The subset of environment variables the resolvers in this module read. It is
25
+ * passed in explicitly so tests can supply their own values. */
30
26
  export type DdlLockEnv = Readonly<Record<string, string | undefined>>;
31
27
  /** `lock_timeout` for the DDL transaction (a Postgres duration string). */
32
28
  export declare function resolveDdlLockTimeout(env?: DdlLockEnv): string;