@fragno-dev/db 0.1.15 → 0.2.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 (402) hide show
  1. package/.turbo/turbo-build.log +242 -179
  2. package/CHANGELOG.md +40 -0
  3. package/README.md +123 -8
  4. package/dist/adapters/adapters.d.ts +5 -5
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/drizzle/drizzle-adapter.d.ts +6 -21
  8. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
  9. package/dist/adapters/drizzle/drizzle-adapter.js +7 -54
  10. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
  11. package/dist/adapters/drizzle/generate.d.ts +3 -0
  12. package/dist/adapters/drizzle/generate.d.ts.map +1 -1
  13. package/dist/adapters/drizzle/generate.js +36 -28
  14. package/dist/adapters/drizzle/generate.js.map +1 -1
  15. package/dist/adapters/generic-sql/driver-config.d.ts +74 -0
  16. package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -0
  17. package/dist/adapters/generic-sql/driver-config.js +94 -0
  18. package/dist/adapters/generic-sql/driver-config.js.map +1 -0
  19. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +43 -0
  20. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -0
  21. package/dist/adapters/generic-sql/generic-sql-adapter.js +87 -0
  22. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -0
  23. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +67 -0
  24. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -0
  25. package/dist/adapters/generic-sql/migration/cold-kysely.js +33 -0
  26. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -0
  27. package/dist/adapters/generic-sql/migration/dialect/mysql.js +60 -0
  28. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -0
  29. package/dist/adapters/generic-sql/migration/dialect/postgres.js +59 -0
  30. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -0
  31. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +96 -0
  32. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -0
  33. package/dist/adapters/generic-sql/migration/executor.d.ts +15 -0
  34. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  35. package/dist/adapters/generic-sql/migration/executor.js +18 -0
  36. package/dist/adapters/generic-sql/migration/executor.js.map +1 -0
  37. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  38. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  39. package/dist/adapters/generic-sql/migration/prepared-migrations.js +68 -0
  40. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -0
  41. package/dist/adapters/generic-sql/migration/sql-generator.js +212 -0
  42. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -0
  43. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +32 -0
  44. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -0
  45. package/dist/adapters/generic-sql/query/cursor-utils.js +37 -0
  46. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -0
  47. package/dist/adapters/generic-sql/query/dialect/mysql.js +33 -0
  48. package/dist/adapters/generic-sql/query/dialect/mysql.js.map +1 -0
  49. package/dist/adapters/generic-sql/query/dialect/postgres.js +32 -0
  50. package/dist/adapters/generic-sql/query/dialect/postgres.js.map +1 -0
  51. package/dist/adapters/generic-sql/query/dialect/sqlite.js +32 -0
  52. package/dist/adapters/generic-sql/query/dialect/sqlite.js.map +1 -0
  53. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +152 -0
  54. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -0
  55. package/dist/adapters/generic-sql/query/select-builder.js +69 -0
  56. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -0
  57. package/dist/adapters/generic-sql/query/sql-query-compiler.js +145 -0
  58. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -0
  59. package/dist/adapters/generic-sql/query/where-builder.js +129 -0
  60. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -0
  61. package/dist/adapters/generic-sql/result-interpreter.js +74 -0
  62. package/dist/adapters/generic-sql/result-interpreter.js.map +1 -0
  63. package/dist/adapters/generic-sql/uow-decoder.js +105 -0
  64. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -0
  65. package/dist/adapters/generic-sql/uow-encoder.js +93 -0
  66. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -0
  67. package/dist/adapters/kysely/kysely-adapter.d.ts +5 -18
  68. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
  69. package/dist/adapters/kysely/kysely-adapter.js +6 -165
  70. package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
  71. package/dist/adapters/{drizzle/drizzle-query.js → shared/from-unit-of-work-compiler.js} +47 -61
  72. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -0
  73. package/dist/adapters/{drizzle/shared.d.ts → shared/table-name-mapper.d.ts} +2 -4
  74. package/dist/adapters/shared/table-name-mapper.d.ts.map +1 -0
  75. package/dist/adapters/shared/table-name-mapper.js +43 -0
  76. package/dist/adapters/shared/table-name-mapper.js.map +1 -0
  77. package/dist/adapters/shared/uow-operation-compiler.js +105 -0
  78. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -0
  79. package/dist/db-fragment-definition-builder.d.ts +107 -19
  80. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  81. package/dist/db-fragment-definition-builder.js +134 -20
  82. package/dist/db-fragment-definition-builder.js.map +1 -1
  83. package/dist/fragments/internal-fragment.d.ts +39 -5
  84. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  85. package/dist/fragments/internal-fragment.js +82 -10
  86. package/dist/fragments/internal-fragment.js.map +1 -1
  87. package/dist/hooks/hooks.d.ts +51 -0
  88. package/dist/hooks/hooks.d.ts.map +1 -0
  89. package/dist/hooks/hooks.js +88 -0
  90. package/dist/hooks/hooks.js.map +1 -0
  91. package/dist/migration-engine/generation-engine.d.ts +0 -2
  92. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  93. package/dist/migration-engine/generation-engine.js +23 -61
  94. package/dist/migration-engine/generation-engine.js.map +1 -1
  95. package/dist/mod.d.ts +34 -10
  96. package/dist/mod.d.ts.map +1 -1
  97. package/dist/mod.js +47 -16
  98. package/dist/mod.js.map +1 -1
  99. package/dist/node_modules/.pnpm/{rou3@0.7.8 → rou3@0.7.10}/node_modules/rou3/dist/index.js +1 -1
  100. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +1 -0
  101. package/dist/packages/fragno/dist/api/fragment-instantiator.js +69 -31
  102. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -1
  103. package/dist/query/column-defaults.js +27 -0
  104. package/dist/query/column-defaults.js.map +1 -0
  105. package/dist/query/cursor.d.ts +4 -4
  106. package/dist/query/cursor.d.ts.map +1 -1
  107. package/dist/query/cursor.js +8 -6
  108. package/dist/query/cursor.js.map +1 -1
  109. package/dist/query/orm/orm.d.ts +1 -1
  110. package/dist/query/orm/orm.js.map +1 -1
  111. package/dist/query/serialize/create-sql-serializer.js +30 -0
  112. package/dist/query/serialize/create-sql-serializer.js.map +1 -0
  113. package/dist/query/serialize/dialect/mysql-serializer.js +87 -0
  114. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -0
  115. package/dist/query/serialize/dialect/postgres-serializer.js +80 -0
  116. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -0
  117. package/dist/query/serialize/dialect/sqlite-serializer.js +93 -0
  118. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -0
  119. package/dist/query/serialize/sql-serializer.js +67 -0
  120. package/dist/query/serialize/sql-serializer.js.map +1 -0
  121. package/dist/query/{query.d.ts → simple-query-interface.d.ts} +5 -5
  122. package/dist/query/simple-query-interface.d.ts.map +1 -0
  123. package/dist/query/{execute-unit-of-work.d.ts → unit-of-work/execute-unit-of-work.d.ts} +50 -4
  124. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  125. package/dist/query/{execute-unit-of-work.js → unit-of-work/execute-unit-of-work.js} +150 -5
  126. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  127. package/dist/query/{retry-policy.d.ts → unit-of-work/retry-policy.d.ts} +1 -1
  128. package/dist/query/unit-of-work/retry-policy.d.ts.map +1 -0
  129. package/dist/query/{retry-policy.js → unit-of-work/retry-policy.js} +1 -1
  130. package/dist/query/unit-of-work/retry-policy.js.map +1 -0
  131. package/dist/query/{unit-of-work.d.ts → unit-of-work/unit-of-work.d.ts} +69 -21
  132. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  133. package/dist/query/{unit-of-work.js → unit-of-work/unit-of-work.js} +83 -22
  134. package/dist/query/unit-of-work/unit-of-work.js.map +1 -0
  135. package/dist/query/value-decoding.js +71 -0
  136. package/dist/query/value-decoding.js.map +1 -0
  137. package/dist/query/value-encoding.js +124 -0
  138. package/dist/query/value-encoding.js.map +1 -0
  139. package/dist/schema/type-conversion/create-sql-type-mapper.js +29 -0
  140. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -0
  141. package/dist/schema/type-conversion/dialect/mysql.js +57 -0
  142. package/dist/schema/type-conversion/dialect/mysql.js.map +1 -0
  143. package/dist/schema/type-conversion/dialect/postgres.js +56 -0
  144. package/dist/schema/type-conversion/dialect/postgres.js.map +1 -0
  145. package/dist/schema/type-conversion/dialect/sqlite.js +52 -0
  146. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -0
  147. package/dist/schema/type-conversion/type-mapping.js +63 -0
  148. package/dist/schema/type-conversion/type-mapping.js.map +1 -0
  149. package/dist/sql-driver/connection/connection-provider.d.ts +13 -0
  150. package/dist/sql-driver/connection/connection-provider.d.ts.map +1 -0
  151. package/dist/sql-driver/connection/connection-provider.js +19 -0
  152. package/dist/sql-driver/connection/connection-provider.js.map +1 -0
  153. package/dist/sql-driver/connection/single-connection-provider.js +23 -0
  154. package/dist/sql-driver/connection/single-connection-provider.js.map +1 -0
  155. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  156. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  157. package/dist/sql-driver/dialects/dialects.d.ts +2 -0
  158. package/dist/sql-driver/dialects/dialects.js +3 -0
  159. package/dist/sql-driver/dialects/durable-object-dialect.d.ts +72 -0
  160. package/dist/sql-driver/dialects/durable-object-dialect.d.ts.map +1 -0
  161. package/dist/sql-driver/dialects/durable-object-dialect.js +130 -0
  162. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -0
  163. package/dist/sql-driver/driver/runtime-driver.d.ts +23 -0
  164. package/dist/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  165. package/dist/sql-driver/driver/runtime-driver.js +56 -0
  166. package/dist/sql-driver/driver/runtime-driver.js.map +1 -0
  167. package/dist/sql-driver/query-executor/default-query-executor.js +26 -0
  168. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -0
  169. package/dist/sql-driver/query-executor/plugin.d.ts +17 -0
  170. package/dist/sql-driver/query-executor/plugin.d.ts.map +1 -0
  171. package/dist/sql-driver/query-executor/query-executor-base.js +25 -0
  172. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -0
  173. package/dist/sql-driver/query-executor/query-executor.d.ts +36 -0
  174. package/dist/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  175. package/dist/sql-driver/sql-driver-adapter.d.ts +29 -0
  176. package/dist/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  177. package/dist/sql-driver/sql-driver-adapter.js +68 -0
  178. package/dist/sql-driver/sql-driver-adapter.js.map +1 -0
  179. package/dist/sql-driver/sql-driver.d.ts +38 -0
  180. package/dist/sql-driver/sql-driver.d.ts.map +1 -0
  181. package/dist/sql-driver/sql-driver.js +1 -0
  182. package/dist/sql-driver/sql.js +50 -0
  183. package/dist/sql-driver/sql.js.map +1 -0
  184. package/dist/with-database.d.ts +6 -2
  185. package/dist/with-database.d.ts.map +1 -1
  186. package/dist/with-database.js +1 -1
  187. package/dist/with-database.js.map +1 -1
  188. package/package.json +39 -12
  189. package/src/adapters/adapters.ts +8 -5
  190. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +61 -169
  191. package/src/adapters/drizzle/{drizzle-adapter-sqlite.test.ts → drizzle-adapter-sqlite3.test.ts} +31 -55
  192. package/src/adapters/drizzle/drizzle-adapter.ts +15 -107
  193. package/src/adapters/drizzle/generate.test.ts +2 -2
  194. package/src/adapters/drizzle/generate.ts +78 -34
  195. package/src/adapters/drizzle/migrate-drizzle.test.ts +19 -0
  196. package/src/adapters/drizzle/shared.ts +0 -34
  197. package/src/adapters/drizzle/test-utils.ts +3 -3
  198. package/src/adapters/generic-sql/README.md +14 -0
  199. package/src/adapters/generic-sql/driver-config.ts +144 -0
  200. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +50 -0
  201. package/src/adapters/generic-sql/generic-sql-adapter.ts +146 -0
  202. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +130 -0
  203. package/src/adapters/generic-sql/migration/cold-kysely.ts +55 -0
  204. package/src/adapters/{kysely/migration/execute-mysql.test.ts → generic-sql/migration/dialect/mysql.test.ts} +342 -484
  205. package/src/adapters/generic-sql/migration/dialect/mysql.ts +104 -0
  206. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +1008 -0
  207. package/src/adapters/generic-sql/migration/dialect/postgres.ts +113 -0
  208. package/src/adapters/{kysely/migration/execute-sqlite.test.ts → generic-sql/migration/dialect/sqlite.test.ts} +307 -510
  209. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +189 -0
  210. package/src/adapters/generic-sql/migration/executor.ts +33 -0
  211. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +661 -0
  212. package/src/adapters/generic-sql/migration/prepared-migrations.ts +214 -0
  213. package/src/adapters/generic-sql/migration/sql-generator.ts +413 -0
  214. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +36 -0
  215. package/src/adapters/generic-sql/query/cursor-utils.ts +56 -0
  216. package/src/adapters/generic-sql/query/dialect/mysql.ts +34 -0
  217. package/src/adapters/generic-sql/query/dialect/postgres.ts +32 -0
  218. package/src/adapters/generic-sql/query/dialect/sqlite.ts +32 -0
  219. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +1568 -0
  220. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +314 -0
  221. package/src/adapters/generic-sql/query/select-builder.test.ts +256 -0
  222. package/src/adapters/generic-sql/query/select-builder.ts +137 -0
  223. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +195 -0
  224. package/src/adapters/generic-sql/query/sql-query-compiler.ts +367 -0
  225. package/src/adapters/generic-sql/query/where-builder.test.ts +744 -0
  226. package/src/adapters/generic-sql/query/where-builder.ts +211 -0
  227. package/src/adapters/generic-sql/result-interpreter.ts +102 -0
  228. package/src/adapters/generic-sql/test/generic-drizzle-adapter-sqlite3.test.ts +899 -0
  229. package/src/adapters/generic-sql/uow-decoder.test.ts +399 -0
  230. package/src/adapters/generic-sql/uow-decoder.ts +152 -0
  231. package/src/adapters/generic-sql/uow-encoder.test.ts +183 -0
  232. package/src/adapters/generic-sql/uow-encoder.ts +131 -0
  233. package/src/adapters/kysely/kysely-adapter-pglite.test.ts +26 -76
  234. package/src/adapters/kysely/{kysely-adapter-sqlite.test.ts → kysely-adapter-sqlocal.test.ts} +76 -17
  235. package/src/adapters/kysely/kysely-adapter.ts +10 -250
  236. package/src/adapters/{drizzle/drizzle-query.ts → shared/from-unit-of-work-compiler.ts} +110 -104
  237. package/src/adapters/shared/table-name-mapper.ts +50 -0
  238. package/src/adapters/shared/uow-operation-compiler.ts +211 -0
  239. package/src/db-fragment-definition-builder.test.ts +2 -2
  240. package/src/db-fragment-definition-builder.ts +461 -50
  241. package/src/db-fragment-instantiator.test.ts +78 -2
  242. package/src/db-fragment-integration.test.ts +14 -16
  243. package/src/fragments/internal-fragment.test.ts +434 -45
  244. package/src/fragments/internal-fragment.ts +183 -20
  245. package/src/hooks/hooks.test.ts +587 -0
  246. package/src/hooks/hooks.ts +179 -0
  247. package/src/migration-engine/generation-engine.test.ts +44 -54
  248. package/src/migration-engine/generation-engine.ts +48 -94
  249. package/src/mod.ts +117 -29
  250. package/src/query/column-defaults.ts +49 -0
  251. package/src/query/cursor.test.ts +31 -6
  252. package/src/query/cursor.ts +11 -7
  253. package/src/query/orm/orm.ts +1 -1
  254. package/src/query/query-type.test.ts +9 -9
  255. package/src/query/serialize/create-sql-serializer.ts +34 -0
  256. package/src/query/serialize/dialect/mysql-serializer.ts +142 -0
  257. package/src/query/serialize/dialect/postgres-serializer.ts +129 -0
  258. package/src/query/serialize/dialect/sqlite-serializer.test.ts +251 -0
  259. package/src/query/serialize/dialect/sqlite-serializer.ts +156 -0
  260. package/src/query/serialize/sql-serializer.ts +143 -0
  261. package/src/query/{query.ts → simple-query-interface.ts} +2 -2
  262. package/src/query/{execute-unit-of-work.test.ts → unit-of-work/execute-unit-of-work.test.ts} +571 -17
  263. package/src/query/{execute-unit-of-work.ts → unit-of-work/execute-unit-of-work.ts} +361 -12
  264. package/src/query/{unit-of-work-coordinator.test.ts → unit-of-work/unit-of-work-coordinator.test.ts} +290 -44
  265. package/src/query/{unit-of-work-types.test.ts → unit-of-work/unit-of-work-types.test.ts} +5 -3
  266. package/src/query/{unit-of-work.test.ts → unit-of-work/unit-of-work.test.ts} +100 -9
  267. package/src/query/{unit-of-work.ts → unit-of-work/unit-of-work.ts} +174 -49
  268. package/src/query/{result-transform.test.ts → value-decoding.test.ts} +45 -427
  269. package/src/query/value-decoding.ts +113 -0
  270. package/src/query/value-encoding.test.ts +390 -0
  271. package/src/query/value-encoding.ts +168 -0
  272. package/src/schema/create.test.ts +5 -1
  273. package/src/schema/serialize.test.ts +165 -407
  274. package/src/schema/type-conversion/create-sql-type-mapper.ts +28 -0
  275. package/src/schema/type-conversion/dialect/mysql.ts +64 -0
  276. package/src/schema/type-conversion/dialect/postgres.ts +62 -0
  277. package/src/schema/type-conversion/dialect/sqlite.ts +63 -0
  278. package/src/schema/type-conversion/type-mapping.test.ts +137 -0
  279. package/src/schema/type-conversion/type-mapping.ts +153 -0
  280. package/src/shared/connection-pool.ts +5 -5
  281. package/src/sql-driver/better-sqlite3.test.ts +126 -0
  282. package/src/sql-driver/connection/connection-provider.ts +27 -0
  283. package/src/sql-driver/connection/single-connection-provider.ts +42 -0
  284. package/src/sql-driver/dialect-adapter/dialect-adapter.ts +9 -0
  285. package/src/sql-driver/dialect-adapter/sqlite-dialect-adapter.ts +7 -0
  286. package/src/sql-driver/dialects/dialects.ts +1 -0
  287. package/src/sql-driver/dialects/durable-object-dialect.ts +260 -0
  288. package/src/sql-driver/driver/runtime-driver.ts +91 -0
  289. package/src/sql-driver/query-executor/default-query-executor.ts +38 -0
  290. package/src/sql-driver/query-executor/plugin.ts +22 -0
  291. package/src/sql-driver/query-executor/query-executor-base.ts +53 -0
  292. package/src/sql-driver/query-executor/query-executor.ts +44 -0
  293. package/src/sql-driver/sql-driver-adapter.ts +96 -0
  294. package/src/sql-driver/sql-driver.ts +53 -0
  295. package/src/sql-driver/sql.ts +57 -0
  296. package/src/sql-driver/sqlocal.test.ts +117 -0
  297. package/src/with-database.ts +35 -23
  298. package/tsdown.config.ts +7 -2
  299. package/dist/adapters/drizzle/drizzle-connection-pool.js +0 -40
  300. package/dist/adapters/drizzle/drizzle-connection-pool.js.map +0 -1
  301. package/dist/adapters/drizzle/drizzle-query.d.ts +0 -23
  302. package/dist/adapters/drizzle/drizzle-query.d.ts.map +0 -1
  303. package/dist/adapters/drizzle/drizzle-query.js.map +0 -1
  304. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +0 -10
  305. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +0 -1
  306. package/dist/adapters/drizzle/drizzle-uow-compiler.js +0 -334
  307. package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +0 -1
  308. package/dist/adapters/drizzle/drizzle-uow-decoder.js +0 -123
  309. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +0 -1
  310. package/dist/adapters/drizzle/drizzle-uow-executor.js +0 -160
  311. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +0 -1
  312. package/dist/adapters/drizzle/join-column-utils.js +0 -28
  313. package/dist/adapters/drizzle/join-column-utils.js.map +0 -1
  314. package/dist/adapters/drizzle/shared.d.ts.map +0 -1
  315. package/dist/adapters/drizzle/shared.js +0 -35
  316. package/dist/adapters/drizzle/shared.js.map +0 -1
  317. package/dist/adapters/kysely/kysely-connection-pool.js +0 -41
  318. package/dist/adapters/kysely/kysely-connection-pool.js.map +0 -1
  319. package/dist/adapters/kysely/kysely-query-builder.js +0 -321
  320. package/dist/adapters/kysely/kysely-query-builder.js.map +0 -1
  321. package/dist/adapters/kysely/kysely-query-compiler.js +0 -67
  322. package/dist/adapters/kysely/kysely-query-compiler.js.map +0 -1
  323. package/dist/adapters/kysely/kysely-query.d.ts +0 -23
  324. package/dist/adapters/kysely/kysely-query.d.ts.map +0 -1
  325. package/dist/adapters/kysely/kysely-query.js +0 -230
  326. package/dist/adapters/kysely/kysely-query.js.map +0 -1
  327. package/dist/adapters/kysely/kysely-shared.d.ts +0 -14
  328. package/dist/adapters/kysely/kysely-shared.d.ts.map +0 -1
  329. package/dist/adapters/kysely/kysely-shared.js +0 -33
  330. package/dist/adapters/kysely/kysely-shared.js.map +0 -1
  331. package/dist/adapters/kysely/kysely-uow-compiler.js +0 -193
  332. package/dist/adapters/kysely/kysely-uow-compiler.js.map +0 -1
  333. package/dist/adapters/kysely/kysely-uow-executor.js +0 -93
  334. package/dist/adapters/kysely/kysely-uow-executor.js.map +0 -1
  335. package/dist/adapters/kysely/migration/execute-base.js +0 -128
  336. package/dist/adapters/kysely/migration/execute-base.js.map +0 -1
  337. package/dist/adapters/kysely/migration/execute-factory.js +0 -34
  338. package/dist/adapters/kysely/migration/execute-factory.js.map +0 -1
  339. package/dist/adapters/kysely/migration/execute-mssql.js +0 -112
  340. package/dist/adapters/kysely/migration/execute-mssql.js.map +0 -1
  341. package/dist/adapters/kysely/migration/execute-mysql.js +0 -93
  342. package/dist/adapters/kysely/migration/execute-mysql.js.map +0 -1
  343. package/dist/adapters/kysely/migration/execute-postgres.js +0 -104
  344. package/dist/adapters/kysely/migration/execute-postgres.js.map +0 -1
  345. package/dist/adapters/kysely/migration/execute-sqlite.js +0 -123
  346. package/dist/adapters/kysely/migration/execute-sqlite.js.map +0 -1
  347. package/dist/adapters/kysely/migration/execute.js +0 -34
  348. package/dist/adapters/kysely/migration/execute.js.map +0 -1
  349. package/dist/migration-engine/create.d.ts +0 -37
  350. package/dist/migration-engine/create.d.ts.map +0 -1
  351. package/dist/migration-engine/create.js +0 -58
  352. package/dist/migration-engine/create.js.map +0 -1
  353. package/dist/migration-engine/shared.d.ts +0 -112
  354. package/dist/migration-engine/shared.d.ts.map +0 -1
  355. package/dist/node_modules/.pnpm/rou3@0.7.8/node_modules/rou3/dist/index.js.map +0 -1
  356. package/dist/query/execute-unit-of-work.d.ts.map +0 -1
  357. package/dist/query/execute-unit-of-work.js.map +0 -1
  358. package/dist/query/query.d.ts.map +0 -1
  359. package/dist/query/result-transform.js +0 -170
  360. package/dist/query/result-transform.js.map +0 -1
  361. package/dist/query/retry-policy.d.ts.map +0 -1
  362. package/dist/query/retry-policy.js.map +0 -1
  363. package/dist/query/unit-of-work.d.ts.map +0 -1
  364. package/dist/query/unit-of-work.js.map +0 -1
  365. package/dist/schema/serialize.js +0 -111
  366. package/dist/schema/serialize.js.map +0 -1
  367. package/src/adapters/drizzle/drizzle-adapter.test.ts +0 -122
  368. package/src/adapters/drizzle/drizzle-connection-pool.ts +0 -66
  369. package/src/adapters/drizzle/drizzle-query.test.ts +0 -499
  370. package/src/adapters/drizzle/drizzle-uow-compiler-mysql.test.ts +0 -1442
  371. package/src/adapters/drizzle/drizzle-uow-compiler-sqlite.test.ts +0 -1414
  372. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +0 -1400
  373. package/src/adapters/drizzle/drizzle-uow-compiler.ts +0 -677
  374. package/src/adapters/drizzle/drizzle-uow-decoder.ts +0 -228
  375. package/src/adapters/drizzle/drizzle-uow-executor.ts +0 -309
  376. package/src/adapters/drizzle/join-column-utils.test.ts +0 -79
  377. package/src/adapters/drizzle/join-column-utils.ts +0 -39
  378. package/src/adapters/kysely/kysely-connection-pool.ts +0 -70
  379. package/src/adapters/kysely/kysely-query-builder.test.ts +0 -1344
  380. package/src/adapters/kysely/kysely-query-builder.ts +0 -666
  381. package/src/adapters/kysely/kysely-query-compiler.ts +0 -127
  382. package/src/adapters/kysely/kysely-query.test.ts +0 -498
  383. package/src/adapters/kysely/kysely-query.ts +0 -399
  384. package/src/adapters/kysely/kysely-shared.ts +0 -57
  385. package/src/adapters/kysely/kysely-uow-compiler.test.ts +0 -986
  386. package/src/adapters/kysely/kysely-uow-compiler.ts +0 -350
  387. package/src/adapters/kysely/kysely-uow-executor.ts +0 -164
  388. package/src/adapters/kysely/kysely-uow-joins.test.ts +0 -794
  389. package/src/adapters/kysely/migration/execute-base.ts +0 -256
  390. package/src/adapters/kysely/migration/execute-factory.ts +0 -53
  391. package/src/adapters/kysely/migration/execute-mssql.ts +0 -250
  392. package/src/adapters/kysely/migration/execute-mysql.ts +0 -211
  393. package/src/adapters/kysely/migration/execute-postgres.test.ts +0 -2657
  394. package/src/adapters/kysely/migration/execute-postgres.ts +0 -234
  395. package/src/adapters/kysely/migration/execute-sqlite.ts +0 -247
  396. package/src/adapters/kysely/migration/execute.ts +0 -50
  397. package/src/adapters/kysely/migration/kysely-migrator.test.ts +0 -261
  398. package/src/query/result-transform.ts +0 -274
  399. package/src/schema/serialize.ts +0 -407
  400. /package/dist/query/{query.js → simple-query-interface.js} +0 -0
  401. /package/src/query/{retry-policy.test.ts → unit-of-work/retry-policy.test.ts} +0 -0
  402. /package/src/query/{retry-policy.ts → unit-of-work/retry-policy.ts} +0 -0
