@fragno-dev/db 0.2.2 → 0.4.1

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 (587) hide show
  1. package/.turbo/turbo-build.log +404 -175
  2. package/CHANGELOG.md +109 -0
  3. package/README.md +54 -9
  4. package/dist/adapters/adapters.d.ts +23 -21
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/generic-sql/driver-config.d.ts +16 -1
  8. package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -1
  9. package/dist/adapters/generic-sql/driver-config.js +23 -1
  10. package/dist/adapters/generic-sql/driver-config.js.map +1 -1
  11. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +24 -9
  12. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
  13. package/dist/adapters/generic-sql/generic-sql-adapter.js +60 -22
  14. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
  15. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +169 -3
  16. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
  17. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -1
  18. package/dist/adapters/generic-sql/migration/dialect/mysql.js +25 -6
  19. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
  20. package/dist/adapters/generic-sql/migration/dialect/postgres.js +7 -6
  21. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
  22. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +193 -16
  23. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
  24. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -1
  25. package/dist/adapters/generic-sql/migration/executor.js +30 -3
  26. package/dist/adapters/generic-sql/migration/executor.js.map +1 -1
  27. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -1
  28. package/dist/adapters/generic-sql/migration/prepared-migrations.js +9 -9
  29. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
  30. package/dist/adapters/generic-sql/migration/sql-generator.js +75 -52
  31. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
  32. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +7 -6
  33. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
  34. package/dist/adapters/generic-sql/query/cursor-utils.js +42 -4
  35. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
  36. package/dist/adapters/generic-sql/query/db-now-sql.js +27 -0
  37. package/dist/adapters/generic-sql/query/db-now-sql.js.map +1 -0
  38. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +32 -21
  39. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
  40. package/dist/adapters/generic-sql/query/select-builder.js +5 -3
  41. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
  42. package/dist/adapters/generic-sql/query/sql-query-compiler.js +49 -18
  43. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
  44. package/dist/adapters/generic-sql/query/where-builder.js +43 -29
  45. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
  46. package/dist/adapters/generic-sql/sqlite-storage.d.ts +13 -0
  47. package/dist/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  48. package/dist/adapters/generic-sql/sqlite-storage.js +15 -0
  49. package/dist/adapters/generic-sql/sqlite-storage.js.map +1 -0
  50. package/dist/adapters/generic-sql/uow-decoder.js +6 -2
  51. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
  52. package/dist/adapters/generic-sql/uow-encoder.js +27 -8
  53. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
  54. package/dist/adapters/in-memory/condition-evaluator.js +135 -0
  55. package/dist/adapters/in-memory/condition-evaluator.js.map +1 -0
  56. package/dist/adapters/in-memory/errors.d.ts +13 -0
  57. package/dist/adapters/in-memory/errors.d.ts.map +1 -0
  58. package/dist/adapters/in-memory/errors.js +23 -0
  59. package/dist/adapters/in-memory/errors.js.map +1 -0
  60. package/dist/adapters/in-memory/in-memory-adapter.d.ts +27 -0
  61. package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -0
  62. package/dist/adapters/in-memory/in-memory-adapter.js +196 -0
  63. package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -0
  64. package/dist/adapters/in-memory/in-memory-uow.js +871 -0
  65. package/dist/adapters/in-memory/in-memory-uow.js.map +1 -0
  66. package/dist/adapters/in-memory/index.d.ts +4 -0
  67. package/dist/adapters/in-memory/index.js +4 -0
  68. package/dist/adapters/in-memory/options.d.ts +30 -0
  69. package/dist/adapters/in-memory/options.d.ts.map +1 -0
  70. package/dist/adapters/in-memory/options.js +62 -0
  71. package/dist/adapters/in-memory/options.js.map +1 -0
  72. package/dist/adapters/in-memory/reference-resolution.js +26 -0
  73. package/dist/adapters/in-memory/reference-resolution.js.map +1 -0
  74. package/dist/adapters/in-memory/sorted-array-index.js +129 -0
  75. package/dist/adapters/in-memory/sorted-array-index.js.map +1 -0
  76. package/dist/adapters/in-memory/store.js +71 -0
  77. package/dist/adapters/in-memory/store.js.map +1 -0
  78. package/dist/adapters/in-memory/value-comparison.js +28 -0
  79. package/dist/adapters/in-memory/value-comparison.js.map +1 -0
  80. package/dist/adapters/shared/from-unit-of-work-compiler.js +51 -24
  81. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
  82. package/dist/adapters/shared/uow-operation-compiler.js +11 -11
  83. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
  84. package/dist/adapters/sql/index.d.ts +5 -0
  85. package/dist/adapters/sql/index.js +4 -0
  86. package/dist/browser/adapters/adapters.d.ts +61 -0
  87. package/dist/browser/adapters/adapters.d.ts.map +1 -0
  88. package/dist/browser/adapters/generic-sql/migration/executor.d.ts +15 -0
  89. package/dist/browser/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  90. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  91. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  92. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts +11 -0
  93. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  94. package/dist/browser/adapters/in-memory/in-memory-adapter.d.ts +5 -0
  95. package/dist/browser/adapters/in-memory/index.d.ts +2 -0
  96. package/dist/browser/adapters/in-memory/options.d.ts +1 -0
  97. package/dist/browser/db-fragment-definition-builder.d.ts +237 -0
  98. package/dist/browser/db-fragment-definition-builder.d.ts.map +1 -0
  99. package/dist/browser/durable-hooks.d.ts +3 -0
  100. package/dist/browser/fragments/internal-fragment.d.ts +317 -0
  101. package/dist/browser/fragments/internal-fragment.d.ts.map +1 -0
  102. package/dist/browser/fragments/internal-fragment.schema.d.ts +1 -0
  103. package/dist/browser/hooks/durable-hooks-logger.d.ts +10 -0
  104. package/dist/browser/hooks/durable-hooks-logger.d.ts.map +1 -0
  105. package/dist/browser/hooks/hooks.d.ts +146 -0
  106. package/dist/browser/hooks/hooks.d.ts.map +1 -0
  107. package/dist/browser/id.js +1 -0
  108. package/dist/browser/internal/adapter-registry.d.ts +4 -0
  109. package/dist/browser/internal/outbox-state.d.ts +2 -0
  110. package/dist/browser/mod.d.ts +15 -0
  111. package/dist/browser/mod.d.ts.map +1 -0
  112. package/dist/browser/mod.js +17 -0
  113. package/dist/browser/mod.js.map +1 -0
  114. package/dist/browser/mod2.d.ts +48 -0
  115. package/dist/browser/mod2.d.ts.map +1 -0
  116. package/dist/browser/naming/sql-naming.d.ts +19 -0
  117. package/dist/browser/naming/sql-naming.d.ts.map +1 -0
  118. package/dist/browser/outbox/outbox.d.ts +21 -0
  119. package/dist/browser/outbox/outbox.d.ts.map +1 -0
  120. package/dist/browser/query/column-defaults.js +1 -0
  121. package/dist/browser/query/condition-builder.d.ts +44 -0
  122. package/dist/browser/query/condition-builder.d.ts.map +1 -0
  123. package/dist/browser/query/condition-builder.js +97 -0
  124. package/dist/browser/query/condition-builder.js.map +1 -0
  125. package/dist/browser/query/cursor.d.ts +105 -0
  126. package/dist/browser/query/cursor.d.ts.map +1 -0
  127. package/dist/browser/query/cursor.js +150 -0
  128. package/dist/browser/query/cursor.js.map +1 -0
  129. package/dist/browser/query/db-now.d.ts +22 -0
  130. package/dist/browser/query/db-now.d.ts.map +1 -0
  131. package/dist/browser/query/db-now.js +33 -0
  132. package/dist/browser/query/db-now.js.map +1 -0
  133. package/dist/browser/query/orm/orm.d.ts +18 -0
  134. package/dist/browser/query/orm/orm.d.ts.map +1 -0
  135. package/dist/browser/query/simple-query-interface.d.ts +108 -0
  136. package/dist/browser/query/simple-query-interface.d.ts.map +1 -0
  137. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts +423 -0
  138. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  139. package/dist/browser/query/unit-of-work/execute-unit-of-work.js +507 -0
  140. package/dist/browser/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  141. package/dist/browser/query/unit-of-work/retry-policy.d.ts +23 -0
  142. package/dist/browser/query/unit-of-work/retry-policy.d.ts.map +1 -0
  143. package/dist/browser/query/unit-of-work/retry-policy.js +40 -0
  144. package/dist/browser/query/unit-of-work/retry-policy.js.map +1 -0
  145. package/dist/browser/query/unit-of-work/unit-of-work.d.ts +703 -0
  146. package/dist/browser/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  147. package/dist/browser/query/unit-of-work/unit-of-work.js +1206 -0
  148. package/dist/browser/query/unit-of-work/unit-of-work.js.map +1 -0
  149. package/dist/browser/query/value-encoding.js +38 -0
  150. package/dist/browser/query/value-encoding.js.map +1 -0
  151. package/dist/browser/schema/create.d.ts +326 -0
  152. package/dist/browser/schema/create.d.ts.map +1 -0
  153. package/dist/browser/schema/create.js +89 -0
  154. package/dist/browser/schema/create.js.map +1 -0
  155. package/dist/browser/schema/generate-id.js +28 -0
  156. package/dist/browser/schema/generate-id.js.map +1 -0
  157. package/dist/browser/shared/providers.d.ts +6 -0
  158. package/dist/browser/shared/providers.d.ts.map +1 -0
  159. package/dist/browser/sql-driver/connection/connection-provider.d.ts +13 -0
  160. package/dist/browser/sql-driver/connection/connection-provider.d.ts.map +1 -0
  161. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  162. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  163. package/dist/browser/sql-driver/driver/runtime-driver.d.ts +23 -0
  164. package/dist/browser/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  165. package/dist/browser/sql-driver/query-executor/plugin.d.ts +17 -0
  166. package/dist/browser/sql-driver/query-executor/plugin.d.ts.map +1 -0
  167. package/dist/browser/sql-driver/query-executor/query-executor.d.ts +36 -0
  168. package/dist/browser/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  169. package/dist/browser/sql-driver/sql-driver-adapter.d.ts +29 -0
  170. package/dist/browser/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  171. package/dist/browser/sql-driver/sql-driver.d.ts +38 -0
  172. package/dist/browser/sql-driver/sql-driver.d.ts.map +1 -0
  173. package/dist/browser/sync/commands.d.ts +15 -0
  174. package/dist/browser/sync/commands.d.ts.map +1 -0
  175. package/dist/browser/sync/commands.js +27 -0
  176. package/dist/browser/sync/commands.js.map +1 -0
  177. package/dist/browser/sync/types.d.ts +63 -0
  178. package/dist/browser/sync/types.d.ts.map +1 -0
  179. package/dist/browser/util/types.d.ts +8 -0
  180. package/dist/browser/util/types.d.ts.map +1 -0
  181. package/dist/browser/with-database.d.ts +29 -0
  182. package/dist/browser/with-database.d.ts.map +1 -0
  183. package/dist/client.d.ts +4 -0
  184. package/dist/client.js +5 -0
  185. package/dist/db-fragment-definition-builder.d.ts +101 -33
  186. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  187. package/dist/db-fragment-definition-builder.js +450 -60
  188. package/dist/db-fragment-definition-builder.js.map +1 -1
  189. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts +20 -0
  190. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts.map +1 -0
  191. package/dist/dispatchers/cloudflare-do/dispatcher.js +147 -0
  192. package/dist/dispatchers/cloudflare-do/dispatcher.js.map +1 -0
  193. package/dist/dispatchers/cloudflare-do/index.d.ts +11 -0
  194. package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -0
  195. package/dist/dispatchers/cloudflare-do/index.js +31 -0
  196. package/dist/dispatchers/cloudflare-do/index.js.map +1 -0
  197. package/dist/dispatchers/node/dispatcher.d.ts +14 -0
  198. package/dist/dispatchers/node/dispatcher.d.ts.map +1 -0
  199. package/dist/dispatchers/node/dispatcher.js +80 -0
  200. package/dist/dispatchers/node/dispatcher.js.map +1 -0
  201. package/dist/dispatchers/node/index.d.ts +12 -0
  202. package/dist/dispatchers/node/index.d.ts.map +1 -0
  203. package/dist/dispatchers/node/index.js +27 -0
  204. package/dist/dispatchers/node/index.js.map +1 -0
  205. package/dist/durable-hooks.d.ts +31 -0
  206. package/dist/durable-hooks.d.ts.map +1 -0
  207. package/dist/durable-hooks.js +23 -0
  208. package/dist/durable-hooks.js.map +1 -0
  209. package/dist/fragments/internal-fragment.d.ts +186 -8
  210. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  211. package/dist/fragments/internal-fragment.js +203 -38
  212. package/dist/fragments/internal-fragment.js.map +1 -1
  213. package/dist/fragments/internal-fragment.routes.js +164 -0
  214. package/dist/fragments/internal-fragment.routes.js.map +1 -0
  215. package/dist/fragments/internal-fragment.schema.d.ts +15 -0
  216. package/dist/fragments/internal-fragment.schema.d.ts.map +1 -0
  217. package/dist/fragments/internal-fragment.schema.js +39 -0
  218. package/dist/fragments/internal-fragment.schema.js.map +1 -0
  219. package/dist/hooks/durable-hooks-logger.d.ts +10 -0
  220. package/dist/hooks/durable-hooks-logger.d.ts.map +1 -0
  221. package/dist/hooks/durable-hooks-logger.js +75 -0
  222. package/dist/hooks/durable-hooks-logger.js.map +1 -0
  223. package/dist/hooks/durable-hooks-processor.d.ts +1 -0
  224. package/dist/hooks/durable-hooks-processor.js +80 -0
  225. package/dist/hooks/durable-hooks-processor.js.map +1 -0
  226. package/dist/hooks/durable-hooks-runtime.js +44 -0
  227. package/dist/hooks/durable-hooks-runtime.js.map +1 -0
  228. package/dist/hooks/hooks.d.ts +100 -1
  229. package/dist/hooks/hooks.d.ts.map +1 -1
  230. package/dist/hooks/hooks.js +254 -27
  231. package/dist/hooks/hooks.js.map +1 -1
  232. package/dist/id.d.ts +2 -2
  233. package/dist/id.js +2 -2
  234. package/dist/internal/adapter-registry.d.ts +11 -0
  235. package/dist/internal/adapter-registry.d.ts.map +1 -0
  236. package/dist/internal/adapter-registry.js +135 -0
  237. package/dist/internal/adapter-registry.js.map +1 -0
  238. package/dist/internal/outbox-state.d.ts +2 -0
  239. package/dist/internal/outbox-state.js +26 -0
  240. package/dist/internal/outbox-state.js.map +1 -0
  241. package/dist/migration-engine/auto-from-schema.d.ts +33 -0
  242. package/dist/migration-engine/auto-from-schema.d.ts.map +1 -0
  243. package/dist/migration-engine/auto-from-schema.js +223 -37
  244. package/dist/migration-engine/auto-from-schema.js.map +1 -1
  245. package/dist/migration-engine/generation-engine.d.ts +16 -10
  246. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  247. package/dist/migration-engine/generation-engine.js +86 -35
  248. package/dist/migration-engine/generation-engine.js.map +1 -1
  249. package/dist/migration-engine/shared.d.ts +113 -0
  250. package/dist/migration-engine/shared.d.ts.map +1 -0
  251. package/dist/migration-engine/shared.js.map +1 -1
  252. package/dist/mod.d.ts +20 -12
  253. package/dist/mod.d.ts.map +1 -1
  254. package/dist/mod.js +18 -12
  255. package/dist/mod.js.map +1 -1
  256. package/dist/naming/sql-naming.d.ts +19 -0
  257. package/dist/naming/sql-naming.d.ts.map +1 -0
  258. package/dist/naming/sql-naming.js +116 -0
  259. package/dist/naming/sql-naming.js.map +1 -0
  260. package/dist/outbox/outbox-builder.js +156 -0
  261. package/dist/outbox/outbox-builder.js.map +1 -0
  262. package/dist/outbox/outbox.d.ts +54 -0
  263. package/dist/outbox/outbox.d.ts.map +1 -0
  264. package/dist/outbox/outbox.js +37 -0
  265. package/dist/outbox/outbox.js.map +1 -0
  266. package/dist/query/column-defaults.js +20 -4
  267. package/dist/query/column-defaults.js.map +1 -1
  268. package/dist/query/condition-builder.d.ts +7 -1
  269. package/dist/query/condition-builder.d.ts.map +1 -1
  270. package/dist/query/condition-builder.js +5 -1
  271. package/dist/query/condition-builder.js.map +1 -1
  272. package/dist/query/cursor-client.d.ts +105 -0
  273. package/dist/query/cursor-client.d.ts.map +1 -0
  274. package/dist/query/cursor-client.js +165 -0
  275. package/dist/query/cursor-client.js.map +1 -0
  276. package/dist/query/cursor.d.ts +3 -1
  277. package/dist/query/cursor.d.ts.map +1 -1
  278. package/dist/query/cursor.js +51 -14
  279. package/dist/query/cursor.js.map +1 -1
  280. package/dist/query/db-now.d.ts +22 -0
  281. package/dist/query/db-now.d.ts.map +1 -0
  282. package/dist/query/db-now.js +35 -0
  283. package/dist/query/db-now.js.map +1 -0
  284. package/dist/query/orm/orm.js.map +1 -1
  285. package/dist/query/serialize/create-sql-serializer.js +5 -4
  286. package/dist/query/serialize/create-sql-serializer.js.map +1 -1
  287. package/dist/query/serialize/dialect/mysql-serializer.js +12 -6
  288. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
  289. package/dist/query/serialize/dialect/postgres-serializer.js +25 -7
  290. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
  291. package/dist/query/serialize/dialect/sqlite-serializer.js +60 -12
  292. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
  293. package/dist/query/serialize/sql-serializer.js +2 -2
  294. package/dist/query/serialize/sql-serializer.js.map +1 -1
  295. package/dist/query/simple-query-interface.d.ts +13 -4
  296. package/dist/query/simple-query-interface.d.ts.map +1 -1
  297. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +37 -2
  298. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  299. package/dist/query/unit-of-work/execute-unit-of-work.js +50 -24
  300. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  301. package/dist/query/unit-of-work/unit-of-work.d.ts +92 -30
  302. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  303. package/dist/query/unit-of-work/unit-of-work.js +136 -11
  304. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  305. package/dist/query/value-decoding.js +16 -6
  306. package/dist/query/value-decoding.js.map +1 -1
  307. package/dist/query/value-encoding.js +29 -9
  308. package/dist/query/value-encoding.js.map +1 -1
  309. package/dist/schema/create.d.ts +103 -35
  310. package/dist/schema/create.d.ts.map +1 -1
  311. package/dist/schema/create.js +172 -58
  312. package/dist/schema/create.js.map +1 -1
  313. package/dist/schema/generate-id.js +2 -2
  314. package/dist/schema/generate-id.js.map +1 -1
  315. package/dist/schema/type-conversion/create-sql-type-mapper.js +4 -3
  316. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  317. package/dist/schema/type-conversion/dialect/sqlite.js +9 -0
  318. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  319. package/dist/schema/validator.d.ts +10 -0
  320. package/dist/schema/validator.d.ts.map +1 -0
  321. package/dist/schema/validator.js +123 -0
  322. package/dist/schema/validator.js.map +1 -0
  323. package/dist/schema-output/drizzle.d.ts +30 -0
  324. package/dist/schema-output/drizzle.d.ts.map +1 -0
  325. package/dist/{adapters/drizzle/generate.js → schema-output/drizzle.js} +88 -60
  326. package/dist/schema-output/drizzle.js.map +1 -0
  327. package/dist/schema-output/prisma.d.ts +17 -0
  328. package/dist/schema-output/prisma.d.ts.map +1 -0
  329. package/dist/schema-output/prisma.js +307 -0
  330. package/dist/schema-output/prisma.js.map +1 -0
  331. package/dist/sql-driver/dialects/durable-object-dialect.js +3 -9
  332. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -1
  333. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -1
  334. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -1
  335. package/dist/sql-driver/sql-driver-adapter.js.map +1 -1
  336. package/dist/sql-driver/sql.js.map +1 -1
  337. package/dist/sync/commands.d.ts +15 -0
  338. package/dist/sync/commands.d.ts.map +1 -0
  339. package/dist/sync/commands.js +27 -0
  340. package/dist/sync/commands.js.map +1 -0
  341. package/dist/sync/index.d.ts +4 -0
  342. package/dist/sync/index.js +4 -0
  343. package/dist/sync/read-tracking.d.ts +25 -0
  344. package/dist/sync/read-tracking.d.ts.map +1 -0
  345. package/dist/sync/read-tracking.js +148 -0
  346. package/dist/sync/read-tracking.js.map +1 -0
  347. package/dist/sync/submit.js +213 -0
  348. package/dist/sync/submit.js.map +1 -0
  349. package/dist/sync/types.d.ts +63 -0
  350. package/dist/sync/types.d.ts.map +1 -0
  351. package/dist/util/default-database-adapter.js +66 -0
  352. package/dist/util/default-database-adapter.js.map +1 -0
  353. package/dist/with-database.d.ts +3 -6
  354. package/dist/with-database.d.ts.map +1 -1
  355. package/dist/with-database.js +8 -7
  356. package/dist/with-database.js.map +1 -1
  357. package/package.json +62 -55
  358. package/src/adapters/adapters.ts +33 -26
  359. package/src/adapters/drizzle/migrate-drizzle.test.ts +99 -41
  360. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +601 -0
  361. package/src/adapters/drizzle/test-utils.ts +13 -8
  362. package/src/adapters/generic-sql/driver-config.ts +38 -0
  363. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +10 -8
  364. package/src/adapters/generic-sql/generic-sql-adapter.ts +117 -34
  365. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +55 -0
  366. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +297 -3
  367. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +120 -0
  368. package/src/adapters/generic-sql/migration/cold-kysely.ts +1 -0
  369. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +27 -8
  370. package/src/adapters/generic-sql/migration/dialect/mysql.ts +47 -8
  371. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +28 -9
  372. package/src/adapters/generic-sql/migration/dialect/postgres.ts +9 -4
  373. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +839 -8
  374. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +396 -53
  375. package/src/adapters/generic-sql/migration/executor.test.ts +52 -0
  376. package/src/adapters/generic-sql/migration/executor.ts +47 -4
  377. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +238 -46
  378. package/src/adapters/generic-sql/migration/prepared-migrations.ts +21 -13
  379. package/src/adapters/generic-sql/migration/sql-generator.ts +145 -66
  380. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +11 -8
  381. package/src/adapters/generic-sql/query/cursor-utils.test.ts +272 -0
  382. package/src/adapters/generic-sql/query/cursor-utils.ts +42 -7
  383. package/src/adapters/generic-sql/query/db-now-sql.ts +49 -0
  384. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +171 -35
  385. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +53 -40
  386. package/src/adapters/generic-sql/query/select-builder.test.ts +16 -11
  387. package/src/adapters/generic-sql/query/select-builder.ts +7 -3
  388. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +75 -6
  389. package/src/adapters/generic-sql/query/sql-query-compiler.ts +129 -24
  390. package/src/adapters/generic-sql/query/where-builder.test.ts +96 -20
  391. package/src/adapters/generic-sql/query/where-builder.ts +112 -41
  392. package/src/adapters/{kysely/kysely-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-migrations.test.ts} +11 -20
  393. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +851 -0
  394. package/src/adapters/{drizzle/drizzle-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-queries.test.ts} +18 -15
  395. package/src/adapters/generic-sql/{test/generic-drizzle-adapter-sqlite3.test.ts → sql-adapter-sqlite3-driver.test.ts} +282 -14
  396. package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +129 -12
  397. package/src/adapters/{kysely/kysely-adapter-sqlocal.test.ts → generic-sql/sql-adapter-sqlocal.test.ts} +9 -7
  398. package/src/adapters/generic-sql/sqlite-storage.ts +20 -0
  399. package/src/adapters/generic-sql/uow-decoder.test.ts +5 -4
  400. package/src/adapters/generic-sql/uow-decoder.ts +23 -5
  401. package/src/adapters/generic-sql/uow-encoder.test.ts +36 -3
  402. package/src/adapters/generic-sql/uow-encoder.ts +48 -13
  403. package/src/adapters/in-memory/condition-evaluator.test.ts +194 -0
  404. package/src/adapters/in-memory/condition-evaluator.ts +280 -0
  405. package/src/adapters/in-memory/errors.ts +20 -0
  406. package/src/adapters/in-memory/in-memory-adapter.ts +388 -0
  407. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +344 -0
  408. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +255 -0
  409. package/src/adapters/in-memory/in-memory-uow.ts +1724 -0
  410. package/src/adapters/in-memory/index.ts +3 -0
  411. package/src/adapters/in-memory/options.test.ts +42 -0
  412. package/src/adapters/in-memory/options.ts +91 -0
  413. package/src/adapters/in-memory/outbox.test.ts +361 -0
  414. package/src/adapters/in-memory/reference-resolution.test.ts +51 -0
  415. package/src/adapters/in-memory/reference-resolution.ts +67 -0
  416. package/src/adapters/in-memory/sorted-array-index.test.ts +124 -0
  417. package/src/adapters/in-memory/sorted-array-index.ts +228 -0
  418. package/src/adapters/in-memory/store.test.ts +69 -0
  419. package/src/adapters/in-memory/store.ts +145 -0
  420. package/src/adapters/in-memory/value-comparison.ts +53 -0
  421. package/src/adapters/in-memory/value-normalization.test.ts +58 -0
  422. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +1207 -0
  423. package/src/adapters/shared/from-unit-of-work-compiler.ts +159 -47
  424. package/src/adapters/shared/uow-operation-compiler.ts +28 -18
  425. package/src/adapters/sql/index.ts +12 -0
  426. package/src/browser/mod.ts +64 -0
  427. package/src/client.ts +19 -0
  428. package/src/db-fragment-definition-builder.test.ts +845 -53
  429. package/src/db-fragment-definition-builder.ts +911 -95
  430. package/src/db-fragment-instantiator.test.ts +210 -94
  431. package/src/db-fragment-integration.test.ts +17 -12
  432. package/src/dispatchers/cloudflare-do/dispatcher.ts +204 -0
  433. package/src/dispatchers/cloudflare-do/index.test.ts +206 -0
  434. package/src/dispatchers/cloudflare-do/index.ts +63 -0
  435. package/src/dispatchers/node/dispatcher.ts +112 -0
  436. package/src/dispatchers/node/index.test.ts +120 -0
  437. package/src/dispatchers/node/index.ts +50 -0
  438. package/src/durable-hooks.test.ts +80 -0
  439. package/src/durable-hooks.ts +67 -0
  440. package/src/fragments/internal-fragment.routes.test.ts +570 -0
  441. package/src/fragments/internal-fragment.routes.ts +334 -0
  442. package/src/fragments/internal-fragment.schema.ts +95 -0
  443. package/src/fragments/internal-fragment.test.ts +505 -83
  444. package/src/fragments/internal-fragment.ts +453 -70
  445. package/src/hooks/durable-hooks-logger.ts +126 -0
  446. package/src/hooks/durable-hooks-processor.pglite.test.ts +87 -0
  447. package/src/hooks/durable-hooks-processor.test.ts +282 -0
  448. package/src/hooks/durable-hooks-processor.ts +173 -0
  449. package/src/hooks/durable-hooks-runtime.test.ts +65 -0
  450. package/src/hooks/durable-hooks-runtime.ts +81 -0
  451. package/src/hooks/hooks.test.ts +455 -34
  452. package/src/hooks/hooks.ts +501 -34
  453. package/src/id.test.ts +34 -0
  454. package/src/id.ts +1 -3
  455. package/src/internal/adapter-registry.test.ts +93 -0
  456. package/src/internal/adapter-registry.ts +239 -0
  457. package/src/internal/outbox-state.ts +43 -0
  458. package/src/migration-engine/auto-from-schema.test.ts +107 -14
  459. package/src/migration-engine/auto-from-schema.ts +365 -44
  460. package/src/migration-engine/create.test.ts +4 -3
  461. package/src/migration-engine/create.ts +1 -1
  462. package/src/migration-engine/generation-engine.test.ts +292 -110
  463. package/src/migration-engine/generation-engine.ts +117 -66
  464. package/src/migration-engine/shared.ts +14 -0
  465. package/src/mod.ts +95 -39
  466. package/src/naming/sql-naming.ts +181 -0
  467. package/src/outbox/outbox-builder.ts +241 -0
  468. package/src/outbox/outbox.test.ts +424 -0
  469. package/src/outbox/outbox.ts +139 -0
  470. package/src/query/column-defaults.ts +42 -4
  471. package/src/query/condition-builder.test.ts +18 -3
  472. package/src/query/condition-builder.ts +7 -0
  473. package/src/query/cursor-client.test.ts +70 -0
  474. package/src/query/cursor-client.ts +263 -0
  475. package/src/query/cursor.test.ts +119 -20
  476. package/src/query/cursor.ts +88 -27
  477. package/src/query/db-now.ts +73 -0
  478. package/src/query/orm/orm.ts +2 -2
  479. package/src/query/query-type.test.ts +4 -3
  480. package/src/query/serialize/create-sql-serializer.ts +10 -5
  481. package/src/query/serialize/dialect/mysql-serializer.ts +13 -5
  482. package/src/query/serialize/dialect/postgres-serializer.ts +35 -5
  483. package/src/query/serialize/dialect/sqlite-serializer.test.ts +90 -3
  484. package/src/query/serialize/dialect/sqlite-serializer.ts +108 -12
  485. package/src/query/serialize/sql-serializer.ts +4 -4
  486. package/src/query/simple-query-interface.ts +15 -4
  487. package/src/query/unit-of-work/execute-unit-of-work.test.ts +372 -10
  488. package/src/query/unit-of-work/execute-unit-of-work.ts +87 -27
  489. package/src/query/unit-of-work/retry-policy.test.ts +1 -0
  490. package/src/query/unit-of-work/tx-builder.test.ts +73 -1
  491. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +17 -16
  492. package/src/query/unit-of-work/unit-of-work-types.test.ts +42 -12
  493. package/src/query/unit-of-work/unit-of-work.test.ts +196 -39
  494. package/src/query/unit-of-work/unit-of-work.ts +309 -38
  495. package/src/query/value-decoding.test.ts +63 -4
  496. package/src/query/value-decoding.ts +32 -6
  497. package/src/query/value-encoding.test.ts +86 -2
  498. package/src/query/value-encoding.ts +56 -6
  499. package/src/schema/create.test.ts +293 -47
  500. package/src/schema/create.ts +406 -70
  501. package/src/schema/generate-id.test.ts +3 -2
  502. package/src/schema/generate-id.ts +2 -2
  503. package/src/schema/serialize.test.ts +18 -5
  504. package/src/schema/type-conversion/create-sql-type-mapper.ts +8 -3
  505. package/src/schema/type-conversion/dialect/sqlite.ts +18 -0
  506. package/src/schema/type-conversion/type-mapping.test.ts +26 -1
  507. package/src/schema/validator.test.ts +199 -0
  508. package/src/schema/validator.ts +232 -0
  509. package/src/{adapters/drizzle/generate.test.ts → schema-output/drizzle.test.ts} +232 -129
  510. package/src/{adapters/drizzle/generate.ts → schema-output/drizzle.ts} +155 -99
  511. package/src/schema-output/prisma.test.ts +694 -0
  512. package/src/schema-output/prisma.ts +593 -0
  513. package/src/sql-driver/better-sqlite3.test.ts +5 -3
  514. package/src/sql-driver/dialects/durable-object-dialect.ts +3 -8
  515. package/src/sql-driver/query-executor/default-query-executor.ts +1 -1
  516. package/src/sql-driver/query-executor/query-executor-base.ts +1 -1
  517. package/src/sql-driver/query-executor/query-executor.ts +1 -1
  518. package/src/sql-driver/sql-driver-adapter.ts +2 -2
  519. package/src/sql-driver/sql.ts +2 -1
  520. package/src/sql-driver/sqlocal.test.ts +4 -2
  521. package/src/sync/commands.test.ts +39 -0
  522. package/src/sync/commands.ts +51 -0
  523. package/src/sync/conflict-checker.test.ts +450 -0
  524. package/src/sync/conflict-checker.ts +248 -0
  525. package/src/sync/index.ts +14 -0
  526. package/src/sync/plan.ts +9 -0
  527. package/src/sync/read-tracking.test.ts +177 -0
  528. package/src/sync/read-tracking.ts +287 -0
  529. package/src/sync/submit.test.ts +205 -0
  530. package/src/sync/submit.ts +328 -0
  531. package/src/sync/types.ts +80 -0
  532. package/src/util/default-database-adapter.ts +119 -0
  533. package/src/with-database.ts +20 -31
  534. package/tsconfig.json +1 -1
  535. package/tsdown.config.ts +38 -24
  536. package/vitest.config.ts +1 -0
  537. package/dist/adapters/drizzle/drizzle-adapter.d.ts +0 -20
  538. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +0 -1
  539. package/dist/adapters/drizzle/drizzle-adapter.js +0 -27
  540. package/dist/adapters/drizzle/drizzle-adapter.js.map +0 -1
  541. package/dist/adapters/drizzle/generate.d.ts +0 -30
  542. package/dist/adapters/drizzle/generate.d.ts.map +0 -1
  543. package/dist/adapters/drizzle/generate.js.map +0 -1
  544. package/dist/adapters/kysely/kysely-adapter.d.ts +0 -19
  545. package/dist/adapters/kysely/kysely-adapter.d.ts.map +0 -1
  546. package/dist/adapters/kysely/kysely-adapter.js +0 -17
  547. package/dist/adapters/kysely/kysely-adapter.js.map +0 -1
  548. package/dist/adapters/shared/table-name-mapper.d.ts +0 -12
  549. package/dist/adapters/shared/table-name-mapper.d.ts.map +0 -1
  550. package/dist/adapters/shared/table-name-mapper.js +0 -43
  551. package/dist/adapters/shared/table-name-mapper.js.map +0 -1
  552. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js +0 -165
  553. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +0 -1
  554. package/dist/packages/fragno/dist/api/bind-services.js +0 -20
  555. package/dist/packages/fragno/dist/api/bind-services.js.map +0 -1
  556. package/dist/packages/fragno/dist/api/error.js +0 -48
  557. package/dist/packages/fragno/dist/api/error.js.map +0 -1
  558. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +0 -320
  559. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +0 -1
  560. package/dist/packages/fragno/dist/api/fragment-instantiator.js +0 -525
  561. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +0 -1
  562. package/dist/packages/fragno/dist/api/fragno-response.js +0 -73
  563. package/dist/packages/fragno/dist/api/fragno-response.js.map +0 -1
  564. package/dist/packages/fragno/dist/api/internal/response-stream.js +0 -81
  565. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +0 -1
  566. package/dist/packages/fragno/dist/api/internal/route.js +0 -10
  567. package/dist/packages/fragno/dist/api/internal/route.js.map +0 -1
  568. package/dist/packages/fragno/dist/api/mutable-request-state.js +0 -97
  569. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +0 -1
  570. package/dist/packages/fragno/dist/api/request-context-storage.js +0 -43
  571. package/dist/packages/fragno/dist/api/request-context-storage.js.map +0 -1
  572. package/dist/packages/fragno/dist/api/request-input-context.js +0 -118
  573. package/dist/packages/fragno/dist/api/request-input-context.js.map +0 -1
  574. package/dist/packages/fragno/dist/api/request-middleware.js +0 -83
  575. package/dist/packages/fragno/dist/api/request-middleware.js.map +0 -1
  576. package/dist/packages/fragno/dist/api/request-output-context.js +0 -119
  577. package/dist/packages/fragno/dist/api/request-output-context.js.map +0 -1
  578. package/dist/packages/fragno/dist/api/route.js +0 -17
  579. package/dist/packages/fragno/dist/api/route.js.map +0 -1
  580. package/dist/packages/fragno/dist/internal/symbols.js +0 -10
  581. package/dist/packages/fragno/dist/internal/symbols.js.map +0 -1
  582. package/dist/schema-generator/schema-generator.d.ts +0 -15
  583. package/dist/schema-generator/schema-generator.d.ts.map +0 -1
  584. package/src/adapters/drizzle/drizzle-adapter.ts +0 -39
  585. package/src/adapters/kysely/kysely-adapter.ts +0 -27
  586. package/src/adapters/shared/table-name-mapper.ts +0 -50
  587. package/src/schema-generator/schema-generator.ts +0 -12
