@fragno-dev/db 0.3.0 → 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 (516) hide show
  1. package/.turbo/turbo-build.log +327 -160
  2. package/CHANGELOG.md +74 -0
  3. package/README.md +24 -0
  4. package/dist/adapters/adapters.d.ts +1 -1
  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/generic-sql-adapter.d.ts +0 -3
  8. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
  9. package/dist/adapters/generic-sql/generic-sql-adapter.js +11 -12
  10. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
  11. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +46 -6
  12. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
  13. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -1
  14. package/dist/adapters/generic-sql/migration/dialect/mysql.js +1 -1
  15. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
  16. package/dist/adapters/generic-sql/migration/dialect/postgres.js +1 -1
  17. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
  18. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +185 -19
  19. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
  20. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -1
  21. package/dist/adapters/generic-sql/migration/executor.js +30 -3
  22. package/dist/adapters/generic-sql/migration/executor.js.map +1 -1
  23. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -1
  24. package/dist/adapters/generic-sql/migration/prepared-migrations.js +3 -3
  25. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
  26. package/dist/adapters/generic-sql/migration/sql-generator.js +1 -1
  27. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
  28. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +1 -1
  29. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
  30. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
  31. package/dist/adapters/generic-sql/query/db-now-sql.js +27 -0
  32. package/dist/adapters/generic-sql/query/db-now-sql.js.map +1 -0
  33. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +9 -6
  34. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
  35. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
  36. package/dist/adapters/generic-sql/query/sql-query-compiler.js +37 -9
  37. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
  38. package/dist/adapters/generic-sql/query/where-builder.js +24 -20
  39. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
  40. package/dist/adapters/generic-sql/uow-decoder.js +1 -1
  41. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
  42. package/dist/adapters/generic-sql/uow-encoder.js +8 -9
  43. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
  44. package/dist/adapters/in-memory/condition-evaluator.js +10 -6
  45. package/dist/adapters/in-memory/condition-evaluator.js.map +1 -1
  46. package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -1
  47. package/dist/adapters/in-memory/in-memory-adapter.js +45 -25
  48. package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -1
  49. package/dist/adapters/in-memory/in-memory-uow.js +236 -13
  50. package/dist/adapters/in-memory/in-memory-uow.js.map +1 -1
  51. package/dist/adapters/in-memory/options.d.ts +2 -0
  52. package/dist/adapters/in-memory/options.d.ts.map +1 -1
  53. package/dist/adapters/in-memory/options.js +3 -2
  54. package/dist/adapters/in-memory/options.js.map +1 -1
  55. package/dist/adapters/in-memory/reference-resolution.js.map +1 -1
  56. package/dist/adapters/in-memory/store.js +1 -1
  57. package/dist/adapters/in-memory/store.js.map +1 -1
  58. package/dist/adapters/shared/from-unit-of-work-compiler.js +51 -24
  59. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
  60. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
  61. package/dist/browser/adapters/adapters.d.ts +61 -0
  62. package/dist/browser/adapters/adapters.d.ts.map +1 -0
  63. package/dist/browser/adapters/generic-sql/migration/executor.d.ts +15 -0
  64. package/dist/browser/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  65. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  66. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  67. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts +11 -0
  68. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  69. package/dist/browser/adapters/in-memory/in-memory-adapter.d.ts +5 -0
  70. package/dist/browser/adapters/in-memory/index.d.ts +2 -0
  71. package/dist/browser/adapters/in-memory/options.d.ts +1 -0
  72. package/dist/browser/db-fragment-definition-builder.d.ts +237 -0
  73. package/dist/browser/db-fragment-definition-builder.d.ts.map +1 -0
  74. package/dist/browser/durable-hooks.d.ts +3 -0
  75. package/dist/browser/fragments/internal-fragment.d.ts +317 -0
  76. package/dist/browser/fragments/internal-fragment.d.ts.map +1 -0
  77. package/dist/browser/fragments/internal-fragment.schema.d.ts +1 -0
  78. package/dist/browser/hooks/durable-hooks-logger.d.ts +10 -0
  79. package/dist/browser/hooks/durable-hooks-logger.d.ts.map +1 -0
  80. package/dist/browser/hooks/hooks.d.ts +146 -0
  81. package/dist/browser/hooks/hooks.d.ts.map +1 -0
  82. package/dist/browser/id.js +1 -0
  83. package/dist/browser/internal/adapter-registry.d.ts +4 -0
  84. package/dist/browser/internal/outbox-state.d.ts +2 -0
  85. package/dist/browser/mod.d.ts +15 -0
  86. package/dist/browser/mod.d.ts.map +1 -0
  87. package/dist/browser/mod.js +17 -0
  88. package/dist/browser/mod.js.map +1 -0
  89. package/dist/browser/mod2.d.ts +48 -0
  90. package/dist/browser/mod2.d.ts.map +1 -0
  91. package/dist/browser/naming/sql-naming.d.ts +19 -0
  92. package/dist/browser/naming/sql-naming.d.ts.map +1 -0
  93. package/dist/browser/outbox/outbox.d.ts +21 -0
  94. package/dist/browser/outbox/outbox.d.ts.map +1 -0
  95. package/dist/browser/query/column-defaults.js +1 -0
  96. package/dist/browser/query/condition-builder.d.ts +44 -0
  97. package/dist/browser/query/condition-builder.d.ts.map +1 -0
  98. package/dist/browser/query/condition-builder.js +97 -0
  99. package/dist/browser/query/condition-builder.js.map +1 -0
  100. package/dist/browser/query/cursor.d.ts +105 -0
  101. package/dist/browser/query/cursor.d.ts.map +1 -0
  102. package/dist/browser/query/cursor.js +150 -0
  103. package/dist/browser/query/cursor.js.map +1 -0
  104. package/dist/browser/query/db-now.d.ts +22 -0
  105. package/dist/browser/query/db-now.d.ts.map +1 -0
  106. package/dist/browser/query/db-now.js +33 -0
  107. package/dist/browser/query/db-now.js.map +1 -0
  108. package/dist/browser/query/orm/orm.d.ts +18 -0
  109. package/dist/browser/query/orm/orm.d.ts.map +1 -0
  110. package/dist/browser/query/simple-query-interface.d.ts +108 -0
  111. package/dist/browser/query/simple-query-interface.d.ts.map +1 -0
  112. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts +423 -0
  113. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  114. package/dist/browser/query/unit-of-work/execute-unit-of-work.js +507 -0
  115. package/dist/browser/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  116. package/dist/browser/query/unit-of-work/retry-policy.d.ts +23 -0
  117. package/dist/browser/query/unit-of-work/retry-policy.d.ts.map +1 -0
  118. package/dist/browser/query/unit-of-work/retry-policy.js +40 -0
  119. package/dist/browser/query/unit-of-work/retry-policy.js.map +1 -0
  120. package/dist/browser/query/unit-of-work/unit-of-work.d.ts +703 -0
  121. package/dist/browser/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  122. package/dist/browser/query/unit-of-work/unit-of-work.js +1206 -0
  123. package/dist/browser/query/unit-of-work/unit-of-work.js.map +1 -0
  124. package/dist/browser/query/value-encoding.js +38 -0
  125. package/dist/browser/query/value-encoding.js.map +1 -0
  126. package/dist/browser/schema/create.d.ts +326 -0
  127. package/dist/browser/schema/create.d.ts.map +1 -0
  128. package/dist/browser/schema/create.js +89 -0
  129. package/dist/browser/schema/create.js.map +1 -0
  130. package/dist/browser/schema/generate-id.js +28 -0
  131. package/dist/browser/schema/generate-id.js.map +1 -0
  132. package/dist/browser/shared/providers.d.ts +6 -0
  133. package/dist/browser/shared/providers.d.ts.map +1 -0
  134. package/dist/browser/sql-driver/connection/connection-provider.d.ts +13 -0
  135. package/dist/browser/sql-driver/connection/connection-provider.d.ts.map +1 -0
  136. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  137. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  138. package/dist/browser/sql-driver/driver/runtime-driver.d.ts +23 -0
  139. package/dist/browser/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  140. package/dist/browser/sql-driver/query-executor/plugin.d.ts +17 -0
  141. package/dist/browser/sql-driver/query-executor/plugin.d.ts.map +1 -0
  142. package/dist/browser/sql-driver/query-executor/query-executor.d.ts +36 -0
  143. package/dist/browser/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  144. package/dist/browser/sql-driver/sql-driver-adapter.d.ts +29 -0
  145. package/dist/browser/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  146. package/dist/browser/sql-driver/sql-driver.d.ts +38 -0
  147. package/dist/browser/sql-driver/sql-driver.d.ts.map +1 -0
  148. package/dist/browser/sync/commands.d.ts +15 -0
  149. package/dist/browser/sync/commands.d.ts.map +1 -0
  150. package/dist/browser/sync/commands.js +27 -0
  151. package/dist/browser/sync/commands.js.map +1 -0
  152. package/dist/browser/sync/types.d.ts +63 -0
  153. package/dist/browser/sync/types.d.ts.map +1 -0
  154. package/dist/browser/util/types.d.ts +8 -0
  155. package/dist/browser/util/types.d.ts.map +1 -0
  156. package/dist/browser/with-database.d.ts +29 -0
  157. package/dist/browser/with-database.d.ts.map +1 -0
  158. package/dist/client.d.ts +4 -0
  159. package/dist/client.js +5 -0
  160. package/dist/db-fragment-definition-builder.d.ts +85 -28
  161. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  162. package/dist/db-fragment-definition-builder.js +374 -46
  163. package/dist/db-fragment-definition-builder.js.map +1 -1
  164. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts +20 -0
  165. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts.map +1 -0
  166. package/dist/dispatchers/cloudflare-do/dispatcher.js +147 -0
  167. package/dist/dispatchers/cloudflare-do/dispatcher.js.map +1 -0
  168. package/dist/dispatchers/cloudflare-do/index.d.ts +5 -20
  169. package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -1
  170. package/dist/dispatchers/cloudflare-do/index.js +23 -55
  171. package/dist/dispatchers/cloudflare-do/index.js.map +1 -1
  172. package/dist/dispatchers/node/dispatcher.d.ts +14 -0
  173. package/dist/dispatchers/node/dispatcher.d.ts.map +1 -0
  174. package/dist/dispatchers/node/dispatcher.js +80 -0
  175. package/dist/dispatchers/node/dispatcher.js.map +1 -0
  176. package/dist/dispatchers/node/index.d.ts +5 -10
  177. package/dist/dispatchers/node/index.d.ts.map +1 -1
  178. package/dist/dispatchers/node/index.js +21 -53
  179. package/dist/dispatchers/node/index.js.map +1 -1
  180. package/dist/durable-hooks.d.ts +31 -0
  181. package/dist/durable-hooks.d.ts.map +1 -0
  182. package/dist/durable-hooks.js +23 -0
  183. package/dist/durable-hooks.js.map +1 -0
  184. package/dist/fragments/internal-fragment.d.ts +128 -27
  185. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  186. package/dist/fragments/internal-fragment.js +125 -78
  187. package/dist/fragments/internal-fragment.js.map +1 -1
  188. package/dist/fragments/internal-fragment.routes.js +138 -3
  189. package/dist/fragments/internal-fragment.routes.js.map +1 -1
  190. package/dist/fragments/internal-fragment.schema.d.ts +7 -1
  191. package/dist/fragments/internal-fragment.schema.d.ts.map +1 -1
  192. package/dist/fragments/internal-fragment.schema.js +18 -1
  193. package/dist/fragments/internal-fragment.schema.js.map +1 -1
  194. package/dist/hooks/durable-hooks-logger.d.ts +10 -0
  195. package/dist/hooks/durable-hooks-logger.d.ts.map +1 -0
  196. package/dist/hooks/durable-hooks-logger.js +75 -0
  197. package/dist/hooks/durable-hooks-logger.js.map +1 -0
  198. package/dist/hooks/durable-hooks-processor.d.ts +1 -14
  199. package/dist/hooks/durable-hooks-processor.js +58 -10
  200. package/dist/hooks/durable-hooks-processor.js.map +1 -1
  201. package/dist/hooks/durable-hooks-runtime.js +44 -0
  202. package/dist/hooks/durable-hooks-runtime.js.map +1 -0
  203. package/dist/hooks/hooks.d.ts +60 -2
  204. package/dist/hooks/hooks.d.ts.map +1 -1
  205. package/dist/hooks/hooks.js +214 -53
  206. package/dist/hooks/hooks.js.map +1 -1
  207. package/dist/id.d.ts +2 -2
  208. package/dist/id.js +2 -2
  209. package/dist/internal/adapter-registry.d.ts +11 -0
  210. package/dist/internal/adapter-registry.d.ts.map +1 -0
  211. package/dist/internal/adapter-registry.js +135 -0
  212. package/dist/internal/adapter-registry.js.map +1 -0
  213. package/dist/internal/outbox-state.d.ts +2 -0
  214. package/dist/internal/outbox-state.js +26 -0
  215. package/dist/internal/outbox-state.js.map +1 -0
  216. package/dist/migration-engine/auto-from-schema.d.ts +33 -0
  217. package/dist/migration-engine/auto-from-schema.d.ts.map +1 -0
  218. package/dist/migration-engine/auto-from-schema.js +210 -27
  219. package/dist/migration-engine/auto-from-schema.js.map +1 -1
  220. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  221. package/dist/migration-engine/generation-engine.js +17 -5
  222. package/dist/migration-engine/generation-engine.js.map +1 -1
  223. package/dist/migration-engine/shared.d.ts +113 -0
  224. package/dist/migration-engine/shared.d.ts.map +1 -0
  225. package/dist/migration-engine/shared.js.map +1 -1
  226. package/dist/mod.d.ts +12 -11
  227. package/dist/mod.d.ts.map +1 -1
  228. package/dist/mod.js +10 -10
  229. package/dist/mod.js.map +1 -1
  230. package/dist/naming/sql-naming.d.ts.map +1 -1
  231. package/dist/naming/sql-naming.js.map +1 -1
  232. package/dist/outbox/outbox-builder.js.map +1 -1
  233. package/dist/outbox/outbox.d.ts +3 -1
  234. package/dist/outbox/outbox.d.ts.map +1 -1
  235. package/dist/outbox/outbox.js.map +1 -1
  236. package/dist/query/column-defaults.js.map +1 -1
  237. package/dist/query/condition-builder.d.ts +7 -1
  238. package/dist/query/condition-builder.d.ts.map +1 -1
  239. package/dist/query/condition-builder.js +5 -1
  240. package/dist/query/condition-builder.js.map +1 -1
  241. package/dist/query/cursor-client.d.ts +105 -0
  242. package/dist/query/cursor-client.d.ts.map +1 -0
  243. package/dist/query/cursor-client.js +165 -0
  244. package/dist/query/cursor-client.js.map +1 -0
  245. package/dist/query/cursor.d.ts.map +1 -1
  246. package/dist/query/cursor.js +7 -1
  247. package/dist/query/cursor.js.map +1 -1
  248. package/dist/query/db-now.d.ts +15 -1
  249. package/dist/query/db-now.d.ts.map +1 -1
  250. package/dist/query/db-now.js +30 -2
  251. package/dist/query/db-now.js.map +1 -1
  252. package/dist/query/orm/orm.js.map +1 -1
  253. package/dist/query/serialize/create-sql-serializer.js +2 -2
  254. package/dist/query/serialize/create-sql-serializer.js.map +1 -1
  255. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
  256. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
  257. package/dist/query/serialize/dialect/sqlite-serializer.js +6 -2
  258. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
  259. package/dist/query/simple-query-interface.d.ts +7 -3
  260. package/dist/query/simple-query-interface.d.ts.map +1 -1
  261. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +37 -2
  262. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  263. package/dist/query/unit-of-work/execute-unit-of-work.js +39 -18
  264. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  265. package/dist/query/unit-of-work/unit-of-work.d.ts +42 -16
  266. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  267. package/dist/query/unit-of-work/unit-of-work.js +50 -6
  268. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  269. package/dist/query/value-decoding.js +8 -1
  270. package/dist/query/value-decoding.js.map +1 -1
  271. package/dist/query/value-encoding.js.map +1 -1
  272. package/dist/schema/create.d.ts +69 -25
  273. package/dist/schema/create.d.ts.map +1 -1
  274. package/dist/schema/create.js +91 -16
  275. package/dist/schema/create.js.map +1 -1
  276. package/dist/schema/type-conversion/create-sql-type-mapper.js +1 -1
  277. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  278. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  279. package/dist/schema/validator.d.ts.map +1 -1
  280. package/dist/schema/validator.js.map +1 -1
  281. package/dist/schema-output/drizzle.d.ts.map +1 -1
  282. package/dist/schema-output/drizzle.js +8 -6
  283. package/dist/schema-output/drizzle.js.map +1 -1
  284. package/dist/schema-output/prisma.d.ts.map +1 -1
  285. package/dist/schema-output/prisma.js +21 -10
  286. package/dist/schema-output/prisma.js.map +1 -1
  287. package/dist/sql-driver/dialects/durable-object-dialect.js +3 -9
  288. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -1
  289. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -1
  290. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -1
  291. package/dist/sql-driver/sql-driver-adapter.js.map +1 -1
  292. package/dist/sql-driver/sql.js.map +1 -1
  293. package/dist/sync/commands.d.ts +15 -0
  294. package/dist/sync/commands.d.ts.map +1 -0
  295. package/dist/sync/commands.js +27 -0
  296. package/dist/sync/commands.js.map +1 -0
  297. package/dist/sync/index.d.ts +4 -0
  298. package/dist/sync/index.js +4 -0
  299. package/dist/sync/read-tracking.d.ts +25 -0
  300. package/dist/sync/read-tracking.d.ts.map +1 -0
  301. package/dist/sync/read-tracking.js +148 -0
  302. package/dist/sync/read-tracking.js.map +1 -0
  303. package/dist/sync/submit.js +213 -0
  304. package/dist/sync/submit.js.map +1 -0
  305. package/dist/sync/types.d.ts +63 -0
  306. package/dist/sync/types.d.ts.map +1 -0
  307. package/dist/util/default-database-adapter.js +6 -1
  308. package/dist/util/default-database-adapter.js.map +1 -1
  309. package/dist/with-database.d.ts +3 -6
  310. package/dist/with-database.d.ts.map +1 -1
  311. package/dist/with-database.js +7 -15
  312. package/dist/with-database.js.map +1 -1
  313. package/package.json +33 -41
  314. package/src/adapters/adapters.ts +5 -4
  315. package/src/adapters/drizzle/migrate-drizzle.test.ts +46 -9
  316. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +5 -3
  317. package/src/adapters/drizzle/test-utils.ts +2 -1
  318. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +5 -3
  319. package/src/adapters/generic-sql/generic-sql-adapter.ts +21 -24
  320. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +1 -0
  321. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +81 -15
  322. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +4 -2
  323. package/src/adapters/generic-sql/migration/cold-kysely.ts +1 -0
  324. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +3 -2
  325. package/src/adapters/generic-sql/migration/dialect/mysql.ts +1 -0
  326. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +5 -4
  327. package/src/adapters/generic-sql/migration/dialect/postgres.ts +2 -1
  328. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +795 -3
  329. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +385 -57
  330. package/src/adapters/generic-sql/migration/executor.test.ts +52 -0
  331. package/src/adapters/generic-sql/migration/executor.ts +47 -4
  332. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +117 -14
  333. package/src/adapters/generic-sql/migration/prepared-migrations.ts +9 -8
  334. package/src/adapters/generic-sql/migration/sql-generator.ts +5 -3
  335. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +3 -3
  336. package/src/adapters/generic-sql/query/cursor-utils.test.ts +3 -2
  337. package/src/adapters/generic-sql/query/cursor-utils.ts +1 -1
  338. package/src/adapters/generic-sql/query/db-now-sql.ts +49 -0
  339. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +144 -8
  340. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +16 -17
  341. package/src/adapters/generic-sql/query/select-builder.test.ts +1 -0
  342. package/src/adapters/generic-sql/query/select-builder.ts +2 -2
  343. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +24 -5
  344. package/src/adapters/generic-sql/query/sql-query-compiler.ts +83 -13
  345. package/src/adapters/generic-sql/query/where-builder.test.ts +7 -5
  346. package/src/adapters/generic-sql/query/where-builder.ts +48 -29
  347. package/src/adapters/generic-sql/sql-adapter-pglite-migrations.test.ts +6 -15
  348. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +52 -7
  349. package/src/adapters/generic-sql/sql-adapter-pglite-queries.test.ts +9 -6
  350. package/src/adapters/generic-sql/sql-adapter-sqlite3-driver.test.ts +273 -5
  351. package/src/adapters/generic-sql/sql-adapter-sqlite3-uow.test.ts +123 -6
  352. package/src/adapters/generic-sql/sql-adapter-sqlocal.test.ts +4 -2
  353. package/src/adapters/generic-sql/uow-decoder.test.ts +4 -3
  354. package/src/adapters/generic-sql/uow-decoder.ts +3 -3
  355. package/src/adapters/generic-sql/uow-encoder.test.ts +4 -2
  356. package/src/adapters/generic-sql/uow-encoder.ts +14 -18
  357. package/src/adapters/in-memory/condition-evaluator.test.ts +2 -1
  358. package/src/adapters/in-memory/condition-evaluator.ts +9 -4
  359. package/src/adapters/in-memory/in-memory-adapter.ts +155 -44
  360. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +50 -2
  361. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +158 -3
  362. package/src/adapters/in-memory/in-memory-uow.ts +402 -26
  363. package/src/adapters/in-memory/options.test.ts +1 -0
  364. package/src/adapters/in-memory/options.ts +5 -1
  365. package/src/adapters/in-memory/outbox.test.ts +361 -0
  366. package/src/adapters/in-memory/reference-resolution.test.ts +3 -2
  367. package/src/adapters/in-memory/reference-resolution.ts +2 -2
  368. package/src/adapters/in-memory/sorted-array-index.test.ts +1 -0
  369. package/src/adapters/in-memory/store.test.ts +1 -0
  370. package/src/adapters/in-memory/store.ts +3 -3
  371. package/src/adapters/in-memory/value-normalization.test.ts +1 -0
  372. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +51 -7
  373. package/src/adapters/shared/from-unit-of-work-compiler.ts +156 -46
  374. package/src/adapters/shared/uow-operation-compiler.ts +3 -3
  375. package/src/browser/mod.ts +64 -0
  376. package/src/client.ts +19 -0
  377. package/src/db-fragment-definition-builder.test.ts +821 -47
  378. package/src/db-fragment-definition-builder.ts +857 -110
  379. package/src/db-fragment-instantiator.test.ts +114 -90
  380. package/src/db-fragment-integration.test.ts +9 -6
  381. package/src/dispatchers/cloudflare-do/dispatcher.ts +204 -0
  382. package/src/dispatchers/cloudflare-do/index.test.ts +145 -12
  383. package/src/dispatchers/cloudflare-do/index.ts +49 -90
  384. package/src/dispatchers/node/dispatcher.ts +112 -0
  385. package/src/dispatchers/node/index.test.ts +43 -14
  386. package/src/dispatchers/node/index.ts +38 -75
  387. package/src/durable-hooks.test.ts +80 -0
  388. package/src/durable-hooks.ts +67 -0
  389. package/src/fragments/internal-fragment.routes.test.ts +570 -0
  390. package/src/fragments/internal-fragment.routes.ts +297 -5
  391. package/src/fragments/internal-fragment.schema.ts +45 -1
  392. package/src/fragments/internal-fragment.test.ts +223 -251
  393. package/src/fragments/internal-fragment.ts +278 -154
  394. package/src/hooks/durable-hooks-logger.ts +126 -0
  395. package/src/hooks/durable-hooks-processor.pglite.test.ts +87 -0
  396. package/src/hooks/durable-hooks-processor.test.ts +179 -14
  397. package/src/hooks/durable-hooks-processor.ts +120 -14
  398. package/src/hooks/durable-hooks-runtime.test.ts +65 -0
  399. package/src/hooks/durable-hooks-runtime.ts +81 -0
  400. package/src/hooks/hooks.test.ts +314 -53
  401. package/src/hooks/hooks.ts +360 -81
  402. package/src/id.test.ts +34 -0
  403. package/src/id.ts +1 -3
  404. package/src/internal/adapter-registry.test.ts +93 -0
  405. package/src/internal/adapter-registry.ts +239 -0
  406. package/src/internal/outbox-state.ts +43 -0
  407. package/src/migration-engine/auto-from-schema.test.ts +93 -0
  408. package/src/migration-engine/auto-from-schema.ts +360 -42
  409. package/src/migration-engine/create.test.ts +2 -1
  410. package/src/migration-engine/create.ts +1 -1
  411. package/src/migration-engine/generation-engine.test.ts +66 -9
  412. package/src/migration-engine/generation-engine.ts +31 -10
  413. package/src/migration-engine/shared.ts +13 -0
  414. package/src/mod.ts +45 -27
  415. package/src/naming/sql-naming.ts +1 -0
  416. package/src/outbox/outbox-builder.ts +2 -2
  417. package/src/outbox/outbox.test.ts +216 -45
  418. package/src/outbox/outbox.ts +3 -1
  419. package/src/query/column-defaults.ts +1 -1
  420. package/src/query/condition-builder.test.ts +15 -0
  421. package/src/query/condition-builder.ts +7 -0
  422. package/src/query/cursor-client.test.ts +70 -0
  423. package/src/query/cursor-client.ts +263 -0
  424. package/src/query/cursor.test.ts +3 -2
  425. package/src/query/cursor.ts +15 -3
  426. package/src/query/db-now.ts +69 -2
  427. package/src/query/orm/orm.ts +2 -2
  428. package/src/query/query-type.test.ts +2 -1
  429. package/src/query/serialize/create-sql-serializer.ts +3 -3
  430. package/src/query/serialize/dialect/mysql-serializer.ts +1 -1
  431. package/src/query/serialize/dialect/postgres-serializer.ts +1 -1
  432. package/src/query/serialize/dialect/sqlite-serializer.test.ts +39 -2
  433. package/src/query/serialize/dialect/sqlite-serializer.ts +18 -5
  434. package/src/query/simple-query-interface.ts +10 -4
  435. package/src/query/unit-of-work/execute-unit-of-work.test.ts +347 -9
  436. package/src/query/unit-of-work/execute-unit-of-work.ts +63 -20
  437. package/src/query/unit-of-work/retry-policy.test.ts +1 -0
  438. package/src/query/unit-of-work/tx-builder.test.ts +73 -1
  439. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +5 -4
  440. package/src/query/unit-of-work/unit-of-work-types.test.ts +41 -11
  441. package/src/query/unit-of-work/unit-of-work.test.ts +28 -2
  442. package/src/query/unit-of-work/unit-of-work.ts +105 -19
  443. package/src/query/value-decoding.test.ts +50 -2
  444. package/src/query/value-decoding.ts +17 -4
  445. package/src/query/value-encoding.test.ts +1 -0
  446. package/src/query/value-encoding.ts +1 -1
  447. package/src/schema/create.test.ts +164 -5
  448. package/src/schema/create.ts +222 -24
  449. package/src/schema/generate-id.test.ts +1 -0
  450. package/src/schema/serialize.test.ts +4 -3
  451. package/src/schema/type-conversion/create-sql-type-mapper.ts +1 -1
  452. package/src/schema/type-conversion/dialect/sqlite.ts +2 -2
  453. package/src/schema/type-conversion/type-mapping.test.ts +2 -1
  454. package/src/schema/validator.test.ts +4 -2
  455. package/src/schema/validator.ts +1 -0
  456. package/src/schema-output/drizzle.test.ts +72 -19
  457. package/src/schema-output/drizzle.ts +24 -18
  458. package/src/schema-output/prisma.test.ts +172 -14
  459. package/src/schema-output/prisma.ts +34 -14
  460. package/src/sql-driver/better-sqlite3.test.ts +5 -3
  461. package/src/sql-driver/dialects/durable-object-dialect.ts +3 -8
  462. package/src/sql-driver/query-executor/default-query-executor.ts +1 -1
  463. package/src/sql-driver/query-executor/query-executor-base.ts +1 -1
  464. package/src/sql-driver/query-executor/query-executor.ts +1 -1
  465. package/src/sql-driver/sql-driver-adapter.ts +2 -2
  466. package/src/sql-driver/sql.ts +2 -1
  467. package/src/sql-driver/sqlocal.test.ts +4 -2
  468. package/src/sync/commands.test.ts +39 -0
  469. package/src/sync/commands.ts +51 -0
  470. package/src/sync/conflict-checker.test.ts +450 -0
  471. package/src/sync/conflict-checker.ts +248 -0
  472. package/src/sync/index.ts +14 -0
  473. package/src/sync/plan.ts +9 -0
  474. package/src/sync/read-tracking.test.ts +177 -0
  475. package/src/sync/read-tracking.ts +287 -0
  476. package/src/sync/submit.test.ts +205 -0
  477. package/src/sync/submit.ts +328 -0
  478. package/src/sync/types.ts +80 -0
  479. package/src/util/default-database-adapter.ts +15 -2
  480. package/src/with-database.ts +20 -50
  481. package/tsconfig.json +1 -1
  482. package/tsdown.config.ts +38 -26
  483. package/vitest.config.ts +1 -0
  484. package/dist/hooks/durable-hooks-processor.d.ts.map +0 -1
  485. package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js +0 -168
  486. package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js.map +0 -1
  487. package/dist/packages/fragno/dist/api/bind-services.js +0 -20
  488. package/dist/packages/fragno/dist/api/bind-services.js.map +0 -1
  489. package/dist/packages/fragno/dist/api/error.js +0 -48
  490. package/dist/packages/fragno/dist/api/error.js.map +0 -1
  491. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +0 -321
  492. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +0 -1
  493. package/dist/packages/fragno/dist/api/fragment-instantiator.js +0 -669
  494. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +0 -1
  495. package/dist/packages/fragno/dist/api/fragno-response.js +0 -73
  496. package/dist/packages/fragno/dist/api/fragno-response.js.map +0 -1
  497. package/dist/packages/fragno/dist/api/internal/response-stream.js +0 -81
  498. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +0 -1
  499. package/dist/packages/fragno/dist/api/internal/route.js +0 -10
  500. package/dist/packages/fragno/dist/api/internal/route.js.map +0 -1
  501. package/dist/packages/fragno/dist/api/mutable-request-state.js +0 -97
  502. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +0 -1
  503. package/dist/packages/fragno/dist/api/request-context-storage.js +0 -43
  504. package/dist/packages/fragno/dist/api/request-context-storage.js.map +0 -1
  505. package/dist/packages/fragno/dist/api/request-input-context.js +0 -185
  506. package/dist/packages/fragno/dist/api/request-input-context.js.map +0 -1
  507. package/dist/packages/fragno/dist/api/request-middleware.js +0 -83
  508. package/dist/packages/fragno/dist/api/request-middleware.js.map +0 -1
  509. package/dist/packages/fragno/dist/api/request-output-context.js +0 -119
  510. package/dist/packages/fragno/dist/api/request-output-context.js.map +0 -1
  511. package/dist/packages/fragno/dist/api/route.js +0 -30
  512. package/dist/packages/fragno/dist/api/route.js.map +0 -1
  513. package/dist/packages/fragno/dist/internal/symbols.js +0 -10
  514. package/dist/packages/fragno/dist/internal/symbols.js.map +0 -1
  515. package/dist/packages/fragno/dist/internal/trace-context.js +0 -12
  516. package/dist/packages/fragno/dist/internal/trace-context.js.map +0 -1