@@ -0,0 +1,93 @@
1
+ import { SQLSerializer } from "../sql-serializer.js";
2
+
3
+ //#region src/query/serialize/dialect/sqlite-serializer.ts
4
+ /**
5
+ * SQLite-specific serializer.
6
+ *
7
+ * SQLite has limited native type support and requires conversions:
8
+ * - JSON → strings (no native JSON support)
9
+ * - Dates → numbers (timestamps)
10
+ * - Booleans → 0/1
11
+ * - BigInts → Buffer (except for internal-id and reference columns → number)
12
+ * - Numbers/strings → Date for timestamps/dates
13
+ */
14
+ var SQLiteSerializer = class extends SQLSerializer {
15
+ constructor(driverConfig) {
16
+ super(driverConfig);
17
+ }
18
+ serializeDate(value) {
19
+ return value.getTime();
20
+ }
21
+ serializeBoolean(value) {
22
+ return value ? 1 : 0;
23
+ }
24
+ serializeBigInt(value, col) {
25
+ if (col.role === "reference" || col.role === "internal-id") {
26
+ if (Math.abs(Number(value)) > Number.MAX_SAFE_INTEGER) throw new RangeError(`Cannot serialize bigint value ${value} for column "${col.name}": value exceeds Number.MAX_SAFE_INTEGER (${Number.MAX_SAFE_INTEGER}). SQLite reference and internal-id columns use INTEGER type which requires values to fit within JavaScript's safe integer range.`);
27
+ return Number(value);
28
+ }
29
+ const buf = Buffer.alloc(8);
30
+ buf.writeBigInt64BE(value);
31
+ return buf;
32
+ }
33
+ deserializeDate(value) {
34
+ if (value instanceof Date) return value;
35
+ if (typeof value === "number" || typeof value === "string") return new Date(value);
36
+ throw new Error(`Cannot deserialize date from value: ${value}`);
37
+ }
38
+ deserializeBoolean(value) {
39
+ if (typeof value === "boolean") return value;
40
+ if (typeof value === "number") return value === 1;
41
+ throw new Error(`Cannot deserialize boolean from value: ${value}`);
42
+ }
43
+ deserializeBigInt(value) {
44
+ if (typeof value === "bigint") return value;
45
+ if (value instanceof Buffer) return value.readBigInt64BE(0);
46
+ if (typeof value === "string") return BigInt(value);
47
+ if (typeof value === "number") return BigInt(value);
48
+ throw new Error(`Cannot deserialize bigint from value: ${value}`);
49
+ }
50
+ serializeJson(value) {
51
+ return JSON.stringify(value);
52
+ }
53
+ deserializeJson(value) {
54
+ if (typeof value !== "string") throw new Error(`Expected JSON string but got ${typeof value}`);
55
+ return JSON.parse(value);
56
+ }
57
+ deserializeBinary(value) {
58
+ if (value instanceof Buffer) return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
59
+ if (value instanceof Uint8Array) return value;
60
+ if (value instanceof ArrayBuffer) return new Uint8Array(value);
61
+ throw new Error(`Cannot deserialize binary from value: ${typeof value}`);
62
+ }
63
+ deserializeInteger(value) {
64
+ if (typeof value === "number") return value;
65
+ if (typeof value === "string") {
66
+ const num = Number(value);
67
+ if (isNaN(num)) throw new Error(`Cannot deserialize integer from invalid string: ${value}`);
68
+ return num;
69
+ }
70
+ if (typeof value === "bigint") {
71
+ if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER) throw new RangeError(`Cannot deserialize integer value ${value}: exceeds safe integer range`);
72
+ return Number(value);
73
+ }
74
+ throw new Error(`Cannot deserialize integer from value: ${typeof value}`);
75
+ }
76
+ deserializeDecimal(value) {
77
+ if (typeof value === "number") return value;
78
+ if (typeof value === "string") {
79
+ const num = parseFloat(value);
80
+ if (isNaN(num)) throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);
81
+ return num;
82
+ }
83
+ throw new Error(`Cannot deserialize decimal from value: ${typeof value}`);
84
+ }
85
+ deserializeString(value) {
86
+ if (typeof value === "string") return value;
87
+ throw new Error(`Cannot deserialize string from value: ${typeof value}`);
88
+ }
89
+ };
90
+
91
+ //#endregion
92
+ export { SQLiteSerializer };
93
+ //# sourceMappingURL=sqlite-serializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-serializer.js","names":[],"sources":["../../../../src/query/serialize/dialect/sqlite-serializer.ts"],"sourcesContent":["import type { AnyColumn } from \"../../../schema/create\";\nimport { SQLSerializer } from \"../sql-serializer\";\nimport type { DriverConfig } from \"../../../adapters/generic-sql/driver-config\";\n\n/**\n * SQLite-specific serializer.\n *\n * SQLite has limited native type support and requires conversions:\n * - JSON → strings (no native JSON support)\n * - Dates → numbers (timestamps)\n * - Booleans → 0/1\n * - BigInts → Buffer (except for internal-id and reference columns → number)\n * - Numbers/strings → Date for timestamps/dates\n */\nexport class SQLiteSerializer extends SQLSerializer {\n constructor(driverConfig: DriverConfig) {\n super(driverConfig);\n }\n\n protected serializeDate(value: Date): number {\n return value.getTime();\n }\n\n protected serializeBoolean(value: boolean): number {\n return value ? 1 : 0;\n }\n\n protected serializeBigInt(value: bigint, col: AnyColumn): number | Buffer {\n // SQLite special case: internal-id and reference columns use integer, not blob\n // These should be converted to numbers for SQLite\n if (col.role === \"reference\" || col.role === \"internal-id\") {\n // Check if the bigint is within the safe integer range to avoid precision loss\n if (Math.abs(Number(value)) > Number.MAX_SAFE_INTEGER) {\n throw new RangeError(\n `Cannot serialize bigint value ${value} for column \"${col.name}\": ` +\n `value exceeds Number.MAX_SAFE_INTEGER (${Number.MAX_SAFE_INTEGER}). ` +\n `SQLite reference and internal-id columns use INTEGER type which requires values ` +\n `to fit within JavaScript's safe integer range.`,\n );\n }\n return Number(value);\n }\n const buf = Buffer.alloc(8);\n buf.writeBigInt64BE(value);\n return buf;\n }\n\n protected deserializeDate(value: unknown): Date {\n if (value instanceof Date) {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"string\") {\n return new Date(value);\n }\n throw new Error(`Cannot deserialize date from value: ${value}`);\n }\n\n protected deserializeBoolean(value: unknown): boolean {\n if (typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"number\") {\n return value === 1;\n }\n throw new Error(`Cannot deserialize boolean from value: ${value}`);\n }\n\n protected deserializeBigInt(value: unknown): bigint {\n if (typeof value === \"bigint\") {\n return value;\n }\n if (value instanceof Buffer) {\n return value.readBigInt64BE(0);\n }\n if (typeof value === \"string\") {\n return BigInt(value);\n }\n if (typeof value === \"number\") {\n return BigInt(value);\n }\n throw new Error(`Cannot deserialize bigint from value: ${value}`);\n }\n\n protected serializeJson(value: unknown): string {\n // SQLite doesn't support native JSON, so we stringify\n return JSON.stringify(value);\n }\n\n protected deserializeJson(value: unknown): unknown {\n // SQLite stores JSON as strings, so we need to parse\n if (typeof value !== \"string\") {\n throw new Error(`Expected JSON string but got ${typeof value}`);\n }\n return JSON.parse(value);\n }\n\n protected deserializeBinary(value: unknown): Uint8Array {\n // SQLite can return Buffer or Uint8Array for BLOB columns\n if (value instanceof Buffer) {\n return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n }\n if (value instanceof Uint8Array) {\n return value;\n }\n if (value instanceof ArrayBuffer) {\n return new Uint8Array(value);\n }\n throw new Error(`Cannot deserialize binary from value: ${typeof value}`);\n }\n\n protected deserializeInteger(value: unknown): number {\n if (typeof value === \"number\") {\n return value;\n }\n // SQLite may return integers as strings for large values\n if (typeof value === \"string\") {\n const num = Number(value);\n if (isNaN(num)) {\n throw new Error(`Cannot deserialize integer from invalid string: ${value}`);\n }\n return num;\n }\n // SQLite may return bigint for large integers\n if (typeof value === \"bigint\") {\n if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER) {\n throw new RangeError(\n `Cannot deserialize integer value ${value}: exceeds safe integer range`,\n );\n }\n return Number(value);\n }\n throw new Error(`Cannot deserialize integer from value: ${typeof value}`);\n }\n\n protected deserializeDecimal(value: unknown): number {\n // SQLite stores decimals as REAL (floating point) or TEXT\n if (typeof value === \"number\") {\n return value;\n }\n if (typeof value === \"string\") {\n const num = parseFloat(value);\n if (isNaN(num)) {\n throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);\n }\n return num;\n }\n throw new Error(`Cannot deserialize decimal from value: ${typeof value}`);\n }\n\n protected deserializeString(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n throw new Error(`Cannot deserialize string from value: ${typeof value}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,IAAa,mBAAb,cAAsC,cAAc;CAClD,YAAY,cAA4B;AACtC,QAAM,aAAa;;CAGrB,AAAU,cAAc,OAAqB;AAC3C,SAAO,MAAM,SAAS;;CAGxB,AAAU,iBAAiB,OAAwB;AACjD,SAAO,QAAQ,IAAI;;CAGrB,AAAU,gBAAgB,OAAe,KAAiC;AAGxE,MAAI,IAAI,SAAS,eAAe,IAAI,SAAS,eAAe;AAE1D,OAAI,KAAK,IAAI,OAAO,MAAM,CAAC,GAAG,OAAO,iBACnC,OAAM,IAAI,WACR,iCAAiC,MAAM,eAAe,IAAI,KAAK,4CACnB,OAAO,iBAAiB,mIAGrE;AAEH,UAAO,OAAO,MAAM;;EAEtB,MAAM,MAAM,OAAO,MAAM,EAAE;AAC3B,MAAI,gBAAgB,MAAM;AAC1B,SAAO;;CAGT,AAAU,gBAAgB,OAAsB;AAC9C,MAAI,iBAAiB,KACnB,QAAO;AAET,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,SAChD,QAAO,IAAI,KAAK,MAAM;AAExB,QAAM,IAAI,MAAM,uCAAuC,QAAQ;;CAGjE,AAAU,mBAAmB,OAAyB;AACpD,MAAI,OAAO,UAAU,UACnB,QAAO;AAET,MAAI,OAAO,UAAU,SACnB,QAAO,UAAU;AAEnB,QAAM,IAAI,MAAM,0CAA0C,QAAQ;;CAGpE,AAAU,kBAAkB,OAAwB;AAClD,MAAI,OAAO,UAAU,SACnB,QAAO;AAET,MAAI,iBAAiB,OACnB,QAAO,MAAM,eAAe,EAAE;AAEhC,MAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAEtB,MAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAEtB,QAAM,IAAI,MAAM,yCAAyC,QAAQ;;CAGnE,AAAU,cAAc,OAAwB;AAE9C,SAAO,KAAK,UAAU,MAAM;;CAG9B,AAAU,gBAAgB,OAAyB;AAEjD,MAAI,OAAO,UAAU,SACnB,OAAM,IAAI,MAAM,gCAAgC,OAAO,QAAQ;AAEjE,SAAO,KAAK,MAAM,MAAM;;CAG1B,AAAU,kBAAkB,OAA4B;AAEtD,MAAI,iBAAiB,OACnB,QAAO,IAAI,WAAW,MAAM,QAAQ,MAAM,YAAY,MAAM,WAAW;AAEzE,MAAI,iBAAiB,WACnB,QAAO;AAET,MAAI,iBAAiB,YACnB,QAAO,IAAI,WAAW,MAAM;AAE9B,QAAM,IAAI,MAAM,yCAAyC,OAAO,QAAQ;;CAG1E,AAAU,mBAAmB,OAAwB;AACnD,MAAI,OAAO,UAAU,SACnB,QAAO;AAGT,MAAI,OAAO,UAAU,UAAU;GAC7B,MAAM,MAAM,OAAO,MAAM;AACzB,OAAI,MAAM,IAAI,CACZ,OAAM,IAAI,MAAM,mDAAmD,QAAQ;AAE7E,UAAO;;AAGT,MAAI,OAAO,UAAU,UAAU;AAC7B,OAAI,QAAQ,OAAO,oBAAoB,QAAQ,OAAO,iBACpD,OAAM,IAAI,WACR,oCAAoC,MAAM,8BAC3C;AAEH,UAAO,OAAO,MAAM;;AAEtB,QAAM,IAAI,MAAM,0CAA0C,OAAO,QAAQ;;CAG3E,AAAU,mBAAmB,OAAwB;AAEnD,MAAI,OAAO,UAAU,SACnB,QAAO;AAET,MAAI,OAAO,UAAU,UAAU;GAC7B,MAAM,MAAM,WAAW,MAAM;AAC7B,OAAI,MAAM,IAAI,CACZ,OAAM,IAAI,MAAM,mDAAmD,QAAQ;AAE7E,UAAO;;AAET,QAAM,IAAI,MAAM,0CAA0C,OAAO,QAAQ;;CAG3E,AAAU,kBAAkB,OAAwB;AAClD,MAAI,OAAO,UAAU,SACnB,QAAO;AAET,QAAM,IAAI,MAAM,yCAAyC,OAAO,QAAQ"}
@@ -0,0 +1,67 @@
1
+ //#region src/query/serialize/sql-serializer.ts
2
+ /**
3
+ * Abstract base class for SQL value serialization/deserialization.
4
+ *
5
+ * Similar to SQLTypeMapper, this class provides a framework for converting values
6
+ * between application format and database format. Each database dialect extends
7
+ * this class and implements abstract methods for dialect-specific conversions.
8
+ *
9
+ * Handles:
10
+ * - Type conversions (Date, boolean, BigInt, etc.)
11
+ * - JSON handling (delegated to dialect-specific implementations)
12
+ * - Binary data conversion (Uint8Array ↔ Buffer)
13
+ */
14
+ var SQLSerializer = class {
15
+ driverConfig;
16
+ constructor(driverConfig) {
17
+ this.driverConfig = driverConfig;
18
+ }
19
+ /**
20
+ * Deserialize a value from database format to application format.
21
+ *
22
+ * @param value - The raw database value
23
+ * @param col - The column schema definition
24
+ * @returns The deserialized value in application format
25
+ * @throws Error if value cannot be deserialized to the expected type
26
+ */
27
+ deserialize(value, col) {
28
+ if (value === null) return null;
29
+ if (col.type === "json") return this.deserializeJson(value);
30
+ if (col.type === "timestamp" || col.type === "date") return this.deserializeDate(value);
31
+ if (col.type === "bool") return this.deserializeBoolean(value);
32
+ if (col.type === "bigint") return this.deserializeBigInt(value);
33
+ if (col.type === "binary") return this.deserializeBinary(value);
34
+ if (col.type === "integer") return this.deserializeInteger(value);
35
+ if (col.type === "decimal") return this.deserializeDecimal(value);
36
+ if (col.type === "string" || typeof col.type === "string" && col.type.startsWith("varchar")) return this.deserializeString(value);
37
+ throw new Error(`Unsupported column type for deserialization: ${col.type}`);
38
+ }
39
+ /**
40
+ * Serialize a value from application format to database format.
41
+ *
42
+ * Note: This method expects FragnoId/FragnoReference objects to be resolved
43
+ * to primitive values before calling. Use resolveFragnoIdValue() from
44
+ * value-encoding.ts for this purpose.
45
+ *
46
+ * @param value - The application value to serialize (should not be FragnoId/FragnoReference)
47
+ * @param col - The column schema definition
48
+ * @param skipDriverConversions - Skip driver-level type conversions (Date->number, boolean->0/1, bigint->Buffer).
49
+ * Set to true when using ORMs like Drizzle that handle these conversions internally.
50
+ * @returns The serialized value in database format
51
+ */
52
+ serialize(value, col, skipDriverConversions = false) {
53
+ if (value === null) return null;
54
+ if (col.type === "json") return this.serializeJson(value);
55
+ if (!skipDriverConversions) {
56
+ if (value instanceof Date) return this.serializeDate(value);
57
+ if (typeof value === "boolean") return this.serializeBoolean(value);
58
+ if (typeof value === "bigint") return this.serializeBigInt(value, col);
59
+ }
60
+ if (col.type === "binary" && value instanceof Uint8Array) return Buffer.from(value);
61
+ return value;
62
+ }
63
+ };
64
+
65
+ //#endregion
66
+ export { SQLSerializer };
67
+ //# sourceMappingURL=sql-serializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-serializer.js","names":[],"sources":["../../../src/query/serialize/sql-serializer.ts"],"sourcesContent":["import type { DriverConfig } from \"../../adapters/generic-sql/driver-config\";\nimport type { AnyColumn } from \"../../schema/create\";\n\n/**\n * Abstract base class for SQL value serialization/deserialization.\n *\n * Similar to SQLTypeMapper, this class provides a framework for converting values\n * between application format and database format. Each database dialect extends\n * this class and implements abstract methods for dialect-specific conversions.\n *\n * Handles:\n * - Type conversions (Date, boolean, BigInt, etc.)\n * - JSON handling (delegated to dialect-specific implementations)\n * - Binary data conversion (Uint8Array ↔ Buffer)\n */\nexport abstract class SQLSerializer {\n protected readonly driverConfig: DriverConfig;\n\n constructor(driverConfig: DriverConfig) {\n this.driverConfig = driverConfig;\n }\n\n /**\n * Deserialize a value from database format to application format.\n *\n * @param value - The raw database value\n * @param col - The column schema definition\n * @returns The deserialized value in application format\n * @throws Error if value cannot be deserialized to the expected type\n */\n deserialize(value: unknown, col: AnyColumn): unknown {\n if (value === null) {\n return null;\n }\n\n // Handle JSON deserialization (delegated to subclass)\n if (col.type === \"json\") {\n return this.deserializeJson(value);\n }\n\n // Handle date/timestamp deserialization\n if (col.type === \"timestamp\" || col.type === \"date\") {\n return this.deserializeDate(value);\n }\n\n // Handle boolean deserialization\n if (col.type === \"bool\") {\n return this.deserializeBoolean(value);\n }\n\n // Handle bigint deserialization\n if (col.type === \"bigint\") {\n return this.deserializeBigInt(value);\n }\n\n // Handle binary deserialization (delegated to subclass for driver flexibility)\n if (col.type === \"binary\") {\n return this.deserializeBinary(value);\n }\n\n // Handle integer deserialization (delegated to subclass - drivers may return string/bigint)\n if (col.type === \"integer\") {\n return this.deserializeInteger(value);\n }\n\n // Handle decimal deserialization (delegated to subclass for driver flexibility)\n if (col.type === \"decimal\") {\n return this.deserializeDecimal(value);\n }\n\n // Handle string/varchar deserialization (delegated to subclass for consistency)\n if (col.type === \"string\" || (typeof col.type === \"string\" && col.type.startsWith(\"varchar\"))) {\n return this.deserializeString(value);\n }\n\n throw new Error(`Unsupported column type for deserialization: ${col.type}`);\n }\n\n /**\n * Serialize a value from application format to database format.\n *\n * Note: This method expects FragnoId/FragnoReference objects to be resolved\n * to primitive values before calling. Use resolveFragnoIdValue() from\n * value-encoding.ts for this purpose.\n *\n * @param value - The application value to serialize (should not be FragnoId/FragnoReference)\n * @param col - The column schema definition\n * @param skipDriverConversions - Skip driver-level type conversions (Date->number, boolean->0/1, bigint->Buffer).\n * Set to true when using ORMs like Drizzle that handle these conversions internally.\n * @returns The serialized value in database format\n */\n serialize(value: unknown, col: AnyColumn, skipDriverConversions = false): unknown {\n if (value === null) {\n return null;\n }\n\n // Handle JSON serialization (delegated to subclass)\n if (col.type === \"json\") {\n return this.serializeJson(value);\n }\n\n // Skip driver-specific type conversions when using ORMs that handle them internally\n if (!skipDriverConversions) {\n // Handle date/timestamp serialization\n if (value instanceof Date) {\n return this.serializeDate(value);\n }\n\n // Handle boolean serialization\n if (typeof value === \"boolean\") {\n return this.serializeBoolean(value);\n }\n\n // Handle bigint serialization\n if (typeof value === \"bigint\") {\n return this.serializeBigInt(value, col);\n }\n }\n\n // Handle binary serialization (most drivers accept Buffer)\n if (col.type === \"binary\" && value instanceof Uint8Array) {\n return Buffer.from(value);\n }\n\n return value;\n }\n\n // Abstract methods for dialect-specific serialization\n protected abstract serializeDate(value: Date): Date | number;\n protected abstract serializeBoolean(value: boolean): boolean | number;\n protected abstract serializeBigInt(value: bigint, col: AnyColumn): bigint | number | Buffer;\n protected abstract serializeJson(value: unknown): unknown;\n\n // Abstract methods for dialect-specific deserialization\n protected abstract deserializeDate(value: unknown): Date;\n protected abstract deserializeBoolean(value: unknown): boolean;\n protected abstract deserializeBigInt(value: unknown): bigint;\n protected abstract deserializeJson(value: unknown): unknown;\n protected abstract deserializeBinary(value: unknown): Uint8Array;\n protected abstract deserializeInteger(value: unknown): number;\n protected abstract deserializeDecimal(value: unknown): number;\n protected abstract deserializeString(value: unknown): string;\n}\n"],"mappings":";;;;;;;;;;;;;AAeA,IAAsB,gBAAtB,MAAoC;CAClC,AAAmB;CAEnB,YAAY,cAA4B;AACtC,OAAK,eAAe;;;;;;;;;;CAWtB,YAAY,OAAgB,KAAyB;AACnD,MAAI,UAAU,KACZ,QAAO;AAIT,MAAI,IAAI,SAAS,OACf,QAAO,KAAK,gBAAgB,MAAM;AAIpC,MAAI,IAAI,SAAS,eAAe,IAAI,SAAS,OAC3C,QAAO,KAAK,gBAAgB,MAAM;AAIpC,MAAI,IAAI,SAAS,OACf,QAAO,KAAK,mBAAmB,MAAM;AAIvC,MAAI,IAAI,SAAS,SACf,QAAO,KAAK,kBAAkB,MAAM;AAItC,MAAI,IAAI,SAAS,SACf,QAAO,KAAK,kBAAkB,MAAM;AAItC,MAAI,IAAI,SAAS,UACf,QAAO,KAAK,mBAAmB,MAAM;AAIvC,MAAI,IAAI,SAAS,UACf,QAAO,KAAK,mBAAmB,MAAM;AAIvC,MAAI,IAAI,SAAS,YAAa,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,WAAW,UAAU,CAC1F,QAAO,KAAK,kBAAkB,MAAM;AAGtC,QAAM,IAAI,MAAM,gDAAgD,IAAI,OAAO;;;;;;;;;;;;;;;CAgB7E,UAAU,OAAgB,KAAgB,wBAAwB,OAAgB;AAChF,MAAI,UAAU,KACZ,QAAO;AAIT,MAAI,IAAI,SAAS,OACf,QAAO,KAAK,cAAc,MAAM;AAIlC,MAAI,CAAC,uBAAuB;AAE1B,OAAI,iBAAiB,KACnB,QAAO,KAAK,cAAc,MAAM;AAIlC,OAAI,OAAO,UAAU,UACnB,QAAO,KAAK,iBAAiB,MAAM;AAIrC,OAAI,OAAO,UAAU,SACnB,QAAO,KAAK,gBAAgB,OAAO,IAAI;;AAK3C,MAAI,IAAI,SAAS,YAAY,iBAAiB,WAC5C,QAAO,OAAO,KAAK,MAAM;AAG3B,SAAO"}
@@ -2,9 +2,9 @@ import { AnySchema, AnyTable, FragnoId, IdColumn, Relation } from "../schema/cre
2
2
  import { Condition, ConditionBuilder } from "./condition-builder.js";