@@ -1,26 +1,32 @@
1
- import { describe, it, expect, expectTypeOf } from "vitest";
1
+ import { describe, it, expect, expectTypeOf, vi } from "vitest";
2
+
3
+ import { InMemoryAdapter } from "../../adapters/in-memory/in-memory-adapter";
4
+ import type { InternalFragmentInstance } from "../../fragments/internal-fragment";
5
+ import { internalSchema } from "../../fragments/internal-fragment.schema";
6
+ import { prepareHookMutations } from "../../hooks/hooks";
2
7
  import { schema, idColumn, FragnoId } from "../../schema/create";
3
- import {
4
- createUnitOfWork,
5
- type IUnitOfWork,
6
- type UOWCompiler,
7
- type UOWDecoder,
8
- type UOWExecutor,
9
- } from "./unit-of-work";
10
8
  import {
11
9
  createServiceTxBuilder,
12
10
  createHandlerTxBuilder,
13
11
  isTxResult,
12
+ serviceCalls,
14
13
  ConcurrencyConflictError,
15
14
  } from "./execute-unit-of-work";
15
+ import type { AwaitedPromisesInObject, TxResult } from "./execute-unit-of-work";
16
16
  import {
17
17
  ExponentialBackoffRetryPolicy,
18
18
  LinearBackoffRetryPolicy,
19
19
  NoRetryPolicy,
20
20
  } from "./retry-policy";