@@ -0,0 +1,1206 @@
1
+ import { generateId } from "../../schema/generate-id.js";
2
+ import { FragnoId } from "../../schema/create.js";
3
+ import { dbInterval, dbNow } from "../db-now.js";
4
+ import { buildCondition } from "../condition-builder.js";
5
+ import { Cursor } from "../cursor.js";
6
+
7
+ //#region src/query/unit-of-work/unit-of-work.ts
8
+ /**
9
+ * Builder for find operations in Unit of Work
10
+ */
11
+ var FindBuilder = class {
12
+ #table;
13
+ #tableName;
14
+ #indexName;
15
+ #whereClause;
16
+ #orderByIndexClause;
17
+ #afterCursor;
18
+ #beforeCursor;
19
+ #pageSizeValue;
20
+ #selectClause;
21
+ #joinClause;
22
+ #countMode = false;
23
+ #cursorMetadata;
24
+ constructor(tableName, table) {
25
+ this.#tableName = tableName;
26
+ this.#table = table;
27
+ }
28
+ /**
29
+ * Specify which index to use and optionally filter the results
30
+ */
31
+ whereIndex(indexName, condition) {
32
+ if (indexName !== "primary" && !(indexName in this.#table.indexes)) throw new Error(`Index "${String(indexName)}" not found on table "${this.#tableName}". Available indexes: primary, ${Object.keys(this.#table.indexes).join(", ")}`);
33
+ this.#indexName = indexName === "primary" ? "_primary" : indexName;
34
+ if (condition) this.#whereClause = condition;
35
+ return this;
36
+ }
37
+ /**
38
+ * Specify columns to select
39
+ * @throws Error if selectCount() has already been called
40
+ */
41
+ select(columns) {
42
+ if (this.#countMode) throw new Error(`Cannot call select() after selectCount() on table "${this.#tableName}". Use either select() or selectCount(), not both.`);
43
+ this.#selectClause = columns;
44
+ return this;
45
+ }
46
+ /**
47
+ * Select count instead of records
48
+ * @throws Error if select() has already been called
49
+ */
50
+ selectCount() {
51
+ if (this.#selectClause !== void 0) throw new Error(`Cannot call selectCount() after select() on table "${this.#tableName}". Use either select() or selectCount(), not both.`);
52
+ this.#countMode = true;
53
+ return this;
54
+ }
55
+ /**
56
+ * Order results by index in ascending or descending order
57
+ */
58
+ orderByIndex(indexName, direction) {
59
+ if (indexName !== "primary" && !(indexName in this.#table.indexes)) throw new Error(`Index "${String(indexName)}" not found on table "${this.#tableName}". Available indexes: primary, ${Object.keys(this.#table.indexes).join(", ")}`);
60
+ this.#orderByIndexClause = {
61
+ indexName: indexName === "primary" ? "_primary" : indexName,
62
+ direction
63
+ };
64
+ return this;
65
+ }
66
+ /**
67
+ * Set cursor to continue pagination after this point (forward pagination)
68
+ * If a Cursor object is provided, its metadata will be used to set defaults for
69
+ * index, orderByIndex, and pageSize (if not explicitly set)
70
+ */
71
+ after(cursor) {
72
+ this.#afterCursor = cursor;
73
+ if (cursor instanceof Cursor) this.#cursorMetadata = cursor;
74
+ return this;
75
+ }
76
+ /**
77
+ * Set cursor to continue pagination before this point (backward pagination)
78
+ * If a Cursor object is provided, its metadata will be used to set defaults for
79
+ * index, orderByIndex, and pageSize (if not explicitly set)
80
+ */
81
+ before(cursor) {
82
+ this.#beforeCursor = cursor;
83
+ if (cursor instanceof Cursor) this.#cursorMetadata = cursor;
84
+ return this;
85
+ }
86
+ /**
87
+ * Set the number of results per page
88
+ * @throws {RangeError} If size is not a positive integer
89
+ */
90
+ pageSize(size) {
91
+ if (!Number.isInteger(size) || size <= 0) throw new RangeError(`pageSize must be a positive integer, received: ${size}`);
92
+ this.#pageSizeValue = size;
93
+ return this;
94
+ }
95
+ /**
96
+ * Add joins to include related data
97
+ * Join where clauses are restricted to indexed columns only
98
+ */
99
+ join(joinFn) {
100
+ this.#joinClause = joinFn;
101
+ return this;
102
+ }
103
+ /**
104
+ * @internal
105
+ */
106
+ build() {
107
+ let indexName = this.#indexName;
108
+ let orderByIndex = this.#orderByIndexClause;
109
+ let pageSize = this.#pageSizeValue;
110
+ if (this.#cursorMetadata) {
111
+ if (!indexName) indexName = this.#cursorMetadata.indexName;
112
+ if (!orderByIndex) orderByIndex = {
113
+ indexName: this.#cursorMetadata.indexName,
114
+ direction: this.#cursorMetadata.orderDirection
115
+ };
116
+ if (pageSize === void 0) pageSize = this.#cursorMetadata.pageSize;
117
+ if (indexName && indexName !== this.#cursorMetadata.indexName) throw new Error(`Index mismatch: builder specifies "${indexName}" but cursor specifies "${this.#cursorMetadata.indexName}"`);
118
+ if (orderByIndex && (orderByIndex.indexName !== this.#cursorMetadata.indexName || orderByIndex.direction !== this.#cursorMetadata.orderDirection)) throw new Error(`Order mismatch: builder and cursor specify different ordering`);
119
+ if (pageSize !== void 0 && pageSize !== this.#cursorMetadata.pageSize) throw new Error(`Page size mismatch: builder specifies ${pageSize} but cursor specifies ${this.#cursorMetadata.pageSize}`);
120
+ }
121
+ if (!indexName) throw new Error(`Must specify an index using .whereIndex() before finalizing find operation on table "${this.#tableName}"`);
122
+ if (this.#countMode) return {
123
+ type: "count",
124
+ indexName,
125
+ options: {
126
+ useIndex: indexName,
127
+ where: this.#whereClause
128
+ }
129
+ };
130
+ let compiledJoins;
131
+ if (this.#joinClause) compiledJoins = buildJoinIndexed(this.#table, this.#joinClause);
132
+ const afterCursor = this.#afterCursor instanceof Cursor ? this.#afterCursor.encode() : this.#afterCursor;
133
+ const beforeCursor = this.#beforeCursor instanceof Cursor ? this.#beforeCursor.encode() : this.#beforeCursor;
134
+ const options = {
135
+ useIndex: indexName,
136
+ select: this.#selectClause,
137
+ where: this.#whereClause,
138
+ orderByIndex,
139
+ after: afterCursor,
140
+ before: beforeCursor,
141
+ pageSize,
142
+ joins: compiledJoins
143
+ };
144
+ return {
145
+ type: "find",
146
+ indexName,
147
+ options
148
+ };
149
+ }
150
+ };
151
+ /**
152
+ * Builder for update operations in Unit of Work
153
+ */
154
+ var UpdateBuilder = class {
155
+ #tableName;
156
+ #id;
157
+ #checkVersion = false;
158
+ #setValues;
159
+ constructor(tableName, id) {
160
+ this.#tableName = tableName;
161
+ this.#id = id;
162
+ }
163
+ /**
164
+ * Specify values to update
165
+ */
166
+ set(values) {
167
+ this.#setValues = values;
168
+ return this;
169
+ }
170
+ /**
171
+ * Database timestamp helper for mutation values.
172
+ */
173
+ now() {
174
+ return dbNow();
175
+ }
176
+ interval(input) {
177
+ return dbInterval(input);
178
+ }
179
+ /**
180
+ * Enable version checking for optimistic concurrency control
181
+ * @throws Error if the ID is just a string (no version available)
182
+ */
183
+ check() {
184
+ if (typeof this.#id === "string") throw new Error(`Cannot use check() with a string ID on table "${this.#tableName}". Version checking requires a FragnoId with version information.`);
185
+ this.#checkVersion = true;
186
+ return this;
187
+ }
188
+ /**
189
+ * @internal
190
+ */
191
+ build() {
192
+ if (!this.#setValues) throw new Error(`Must specify values using .set() before finalizing update operation on table "${this.#tableName}"`);
193
+ return {
194
+ id: this.#id,
195
+ checkVersion: this.#checkVersion,
196
+ set: this.#setValues
197
+ };
198
+ }
199
+ };
200
+ /**
201
+ * Builder for delete operations in Unit of Work
202
+ */
203
+ var DeleteBuilder = class {
204
+ #tableName;
205
+ #id;
206
+ #checkVersion = false;
207
+ constructor(tableName, id) {
208
+ this.#tableName = tableName;
209
+ this.#id = id;
210
+ }
211
+ /**
212
+ * Enable version checking for optimistic concurrency control
213
+ * @throws Error if the ID is just a string (no version available)
214
+ */
215
+ check() {
216
+ if (typeof this.#id === "string") throw new Error(`Cannot use check() with a string ID on table "${this.#tableName}". Version checking requires a FragnoId with version information.`);
217
+ this.#checkVersion = true;
218
+ return this;
219
+ }
220
+ /**
221
+ * @internal
222
+ */
223
+ build() {
224
+ return {
225
+ id: this.#id,
226
+ checkVersion: this.#checkVersion
227
+ };
228
+ }
229
+ };
230
+ /**
231
+ * Builder for join operations in Unit of Work
232
+ * Similar to FindBuilder but tailored for joins (no cursor pagination, no count mode)
233
+ */
234
+ var JoinFindBuilder = class {
235
+ #table;
236
+ #tableName;
237
+ #indexName;
238
+ #whereClause;
239
+ #orderByIndexClause;
240
+ #pageSizeValue;
241
+ #selectClause;
242
+ #joinClause;
243
+ constructor(tableName, table) {
244
+ this.#tableName = tableName;
245
+ this.#table = table;
246
+ }
247
+ /**
248
+ * Specify which index to use and optionally filter the results
249
+ */
250
+ whereIndex(indexName, condition) {
251
+ if (indexName !== "primary" && !(indexName in this.#table.indexes)) throw new Error(`Index "${String(indexName)}" not found on table "${this.#tableName}". Available indexes: primary, ${Object.keys(this.#table.indexes).join(", ")}`);
252
+ this.#indexName = indexName === "primary" ? "_primary" : indexName;
253
+ if (condition) this.#whereClause = condition;
254
+ return this;
255
+ }
256
+ /**
257
+ * Specify columns to select
258
+ */
259
+ select(columns) {
260
+ this.#selectClause = columns;
261
+ return this;
262
+ }
263
+ /**
264
+ * Order results by index in ascending or descending order
265
+ */
266
+ orderByIndex(indexName, direction) {
267
+ if (indexName !== "primary" && !(indexName in this.#table.indexes)) throw new Error(`Index "${String(indexName)}" not found on table "${this.#tableName}". Available indexes: primary, ${Object.keys(this.#table.indexes).join(", ")}`);
268
+ this.#orderByIndexClause = {
269
+ indexName: indexName === "primary" ? "_primary" : indexName,
270
+ direction
271
+ };
272
+ return this;
273
+ }
274
+ /**
275
+ * Set the number of results to return
276
+ * @throws {RangeError} If size is not a positive integer
277
+ */
278
+ pageSize(size) {
279
+ if (!Number.isInteger(size) || size <= 0) throw new RangeError(`pageSize must be a positive integer, received: ${size}`);
280
+ this.#pageSizeValue = size;
281
+ return this;
282
+ }
283
+ /**
284
+ * Add joins to include related data
285
+ * Join where clauses are restricted to indexed columns only
286
+ */
287
+ join(joinFn) {
288
+ this.#joinClause = joinFn;
289
+ return this;
290
+ }
291
+ /**
292
+ * @internal
293
+ */
294
+ build() {
295
+ let compiledJoins;
296
+ if (this.#joinClause) compiledJoins = buildJoinIndexed(this.#table, this.#joinClause);
297
+ return {
298
+ indexName: this.#indexName,
299
+ select: this.#selectClause,
300
+ where: this.#whereClause,
301
+ orderByIndex: this.#orderByIndexClause,
302
+ pageSize: this.#pageSizeValue,
303
+ joins: compiledJoins
304
+ };
305
+ }
306
+ };
307
+ /**
308
+ * Build join operations with indexed-only where clauses for Unit of Work
309
+ * This ensures all join conditions can leverage indexes for optimal performance
310
+ */
311
+ function buildJoinIndexed(table, fn) {
312
+ const compiled = [];
313
+ const builder = {};
314
+ for (const name in table.relations) {
315
+ const relation = table.relations[name];
316
+ builder[name] = (builderFn) => {
317
+ const joinBuilder = new JoinFindBuilder(relation.table.name, relation.table);
318
+ if (builderFn) builderFn(joinBuilder);
319
+ const config = joinBuilder.build();
320
+ let conditions;
321
+ if (config.where) {
322
+ const cond = buildCondition(relation.table.columns, config.where);
323
+ if (cond === true) conditions = void 0;
324
+ else if (cond === false) {
325
+ compiled.push({
326
+ relation,
327
+ options: false
328
+ });
329
+ delete builder[name];
330
+ return builder;
331
+ } else conditions = cond;
332
+ }
333
+ let orderBy;
334
+ if (config.orderByIndex) {
335
+ const index = relation.table.indexes[config.orderByIndex.indexName];
336
+ if (index) orderBy = index.columns.map((col) => [col, config.orderByIndex.direction]);
337
+ else orderBy = [[relation.table.getIdColumn(), config.orderByIndex.direction]];
338
+ }
339
+ compiled.push({
340
+ relation,
341
+ options: {
342
+ select: config.select ?? true,
343
+ where: conditions,
344
+ orderBy,
345
+ join: config.joins,
346
+ limit: config.pageSize
347
+ }
348
+ });
349
+ delete builder[name];
350
+ return builder;
351
+ };
352
+ }
353
+ fn(builder);
354
+ return compiled;
355
+ }
356
+ function createUnitOfWork(compiler, executor, decoder, schemaNamespaceMap, name) {
357
+ return new UnitOfWork(compiler, executor, decoder, name, void 0, schemaNamespaceMap);
358
+ }
359
+ function isUowInstrumentationInjection(value) {
360
+ if (!value || typeof value !== "object") return false;
361
+ const injection = value;
362
+ return injection.type === "conflict" || injection.type === "error";
363
+ }
364
+ /**
365
+ * Encapsulates a promise with its resolver/rejecter functions.
366
+ * Simplifies management of deferred promises with built-in error handling.
367
+ */
368
+ var DeferredPromise = class {
369
+ #resolve;
370
+ #reject;
371
+ #promise;
372
+ constructor() {
373
+ const { promise, resolve, reject } = Promise.withResolvers();
374
+ this.#promise = promise;
375
+ this.#resolve = resolve;
376
+ this.#reject = reject;
377
+ this.#promise.catch(() => {});
378
+ }
379
+ get promise() {
380
+ return this.#promise;
381
+ }
382
+ resolve(value) {
383
+ this.#resolve?.(value);
384
+ }
385
+ reject(error) {
386
+ this.#reject?.(error);
387
+ }
388
+ /**
389
+ * Reset to a new promise
390
+ */
391
+ reset() {
392
+ const { promise, resolve, reject } = Promise.withResolvers();
393
+ this.#promise = promise;
394
+ this.#resolve = resolve;
395
+ this.#reject = reject;
396
+ this.#promise.catch(() => {});
397
+ }
398
+ };
399
+ /**
400
+ * Tracks readiness signals from a group of children.
401
+ * Maintains a promise that resolves when all registered children have signaled.
402
+ */
403
+ var ReadinessTracker = class {
404
+ #expectedCount = 0;
405
+ #signalCount = 0;
406
+ #resolve;
407
+ #promise = Promise.resolve();
408
+ get promise() {
409
+ return this.#promise;
410
+ }
411
+ /**
412
+ * Register that we're expecting a signal from a child
413
+ */
414
+ registerChild() {
415
+ if (this.#expectedCount === 0) {
416
+ const { promise, resolve } = Promise.withResolvers();
417
+ this.#promise = promise;
418
+ this.#resolve = resolve;
419
+ }
420
+ this.#expectedCount++;
421
+ }
422
+ /**
423
+ * Signal that one child is ready
424
+ */
425
+ signal() {
426
+ this.#signalCount++;
427
+ if (this.#signalCount >= this.#expectedCount && this.#resolve) this.#resolve();
428
+ }
429
+ /**
430
+ * Reset to initial state
431
+ */
432
+ reset() {
433
+ this.#expectedCount = 0;
434
+ this.#signalCount = 0;
435
+ this.#resolve = void 0;
436
+ this.#promise = Promise.resolve();
437
+ }
438
+ };
439
+ /**
440
+ * Manages parent-child relationships and readiness coordination for Unit of Work instances.
441
+ * This allows parent UOWs to wait for all child UOWs to signal readiness before executing phases.
442
+ */
443
+ var UOWChildCoordinator = class {
444
+ #parent = null;
445
+ #parentCoordinator = null;
446
+ #children = /* @__PURE__ */ new Set();
447
+ #isRestricted = false;
448
+ #retrievalTracker = new ReadinessTracker();
449
+ #mutationTracker = new ReadinessTracker();
450
+ get isRestricted() {
451
+ return this.#isRestricted;
452
+ }
453
+ get parent() {
454
+ return this.#parent;
455
+ }
456
+ get children() {
457
+ return this.#children;
458
+ }
459
+ get retrievalReadinessPromise() {
460
+ return this.#retrievalTracker.promise;
461
+ }
462
+ get mutationReadinessPromise() {
463
+ return this.#mutationTracker.promise;
464
+ }
465
+ /**
466
+ * Mark this UOW as a restricted child of the given parent
467
+ */
468
+ setAsRestricted(parent, parentCoordinator) {
469
+ this.#parent = parent;
470
+ this.#parentCoordinator = parentCoordinator;
471
+ this.#isRestricted = true;
472
+ }
473
+ /**
474
+ * Register a child UOW
475
+ */
476
+ addChild(child) {
477
+ this.#children.add(child);
478
+ this.#retrievalTracker.registerChild();
479
+ this.#mutationTracker.registerChild();
480
+ }
481
+ /**
482
+ * Signal that this child is ready for retrieval phase execution.
483
+ * Only valid for restricted (child) UOWs.
484
+ */
485
+ signalReadyForRetrieval() {
486
+ if (!this.#parentCoordinator) throw new Error("signalReadyForRetrieval() can only be called on restricted child UOWs");
487
+ this.#parentCoordinator.notifyChildReadyForRetrieval();
488
+ }
489
+ /**
490
+ * Signal that this child is ready for mutation phase execution.
491
+ * Only valid for restricted (child) UOWs.
492
+ */
493
+ signalReadyForMutation() {
494
+ if (!this.#parentCoordinator) throw new Error("signalReadyForMutation() can only be called on restricted child UOWs");
495
+ this.#parentCoordinator.notifyChildReadyForMutation();
496
+ }
497
+ /**
498
+ * Notify this coordinator that a child is ready for retrieval (internal use).
499
+ * Called by child UOWs when they signal readiness.
500
+ */
501
+ notifyChildReadyForRetrieval() {
502
+ this.#retrievalTracker.signal();
503
+ }
504
+ /**
505
+ * Notify this coordinator that a child is ready for mutation (internal use).
506
+ * Called by child UOWs when they signal readiness.
507
+ */
508
+ notifyChildReadyForMutation() {
509
+ this.#mutationTracker.signal();
510
+ }
511
+ /**
512
+ * Reset coordination state for retry support
513
+ */
514
+ reset() {
515
+ this.#children.clear();
516
+ this.#retrievalTracker.reset();
517
+ this.#mutationTracker.reset();
518
+ }
519
+ };
520
+ /**
521
+ * Unit of Work implementation with optimistic concurrency control
522
+ *
523
+ * UOW has two phases:
524
+ * 1. Retrieval phase: Read operations to fetch entities with their versions
525
+ * 2. Mutation phase: Write operations that check versions before committing
526
+ *
527
+ * This is the untyped base storage. Use TypedUnitOfWork for type-safe operations.
528
+ *
529
+ * @example
530
+ * ```ts
531
+ * const uow = queryEngine.createUnitOfWork("update-user-balance");
532
+ * const typedUow = uow.forSchema(mySchema);
533
+ *
534
+ * // Retrieval phase
535
+ * typedUow.find("users", (b) => b.whereIndex("primary", (eb) => eb("id", "=", userId)));
536
+ *
537
+ * // Execute retrieval and transition to mutation phase
538
+ * const [users] = await uow.executeRetrieve();
539
+ *
540
+ * // Mutation phase with version check
541
+ * const user = users[0];
542
+ * typedUow.update("users", user.id, (b) => b.set({ balance: newBalance }).check());
543
+ *
544
+ * // Execute mutations
545
+ * const { success } = await uow.executeMutations();
546
+ * if (!success) {
547
+ * // Handle version conflict
548
+ * }
549
+ * ```
550
+ */
551
+ var UnitOfWork = class UnitOfWork {
552
+ #name;
553
+ #config;
554
+ #idempotencyKey;
555
+ #state = "building-retrieval";
556
+ #retrievalOps = [];
557
+ #mutationOps = [];
558
+ #compiler;
559
+ #executor;
560
+ #decoder;
561
+ #schemaNamespaceMap;
562
+ #retrievalResults;
563
+ #createdInternalIds = [];
564
+ #readTrackingEnabled = false;
565
+ #retrievalPhaseDeferred = new DeferredPromise();
566
+ #mutationPhaseDeferred = new DeferredPromise();
567
+ #retrievalError = null;
568
+ #mutationError = null;
569
+ #coordinator = new UOWChildCoordinator();
570
+ #triggeredHooks = [];
571
+ constructor(compiler, executor, decoder, name, config, schemaNamespaceMap) {
572
+ this.#compiler = compiler;
573
+ this.#executor = executor;
574
+ this.#decoder = decoder;
575
+ this.#schemaNamespaceMap = schemaNamespaceMap ?? /* @__PURE__ */ new WeakMap();
576
+ this.#name = name;
577
+ this.#config = config;
578
+ this.#idempotencyKey = config?.idempotencyKey ?? crypto.randomUUID();
579
+ }
580
+ #createInstrumentationContext(phase) {
581
+ return {
582
+ phase,
583
+ uowName: this.#name,
584
+ idempotencyKey: this.#idempotencyKey,
585
+ retrievalOpsCount: this.#retrievalOps.length,
586
+ mutationOpsCount: this.#mutationOps.length,
587
+ uow: this
588
+ };
589
+ }
590
+ async #runInstrumentation(phase) {
591
+ const hook = this.#config?.instrumentation?.[phase];
592
+ if (!hook) return null;
593
+ const result = await hook(this.#createInstrumentationContext(phase));
594
+ if (isUowInstrumentationInjection(result)) return result;
595
+ return null;
596
+ }
597
+ async #runInstrumentationFinalizer(phase) {
598
+ const hook = this.#config?.instrumentationFinalizer?.[phase];
599
+ if (!hook) return;
600
+ await hook(this.#createInstrumentationContext(phase));
601
+ }
602
+ #handleRetrieveInjection(injection) {
603
+ if (injection.type === "error") throw injection.error;
604
+ throw new Error(injection.reason ?? "Injected conflict");
605
+ }
606
+ #handleMutationInjection(injection) {
607
+ if (injection.type === "error") throw injection.error;
608
+ this.#state = "executed";
609
+ this.#createdInternalIds.length = 0;
610
+ this.#mutationPhaseDeferred.resolve();
611
+ return { success: false };
612
+ }
613
+ /**
614
+ * Register a schema with its namespace for cross-fragment operations.
615
+ * This is used for internal fragments like hooks that need to create
616
+ * records in a different schema during the same transaction.
617
+ */
618
+ registerSchema(schema, namespace) {
619
+ this.#schemaNamespaceMap.set(schema, namespace);
620
+ }
621
+ /**
622
+ * Get a schema-specific typed view of this UOW for type-safe operations.
623
+ * Returns a wrapper that provides typed operations for the given schema.
624
+ * The namespace is automatically resolved from the schema-namespace map.
625
+ * The optional hooks parameter is for type inference only - pass your hooks map
626
+ * to get proper typing for triggerHook. The value is not used at runtime.
627
+ */
628
+ forSchema(schema, _hooks) {
629
+ return new TypedUnitOfWork(schema, this.#schemaNamespaceMap.get(schema), this);
630
+ }
631
+ /**
632
+ * Create a restricted child UOW that cannot execute phases.
633
+ * The child shares the same operation storage but must signal readiness
634
+ * before the parent can execute each phase.
635
+ *
636
+ * @param options.readyFor - Controls automatic readiness signaling:
637
+ * - "mutation" (default): Signals ready for both retrieval and mutation immediately
638
+ * - "retrieval": Signals ready for retrieval only
639
+ * - "none": No automatic signaling, caller must signal manually
640
+ */
641
+ restrict(options) {
642
+ const readyFor = options?.readyFor ?? "mutation";
643
+ const child = new UnitOfWork(this.#compiler, this.#executor, this.#decoder, this.#name, {
644
+ ...this.#config,
645
+ idempotencyKey: this.#idempotencyKey
646
+ }, this.#schemaNamespaceMap);
647
+ child.#coordinator.setAsRestricted(this, this.#coordinator);
648
+ child.#retrievalOps = this.#retrievalOps;
649
+ child.#mutationOps = this.#mutationOps;
650
+ child.#retrievalResults = this.#retrievalResults;
651
+ child.#createdInternalIds = this.#createdInternalIds;
652
+ child.#readTrackingEnabled = this.#readTrackingEnabled;
653
+ child.#retrievalPhaseDeferred = this.#retrievalPhaseDeferred;
654
+ child.#mutationPhaseDeferred = this.#mutationPhaseDeferred;
655
+ child.#retrievalError = this.#retrievalError;
656
+ child.#mutationError = this.#mutationError;
657
+ child.#triggeredHooks = this.#triggeredHooks;
658
+ this.#coordinator.addChild(child);
659
+ if (readyFor === "mutation" || readyFor === "retrieval") child.signalReadyForRetrieval();
660
+ if (readyFor === "mutation") child.signalReadyForMutation();
661
+ return child;
662
+ }
663
+ /**
664
+ * Signal that this child is ready for retrieval phase execution.
665
+ * Only valid for restricted (child) UOWs.
666
+ */
667
+ signalReadyForRetrieval() {
668
+ this.#coordinator.signalReadyForRetrieval();
669
+ }
670
+ /**
671
+ * Signal that this child is ready for mutation phase execution.
672
+ * Only valid for restricted (child) UOWs.
673
+ */
674
+ signalReadyForMutation() {
675
+ this.#coordinator.signalReadyForMutation();
676
+ }
677
+ /**
678
+ * Reset the UOW to initial state for retry support.
679
+ * Clears operations, resets state, and resets phase promises.
680
+ */
681
+ reset() {
682
+ if (this.#coordinator.isRestricted) throw new Error("reset() cannot be called on restricted child UOWs");
683
+ this.#retrievalOps = [];
684
+ this.#mutationOps = [];
685
+ this.#retrievalResults = void 0;
686
+ this.#createdInternalIds = [];
687
+ this.#readTrackingEnabled = false;
688
+ this.#state = "building-retrieval";
689
+ this.#retrievalError = null;
690
+ this.#mutationError = null;
691
+ this.#retrievalPhaseDeferred.reset();
692
+ this.#mutationPhaseDeferred.reset();
693
+ this.#coordinator.reset();
694
+ this.#triggeredHooks = [];
695
+ }
696
+ /**
697
+ * Trigger a hook to be executed after the transaction commits.
698
+ */
699
+ triggerHook(namespace, hookName, payload, options) {
700
+ this.#triggeredHooks.push({
701
+ namespace,
702
+ hookName,
703
+ payload,
704
+ options
705
+ });
706
+ }
707
+ /**
708
+ * Get all triggered hooks for this UOW.
709
+ */
710
+ getTriggeredHooks() {
711
+ return this.#triggeredHooks;
712
+ }
713
+ get state() {
714
+ return this.#coordinator.parent?.state ?? this.#state;
715
+ }
716
+ enableReadTracking() {
717
+ this.#readTrackingEnabled = true;
718
+ }
719
+ get readTrackingEnabled() {
720
+ return this.#readTrackingEnabled;
721
+ }
722
+ get name() {
723
+ return this.#name;
724
+ }
725
+ get idempotencyKey() {
726
+ return this.#idempotencyKey;
727
+ }
728
+ /**
729
+ * Promise that resolves when the retrieval phase is executed
730
+ * Service methods can await this to coordinate multi-phase logic
731
+ */
732
+ get retrievalPhase() {
733
+ return this.#retrievalPhaseDeferred.promise;
734
+ }
735
+ /**
736
+ * Promise that resolves when the mutation phase is executed
737
+ * Service methods can await this to coordinate multi-phase logic
738
+ */
739
+ get mutationPhase() {
740
+ return this.#mutationPhaseDeferred.promise;
741
+ }
742
+ /**
743
+ * Execute the retrieval phase and transition to mutation phase
744
+ * Returns all results from find operations
745
+ */
746
+ async executeRetrieve() {
747
+ if (this.#coordinator.isRestricted) throw new Error("executeRetrieve() cannot be called on restricted child UOWs");
748
+ if (this.#state !== "building-retrieval") throw new Error(`Cannot execute retrieval from state ${this.#state}. Must be in building-retrieval state.`);
749
+ let afterRan = false;
750
+ let failed = false;
751
+ try {
752
+ await this.#coordinator.retrievalReadinessPromise;
753
+ const beforeInjection = await this.#runInstrumentation("beforeRetrieve");
754
+ if (beforeInjection) return this.#handleRetrieveInjection(beforeInjection);
755
+ if (this.#retrievalOps.length === 0) {
756
+ this.#state = "building-mutation";
757
+ const emptyResults = [];
758
+ afterRan = true;
759
+ const afterInjection$1 = await this.#runInstrumentation("afterRetrieve");
760
+ if (afterInjection$1) return this.#handleRetrieveInjection(afterInjection$1);
761
+ this.#retrievalPhaseDeferred.resolve(emptyResults);
762
+ return emptyResults;
763
+ }
764
+ const retrievalBatch = [];
765
+ for (const op of this.#retrievalOps) {
766
+ const compiled = this.#compiler.compileRetrievalOperation(op);
767
+ if (compiled !== null) {
768
+ this.#config?.onQuery?.(compiled);
769
+ retrievalBatch.push(compiled);
770
+ }
771
+ }
772
+ if (this.#config?.dryRun) {
773
+ this.#state = "executed";
774
+ const emptyResults = [];
775
+ afterRan = true;
776
+ const afterInjection$1 = await this.#runInstrumentation("afterRetrieve");
777
+ if (afterInjection$1) return this.#handleRetrieveInjection(afterInjection$1);
778
+ this.#retrievalPhaseDeferred.resolve(emptyResults);
779
+ return emptyResults;
780
+ }
781
+ const rawResults = await this.#executor.executeRetrievalPhase(retrievalBatch);
782
+ this.#retrievalResults = this.#decoder.decode(rawResults, this.#retrievalOps);
783
+ this.#state = "building-mutation";
784
+ afterRan = true;
785
+ const afterInjection = await this.#runInstrumentation("afterRetrieve");
786
+ if (afterInjection) return this.#handleRetrieveInjection(afterInjection);
787
+ this.#retrievalPhaseDeferred.resolve(this.#retrievalResults);
788
+ return this.#retrievalResults;
789
+ } catch (error) {
790
+ this.#retrievalError = error instanceof Error ? error : new Error(String(error));
791
+ failed = true;
792
+ throw error;
793
+ } finally {
794
+ try {
795
+ await this.#runInstrumentationFinalizer("afterRetrieve");
796
+ } catch {}
797
+ if (!afterRan && failed) try {
798
+ await this.#runInstrumentation("afterRetrieve");
799
+ } catch {}
800
+ }
801
+ }
802
+ /**
803
+ * Execute the mutation phase
804
+ * Returns success flag indicating if mutations completed without conflicts
805
+ */
806
+ async executeMutations() {
807
+ if (this.#coordinator.isRestricted) throw new Error("executeMutations() cannot be called on restricted child UOWs");
808
+ if (this.#state === "executed") throw new Error(`Cannot execute mutations from state ${this.#state}.`);
809
+ let afterRan = false;
810
+ let failed = false;
811
+ try {
812
+ await this.#coordinator.mutationReadinessPromise;
813
+ const beforeInjection = await this.#runInstrumentation("beforeMutate");
814
+ if (beforeInjection) return this.#handleMutationInjection(beforeInjection);
815
+ const mutationBatch = [];
816
+ for (const op of this.#mutationOps) {
817
+ const compiled = this.#compiler.compileMutationOperation(op);
818
+ if (compiled !== null) {
819
+ compiled.uowId = this.#idempotencyKey;
820
+ this.#config?.onQuery?.(compiled);
821
+ mutationBatch.push(compiled);
822
+ }
823
+ }
824
+ if (this.#config?.dryRun) {
825
+ this.#state = "executed";
826
+ afterRan = true;
827
+ const afterInjection$1 = await this.#runInstrumentation("afterMutate");
828
+ if (afterInjection$1) return this.#handleMutationInjection(afterInjection$1);
829
+ this.#mutationPhaseDeferred.resolve();
830
+ return { success: true };
831
+ }
832
+ const result = await this.#executor.executeMutationPhase(mutationBatch);
833
+ this.#state = "executed";
834
+ if (result.success) {
835
+ this.#createdInternalIds.length = 0;
836
+ this.#createdInternalIds.push(...result.createdInternalIds);
837
+ }
838
+ afterRan = true;
839
+ const afterInjection = await this.#runInstrumentation("afterMutate");
840
+ if (afterInjection) return this.#handleMutationInjection(afterInjection);
841
+ this.#mutationPhaseDeferred.resolve();
842
+ return { success: result.success };
843
+ } catch (error) {
844
+ this.#mutationError = error instanceof Error ? error : new Error(String(error));
845
+ failed = true;
846
+ throw error;
847
+ } finally {
848
+ try {
849
+ await this.#runInstrumentationFinalizer("afterMutate");
850
+ } catch {}
851
+ if (!afterRan && failed) try {
852
+ await this.#runInstrumentation("afterMutate");
853
+ } catch {}
854
+ }
855
+ }
856
+ /**
857
+ * Get the retrieval operations (for inspection/debugging)
858
+ */
859
+ getRetrievalOperations() {
860
+ return this.#retrievalOps;
861
+ }
862
+ /**
863
+ * Get the mutation operations (for inspection/debugging)
864
+ */
865
+ getMutationOperations() {
866
+ return this.#mutationOps;
867
+ }
868
+ /**
869
+ * @internal
870
+ * Add a retrieval operation (used by TypedUnitOfWork)
871
+ */
872
+ addRetrievalOperation(op) {
873
+ if (this.state !== "building-retrieval") throw new Error(`Cannot add retrieval operation in state ${this.state}. Must be in building-retrieval state.`);
874
+ this.#retrievalOps.push(op);
875
+ return this.#retrievalOps.length - 1;
876
+ }
877
+ /**
878
+ * @internal
879
+ * Add a mutation operation (used by TypedUnitOfWork)
880
+ */
881
+ addMutationOperation(op) {
882
+ if (this.state === "executed") throw new Error(`Cannot add mutation operation in executed state.`);
883
+ this.#mutationOps.push(op);
884
+ }
885
+ /**
886
+ * Get the IDs of created entities after executeMutations() has been called.
887
+ * Returns FragnoId objects with external IDs (always available) and internal IDs
888
+ * (available when database supports RETURNING).
889
+ *
890
+ * @throws Error if called before executeMutations()
891
+ * @returns Array of FragnoIds in the same order as create() calls
892
+ */
893
+ getCreatedIds() {
894
+ if (this.state !== "executed") throw new Error(`getCreatedIds() can only be called after executeMutations(). Current state: ${this.state}`);
895
+ const createdIds = [];
896
+ let createIndex = 0;
897
+ for (const op of this.#mutationOps) if (op.type === "create") {
898
+ const internalId = this.#createdInternalIds[createIndex] ?? void 0;
899
+ createdIds.push(new FragnoId({
900
+ externalId: op.generatedExternalId,
901
+ internalId,
902
+ version: 0
903
+ }));
904
+ createIndex++;
905
+ }
906
+ return createdIds;
907
+ }
908
+ /**
909
+ * @internal
910
+ * Compile the unit of work to executable queries for testing
911
+ */
912
+ compile(compiler) {
913
+ const retrievalBatch = [];
914
+ for (const op of this.#retrievalOps) {
915
+ const compiled = compiler.compileRetrievalOperation(op);
916
+ if (compiled !== null) retrievalBatch.push(compiled);
917
+ }
918
+ const mutationBatch = [];
919
+ for (const op of this.#mutationOps) {
920
+ const compiled = compiler.compileMutationOperation(op);
921
+ if (compiled !== null) {
922
+ compiled.uowId = this.#idempotencyKey;
923
+ mutationBatch.push(compiled);
924
+ }
925
+ }
926
+ return {
927
+ name: this.#name,
928
+ retrievalBatch,
929
+ mutationBatch
930
+ };
931
+ }
932
+ };
933
+ /**
934
+ * A typed facade around a UnitOfWork that provides type-safe operations for a specific schema.
935
+ * All operations are stored in the underlying UOW, but this facade ensures type safety and
936
+ * filters retrieval results to only include operations added through this facade.
937
+ */
938
+ var TypedUnitOfWork = class {
939
+ #schema;
940
+ #namespace;
941
+ #uow;
942
+ #operationIndices = [];
943
+ #cachedRetrievalPhase;
944
+ constructor(schema, namespace, uow) {
945
+ this.#schema = schema;
946
+ this.#namespace = namespace;
947
+ this.#uow = uow;
948
+ }
949
+ /**
950
+ * Type-only access to retrieval results for this typed UOW.
951
+ */
952
+ get $results() {
953
+ throw new Error("type only");
954
+ }
955
+ get schema() {
956
+ return this.#schema;
957
+ }
958
+ get name() {
959
+ return this.#uow.name;
960
+ }
961
+ get idempotencyKey() {
962
+ return this.#uow.idempotencyKey;
963
+ }
964
+ get state() {
965
+ return this.#uow.state;
966
+ }
967
+ get retrievalPhase() {
968
+ if (!this.#cachedRetrievalPhase) this.#cachedRetrievalPhase = this.#uow.retrievalPhase.then((allResults) => {
969
+ const allOperations = this.#uow.getRetrievalOperations();
970
+ return this.#operationIndices.map((opIndex) => {
971
+ const result = allResults[opIndex];
972
+ const operation = allOperations[opIndex];
973
+ if (operation?.type === "find" && operation.withSingleResult) return Array.isArray(result) ? result[0] ?? null : result;
974
+ return result;
975
+ });
976
+ });
977
+ return this.#cachedRetrievalPhase;
978
+ }
979
+ get mutationPhase() {
980
+ return this.#uow.mutationPhase;
981
+ }
982
+ getRetrievalOperations() {
983
+ return this.#uow.getRetrievalOperations();
984
+ }
985
+ getMutationOperations() {
986
+ return this.#uow.getMutationOperations();
987
+ }
988
+ getCreatedIds() {
989
+ return this.#uow.getCreatedIds();
990
+ }
991
+ async executeRetrieve() {
992
+ return this.#uow.executeRetrieve();
993
+ }
994
+ async executeMutations() {
995
+ return this.#uow.executeMutations();
996
+ }
997
+ restrict(options) {
998
+ return this.#uow.restrict(options);
999
+ }
1000
+ signalReadyForRetrieval() {
1001
+ this.#uow.signalReadyForRetrieval();
1002
+ }
1003
+ signalReadyForMutation() {
1004
+ this.#uow.signalReadyForMutation();
1005
+ }
1006
+ reset() {
1007
+ return this.#uow.reset();
1008
+ }
1009
+ forSchema(schema, hooks) {
1010
+ return this.#uow.forSchema(schema, hooks);
1011
+ }
1012
+ /**
1013
+ * Database timestamp helper for inserts.
1014
+ */
1015
+ now() {
1016
+ return dbNow();
1017
+ }
1018
+ /**
1019
+ * Build a database interval for use with now().plus(...).
1020
+ */
1021
+ interval(input) {
1022
+ return dbInterval(input);
1023
+ }
1024
+ registerSchema(schema, namespace) {
1025
+ this.#uow.registerSchema(schema, namespace);
1026
+ }
1027
+ compile(compiler) {
1028
+ return this.#uow.compile(compiler);
1029
+ }
1030
+ find(tableName, builderFn) {
1031
+ const table = this.#schema.tables[tableName];
1032
+ if (!table) throw new Error(`Table ${tableName} not found in schema`);
1033
+ const builder = new FindBuilder(tableName, table);
1034
+ if (builderFn) builderFn(builder);
1035
+ else builder.whereIndex("primary");
1036
+ const { indexName, options, type } = builder.build();
1037
+ const operationIndex = this.#uow.addRetrievalOperation({
1038
+ type,
1039
+ schema: this.#schema,
1040
+ namespace: this.#namespace,
1041
+ table,
1042
+ indexName,
1043
+ options,
1044
+ readTracking: this.#uow.readTrackingEnabled
1045
+ });
1046
+ this.#operationIndices.push(operationIndex);
1047
+ return this;
1048
+ }
1049
+ findFirst(tableName, builderFn) {
1050
+ const table = this.#schema.tables[tableName];
1051
+ if (!table) throw new Error(`Table ${tableName} not found in schema`);
1052
+ const builder = new FindBuilder(tableName, table);
1053
+ if (builderFn) builderFn(builder);
1054
+ else builder.whereIndex("primary");
1055
+ builder.pageSize(1);
1056
+ const { indexName, options, type } = builder.build();
1057
+ const operationIndex = this.#uow.addRetrievalOperation({
1058
+ type,
1059
+ schema: this.#schema,
1060
+ namespace: this.#namespace,
1061
+ table,
1062
+ indexName,
1063
+ options,
1064
+ withSingleResult: true,
1065
+ readTracking: this.#uow.readTrackingEnabled
1066
+ });
1067
+ this.#operationIndices.push(operationIndex);
1068
+ return this;
1069
+ }
1070
+ findWithCursor(tableName, builderFn) {
1071
+ const table = this.#schema.tables[tableName];
1072
+ if (!table) throw new Error(`Table ${tableName} not found in schema`);
1073
+ const builder = new FindBuilder(tableName, table);
1074
+ builderFn(builder);
1075
+ const { indexName, options, type } = builder.build();
1076
+ const operationIndex = this.#uow.addRetrievalOperation({
1077
+ type,
1078
+ schema: this.#schema,
1079
+ namespace: this.#namespace,
1080
+ table,
1081
+ indexName,
1082
+ options,
1083
+ withCursor: true,
1084
+ readTracking: this.#uow.readTrackingEnabled
1085
+ });
1086
+ this.#operationIndices.push(operationIndex);
1087
+ return this;
1088
+ }
1089
+ /**
1090
+ * Generate a new ID for a table without creating a record.
1091
+ * This is useful when you need to reference an ID before actually creating the record,
1092
+ * or when you need to pass the ID to external services.
1093
+ *
1094
+ * @example
1095
+ * ```ts
1096
+ * const userId = uow.generateId("users");
1097
+ * // Use userId in related records or pass to external services
1098
+ * uow.create("users", { id: userId, name: "John" });
1099
+ * ```
1100
+ */
1101
+ generateId(tableName) {
1102
+ return generateId(this.#schema, tableName);
1103
+ }
1104
+ create(tableName, values) {
1105
+ const tableSchema = this.#schema.tables[tableName];
1106
+ if (!tableSchema) throw new Error(`Table ${tableName} not found in schema`);
1107
+ const idColumn = tableSchema.getIdColumn();
1108
+ let externalId;
1109
+ let updatedValues = values;
1110
+ const providedIdValue = values[idColumn.name];
1111
+ if (providedIdValue !== void 0) if (typeof providedIdValue === "object" && providedIdValue !== null && "externalId" in providedIdValue) externalId = providedIdValue.externalId;
1112
+ else externalId = providedIdValue;
1113
+ else {
1114
+ const generated = idColumn.generateDefaultValue();
1115
+ if (generated === void 0) throw new Error(`No ID value provided and ID column ${idColumn.name} has no default generator`);
1116
+ externalId = generated;
1117
+ updatedValues = {
1118
+ ...values,
1119
+ [idColumn.name]: externalId
1120
+ };
1121
+ }
1122
+ this.#uow.addMutationOperation({
1123
+ type: "create",
1124
+ schema: this.#schema,
1125
+ namespace: this.#namespace,
1126
+ table: tableName,
1127
+ values: updatedValues,
1128
+ generatedExternalId: externalId
1129
+ });
1130
+ return FragnoId.fromExternal(externalId, 0);
1131
+ }
1132
+ update(tableName, id, builderFn) {
1133
+ const builder = new UpdateBuilder(tableName, id);
1134
+ builderFn(builder);
1135
+ const { id: opId, checkVersion, set } = builder.build();
1136
+ this.#uow.addMutationOperation({
1137
+ type: "update",
1138
+ schema: this.#schema,
1139
+ namespace: this.#namespace,
1140
+ table: tableName,
1141
+ id: opId,
1142
+ checkVersion,
1143
+ set
1144
+ });
1145
+ }
1146
+ delete(tableName, id, builderFn) {
1147
+ const builder = new DeleteBuilder(tableName, id);
1148
+ builderFn?.(builder);
1149
+ const { id: opId, checkVersion } = builder.build();
1150
+ this.#uow.addMutationOperation({
1151
+ type: "delete",
1152
+ schema: this.#schema,
1153
+ namespace: this.#namespace,
1154
+ table: tableName,
1155
+ id: opId,
1156
+ checkVersion
1157
+ });
1158
+ }
1159
+ /**
1160
+ * Check that a record's version hasn't changed since retrieval.
1161
+ * This is useful for ensuring related records remain unchanged during a transaction.
1162
+ *
1163
+ * @param tableName - The table name
1164
+ * @param id - The FragnoId with version information (string IDs are not allowed)
1165
+ * @throws Error if the ID is a string without version information
1166
+ *
1167
+ * @example
1168
+ * ```ts
1169
+ * // Ensure both accounts haven't changed before creating a transfer
1170
+ * uow.check("accounts", fromAccount.id);
1171
+ * uow.check("accounts", toAccount.id);
1172
+ * uow.create("transactions", { fromAccountId, toAccountId, amount });
1173
+ * ```
1174
+ */
1175
+ check(tableName, id) {
1176
+ this.#uow.addMutationOperation({
1177
+ type: "check",
1178
+ schema: this.#schema,
1179
+ namespace: this.#namespace,
1180
+ table: tableName,
1181
+ id
1182
+ });
1183
+ }
1184
+ get $hooks() {
1185
+ throw new Error("type only");
1186
+ }
1187
+ get namespace() {
1188
+ return this.#namespace;
1189
+ }
1190
+ /**
1191
+ * Trigger a hook to be executed after the transaction commits.
1192
+ * The namespace is automatically injected from this typed view's schema registration.
1193
+ */
1194
+ triggerHook(hookName, payload, options) {
1195
+ if (this.#namespace === void 0) throw new Error("Cannot trigger hook: schema has no registered namespace. Ensure the schema is registered with a namespace via registerSchema().");
1196
+ const hookNamespace = this.#namespace ?? this.#schema.name;
1197
+ this.#uow.triggerHook(hookNamespace, hookName, payload, options);
1198
+ }
1199
+ getTriggeredHooks() {
1200
+ return this.#uow.getTriggeredHooks();
1201
+ }
1202
+ };
1203
+
1204
+ //#endregion
1205
+ export { TypedUnitOfWork, UnitOfWork, createUnitOfWork };
1206
+ //# sourceMappingURL=unit-of-work.js.map