3
3
  import { CursorResult } from "./cursor.js";
4
4
  import { Prettify } from "../util/types.js";
5
- import { DeleteBuilder, FindBuilder, TypedUnitOfWork, UpdateBuilder, UpdateManyBuilder } from "./unit-of-work.js";
5
+ import { DeleteBuilder, FindBuilder, TypedUnitOfWork, UpdateBuilder, UpdateManyBuilder } from "./unit-of-work/unit-of-work.js";
6
6
 
7
- //#region src/query/query.d.ts
7
+ //#region src/query/simple-query-interface.d.ts
8
8
  type AnySelectClause = SelectClause<AnyTable>;
9
9
  type SelectClause<T extends AnyTable> = true | (keyof T["columns"])[];
10
10
  type RawColumnValues<T extends AnyTable> = { [K in keyof T["columns"] as string extends K ? never : K]: T["columns"][K]["$out"] };
@@ -42,7 +42,7 @@ type FindManyOptions<T extends AnyTable = AnyTable, Select extends SelectClause<
42
42
  } & (IsRoot extends true ? {
43
43
  offset?: number;
44
44
  } : {});
45
- interface AbstractQuery<TSchema extends AnySchema, TUOWConfig = void> {
45
+ interface SimpleQueryInterface<TSchema extends AnySchema, TUOWConfig = void> {
46
46
  /**
47
47
  * Find multiple records using a builder pattern
48
48
  */
@@ -96,5 +96,5 @@ interface AbstractQuery<TSchema extends AnySchema, TUOWConfig = void> {
96
96
  createUnitOfWork: (name?: string, config?: TUOWConfig) => TypedUnitOfWork<TSchema, [], unknown>;
97
97
  }
98
98
  //#endregion
99
- export { AbstractQuery, AnySelectClause, ExtractJoinOut, ExtractSelect, FindFirstOptions, FindManyOptions, JoinBuilder, OrderBy, RawColumnValues, SelectClause, SelectResult, TableToColumnValues, TableToInsertValues, TableToUpdateValues };
100
- //# sourceMappingURL=query.d.ts.map
99
+ export { AnySelectClause, ExtractJoinOut, ExtractSelect, FindFirstOptions, FindManyOptions, JoinBuilder, OrderBy, RawColumnValues, SelectClause, SelectResult, SimpleQueryInterface, TableToColumnValues, TableToInsertValues, TableToUpdateValues };
100
+ //# sourceMappingURL=simple-query-interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simple-query-interface.d.ts","names":[],"sources":["../../src/query/simple-query-interface.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
- import { AnySchema, FragnoId } from "../schema/create.js";
2
- import { IUnitOfWork, TypedUnitOfWork } from "./unit-of-work.js";
1
+ import { AnySchema, FragnoId } from "../../schema/create.js";
3
2
  import { RetryPolicy } from "./retry-policy.js";
3
+ import { HooksMap } from "../../hooks/hooks.js";
4
+ import { IUnitOfWork, TypedUnitOfWork } from "./unit-of-work.js";
4
5
 
5
- //#region src/query/execute-unit-of-work.d.ts
6
+ //#region src/query/unit-of-work/execute-unit-of-work.d.ts
6
7
 
7
8
  /**
8
9
  * Type utility that unwraps promises 1 level deep in objects, arrays, or direct promises
@@ -117,7 +118,52 @@ interface ExecuteRestrictedUnitOfWorkOptions {
117
118
  * Abort signal to cancel execution
118
119
  */
119
120
  signal?: AbortSignal;
121
+ /**
122
+ * Callback invoked before mutations are executed.
123
+ * Use this to add additional mutation operations (e.g., hook event records).
124
+ */
125
+ onBeforeMutate?: (uow: IUnitOfWork) => void;
126
+ /**
127
+ * Callback invoked after successful mutation phase.
128
+ * Use this for post-mutation processing like hook execution.
129
+ */
130
+ onSuccess?: (uow: IUnitOfWork) => Promise<void>;
131
+ }
132
+ /**
133
+ * Context provided to handler tx callbacks
134
+ */
135
+ interface TxPhaseContext<THooks extends HooksMap> {
136
+ /**
137
+ * Get a typed Unit of Work for the given schema
138
+ */
139
+ forSchema: <S extends AnySchema, H extends HooksMap = THooks>(schema: S, hooks?: H) => TypedUnitOfWork<S, [], unknown, H>;
140
+ }
141
+ /**
142
+ * Handler callbacks for tx() - SYNCHRONOUS ONLY (no Promise return allowed)
143
+ * This prevents accidentally awaiting services in the wrong place
144
+ */
145
+ interface HandlerTxCallbacks<TRetrieveResult, TMutationResult, THooks extends HooksMap> {
146
+ /**
147
+ * Retrieval phase callback - schedules retrievals and optionally calls services
148
+ * Must be synchronous - cannot await promises
149
+ */
150
+ retrieve?: (context: TxPhaseContext<THooks>) => TRetrieveResult;
151
+ /**
152
+ * Mutation phase callback - receives retrieve result, schedules mutations
153
+ * Must be synchronous - cannot await promises (but may return a promise to be awaited)
154
+ */
155
+ mutate?: (context: TxPhaseContext<THooks>, retrieveResult: TRetrieveResult) => TMutationResult;
156
+ }
157
+ interface ServiceTxCallbacks<TSchema extends AnySchema, TRetrievalResults extends unknown[], TMutationResult, THooks extends HooksMap> {
158
+ /**
159
+ * Retrieval phase callback - schedules retrievals, returns typed UOW
160
+ */
161
+ retrieve?: (uow: TypedUnitOfWork<TSchema, [], unknown, THooks>) => TypedUnitOfWork<TSchema, TRetrievalResults, unknown, THooks>;
162
+ /**
163
+ * Mutation phase callback - receives retrieval results, schedules mutations and hooks
164
+ */
165
+ mutate?: (uow: TypedUnitOfWork<TSchema, TRetrievalResults, unknown, THooks>, results: TRetrievalResults) => TMutationResult | Promise<TMutationResult>;
120
166
  }
121
167
  //#endregion
122
- export { AwaitedPromisesInObject, ExecuteRestrictedUnitOfWorkOptions, ExecuteUnitOfWorkCallbacks, ExecuteUnitOfWorkOptions, ExecuteUnitOfWorkResult, executeUnitOfWork };
168
+ export { AwaitedPromisesInObject, ExecuteRestrictedUnitOfWorkOptions, ExecuteUnitOfWorkCallbacks, ExecuteUnitOfWorkOptions, ExecuteUnitOfWorkResult, HandlerTxCallbacks, ServiceTxCallbacks, executeUnitOfWork };
123
169
  //# sourceMappingURL=execute-unit-of-work.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute-unit-of-work.d.ts","names":[],"sources":["../../../src/query/unit-of-work/execute-unit-of-work.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1,6 +1,16 @@
1
1
  import { ExponentialBackoffRetryPolicy, NoRetryPolicy } from "./retry-policy.js";
2
2
 
3
- //#region src/query/execute-unit-of-work.ts
3
+ //#region src/query/unit-of-work/execute-unit-of-work.ts
4
+ /**
5
+ * Error thrown when a Unit of Work execution fails due to optimistic concurrency conflict.
6
+ * This error triggers automatic retry behavior in executeRestrictedUnitOfWork.
7
+ */
8
+ var ConcurrencyConflictError = class extends Error {
9
+ constructor(message = "Optimistic concurrency conflict detected") {
10
+ super(message);
11
+ this.name = "ConcurrencyConflictError";
12
+ }
13
+ };
4
14
  /**
5
15
  * Await promises in an object 1 level deep
6
16
  */
@@ -152,8 +162,8 @@ async function executeRestrictedUnitOfWork(callback, options) {
152
162
  try {
153
163
  const baseUow = options.createUnitOfWork();
154
164
  return await awaitPromisesInObject(await callback({
155
- forSchema: (schema) => {
156
- return baseUow.forSchema(schema);
165
+ forSchema: (schema, hooks) => {
166
+ return baseUow.forSchema(schema, hooks);
157
167
  },
158
168
  executeRetrieve: async () => {
159
169
  await baseUow.executeRetrieve();
@@ -161,13 +171,66 @@ async function executeRestrictedUnitOfWork(callback, options) {
161
171
  executeMutate: async () => {
162
172
  if (baseUow.state === "executed") return;
163
173
  if (baseUow.state === "building-retrieval") await baseUow.executeRetrieve();
164
- if (!(await baseUow.executeMutations()).success) throw new Error("Mutations failed due to conflict");
174
+ if (options.onBeforeMutate) options.onBeforeMutate(baseUow);
175
+ if (!(await baseUow.executeMutations()).success) throw new ConcurrencyConflictError();
176
+ if (options.onSuccess) await options.onSuccess(baseUow);
165
177
  },
166
178
  nonce: baseUow.nonce,
167
179
  currentAttempt: attempt
168
180
  }));
169
181
  } catch (error) {
170
182
  if (signal?.aborted) throw new Error("Unit of Work execution aborted");
183
+ if (!(error instanceof ConcurrencyConflictError)) throw error;
184
+ if (!retryPolicy.shouldRetry(attempt, error, signal)) {
185
+ if (signal?.aborted) throw new Error("Unit of Work execution aborted");
186
+ throw new Error("Unit of Work execution failed: optimistic concurrency conflict", { cause: error });
187
+ }
188
+ const delayMs = retryPolicy.getDelayMs(attempt);
189
+ if (delayMs > 0) await new Promise((resolve) => setTimeout(resolve, delayMs));
190
+ attempt++;
191
+ }
192
+ }
193
+ }
194
+ /**
195
+ * Execute a transaction with array syntax (handler context).
196
+ * Takes a factory function that creates an array of service promises, enabling proper retry support.
197
+ *
198
+ * @param servicesFactory - Function that creates an array of service promises
199
+ * @param options - Configuration including UOW factory, retry policy, and abort signal
200
+ * @returns Promise resolving to array of awaited service results
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * const [result1, result2] = await executeTxArray(
205
+ * () => [
206
+ * executeServiceTx(schema, callbacks1, uow),
207
+ * executeServiceTx(schema, callbacks2, uow)
208
+ * ],
209
+ * { createUnitOfWork }
210
+ * );
211
+ * ```
212
+ */
213
+ async function executeTxArray(servicesFactory, options) {
214
+ const retryPolicy = options.retryPolicy ?? new ExponentialBackoffRetryPolicy({
215
+ maxRetries: 5,
216
+ initialDelayMs: 10,
217
+ maxDelayMs: 100
218
+ });
219
+ const signal = options.signal;
220
+ let attempt = 0;
221
+ while (true) {
222
+ if (signal?.aborted) throw new Error("Unit of Work execution aborted");
223
+ try {
224
+ const baseUow = options.createUnitOfWork();
225
+ const services = servicesFactory();
226
+ await baseUow.executeRetrieve();
227
+ if (options.onBeforeMutate) options.onBeforeMutate(baseUow);
228
+ if (!(await baseUow.executeMutations()).success) throw new ConcurrencyConflictError();
229
+ if (options.onSuccess) await options.onSuccess(baseUow);
230
+ return await Promise.all(services);
231
+ } catch (error) {
232
+ if (signal?.aborted) throw new Error("Unit of Work execution aborted");
233
+ if (!(error instanceof ConcurrencyConflictError)) throw error;
171
234
  if (!retryPolicy.shouldRetry(attempt, error, signal)) {
172
235
  if (signal?.aborted) throw new Error("Unit of Work execution aborted");
173
236
  throw new Error("Unit of Work execution failed: optimistic concurrency conflict", { cause: error });
@@ -178,7 +241,89 @@ async function executeRestrictedUnitOfWork(callback, options) {
178
241
  }
179
242
  }
180
243
  }
244
+ /**
245
+ * Execute a transaction with callback syntax (handler context).
246
+ * Callbacks are synchronous only to prevent accidentally awaiting services in wrong place.
247
+ *
248
+ * @param callbacks - Object containing retrieve and mutate callbacks
249
+ * @param options - Configuration including UOW factory, retry policy, and abort signal
250
+ * @returns Promise resolving to the mutation result with promises awaited 1 level deep
251
+ */
252
+ async function executeTxCallbacks(callbacks, options) {
253
+ const retryPolicy = options.retryPolicy ?? new ExponentialBackoffRetryPolicy({
254
+ maxRetries: 5,
255
+ initialDelayMs: 10,
256
+ maxDelayMs: 100
257
+ });
258
+ const signal = options.signal;
259
+ let attempt = 0;
260
+ while (true) {
261
+ if (signal?.aborted) throw new Error("Unit of Work execution aborted");
262
+ try {
263
+ const baseUow = options.createUnitOfWork();
264
+ const context = { forSchema: (schema, hooks) => {
265
+ return baseUow.forSchema(schema, hooks);
266
+ } };
267
+ let retrieveResult;
268
+ if (callbacks.retrieve) retrieveResult = callbacks.retrieve(context);
269
+ else retrieveResult = void 0;
270
+ await baseUow.executeRetrieve();
271
+ let mutationResult;
272
+ if (callbacks.mutate) mutationResult = callbacks.mutate(context, retrieveResult);
273
+ else mutationResult = retrieveResult;
274
+ const awaitedMutationResult = await awaitPromisesInObject(mutationResult);
275
+ if (options.onBeforeMutate) options.onBeforeMutate(baseUow);
276
+ if (!(await baseUow.executeMutations()).success) throw new ConcurrencyConflictError();
277
+ if (options.onSuccess) await options.onSuccess(baseUow);
278
+ return awaitedMutationResult;
279
+ } catch (error) {
280
+ if (signal?.aborted) throw new Error("Unit of Work execution aborted");
281
+ if (!(error instanceof ConcurrencyConflictError)) throw error;
282
+ if (!retryPolicy.shouldRetry(attempt, error, signal)) {
283
+ if (signal?.aborted) throw new Error("Unit of Work execution aborted");
284
+ throw new Error("Unit of Work execution failed: optimistic concurrency conflict", { cause: error });
285
+ }
286
+ const delayMs = retryPolicy.getDelayMs(attempt);
287
+ if (delayMs > 0) await new Promise((resolve) => setTimeout(resolve, delayMs));
288
+ attempt++;
289
+ }
290
+ }
291
+ }
292
+ /**
293
+ * Execute a transaction for service context.
294
+ * Service callbacks can be async for ergonomic async work.
295
+ *
296
+ * @param schema - Schema to use for the transaction
297
+ * @param callbacks - Object containing retrieve and mutate callbacks
298
+ * @param baseUow - Base Unit of Work (restricted) to use
299
+ * @returns Promise resolving to the mutation result with promises awaited 1 level deep
300
+ */
301
+ async function executeServiceTx(schema, callbacks, baseUow) {
302
+ const typedUow = baseUow.restrict({ readyFor: "none" }).forSchema(schema);
303
+ let retrievalUow;
304
+ try {
305
+ if (callbacks.retrieve) retrievalUow = callbacks.retrieve(typedUow);
306
+ else retrievalUow = typedUow;
307
+ } catch (error) {
308
+ typedUow.signalReadyForRetrieval();
309
+ typedUow.signalReadyForMutation();
310
+ throw error;
311
+ }
312
+ typedUow.signalReadyForRetrieval();
313
+ const results = await retrievalUow.retrievalPhase;
314
+ let mutationResult;
315
+ try {
316
+ if (callbacks.mutate) mutationResult = await callbacks.mutate(retrievalUow, results);
317
+ else mutationResult = void 0;
318
+ } catch (error) {
319
+ typedUow.signalReadyForMutation();
320
+ throw error;
321
+ }
322
+ typedUow.signalReadyForMutation();
323
+ await retrievalUow.mutationPhase;
324
+ return await awaitPromisesInObject(mutationResult);
325
+ }
181
326
 
182
327
  //#endregion
183
- export { executeRestrictedUnitOfWork, executeUnitOfWork };
328
+ export { executeRestrictedUnitOfWork, executeServiceTx, executeTxArray, executeTxCallbacks, executeUnitOfWork };
184
329
  //# sourceMappingURL=execute-unit-of-work.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute-unit-of-work.js","names":["retrievalUow: TypedUnitOfWork<TSchema, TRetrievalResults, TRawInput>","mutationResult: TMutationResult","context: TxPhaseContext<THooks>","retrieveResult: TRetrieveResult","retrievalUow: TypedUnitOfWork<TSchema, TRetrievalResults, unknown, THooks>"],"sources":["../../../src/query/unit-of-work/execute-unit-of-work.ts"],"sourcesContent":["import type { AnySchema } from \"../../schema/create\";\nimport type { TypedUnitOfWork, IUnitOfWork } from \"./unit-of-work\";\nimport type { HooksMap } from \"../../hooks/hooks\";\nimport { NoRetryPolicy, ExponentialBackoffRetryPolicy, type RetryPolicy } from \"./retry-policy\";\nimport type { FragnoId } from \"../../schema/create\";\n\n/**\n * Error thrown when a Unit of Work execution fails due to optimistic concurrency conflict.\n * This error triggers automatic retry behavior in executeRestrictedUnitOfWork.\n */\nexport class ConcurrencyConflictError extends Error {\n constructor(message = \"Optimistic concurrency conflict detected\") {\n super(message);\n this.name = \"ConcurrencyConflictError\";\n }\n}\n\n/**\n * Type utility that unwraps promises 1 level deep in objects, arrays, or direct promises\n * Handles tuples, arrays, objects, and direct promises\n */\nexport type AwaitedPromisesInObject<T> =\n // First check if it's a Promise\n T extends Promise<infer U>\n ? Awaited<U>\n : // Check for arrays with known length (tuples) - preserves tuple structure\n T extends readonly [unknown, ...unknown[]]\n ? { [K in keyof T]: AwaitedPromisesInObject<T[K]> }\n : T extends [unknown, ...unknown[]]\n ? { [K in keyof T]: AwaitedPromisesInObject<T[K]> }\n : // Check for regular arrays (unknown length)\n T extends (infer U)[]\n ? Awaited<U>[]\n : T extends readonly (infer U)[]\n ? readonly Awaited<U>[]\n : // Check for objects\n T extends Record<string, unknown>\n ? {\n [K in keyof T]: T[K] extends Promise<infer U> ? Awaited<U> : T[K];\n }\n : // Otherwise return as-is\n T;\n\n/**\n * Await promises in an object 1 level deep\n */\nasync function awaitPromisesInObject<T>(obj: T): Promise<AwaitedPromisesInObject<T>> {\n if (obj === null || obj === undefined) {\n return obj as AwaitedPromisesInObject<T>;\n }\n\n if (typeof obj !== \"object\") {\n return obj as AwaitedPromisesInObject<T>;\n }\n\n // Check if it's a Promise\n if (obj instanceof Promise) {\n return (await obj) as AwaitedPromisesInObject<T>;\n }\n\n // Check if it's an array\n if (Array.isArray(obj)) {\n const awaited = await Promise.all(\n obj.map((item) => (item instanceof Promise ? item : Promise.resolve(item))),\n );\n return awaited as AwaitedPromisesInObject<T>;\n }\n\n // It's a plain object - await promises in each property\n const result = {} as T;\n const entries = Object.entries(obj as Record<string, unknown>);\n const awaitedEntries = await Promise.all(\n entries.map(async ([key, value]) => {\n const awaitedValue = value instanceof Promise ? await value : value;\n return [key, awaitedValue] as const;\n }),\n );\n\n for (const [key, value] of awaitedEntries) {\n (result as Record<string, unknown>)[key] = value;\n }\n\n return result as AwaitedPromisesInObject<T>;\n}\n\n/**\n * Result of executing a Unit of Work with retry support\n * Promises in mutationResult are unwrapped 1 level deep\n */\nexport type ExecuteUnitOfWorkResult<TRetrievalResults, TMutationResult> =\n | {\n success: true;\n results: TRetrievalResults;\n mutationResult: AwaitedPromisesInObject<TMutationResult>;\n createdIds: FragnoId[];\n nonce: string;\n }\n | {\n success: false;\n reason: \"conflict\";\n }\n | {\n success: false;\n reason: \"aborted\";\n }\n | {\n success: false;\n reason: \"error\";\n error: unknown;\n };\n\n/**\n * Callbacks for executing a Unit of Work\n */\nexport interface ExecuteUnitOfWorkCallbacks<\n TSchema extends AnySchema,\n TRetrievalResults extends unknown[],\n TMutationResult,\n TRawInput,\n> {\n /**\n * Retrieval phase callback - adds retrieval operations to the UOW\n */\n retrieve?: (\n uow: TypedUnitOfWork<TSchema, [], TRawInput>,\n ) => TypedUnitOfWork<TSchema, TRetrievalResults, TRawInput>;\n\n /**\n * Mutation phase callback - receives UOW and retrieval results, adds mutation operations\n */\n mutate?: (\n uow: TypedUnitOfWork<TSchema, TRetrievalResults, TRawInput>,\n results: TRetrievalResults,\n ) => TMutationResult | Promise<TMutationResult>;\n\n /**\n * Success callback - invoked after successful execution\n * Promises in mutationResult are already unwrapped 1 level deep\n */\n onSuccess?: (result: {\n results: TRetrievalResults;\n mutationResult: AwaitedPromisesInObject<TMutationResult>;\n createdIds: FragnoId[];\n nonce: string;\n }) => void | Promise<void>;\n}\n\n/**\n * Options for executing a Unit of Work\n */\nexport interface ExecuteUnitOfWorkOptions<TSchema extends AnySchema, TRawInput> {\n /**\n * Factory function that creates or resets a UOW instance for each attempt\n */\n createUnitOfWork: () => TypedUnitOfWork<TSchema, [], TRawInput>;\n\n /**\n * Retry policy for handling optimistic concurrency conflicts\n */\n retryPolicy?: RetryPolicy;\n\n /**\n * Abort signal to cancel execution\n */\n signal?: AbortSignal;\n}\n\n/**\n * Create a bound version of executeUnitOfWork with a pre-configured UOW factory.\n * This is useful for handler contexts where the factory is already known.\n *\n * @param createUnitOfWork - Factory function that creates a fresh UOW instance\n * @returns A bound executeUnitOfWork function that doesn't require the factory parameter\n *\n * @example\n * ```ts\n * const boundExecute = createExecuteUnitOfWork(() => db.createUnitOfWork());\n * const result = await boundExecute({\n * retrieve: (uow) => uow.find(\"users\", (b) => b.whereIndex(\"primary\")),\n * mutate: (uow, [users]) => {\n * uow.update(\"users\", users[0].id, (b) => b.set({ balance: newBalance }));\n * }\n * });\n * ```\n */\nexport function createExecuteUnitOfWork<TSchema extends AnySchema, TRawInput>(\n createUnitOfWork: () => TypedUnitOfWork<TSchema, [], TRawInput>,\n) {\n return async function <TRetrievalResults extends unknown[], TMutationResult = void>(\n callbacks: ExecuteUnitOfWorkCallbacks<TSchema, TRetrievalResults, TMutationResult, TRawInput>,\n options?: Omit<ExecuteUnitOfWorkOptions<TSchema, TRawInput>, \"createUnitOfWork\">,\n ): Promise<ExecuteUnitOfWorkResult<TRetrievalResults, TMutationResult>> {\n return executeUnitOfWork(callbacks, { ...options, createUnitOfWork });\n };\n}\n\n/**\n * Execute a Unit of Work with automatic retry support for optimistic concurrency conflicts.\n *\n * This function orchestrates the two-phase execution (retrieval + mutation) with retry logic.\n * It creates fresh UOW instances for each attempt.\n *\n * @param callbacks - Object containing retrieve, mutate, and onSuccess callbacks\n * @param options - Configuration including UOW factory, retry policy, and abort signal\n * @returns Promise resolving to the execution result\n *\n * @example\n * ```ts\n * const result = await executeUnitOfWork(\n * {\n * retrieve: (uow) => uow.find(\"users\", (b) => b.whereIndex(\"primary\")),\n * mutate: (uow, [users]) => {\n * const user = users[0];\n * uow.update(\"users\", user.id, (b) => b.set({ balance: newBalance }));\n * },\n * onSuccess: async ({ results, mutationResult }) => {\n * console.log(\"Update successful!\");\n * }\n * },\n * {\n * createUnitOfWork: () => queryEngine.createUnitOfWork(),\n * retryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 })\n * }\n * );\n * ```\n */\nexport async function executeUnitOfWork<\n TSchema extends AnySchema,\n TRetrievalResults extends unknown[],\n TMutationResult = void,\n TRawInput = unknown,\n>(\n callbacks: ExecuteUnitOfWorkCallbacks<TSchema, TRetrievalResults, TMutationResult, TRawInput>,\n options: ExecuteUnitOfWorkOptions<TSchema, TRawInput>,\n): Promise<ExecuteUnitOfWorkResult<TRetrievalResults, TMutationResult>> {\n // Validate that at least one of retrieve or mutate is provided\n if (!callbacks.retrieve && !callbacks.mutate) {\n throw new Error(\"At least one of 'retrieve' or 'mutate' callbacks must be provided\");\n }\n\n const retryPolicy = options.retryPolicy ?? new NoRetryPolicy();\n const signal = options.signal;\n let attempt = 0;\n\n while (true) {\n // Check if aborted before starting attempt\n if (signal?.aborted) {\n return { success: false, reason: \"aborted\" };\n }\n\n try {\n // Create a fresh UOW for this attempt\n const uow = options.createUnitOfWork();\n\n // Apply retrieval phase if provided\n let retrievalUow: TypedUnitOfWork<TSchema, TRetrievalResults, TRawInput>;\n if (callbacks.retrieve) {\n retrievalUow = callbacks.retrieve(uow);\n } else {\n // No retrieval phase, use empty UOW with type cast\n // This is safe because when there's no retrieve, TRetrievalResults should be []\n retrievalUow = uow as unknown as TypedUnitOfWork<TSchema, TRetrievalResults, TRawInput>;\n }\n\n // Execute retrieval phase\n const results = (await retrievalUow.executeRetrieve()) as TRetrievalResults;\n\n // Invoke mutation phase callback if provided\n let mutationResult: TMutationResult;\n if (callbacks.mutate) {\n mutationResult = await callbacks.mutate(retrievalUow, results);\n } else {\n mutationResult = undefined as TMutationResult;\n }\n\n // Execute mutation phase\n const { success } = await retrievalUow.executeMutations();\n\n if (success) {\n // Success! Get created IDs and nonce, then invoke onSuccess if provided\n const createdIds = retrievalUow.getCreatedIds();\n const nonce = retrievalUow.nonce;\n\n // Await promises in mutationResult (1 level deep)\n const awaitedMutationResult = await awaitPromisesInObject(mutationResult);\n\n if (callbacks.onSuccess) {\n await callbacks.onSuccess({\n results,\n mutationResult: awaitedMutationResult,\n createdIds,\n nonce,\n });\n }\n\n return {\n success: true,\n results,\n mutationResult: awaitedMutationResult,\n createdIds,\n nonce,\n };\n }\n\n // Failed - check if we should retry\n // attempt represents the number of attempts completed so far\n if (!retryPolicy.shouldRetry(attempt, undefined, signal)) {\n // No more retries\n return { success: false, reason: \"conflict\" };\n }\n\n const delayMs = retryPolicy.getDelayMs(attempt);\n if (delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n attempt++;\n } catch (error) {\n // An error was thrown during execution\n return { success: false, reason: \"error\", error };\n }\n }\n}\n\n/**\n * Options for executing a Unit of Work with restricted access\n */\nexport interface ExecuteRestrictedUnitOfWorkOptions {\n /**\n * Factory function that creates or resets a UOW instance for each attempt\n */\n createUnitOfWork: () => IUnitOfWork;\n\n /**\n * Retry policy for handling optimistic concurrency conflicts\n */\n retryPolicy?: RetryPolicy;\n\n /**\n * Abort signal to cancel execution\n */\n signal?: AbortSignal;\n\n /**\n * Callback invoked before mutations are executed.\n * Use this to add additional mutation operations (e.g., hook event records).\n */\n onBeforeMutate?: (uow: IUnitOfWork) => void;\n\n /**\n * Callback invoked after successful mutation phase.\n * Use this for post-mutation processing like hook execution.\n */\n onSuccess?: (uow: IUnitOfWork) => Promise<void>;\n}\n\n/**\n * Context provided to handler tx callbacks\n */\nexport interface TxPhaseContext<THooks extends HooksMap> {\n /**\n * Get a typed Unit of Work for the given schema\n */\n forSchema: <S extends AnySchema, H extends HooksMap = THooks>(\n schema: S,\n hooks?: H,\n ) => TypedUnitOfWork<S, [], unknown, H>;\n}\n\n/**\n * Handler callbacks for tx() - SYNCHRONOUS ONLY (no Promise return allowed)\n * This prevents accidentally awaiting services in the wrong place\n */\nexport interface HandlerTxCallbacks<TRetrieveResult, TMutationResult, THooks extends HooksMap> {\n /**\n * Retrieval phase callback - schedules retrievals and optionally calls services\n * Must be synchronous - cannot await promises\n */\n retrieve?: (context: TxPhaseContext<THooks>) => TRetrieveResult;\n /**\n * Mutation phase callback - receives retrieve result, schedules mutations\n * Must be synchronous - cannot await promises (but may return a promise to be awaited)\n */\n mutate?: (context: TxPhaseContext<THooks>, retrieveResult: TRetrieveResult) => TMutationResult;\n}\n\nexport interface ServiceTxCallbacks<\n TSchema extends AnySchema,\n TRetrievalResults extends unknown[],\n TMutationResult,\n THooks extends HooksMap,\n> {\n /**\n * Retrieval phase callback - schedules retrievals, returns typed UOW\n */\n retrieve?: (\n uow: TypedUnitOfWork<TSchema, [], unknown, THooks>,\n ) => TypedUnitOfWork<TSchema, TRetrievalResults, unknown, THooks>;\n /**\n * Mutation phase callback - receives retrieval results, schedules mutations and hooks\n */\n mutate?: (\n uow: TypedUnitOfWork<TSchema, TRetrievalResults, unknown, THooks>,\n results: TRetrievalResults,\n ) => TMutationResult | Promise<TMutationResult>;\n}\n\n/**\n * Execute a Unit of Work with explicit phase control and automatic retry support.\n *\n * This function provides an alternative API where users write a single callback that receives\n * a context object with forSchema, executeRetrieve, and executeMutate methods. The user can\n * create schema-specific UOWs via forSchema, then call executeRetrieve() and executeMutate()\n * to execute the retrieval and mutation phases. The entire callback is re-executed on optimistic\n * concurrency conflicts, ensuring retries work properly.\n *\n * @param callback - Async function that receives a context with forSchema, executeRetrieve, executeMutate, nonce, and currentAttempt\n * @param options - Configuration including UOW factory, retry policy, and abort signal\n * @returns Promise resolving to the callback's return value\n * @throws Error if retries are exhausted or callback throws an error\n *\n * @example\n * ```ts\n * const { userId, profileId } = await executeRestrictedUnitOfWork(\n * async ({ forSchema, executeRetrieve, executeMutate, nonce, currentAttempt }) => {\n * const uow = forSchema(schema);\n * const userId = uow.create(\"users\", { name: \"John\" });\n *\n * // Execute retrieval phase\n * await executeRetrieve();\n *\n * const profileId = uow.create(\"profiles\", { userId });\n *\n * // Execute mutation phase\n * await executeMutate();\n *\n * return { userId, profileId };\n * },\n * {\n * createUnitOfWork: () => db.createUnitOfWork(),\n * retryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 5 })\n * }\n * );\n * ```\n */\nexport async function executeRestrictedUnitOfWork<TResult, THooks extends HooksMap = {}>(\n callback: (context: {\n forSchema: <S extends AnySchema, H extends HooksMap = THooks>(\n schema: S,\n hooks?: H,\n ) => TypedUnitOfWork<S, [], unknown, H>;\n executeRetrieve: () => Promise<void>;\n executeMutate: () => Promise<void>;\n nonce: string;\n currentAttempt: number;\n }) => Promise<TResult>,\n options: ExecuteRestrictedUnitOfWorkOptions,\n): Promise<AwaitedPromisesInObject<TResult>> {\n // Default retry policy with small, fast retries for optimistic concurrency\n const retryPolicy =\n options.retryPolicy ??\n new ExponentialBackoffRetryPolicy({\n maxRetries: 5,\n initialDelayMs: 10,\n maxDelayMs: 100,\n });\n const signal = options.signal;\n let attempt = 0;\n\n while (true) {\n // Check if aborted before starting attempt\n if (signal?.aborted) {\n throw new Error(\"Unit of Work execution aborted\");\n }\n\n try {\n // Create a fresh UOW for this attempt\n const baseUow = options.createUnitOfWork();\n\n const context = {\n forSchema: <S extends AnySchema, H extends HooksMap = THooks>(schema: S, hooks?: H) => {\n return baseUow.forSchema(schema, hooks);\n },\n executeRetrieve: async () => {\n await baseUow.executeRetrieve();\n },\n executeMutate: async () => {\n if (baseUow.state === \"executed\") {\n return;\n }\n\n if (baseUow.state === \"building-retrieval\") {\n await baseUow.executeRetrieve();\n }\n\n // Add hook mutations before executing\n if (options.onBeforeMutate) {\n options.onBeforeMutate(baseUow);\n }\n\n const result = await baseUow.executeMutations();\n if (!result.success) {\n throw new ConcurrencyConflictError();\n }\n\n if (options.onSuccess) {\n await options.onSuccess(baseUow);\n }\n },\n nonce: baseUow.nonce,\n currentAttempt: attempt,\n };\n\n // Execute the callback which will call executeRetrieve and executeMutate\n const result = await callback(context);\n\n // Await promises in the result object (1 level deep)\n const awaitedResult = await awaitPromisesInObject(result);\n\n // Return the awaited result\n return awaitedResult;\n } catch (error) {\n if (signal?.aborted) {\n throw new Error(\"Unit of Work execution aborted\");\n }\n\n // Only retry concurrency conflicts, not other errors\n if (!(error instanceof ConcurrencyConflictError)) {\n // Not a concurrency conflict - throw immediately without retry\n throw error;\n }\n\n if (!retryPolicy.shouldRetry(attempt, error, signal)) {\n // No more retries - check again if aborted or throw conflict error\n if (signal?.aborted) {\n throw new Error(\"Unit of Work execution aborted\");\n }\n throw new Error(\"Unit of Work execution failed: optimistic concurrency conflict\", {\n cause: error,\n });\n }\n\n const delayMs = retryPolicy.getDelayMs(attempt);\n if (delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n attempt++;\n }\n }\n}\n\n/**\n * Execute a transaction with array syntax (handler context).\n * Takes a factory function that creates an array of service promises, enabling proper retry support.\n *\n * @param servicesFactory - Function that creates an array of service promises\n * @param options - Configuration including UOW factory, retry policy, and abort signal\n * @returns Promise resolving to array of awaited service results\n *\n * @example\n * ```ts\n * const [result1, result2] = await executeTxArray(\n * () => [\n * executeServiceTx(schema, callbacks1, uow),\n * executeServiceTx(schema, callbacks2, uow)\n * ],\n * { createUnitOfWork }\n * );\n * ```\n */\nexport async function executeTxArray<T extends readonly unknown[]>(\n servicesFactory: () => readonly [...{ [K in keyof T]: Promise<T[K]> }],\n options: ExecuteRestrictedUnitOfWorkOptions,\n): Promise<{ [K in keyof T]: T[K] }> {\n const retryPolicy =\n options.retryPolicy ??\n new ExponentialBackoffRetryPolicy({\n maxRetries: 5,\n initialDelayMs: 10,\n maxDelayMs: 100,\n });\n const signal = options.signal;\n let attempt = 0;\n\n while (true) {\n // Check if aborted before starting attempt\n if (signal?.aborted) {\n throw new Error(\"Unit of Work execution aborted\");\n }\n\n try {\n // Create a fresh UOW for this attempt\n const baseUow = options.createUnitOfWork();\n\n // Call factory to create fresh service promises for this attempt\n const services = servicesFactory();\n\n await baseUow.executeRetrieve();\n\n if (options.onBeforeMutate) {\n options.onBeforeMutate(baseUow);\n }\n\n const result = await baseUow.executeMutations();\n if (!result.success) {\n throw new ConcurrencyConflictError();\n }\n\n if (options.onSuccess) {\n await options.onSuccess(baseUow);\n }\n\n // Now await all service promises - they should all resolve now that mutations executed\n const results = await Promise.all(services);\n return results as { [K in keyof T]: T[K] };\n } catch (error) {\n if (signal?.aborted) {\n throw new Error(\"Unit of Work execution aborted\");\n }\n\n // Only retry concurrency conflicts, not other errors\n if (!(error instanceof ConcurrencyConflictError)) {\n throw error;\n }\n\n if (!retryPolicy.shouldRetry(attempt, error, signal)) {\n if (signal?.aborted) {\n throw new Error(\"Unit of Work execution aborted\");\n }\n throw new Error(\"Unit of Work execution failed: optimistic concurrency conflict\", {\n cause: error,\n });\n }\n\n const delayMs = retryPolicy.getDelayMs(attempt);\n if (delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n attempt++;\n }\n }\n}\n\n/**\n * Execute a transaction with callback syntax (handler context).\n * Callbacks are synchronous only to prevent accidentally awaiting services in wrong place.\n *\n * @param callbacks - Object containing retrieve and mutate callbacks\n * @param options - Configuration including UOW factory, retry policy, and abort signal\n * @returns Promise resolving to the mutation result with promises awaited 1 level deep\n */\nexport async function executeTxCallbacks<\n TRetrieveResult,\n TMutationResult,\n THooks extends HooksMap = {},\n>(\n callbacks: HandlerTxCallbacks<TRetrieveResult, TMutationResult, THooks>,\n options: ExecuteRestrictedUnitOfWorkOptions,\n): Promise<AwaitedPromisesInObject<TMutationResult>> {\n const retryPolicy =\n options.retryPolicy ??\n new ExponentialBackoffRetryPolicy({\n maxRetries: 5,\n initialDelayMs: 10,\n maxDelayMs: 100,\n });\n const signal = options.signal;\n let attempt = 0;\n\n while (true) {\n // Check if aborted before starting attempt\n if (signal?.aborted) {\n throw new Error(\"Unit of Work execution aborted\");\n }\n\n try {\n // Create a fresh UOW for this attempt\n const baseUow = options.createUnitOfWork();\n\n const context: TxPhaseContext<THooks> = {\n forSchema: <S extends AnySchema, H extends HooksMap = THooks>(schema: S, hooks?: H) => {\n return baseUow.forSchema(schema, hooks);\n },\n };\n\n let retrieveResult: TRetrieveResult;\n if (callbacks.retrieve) {\n retrieveResult = callbacks.retrieve(context);\n } else {\n retrieveResult = undefined as TRetrieveResult;\n }\n\n await baseUow.executeRetrieve();\n\n let mutationResult: TMutationResult;\n if (callbacks.mutate) {\n mutationResult = callbacks.mutate(context, retrieveResult);\n } else {\n mutationResult = retrieveResult as unknown as TMutationResult;\n }\n\n const awaitedMutationResult = await awaitPromisesInObject(mutationResult);\n\n if (options.onBeforeMutate) {\n options.onBeforeMutate(baseUow);\n }\n\n const result = await baseUow.executeMutations();\n if (!result.success) {\n throw new ConcurrencyConflictError();\n }\n\n if (options.onSuccess) {\n await options.onSuccess(baseUow);\n }\n\n return awaitedMutationResult;\n } catch (error) {\n if (signal?.aborted) {\n throw new Error(\"Unit of Work execution aborted\");\n }\n\n // Only retry concurrency conflicts, not other errors\n if (!(error instanceof ConcurrencyConflictError)) {\n throw error;\n }\n\n if (!retryPolicy.shouldRetry(attempt, error, signal)) {\n if (signal?.aborted) {\n throw new Error(\"Unit of Work execution aborted\");\n }\n throw new Error(\"Unit of Work execution failed: optimistic concurrency conflict\", {\n cause: error,\n });\n }\n\n const delayMs = retryPolicy.getDelayMs(attempt);\n if (delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n attempt++;\n }\n }\n}\n\n/**\n * Execute a transaction for service context.\n * Service callbacks can be async for ergonomic async work.\n *\n * @param schema - Schema to use for the transaction\n * @param callbacks - Object containing retrieve and mutate callbacks\n * @param baseUow - Base Unit of Work (restricted) to use\n * @returns Promise resolving to the mutation result with promises awaited 1 level deep\n */\nexport async function executeServiceTx<\n TSchema extends AnySchema,\n TRetrievalResults extends unknown[],\n TMutationResult,\n THooks extends HooksMap,\n>(\n schema: TSchema,\n callbacks: ServiceTxCallbacks<TSchema, TRetrievalResults, TMutationResult, THooks>,\n baseUow: IUnitOfWork,\n): Promise<AwaitedPromisesInObject<TMutationResult>> {\n const typedUow = baseUow.restrict({ readyFor: \"none\" }).forSchema<TSchema, THooks>(schema);\n\n let retrievalUow: TypedUnitOfWork<TSchema, TRetrievalResults, unknown, THooks>;\n try {\n if (callbacks.retrieve) {\n retrievalUow = callbacks.retrieve(typedUow);\n } else {\n // Safe cast: when there's no retrieve callback, TRetrievalResults should be []\n retrievalUow = typedUow as unknown as TypedUnitOfWork<\n TSchema,\n TRetrievalResults,\n unknown,\n THooks\n >;\n }\n } catch (error) {\n typedUow.signalReadyForRetrieval();\n typedUow.signalReadyForMutation();\n throw error;\n }\n\n typedUow.signalReadyForRetrieval();\n\n // Safe cast: retrievalPhase returns the correct type based on the UOW's type parameters\n const results = (await retrievalUow.retrievalPhase) as TRetrievalResults;\n\n let mutationResult: TMutationResult;\n try {\n if (callbacks.mutate) {\n mutationResult = await callbacks.mutate(retrievalUow, results);\n } else {\n // Safe cast: when there's no mutate callback, TMutationResult should be void\n mutationResult = undefined as TMutationResult;\n }\n } catch (error) {\n typedUow.signalReadyForMutation();\n throw error;\n }\n\n typedUow.signalReadyForMutation();\n\n await retrievalUow.mutationPhase;\n\n return await awaitPromisesInObject(mutationResult);\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- //#region src/query/retry-policy.d.ts
1
+ //#region src/query/unit-of-work/retry-policy.d.ts
2
2
  /**
3
3
  * Policy for retrying failed Unit of Work operations
4
4
  */
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry-policy.d.ts","names":[],"sources":["../../../src/query/unit-of-work/retry-policy.ts"],"sourcesContent":[],"mappings":";;AAGA;AAqBA;AA0Ba,UA/CI,WAAA,CA+CJ;EAMU;;;;AA0BvB;AAqBA;;EAW0D,WAAA,CAAA,OAAA,EAAA,MAAA,EAAA,KAAA,CAAA,EAAA,OAAA,EAAA,MAAA,CAAA,EAvGD,WAuGC,CAAA,EAAA,OAAA;EAXT;;AA6BjD;;;;;;;;UA5GiB,oCAAA;;;;;;;;;;;;;;;;;;;;;;cA0BJ,6BAAA,YAAyC;;wBAM/B;0DAOmC;;;;;;UAmBzC,+BAAA;;;;;;;;;;;;;;;;;;cAqBJ,wBAAA,YAAoC;;wBAK1B;0DAMmC;;;;;;cAkB7C,aAAA,YAAyB;4DACsB"}
@@ -1,4 +1,4 @@
1
- //#region src/query/retry-policy.ts
1
+ //#region src/query/unit-of-work/retry-policy.ts
2
2
  /**
3
3
  * Exponential backoff retry policy
4
4
  * Delay increases exponentially: initialDelay * (multiplier ^ attempt)
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry-policy.js","names":["#maxRetries","#initialDelayMs","#maxDelayMs","#backoffMultiplier","#delayMs","#incrementMs"],"sources":["../../../src/query/unit-of-work/retry-policy.ts"],"sourcesContent":["/**\n * Policy for retrying failed Unit of Work operations\n */\nexport interface RetryPolicy {\n /**\n * Determines if the operation should be retried\n * @param attempt - The current attempt number (0-indexed)\n * @param error - Optional error from the previous attempt\n * @param signal - Optional AbortSignal to check for cancellation\n * @returns true if the operation should be retried, false otherwise\n */\n shouldRetry(attempt: number, error?: unknown, signal?: AbortSignal): boolean;\n\n /**\n * Gets the delay in milliseconds before the next retry attempt\n * @param attempt - The current attempt number (0-indexed)\n * @returns Delay in milliseconds\n */\n getDelayMs(attempt: number): number;\n}\n\n/**\n * Options for exponential backoff retry policy\n */\nexport interface ExponentialBackoffRetryPolicyOptions {\n /**\n * Maximum number of retry attempts (default: 3)\n */\n maxRetries?: number;\n\n /**\n * Initial delay in milliseconds (default: 100)\n */\n initialDelayMs?: number;\n\n /**\n * Maximum delay in milliseconds (default: 10000)\n */\n maxDelayMs?: number;\n\n /**\n * Multiplier for exponential backoff (default: 2)\n */\n backoffMultiplier?: number;\n}\n\n/**\n * Exponential backoff retry policy\n * Delay increases exponentially: initialDelay * (multiplier ^ attempt)\n */\nexport class ExponentialBackoffRetryPolicy implements RetryPolicy {\n readonly #maxRetries: number;\n readonly #initialDelayMs: number;\n readonly #maxDelayMs: number;\n readonly #backoffMultiplier: number;\n\n constructor(options: ExponentialBackoffRetryPolicyOptions = {}) {\n this.#maxRetries = options.maxRetries ?? 3;\n this.#initialDelayMs = options.initialDelayMs ?? 100;\n this.#maxDelayMs = options.maxDelayMs ?? 10000;\n this.#backoffMultiplier = options.backoffMultiplier ?? 2;\n }\n\n shouldRetry(attempt: number, _error?: unknown, signal?: AbortSignal): boolean {\n // Check if operation was aborted\n if (signal?.aborted) {\n return false;\n }\n\n // Check if we've exceeded max retries\n return attempt < this.#maxRetries;\n }\n\n getDelayMs(attempt: number): number {\n const delay = this.#initialDelayMs * Math.pow(this.#backoffMultiplier, attempt);\n return Math.min(delay, this.#maxDelayMs);\n }\n}\n\n/**\n * Options for linear backoff retry policy\n */\nexport interface LinearBackoffRetryPolicyOptions {\n /**\n * Maximum number of retry attempts (default: 3)\n */\n maxRetries?: number;\n\n /**\n * Base delay in milliseconds (default: 100)\n */\n delayMs?: number;\n\n /**\n * Increment added to delay for each attempt in milliseconds (default: 100)\n */\n incrementMs?: number;\n}\n\n/**\n * Linear backoff retry policy\n * Delay increases linearly: delayMs + (attempt * incrementMs)\n */\nexport class LinearBackoffRetryPolicy implements RetryPolicy {\n readonly #maxRetries: number;\n readonly #delayMs: number;\n readonly #incrementMs: number;\n\n constructor(options: LinearBackoffRetryPolicyOptions = {}) {\n this.#maxRetries = options.maxRetries ?? 3;\n this.#delayMs = options.delayMs ?? 100;\n this.#incrementMs = options.incrementMs ?? 100;\n }\n\n shouldRetry(attempt: number, _error?: unknown, signal?: AbortSignal): boolean {\n // Check if operation was aborted\n if (signal?.aborted) {\n return false;\n }\n\n // Check if we've exceeded max retries\n return attempt < this.#maxRetries;\n }\n\n getDelayMs(attempt: number): number {\n return this.#delayMs + attempt * this.#incrementMs;\n }\n}\n\n/**\n * No retry policy - never retries failed operations\n */\nexport class NoRetryPolicy implements RetryPolicy {\n shouldRetry(_attempt: number, _error?: unknown, _signal?: AbortSignal): boolean {\n return false;\n }\n\n getDelayMs(_attempt: number): number {\n return 0;\n }\n}\n"],"mappings":";;;;;AAkDA,IAAa,gCAAb,MAAkE;CAChE,CAASA;CACT,CAASC;CACT,CAASC;CACT,CAASC;CAET,YAAY,UAAgD,EAAE,EAAE;AAC9D,QAAKH,aAAc,QAAQ,cAAc;AACzC,QAAKC,iBAAkB,QAAQ,kBAAkB;AACjD,QAAKC,aAAc,QAAQ,cAAc;AACzC,QAAKC,oBAAqB,QAAQ,qBAAqB;;CAGzD,YAAY,SAAiB,QAAkB,QAA+B;AAE5E,MAAI,QAAQ,QACV,QAAO;AAIT,SAAO,UAAU,MAAKH;;CAGxB,WAAW,SAAyB;EAClC,MAAM,QAAQ,MAAKC,iBAAkB,KAAK,IAAI,MAAKE,mBAAoB,QAAQ;AAC/E,SAAO,KAAK,IAAI,OAAO,MAAKD,WAAY;;;;;;;AA4B5C,IAAa,2BAAb,MAA6D;CAC3D,CAASF;CACT,CAASI;CACT,CAASC;CAET,YAAY,UAA2C,EAAE,EAAE;AACzD,QAAKL,aAAc,QAAQ,cAAc;AACzC,QAAKI,UAAW,QAAQ,WAAW;AACnC,QAAKC,cAAe,QAAQ,eAAe;;CAG7C,YAAY,SAAiB,QAAkB,QAA+B;AAE5E,MAAI,QAAQ,QACV,QAAO;AAIT,SAAO,UAAU,MAAKL;;CAGxB,WAAW,SAAyB;AAClC,SAAO,MAAKI,UAAW,UAAU,MAAKC;;;;;;AAO1C,IAAa,gBAAb,MAAkD;CAChD,YAAY,UAAkB,QAAkB,SAAgC;AAC9E,SAAO;;CAGT,WAAW,UAA0B;AACnC,SAAO"}