21
- import type { AwaitedPromisesInObject, TxResult } from "./execute-unit-of-work";
21
+ import {
22
+ createUnitOfWork,
23
+ type IUnitOfWork,
24
+ type UOWCompiler,
25
+ type UOWDecoder,
26
+ type UOWExecutor,
27
+ } from "./unit-of-work";
22
28
 
23
- const testSchema = schema((s) =>
29
+ const testSchema = schema("test", (s) =>
24
30
  s.addTable("users", (t) =>
25
31
  t
26
32
  .addColumn("id", idColumn())
@@ -31,6 +37,42 @@ const testSchema = schema((s) =>
31
37
  ),
32
38
  );
33
39
 
40
+ function setupCrossSchemaHookTest() {
41
+ const adapter = new InMemoryAdapter();
42
+ const schemaA = schema("alpha", (s) =>
43
+ s.addTable("items", (t) => t.addColumn("id", idColumn()).addColumn("label", "string")),
44
+ );
45
+ const schemaB = schema("beta", (s) =>
46
+ s.addTable("items", (t) => t.addColumn("id", idColumn()).addColumn("label", "string")),
47
+ );
48
+ const namespaceA = "alpha";
49
+ const namespaceB = "beta";
50
+
51
+ const queryA = adapter.createQueryEngine(schemaA, namespaceA);
52
+ const queryB = adapter.createQueryEngine(schemaB, namespaceB);
53
+ const internalQuery = adapter.createQueryEngine(internalSchema, null);
54
+
55
+ const internalFragment = {
56
+ $internal: {
57
+ deps: {
58
+ schema: internalSchema,
59
+ namespace: null,
60
+ },
61
+ },
62
+ } as InternalFragmentInstance;
63
+
64
+ return {
65
+ schemaA,
66
+ schemaB,
67
+ namespaceA,
68
+ namespaceB,
69
+ queryA,
70
+ queryB,
71
+ internalQuery,
72
+ internalFragment,
73
+ };
74
+ }
75
+
34
76
  describe("AwaitedPromisesInObject type tests", () => {
35
77
  it("should unwrap promises in objects", () => {
36
78
  type Input = { a: Promise<string>; b: number };
@@ -390,6 +432,36 @@ describe("Unified Tx API", () => {
390
432
  expect(users[1].name).toBe("Bob");
391
433
  });
392
434
 
435
+ it("should call onAfterRetrieve with full results", async () => {
436
+ const compiler = createMockCompiler();
437
+ const mockUsers = [
438
+ {
439
+ id: FragnoId.fromExternal("1", 1),
440
+ email: "alice@example.com",
441
+ name: "Alice",
442
+ balance: 100,
443
+ },
444
+ ];
445
+ const executor: UOWExecutor<unknown, unknown> = {
446
+ executeRetrievalPhase: async () => [mockUsers],
447
+ executeMutationPhase: async () => ({ success: true, createdInternalIds: [] }),
448
+ };
449
+ const decoder = createMockDecoder();
450
+ const onAfterRetrieve = vi.fn();
451
+
452
+ await createHandlerTxBuilder({
453
+ createUnitOfWork: () => createUnitOfWork(compiler, executor, decoder),
454
+ onAfterRetrieve,
455
+ })
456
+ .retrieve(({ forSchema }) =>
457
+ forSchema(testSchema).find("users", (b) => b.whereIndex("idx_email")),
458
+ )
459
+ .execute();
460
+
461
+ expect(onAfterRetrieve).toHaveBeenCalledOnce();
462
+ expect(onAfterRetrieve.mock.calls[0]?.[1]).toEqual([mockUsers]);
463
+ });
464
+
393
465
  it("should execute a simple mutate-only transaction", async () => {
394
466
  const compiler = createMockCompiler();
395
467
  const executor: UOWExecutor<unknown, unknown> = {
@@ -414,6 +486,26 @@ describe("Unified Tx API", () => {
414
486
  expect(result.userId).toBeInstanceOf(FragnoId);
415
487
  });
416
488
 
489
+ it("should throw when retry policy is provided without retrieve operations", async () => {
490
+ const compiler = createMockCompiler();
491
+ const executor: UOWExecutor<unknown, unknown> = {
492
+ executeRetrievalPhase: async () => [],
493
+ executeMutationPhase: async () => ({ success: false }),
494
+ };
495
+ const decoder = createMockDecoder();
496
+
497
+ await expect(
498
+ createHandlerTxBuilder({
499
+ createUnitOfWork: () => createUnitOfWork(compiler, executor, decoder),
500
+ retryPolicy: new NoRetryPolicy(),
501
+ })
502
+ .mutate(() => ({ done: true }))
503
+ .execute(),
504
+ ).rejects.toThrow(
505
+ "Retry policy is only supported when the transaction includes retrieve operations.",
506
+ );
507
+ });
508
+
417
509
  it("should execute a transaction with serviceCalls as retrieve source", async () => {
418
510
  const compiler = createMockCompiler();
419
511
  const mockUser = {
@@ -753,6 +845,72 @@ describe("Unified Tx API", () => {
753
845
  expect(result.finalDepUserId).toBeInstanceOf(FragnoId);
754
846
  });
755
847
 
848
+ it("should preserve tuple inference for dynamic serviceCalls using helper", async () => {
849
+ const compiler = createMockCompiler();
850
+ const executor: UOWExecutor<unknown, unknown> = {
851
+ executeRetrievalPhase: async () => [],
852
+ executeMutationPhase: async () => ({ success: true, createdInternalIds: [BigInt(1)] }),
853
+ };
854
+ const decoder = createMockDecoder();
855
+
856
+ let currentUow: IUnitOfWork | null = null;
857
+
858
+ type UserData = { id: FragnoId; email: string };
859
+ type Stats = { count: number };
860
+ type HistoryEntry = { page: number };
861
+
862
+ const getUser = () =>
863
+ createServiceTxBuilder(testSchema, currentUow!)
864
+ .mutate(({ uow }): UserData => {
865
+ const userId = uow.create("users", {
866
+ email: "user@example.com",
867
+ name: "User",
868
+ balance: 0,
869
+ });
870
+ return { id: userId, email: "user@example.com" };
871
+ })
872
+ .build();
873
+
874
+ const getStats = () =>
875
+ createServiceTxBuilder(testSchema, currentUow!)
876
+ .mutate((): Stats => ({ count: 42 }))
877
+ .build();
878
+
879
+ const listHistory = (page: number) =>
880
+ createServiceTxBuilder(testSchema, currentUow!)
881
+ .mutate((): HistoryEntry => ({ page }))
882
+ .build();
883
+
884
+ const result = await createHandlerTxBuilder({
885
+ createUnitOfWork: () => {
886
+ currentUow = createUnitOfWork(compiler, executor, decoder);
887
+ return currentUow;
888
+ },
889
+ })
890
+ .withServiceCalls(() => {
891
+ const historyCalls = Array.from({ length: 2 }, (_, idx) => listHistory(idx + 1));
892
+ return serviceCalls(getUser(), getStats(), ...historyCalls);
893
+ })
894
+ .mutate(({ serviceIntermediateResult }) => {
895
+ const [user, stats, ...history] = serviceIntermediateResult;
896
+
897
+ expectTypeOf(user).toEqualTypeOf<UserData>();
898
+ expectTypeOf(stats).toEqualTypeOf<Stats>();
899
+ expectTypeOf(history).items.toEqualTypeOf<HistoryEntry>();
900
+
901
+ return {
902
+ userId: user.id,
903
+ count: stats.count,
904
+ pages: history.map((entry) => entry.page),
905
+ };
906
+ })
907
+ .execute();
908
+
909
+ expect(result.count).toBe(42);
910
+ expect(result.pages).toEqual([1, 2]);
911
+ expect(result.userId).toBeInstanceOf(FragnoId);
912
+ });
913
+
756
914
  it("should retry on concurrency conflict", async () => {
757
915
  const compiler = createMockCompiler();
758
916
  let mutationAttempts = 0;
@@ -772,6 +930,7 @@ describe("Unified Tx API", () => {
772
930
  createUnitOfWork: () => createUnitOfWork(compiler, executor, decoder),
773
931
  retryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 5, initialDelayMs: 1 }),
774
932
  })
933
+ .retrieve(({ forSchema }) => forSchema(testSchema).find("users"))
775
934
  .mutate(({ forSchema }) => {
776
935
  forSchema(testSchema).create("users", {
777
936
  email: "test@example.com",
@@ -801,6 +960,7 @@ describe("Unified Tx API", () => {
801
960
  createUnitOfWork: () => createUnitOfWork(compiler, executor, decoder),
802
961
  retryPolicy: new NoRetryPolicy(),
803
962
  })
963
+ .retrieve(({ forSchema }) => forSchema(testSchema).find("users"))
804
964
  .mutate(() => ({ done: true }))
805
965
  .execute(),
806
966
  ).rejects.toThrow(ConcurrencyConflictError);
@@ -850,6 +1010,7 @@ describe("Unified Tx API", () => {
850
1010
  },
851
1011
  retryPolicy: new LinearBackoffRetryPolicy({ maxRetries: 3, delayMs: 1 }),
852
1012
  })
1013
+ .retrieve(({ forSchema }) => forSchema(testSchema).find("users"))
853
1014
  .mutate(({ forSchema }) => {
854
1015
  forSchema(testSchema).create("users", {
855
1016
  email: "test@example.com",
@@ -882,11 +1043,94 @@ describe("Unified Tx API", () => {
882
1043
  retryPolicy: new LinearBackoffRetryPolicy({ maxRetries: 5, delayMs: 100 }),
883
1044
  signal: controller.signal,
884
1045
  })
1046
+ .retrieve(({ forSchema }) => forSchema(testSchema).find("users"))
885
1047
  .mutate(() => ({ done: true }))
886
1048
  .execute(),
887
1049
  ).rejects.toThrow("Transaction execution aborted");
888
1050
  });
889
1051
 
1052
+ it("should propagate error when mutate callback rejects a duplicate via retrieve guard", async () => {
1053
+ const compiler = createMockCompiler();
1054
+ const existingUser = {
1055
+ id: FragnoId.fromExternal("existing-1", 1),
1056
+ email: "alice@example.com",
1057
+ name: "Alice",
1058
+ balance: 100,
1059
+ };
1060
+ const executor: UOWExecutor<unknown, unknown> = {
1061
+ executeRetrievalPhase: async () => [[existingUser]],
1062
+ executeMutationPhase: async () => ({ success: true, createdInternalIds: [] }),
1063
+ };
1064
+ const decoder = createMockDecoder();
1065
+
1066
+ let currentUow: IUnitOfWork | null = null;
1067
+
1068
+ const createIfNotExists = (email: string) => {
1069
+ return createServiceTxBuilder(testSchema, currentUow!)
1070
+ .retrieve((uow) =>
1071
+ uow.find("users", (b) => b.whereIndex("idx_email", (eb) => eb("email", "=", email))),
1072
+ )
1073
+ .mutate(({ uow, retrieveResult: [users] }) => {
1074
+ if (users.length > 0) {
1075
+ throw new Error("ALREADY_EXISTS");
1076
+ }
1077
+ const id = uow.create("users", { email, name: "New", balance: 0 });
1078
+ return { id };
1079
+ })
1080
+ .build();
1081
+ };
1082
+
1083
+ await expect(
1084
+ createHandlerTxBuilder({
1085
+ createUnitOfWork: () => {
1086
+ currentUow = createUnitOfWork(compiler, executor, decoder);
1087
+ return currentUow;
1088
+ },
1089
+ })
1090
+ .withServiceCalls(() => [createIfNotExists("alice@example.com")])
1091
+ .transform(({ serviceResult: [result] }) => result)
1092
+ .execute(),
1093
+ ).rejects.toThrow("ALREADY_EXISTS");
1094
+ });
1095
+
1096
+ it("should succeed when retrieve guard finds no existing record", async () => {
1097
+ const compiler = createMockCompiler();
1098
+ const executor: UOWExecutor<unknown, unknown> = {
1099
+ executeRetrievalPhase: async () => [[]],
1100
+ executeMutationPhase: async () => ({ success: true, createdInternalIds: [BigInt(1)] }),
1101
+ };
1102
+ const decoder = createMockDecoder();
1103
+
1104
+ let currentUow: IUnitOfWork | null = null;
1105
+
1106
+ const createIfNotExists = (email: string) => {
1107
+ return createServiceTxBuilder(testSchema, currentUow!)
1108
+ .retrieve((uow) =>
1109
+ uow.find("users", (b) => b.whereIndex("idx_email", (eb) => eb("email", "=", email))),
1110
+ )
1111
+ .mutate(({ uow, retrieveResult: [users] }) => {
1112
+ if (users.length > 0) {
1113
+ throw new Error("ALREADY_EXISTS");
1114
+ }
1115
+ const id = uow.create("users", { email, name: "New", balance: 0 });
1116
+ return { id };
1117
+ })
1118
+ .build();
1119
+ };
1120
+
1121
+ const result = await createHandlerTxBuilder({
1122
+ createUnitOfWork: () => {
1123
+ currentUow = createUnitOfWork(compiler, executor, decoder);
1124
+ return currentUow;
1125
+ },
1126
+ })
1127
+ .withServiceCalls(() => [createIfNotExists("new@example.com")])
1128
+ .transform(({ serviceResult: [result] }) => result)
1129
+ .execute();
1130
+
1131
+ expect(result.id).toBeInstanceOf(FragnoId);
1132
+ });
1133
+
890
1134
  it("should pass serviceResult to transform callback with final results", async () => {
891
1135
  const compiler = createMockCompiler();
892
1136
  const mockUser = {
@@ -1523,6 +1767,7 @@ describe("Unified Tx API", () => {
1523
1767
  await createHandlerTxBuilder({
1524
1768
  createUnitOfWork: () => {
1525
1769
  currentUow = createUnitOfWork(compiler, executor, decoder);
1770
+ currentUow.registerSchema(testSchema, "test");
1526
1771
  return currentUow;
1527
1772
  },
1528
1773
  })
@@ -1592,6 +1837,7 @@ describe("Unified Tx API", () => {
1592
1837
  await createHandlerTxBuilder({
1593
1838
  createUnitOfWork: () => {
1594
1839
  currentUow = createUnitOfWork(compiler, executor, decoder);
1840
+ currentUow.registerSchema(testSchema, "test");
1595
1841
  return currentUow;
1596
1842
  },
1597
1843
  })
@@ -1607,6 +1853,122 @@ describe("Unified Tx API", () => {
1607
1853
  payload: { userId: expect.any(String) },
1608
1854
  });
1609
1855
  });
1856
+
1857
+ it("should create hook records when handler uses schema A and service uses schema B", async () => {
1858
+ const { schemaA, schemaB, namespaceA, namespaceB, queryA, internalQuery, internalFragment } =
1859
+ setupCrossSchemaHookTest();
1860
+
1861
+ type HooksA = {
1862
+ onAlpha: (payload: { value: string }) => void;
1863
+ };
1864
+ type HooksB = {
1865
+ onBeta: (payload: { value: string }) => void;
1866
+ };
1867
+
1868
+ const hooksA: HooksA = {
1869
+ onAlpha: (_payload) => {},
1870
+ };
1871
+ const hooksB: HooksB = {
1872
+ onBeta: (_payload) => {},
1873
+ };
1874
+
1875
+ let currentUow: IUnitOfWork | null = null;
1876
+
1877
+ const serviceInSchemaB = (value: string) =>
1878
+ createServiceTxBuilder(schemaB, currentUow!, hooksB)
1879
+ .mutate(({ uow }) => {
1880
+ uow.create("items", { label: value });
1881
+ uow.triggerHook("onBeta", { value });
1882
+ })
1883
+ .build();
1884
+
1885
+ await createHandlerTxBuilder({
1886
+ createUnitOfWork: () => {
1887
+ currentUow = queryA.createBaseUnitOfWork();
1888
+ currentUow.registerSchema(schemaA, namespaceA);
1889
+ currentUow.registerSchema(schemaB, namespaceB);
1890
+ currentUow.registerSchema(internalSchema, null);
1891
+ return currentUow;
1892
+ },
1893
+ onBeforeMutate: (uow) => {
1894
+ prepareHookMutations(uow, internalFragment);
1895
+ },
1896
+ })
1897
+ .mutate(({ forSchema }) => {
1898
+ const uow = forSchema(schemaA, hooksA);
1899
+ uow.create("items", { label: "alpha" });
1900
+ uow.triggerHook("onAlpha", { value: "alpha" });
1901
+ })
1902
+ .withServiceCalls(() => [serviceInSchemaB("beta")] as const)
1903
+ .execute();
1904
+
1905
+ const hooks = await internalQuery.find("fragno_hooks");
1906
+ expect(hooks).toHaveLength(2);
1907
+ expect(hooks).toEqual(
1908
+ expect.arrayContaining([
1909
+ expect.objectContaining({ hookName: "onAlpha", namespace: namespaceA }),
1910
+ expect.objectContaining({ hookName: "onBeta", namespace: namespaceB }),
1911
+ ]),
1912
+ );
1913
+ });
1914
+
1915
+ it("should create hook records when handler uses schema B and service uses schema A", async () => {
1916
+ const { schemaA, schemaB, namespaceA, namespaceB, queryB, internalQuery, internalFragment } =
1917
+ setupCrossSchemaHookTest();
1918
+
1919
+ type HooksA = {
1920
+ onAlpha: (payload: { value: string }) => void;
1921
+ };
1922
+ type HooksB = {
1923
+ onBeta: (payload: { value: string }) => void;
1924
+ };
1925
+
1926
+ const hooksA: HooksA = {
1927
+ onAlpha: (_payload) => {},
1928
+ };
1929
+ const hooksB: HooksB = {
1930
+ onBeta: (_payload) => {},
1931
+ };
1932
+
1933
+ let currentUow: IUnitOfWork | null = null;
1934
+
1935
+ const serviceInSchemaA = (value: string) =>
1936
+ createServiceTxBuilder(schemaA, currentUow!, hooksA)
1937
+ .mutate(({ uow }) => {
1938
+ uow.create("items", { label: value });
1939
+ uow.triggerHook("onAlpha", { value });
1940
+ })
1941
+ .build();
1942
+
1943
+ await createHandlerTxBuilder({
1944
+ createUnitOfWork: () => {
1945
+ currentUow = queryB.createBaseUnitOfWork();
1946
+ currentUow.registerSchema(schemaA, namespaceA);
1947
+ currentUow.registerSchema(schemaB, namespaceB);
1948
+ currentUow.registerSchema(internalSchema, null);
1949
+ return currentUow;
1950
+ },
1951
+ onBeforeMutate: (uow) => {
1952
+ prepareHookMutations(uow, internalFragment);
1953
+ },
1954
+ })
1955
+ .mutate(({ forSchema }) => {
1956
+ const uow = forSchema(schemaB, hooksB);
1957
+ uow.create("items", { label: "beta" });
1958
+ uow.triggerHook("onBeta", { value: "beta" });
1959
+ })
1960
+ .withServiceCalls(() => [serviceInSchemaA("alpha")] as const)
1961
+ .execute();
1962
+
1963
+ const hooks = await internalQuery.find("fragno_hooks");
1964
+ expect(hooks).toHaveLength(2);
1965
+ expect(hooks).toEqual(
1966
+ expect.arrayContaining([
1967
+ expect.objectContaining({ hookName: "onAlpha", namespace: namespaceA }),
1968
+ expect.objectContaining({ hookName: "onBeta", namespace: namespaceB }),
1969
+ ]),
1970
+ );
1971
+ });
1610
1972
  });
1611
1973
 
1612
1974
  describe("error handling in createServiceTx", () => {
@@ -1,7 +1,7 @@
1
+ import type { HooksMap } from "../../hooks/hooks";
1
2
  import type { AnySchema } from "../../schema/create";
3
+ import { ExponentialBackoffRetryPolicy, NoRetryPolicy, type RetryPolicy } from "./retry-policy";
2
4
  import type { TypedUnitOfWork, IUnitOfWork } from "./unit-of-work";
3
- import type { HooksMap } from "../../hooks/hooks";
4
- import { ExponentialBackoffRetryPolicy, type RetryPolicy } from "./retry-policy";
5
5
 
6
6
  /**
7
7
  * Symbol to identify TxResult objects
@@ -58,6 +58,26 @@ export type ExtractServiceFinalResults<T extends readonly unknown[]> = {
58
58
  [K in keyof T]: ExtractTxFinalResult<T[K]>;
59
59
  };
60
60
 
61
+ /**
62
+ * Helper to preserve tuple inference for service calls, especially with spreads.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * const historyCalls = Array.from({ length: 3 }, () => svc.listHistory(...));
67
+ * return serviceCalls(
68
+ * svc.getInstanceStatus(...),
69
+ * svc.getInstanceRunNumber(...),
70
+ * ...historyCalls,
71
+ * );
72
+ * ```
73
+ */
74
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
+ export function serviceCalls<const T extends readonly (TxResult<any, any> | undefined)[]>(
76
+ ...calls: T
77
+ ): T {
78
+ return calls;
79
+ }
80
+
61
81
  /**
62
82
  * Context passed to mutate callback for service methods
63
83
  */
@@ -491,6 +511,12 @@ export interface ExecuteTxOptions {
491
511
  */
492
512
  signal?: AbortSignal;
493
513
 
514
+ /**
515
+ * Callback invoked after retrieval phase completes.
516
+ * Use this to inspect retrieval operations and results (e.g., read tracking).
517
+ */
518
+ onAfterRetrieve?: (uow: IUnitOfWork, results: unknown[]) => void | Promise<void>;
519
+
494
520
  /**
495
521
  * Callback invoked before mutations are executed.
496
522
  * Use this to add additional mutation operations (e.g., hook event records).
@@ -502,6 +528,11 @@ export interface ExecuteTxOptions {
502
528
  * Use this for post-mutation processing like hook execution.
503
529
  */
504
530
  onAfterMutate?: (uow: IUnitOfWork) => Promise<void>;
531
+
532
+ /**
533
+ * Plan mode suppresses hook execution while still running serviceTx logic.
534
+ */
535
+ planMode?: boolean;
505
536
  }
506
537
 
507
538
  /**
@@ -724,13 +755,6 @@ async function executeTx(
724
755
  type TServiceCalls = readonly (TxResult<any, any> | undefined)[];
725
756
  type TMutateResult = unknown;
726
757
  type THooks = HooksMap;
727
- const retryPolicy =
728
- options.retryPolicy ??
729
- new ExponentialBackoffRetryPolicy({
730
- maxRetries: 5,
731
- initialDelayMs: 10,
732
- maxDelayMs: 100,
733
- });
734
758
  const signal = options.signal;
735
759
  let attempt = 0;
736
760
 
@@ -740,9 +764,15 @@ async function executeTx(
740
764
  throw new Error("Transaction execution aborted");
741
765
  }
742
766
 
767
+ let retryPolicy: RetryPolicy | undefined;
768
+
743
769
  try {
744
770
  // Create a fresh UOW for this attempt
745
771
  const baseUow = options.createUnitOfWork();
772
+ if (options.onAfterRetrieve) {
773
+ const readTrackingUow = baseUow as { enableReadTracking?: () => void };
774
+ readTrackingUow.enableReadTracking?.();
775
+ }
746
776
 
747
777
  // Create handler context
748
778
  const context: HandlerTxContext<THooks> = {
@@ -764,7 +794,28 @@ async function executeTx(
764
794
 
765
795
  const allServiceCallTxResults = serviceCalls ? collectAllTxResults([...serviceCalls]) : [];
766
796
 
767
- await baseUow.executeRetrieve();
797
+ const hasRetrieveOps = baseUow.getRetrievalOperations().length > 0;
798
+ if (!hasRetrieveOps) {
799
+ if (options.retryPolicy) {
800
+ throw new Error(
801
+ "Retry policy is only supported when the transaction includes retrieve operations.",
802
+ );
803
+ }
804
+ retryPolicy = new NoRetryPolicy();
805
+ } else {
806
+ retryPolicy =
807
+ options.retryPolicy ??
808
+ new ExponentialBackoffRetryPolicy({
809
+ maxRetries: 5,
810
+ initialDelayMs: 10,
811
+ maxDelayMs: 100,
812
+ });
813
+ }
814
+
815
+ const allRetrieveResults = await baseUow.executeRetrieve();
816
+ if (options.onAfterRetrieve) {
817
+ await options.onAfterRetrieve(baseUow, allRetrieveResults);
818
+ }
768
819
 
769
820
  // Get retrieve results from TypedUnitOfWork's retrievalPhase or default to empty array
770
821
  const retrieveResult: TRetrieveResults = typedUowFromRetrieve
@@ -827,7 +878,7 @@ async function executeTx(
827
878
  mutateResult = callbacks.mutate(mutateCtx);
828
879
  }
829
880
 
830
- if (options.onBeforeMutate) {
881
+ if (!options.planMode && options.onBeforeMutate) {
831
882
  options.onBeforeMutate(baseUow);
832
883
  }
833
884
  const result = await baseUow.executeMutations();
@@ -870,7 +921,7 @@ async function executeTx(
870
921
  finalResult = serviceFinalResults;
871
922
  }
872
923
 
873
- if (options.onAfterMutate) {
924
+ if (!options.planMode && options.onAfterMutate) {
874
925
  await options.onAfterMutate(baseUow);
875
926
  }
876
927
 
@@ -885,6 +936,10 @@ async function executeTx(
885
936
  throw error;
886
937
  }
887
938
 
939
+ if (!retryPolicy) {
940
+ throw error;
941
+ }
942
+
888
943
  if (!retryPolicy.shouldRetry(attempt, error, signal)) {
889
944
  if (signal?.aborted) {
890
945
  throw new Error("Transaction execution aborted");
@@ -1538,6 +1593,7 @@ interface HandlerTxBuilderState<
1538
1593
  > {
1539
1594
  options: ExecuteTxOptions;
1540
1595
  hooks?: THooks;
1596
+ executeWrapper?: <T>(run: () => Promise<T>) => Promise<T>;
1541
1597
  withServiceCallsFn?: () => TServiceCalls;
1542
1598
  retrieveFn?: (context: {
1543
1599
  forSchema: <S extends AnySchema, H extends HooksMap = THooks>(
@@ -1874,22 +1930,24 @@ export class HandlerTxBuilder<
1874
1930
  : undefined,
1875
1931
  };
1876
1932
 
1877
- // Use the existing executeTx implementation
1878
- return executeTx(callbacks as Parameters<typeof executeTx>[0], state.options) as Promise<
1879
- AwaitedPromisesInObject<
1880
- InferBuilderResultType<
1881
- TRetrieveResults,
1882
- TRetrieveSuccessResult,
1883
- TServiceCalls,
1884
- TMutateResult,
1885
- TTransformResult,
1886
- HasTransform,
1887
- HasMutate,
1888
- HasTransformRetrieve,
1889
- HasRetrieve
1933
+ const run = () =>
1934
+ executeTx(callbacks as Parameters<typeof executeTx>[0], state.options) as Promise<
1935
+ AwaitedPromisesInObject<
1936
+ InferBuilderResultType<
1937
+ TRetrieveResults,
1938
+ TRetrieveSuccessResult,
1939
+ TServiceCalls,
1940
+ TMutateResult,
1941
+ TTransformResult,
1942
+ HasTransform,
1943
+ HasMutate,
1944
+ HasTransformRetrieve,
1945
+ HasRetrieve
1946
+ >
1890
1947
  >
1891
- >
1892
- >;
1948
+ >;
1949
+
1950
+ return state.executeWrapper ? state.executeWrapper(run) : run();
1893
1951
  }
1894
1952
  }
1895
1953
 
@@ -1899,9 +1957,11 @@ export class HandlerTxBuilder<
1899
1957
  export function createHandlerTxBuilder<THooks extends HooksMap = {}>(
1900
1958
  options: ExecuteTxOptions,
1901
1959
  hooks?: THooks,
1960
+ executeWrapper?: <T>(run: () => Promise<T>) => Promise<T>,
1902
1961
  ): HandlerTxBuilder<readonly [], [], [], unknown, unknown, false, false, false, false, THooks> {
1903
1962
  return new HandlerTxBuilder({
1904
1963
  options,
1905
1964
  hooks,
1965
+ executeWrapper,
1906
1966
  });
1907
1967
  }
@@ -1,4 +1,5 @@
1
1
  import { describe, it, expect } from "vitest";
2
+
2
3
  import {
3
4
  ExponentialBackoffRetryPolicy,
4
5
  LinearBackoffRetryPolicy,