@fragno-dev/db 0.1.14 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (445) hide show
  1. package/.turbo/turbo-build.log +242 -139
  2. package/CHANGELOG.md +47 -0
  3. package/README.md +123 -8
  4. package/dist/adapters/adapters.d.ts +19 -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 -19
  8. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
  9. package/dist/adapters/drizzle/drizzle-adapter.js +7 -47
  10. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
  11. package/dist/adapters/drizzle/generate.d.ts +7 -1
  12. package/dist/adapters/drizzle/generate.d.ts.map +1 -1
  13. package/dist/adapters/drizzle/generate.js +46 -45
  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 -16
  68. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
  69. package/dist/adapters/kysely/kysely-adapter.js +6 -159
  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} +48 -62
  72. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -0
  73. package/dist/adapters/{kysely/kysely-shared.d.ts → shared/table-name-mapper.d.ts} +3 -2
  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 +186 -0
  80. package/dist/db-fragment-definition-builder.d.ts.map +1 -0
  81. package/dist/db-fragment-definition-builder.js +207 -0
  82. package/dist/db-fragment-definition-builder.js.map +1 -0
  83. package/dist/fragments/internal-fragment.d.ts +53 -0
  84. package/dist/fragments/internal-fragment.d.ts.map +1 -0
  85. package/dist/fragments/internal-fragment.js +111 -0
  86. package/dist/fragments/internal-fragment.js.map +1 -0
  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 +38 -56
  94. package/dist/migration-engine/generation-engine.js.map +1 -1
  95. package/dist/mod.d.ts +35 -23
  96. package/dist/mod.d.ts.map +1 -1
  97. package/dist/mod.js +48 -45
  98. package/dist/mod.js.map +1 -1
  99. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js +165 -0
  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/bind-services.js +20 -0
  102. package/dist/packages/fragno/dist/api/bind-services.js.map +1 -0
  103. package/dist/packages/fragno/dist/api/error.js +48 -0
  104. package/dist/packages/fragno/dist/api/error.js.map +1 -0
  105. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +320 -0
  106. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -0
  107. package/dist/packages/fragno/dist/api/fragment-instantiator.js +525 -0
  108. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -0
  109. package/dist/packages/fragno/dist/api/fragno-response.js +73 -0
  110. package/dist/packages/fragno/dist/api/fragno-response.js.map +1 -0
  111. package/dist/packages/fragno/dist/api/internal/response-stream.js +81 -0
  112. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +1 -0
  113. package/dist/packages/fragno/dist/api/internal/route.js +10 -0
  114. package/dist/packages/fragno/dist/api/internal/route.js.map +1 -0
  115. package/dist/packages/fragno/dist/api/mutable-request-state.js +97 -0
  116. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +1 -0
  117. package/dist/packages/fragno/dist/api/request-context-storage.js +43 -0
  118. package/dist/packages/fragno/dist/api/request-context-storage.js.map +1 -0
  119. package/dist/packages/fragno/dist/api/request-input-context.js +118 -0
  120. package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -0
  121. package/dist/packages/fragno/dist/api/request-middleware.js +83 -0
  122. package/dist/packages/fragno/dist/api/request-middleware.js.map +1 -0
  123. package/dist/packages/fragno/dist/api/request-output-context.js +119 -0
  124. package/dist/packages/fragno/dist/api/request-output-context.js.map +1 -0
  125. package/dist/packages/fragno/dist/api/route.js +17 -0
  126. package/dist/packages/fragno/dist/api/route.js.map +1 -0
  127. package/dist/packages/fragno/dist/internal/symbols.js +10 -0
  128. package/dist/packages/fragno/dist/internal/symbols.js.map +1 -0
  129. package/dist/query/column-defaults.js +27 -0
  130. package/dist/query/column-defaults.js.map +1 -0
  131. package/dist/query/cursor.d.ts +14 -6
  132. package/dist/query/cursor.d.ts.map +1 -1
  133. package/dist/query/cursor.js +16 -7
  134. package/dist/query/cursor.js.map +1 -1
  135. package/dist/query/orm/orm.d.ts +1 -1
  136. package/dist/query/orm/orm.js.map +1 -1
  137. package/dist/query/serialize/create-sql-serializer.js +30 -0
  138. package/dist/query/serialize/create-sql-serializer.js.map +1 -0
  139. package/dist/query/serialize/dialect/mysql-serializer.js +87 -0
  140. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -0
  141. package/dist/query/serialize/dialect/postgres-serializer.js +80 -0
  142. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -0
  143. package/dist/query/serialize/dialect/sqlite-serializer.js +93 -0
  144. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -0
  145. package/dist/query/serialize/sql-serializer.js +67 -0
  146. package/dist/query/serialize/sql-serializer.js.map +1 -0
  147. package/dist/query/{query.d.ts → simple-query-interface.d.ts} +6 -6
  148. package/dist/query/simple-query-interface.d.ts.map +1 -0
  149. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +133 -0
  150. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  151. package/dist/query/unit-of-work/execute-unit-of-work.js +197 -0
  152. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  153. package/dist/query/unit-of-work/retry-policy.d.ts +88 -0
  154. package/dist/query/unit-of-work/retry-policy.d.ts.map +1 -0
  155. package/dist/query/unit-of-work/retry-policy.js +61 -0
  156. package/dist/query/unit-of-work/retry-policy.js.map +1 -0
  157. package/dist/query/{unit-of-work.d.ts → unit-of-work/unit-of-work.d.ts} +145 -58
  158. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  159. package/dist/query/{unit-of-work.js → unit-of-work/unit-of-work.js} +435 -198
  160. package/dist/query/unit-of-work/unit-of-work.js.map +1 -0
  161. package/dist/query/value-decoding.js +71 -0
  162. package/dist/query/value-decoding.js.map +1 -0
  163. package/dist/query/value-encoding.js +124 -0
  164. package/dist/query/value-encoding.js.map +1 -0
  165. package/dist/schema/create.d.ts +3 -0
  166. package/dist/schema/create.d.ts.map +1 -1
  167. package/dist/schema/create.js +4 -0
  168. package/dist/schema/create.js.map +1 -1
  169. package/dist/schema/type-conversion/create-sql-type-mapper.js +29 -0
  170. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -0
  171. package/dist/schema/type-conversion/dialect/mysql.js +57 -0
  172. package/dist/schema/type-conversion/dialect/mysql.js.map +1 -0
  173. package/dist/schema/type-conversion/dialect/postgres.js +56 -0
  174. package/dist/schema/type-conversion/dialect/postgres.js.map +1 -0
  175. package/dist/schema/type-conversion/dialect/sqlite.js +52 -0
  176. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -0
  177. package/dist/schema/type-conversion/type-mapping.js +63 -0
  178. package/dist/schema/type-conversion/type-mapping.js.map +1 -0
  179. package/dist/sql-driver/connection/connection-provider.d.ts +13 -0
  180. package/dist/sql-driver/connection/connection-provider.d.ts.map +1 -0
  181. package/dist/sql-driver/connection/connection-provider.js +19 -0
  182. package/dist/sql-driver/connection/connection-provider.js.map +1 -0
  183. package/dist/sql-driver/connection/single-connection-provider.js +23 -0
  184. package/dist/sql-driver/connection/single-connection-provider.js.map +1 -0
  185. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  186. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  187. package/dist/sql-driver/dialects/dialects.d.ts +2 -0
  188. package/dist/sql-driver/dialects/dialects.js +3 -0
  189. package/dist/sql-driver/dialects/durable-object-dialect.d.ts +72 -0
  190. package/dist/sql-driver/dialects/durable-object-dialect.d.ts.map +1 -0
  191. package/dist/sql-driver/dialects/durable-object-dialect.js +130 -0
  192. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -0
  193. package/dist/sql-driver/driver/runtime-driver.d.ts +23 -0
  194. package/dist/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  195. package/dist/sql-driver/driver/runtime-driver.js +56 -0
  196. package/dist/sql-driver/driver/runtime-driver.js.map +1 -0
  197. package/dist/sql-driver/query-executor/default-query-executor.js +26 -0
  198. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -0
  199. package/dist/sql-driver/query-executor/plugin.d.ts +17 -0
  200. package/dist/sql-driver/query-executor/plugin.d.ts.map +1 -0
  201. package/dist/sql-driver/query-executor/query-executor-base.js +25 -0
  202. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -0
  203. package/dist/sql-driver/query-executor/query-executor.d.ts +36 -0
  204. package/dist/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  205. package/dist/sql-driver/sql-driver-adapter.d.ts +29 -0
  206. package/dist/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  207. package/dist/sql-driver/sql-driver-adapter.js +68 -0
  208. package/dist/sql-driver/sql-driver-adapter.js.map +1 -0
  209. package/dist/sql-driver/sql-driver.d.ts +38 -0
  210. package/dist/sql-driver/sql-driver.d.ts.map +1 -0
  211. package/dist/sql-driver/sql-driver.js +1 -0
  212. package/dist/sql-driver/sql.js +50 -0
  213. package/dist/sql-driver/sql.js.map +1 -0
  214. package/dist/with-database.d.ts +32 -0
  215. package/dist/with-database.d.ts.map +1 -0
  216. package/dist/with-database.js +34 -0
  217. package/dist/with-database.js.map +1 -0
  218. package/package.json +43 -9
  219. package/src/adapters/adapters.ts +23 -4
  220. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +140 -185
  221. package/src/adapters/drizzle/{drizzle-adapter-sqlite.test.ts → drizzle-adapter-sqlite3.test.ts} +187 -55
  222. package/src/adapters/drizzle/drizzle-adapter.ts +14 -93
  223. package/src/adapters/drizzle/generate.test.ts +102 -269
  224. package/src/adapters/drizzle/generate.ts +89 -63
  225. package/src/adapters/drizzle/migrate-drizzle.test.ts +19 -0
  226. package/src/adapters/drizzle/shared.ts +0 -34
  227. package/src/adapters/drizzle/test-utils.ts +36 -5
  228. package/src/adapters/generic-sql/README.md +14 -0
  229. package/src/adapters/generic-sql/driver-config.ts +144 -0
  230. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +50 -0
  231. package/src/adapters/generic-sql/generic-sql-adapter.ts +146 -0
  232. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +130 -0
  233. package/src/adapters/generic-sql/migration/cold-kysely.ts +55 -0
  234. package/src/adapters/{kysely/migration/execute-mysql.test.ts → generic-sql/migration/dialect/mysql.test.ts} +342 -484
  235. package/src/adapters/generic-sql/migration/dialect/mysql.ts +104 -0
  236. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +1008 -0
  237. package/src/adapters/generic-sql/migration/dialect/postgres.ts +113 -0
  238. package/src/adapters/{kysely/migration/execute-sqlite.test.ts → generic-sql/migration/dialect/sqlite.test.ts} +307 -510
  239. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +189 -0
  240. package/src/adapters/generic-sql/migration/executor.ts +33 -0
  241. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +661 -0
  242. package/src/adapters/generic-sql/migration/prepared-migrations.ts +214 -0
  243. package/src/adapters/generic-sql/migration/sql-generator.ts +413 -0
  244. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +36 -0
  245. package/src/adapters/generic-sql/query/cursor-utils.ts +56 -0
  246. package/src/adapters/generic-sql/query/dialect/mysql.ts +34 -0
  247. package/src/adapters/generic-sql/query/dialect/postgres.ts +32 -0
  248. package/src/adapters/generic-sql/query/dialect/sqlite.ts +32 -0
  249. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +1568 -0
  250. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +314 -0
  251. package/src/adapters/generic-sql/query/select-builder.test.ts +256 -0
  252. package/src/adapters/generic-sql/query/select-builder.ts +137 -0
  253. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +195 -0
  254. package/src/adapters/generic-sql/query/sql-query-compiler.ts +367 -0
  255. package/src/adapters/generic-sql/query/where-builder.test.ts +744 -0
  256. package/src/adapters/generic-sql/query/where-builder.ts +211 -0
  257. package/src/adapters/generic-sql/result-interpreter.ts +102 -0
  258. package/src/adapters/generic-sql/test/generic-drizzle-adapter-sqlite3.test.ts +899 -0
  259. package/src/adapters/generic-sql/uow-decoder.test.ts +399 -0
  260. package/src/adapters/generic-sql/uow-decoder.ts +152 -0
  261. package/src/adapters/generic-sql/uow-encoder.test.ts +183 -0
  262. package/src/adapters/generic-sql/uow-encoder.ts +131 -0
  263. package/src/adapters/kysely/kysely-adapter-pglite.test.ts +90 -96
  264. package/src/adapters/kysely/kysely-adapter-sqlocal.test.ts +215 -0
  265. package/src/adapters/kysely/kysely-adapter.ts +10 -242
  266. package/src/adapters/{drizzle/drizzle-query.ts → shared/from-unit-of-work-compiler.ts} +111 -106
  267. package/src/adapters/shared/table-name-mapper.ts +50 -0
  268. package/src/adapters/shared/uow-operation-compiler.ts +211 -0
  269. package/src/db-fragment-definition-builder.test.ts +887 -0
  270. package/src/db-fragment-definition-builder.ts +737 -0
  271. package/src/db-fragment-instantiator.test.ts +543 -0
  272. package/src/db-fragment-integration.test.ts +406 -0
  273. package/src/fragments/internal-fragment.test.ts +549 -0
  274. package/src/fragments/internal-fragment.ts +249 -0
  275. package/src/hooks/hooks.test.ts +575 -0
  276. package/src/hooks/hooks.ts +179 -0
  277. package/src/migration-engine/generation-engine.test.ts +60 -27
  278. package/src/migration-engine/generation-engine.ts +99 -92
  279. package/src/mod.ts +139 -78
  280. package/src/query/column-defaults.ts +49 -0
  281. package/src/query/cursor.test.ts +147 -3
  282. package/src/query/cursor.ts +25 -8
  283. package/src/query/orm/orm.ts +1 -1
  284. package/src/query/query-type.test.ts +9 -9
  285. package/src/query/serialize/create-sql-serializer.ts +34 -0
  286. package/src/query/serialize/dialect/mysql-serializer.ts +142 -0
  287. package/src/query/serialize/dialect/postgres-serializer.ts +129 -0
  288. package/src/query/serialize/dialect/sqlite-serializer.test.ts +251 -0
  289. package/src/query/serialize/dialect/sqlite-serializer.ts +156 -0
  290. package/src/query/serialize/sql-serializer.ts +143 -0
  291. package/src/query/{query.ts → simple-query-interface.ts} +4 -4
  292. package/src/query/unit-of-work/execute-unit-of-work.test.ts +1310 -0
  293. package/src/query/unit-of-work/execute-unit-of-work.ts +504 -0
  294. package/src/query/unit-of-work/retry-policy.test.ts +217 -0
  295. package/src/query/unit-of-work/retry-policy.ts +141 -0
  296. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +831 -0
  297. package/src/query/{unit-of-work-types.test.ts → unit-of-work/unit-of-work-types.test.ts} +7 -5
  298. package/src/query/unit-of-work/unit-of-work.test.ts +1716 -0
  299. package/src/query/{unit-of-work.ts → unit-of-work/unit-of-work.ts} +716 -420
  300. package/src/query/{result-transform.test.ts → value-decoding.test.ts} +45 -298
  301. package/src/query/value-decoding.ts +113 -0
  302. package/src/query/value-encoding.test.ts +390 -0
  303. package/src/query/value-encoding.ts +168 -0
  304. package/src/schema/create.test.ts +5 -1
  305. package/src/schema/create.ts +5 -0
  306. package/src/schema/serialize.test.ts +165 -407
  307. package/src/schema/type-conversion/create-sql-type-mapper.ts +28 -0
  308. package/src/schema/type-conversion/dialect/mysql.ts +64 -0
  309. package/src/schema/type-conversion/dialect/postgres.ts +62 -0
  310. package/src/schema/type-conversion/dialect/sqlite.ts +63 -0
  311. package/src/schema/type-conversion/type-mapping.test.ts +137 -0
  312. package/src/schema/type-conversion/type-mapping.ts +153 -0
  313. package/src/shared/connection-pool.ts +5 -5
  314. package/src/sql-driver/better-sqlite3.test.ts +126 -0
  315. package/src/sql-driver/connection/connection-provider.ts +27 -0
  316. package/src/sql-driver/connection/single-connection-provider.ts +42 -0
  317. package/src/sql-driver/dialect-adapter/dialect-adapter.ts +9 -0
  318. package/src/sql-driver/dialect-adapter/sqlite-dialect-adapter.ts +7 -0
  319. package/src/sql-driver/dialects/dialects.ts +1 -0
  320. package/src/sql-driver/dialects/durable-object-dialect.ts +260 -0
  321. package/src/sql-driver/driver/runtime-driver.ts +91 -0
  322. package/src/sql-driver/query-executor/default-query-executor.ts +38 -0
  323. package/src/sql-driver/query-executor/plugin.ts +22 -0
  324. package/src/sql-driver/query-executor/query-executor-base.ts +53 -0
  325. package/src/sql-driver/query-executor/query-executor.ts +44 -0
  326. package/src/sql-driver/sql-driver-adapter.ts +96 -0
  327. package/src/sql-driver/sql-driver.ts +53 -0
  328. package/src/sql-driver/sql.ts +57 -0
  329. package/src/sql-driver/sqlocal.test.ts +117 -0
  330. package/src/with-database.ts +152 -0
  331. package/tsdown.config.ts +8 -2
  332. package/dist/adapters/drizzle/drizzle-connection-pool.js +0 -40
  333. package/dist/adapters/drizzle/drizzle-connection-pool.js.map +0 -1
  334. package/dist/adapters/drizzle/drizzle-query.d.ts +0 -23
  335. package/dist/adapters/drizzle/drizzle-query.d.ts.map +0 -1
  336. package/dist/adapters/drizzle/drizzle-query.js.map +0 -1
  337. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +0 -10
  338. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +0 -1
  339. package/dist/adapters/drizzle/drizzle-uow-compiler.js +0 -315
  340. package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +0 -1
  341. package/dist/adapters/drizzle/drizzle-uow-decoder.js +0 -116
  342. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +0 -1
  343. package/dist/adapters/drizzle/drizzle-uow-executor.js +0 -149
  344. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +0 -1
  345. package/dist/adapters/drizzle/join-column-utils.js +0 -28
  346. package/dist/adapters/drizzle/join-column-utils.js.map +0 -1
  347. package/dist/adapters/drizzle/shared.d.ts +0 -14
  348. package/dist/adapters/drizzle/shared.d.ts.map +0 -1
  349. package/dist/adapters/drizzle/shared.js +0 -35
  350. package/dist/adapters/drizzle/shared.js.map +0 -1
  351. package/dist/adapters/kysely/kysely-connection-pool.js +0 -41
  352. package/dist/adapters/kysely/kysely-connection-pool.js.map +0 -1
  353. package/dist/adapters/kysely/kysely-query-builder.js +0 -321
  354. package/dist/adapters/kysely/kysely-query-builder.js.map +0 -1
  355. package/dist/adapters/kysely/kysely-query-compiler.js +0 -66
  356. package/dist/adapters/kysely/kysely-query-compiler.js.map +0 -1
  357. package/dist/adapters/kysely/kysely-query.d.ts +0 -22
  358. package/dist/adapters/kysely/kysely-query.d.ts.map +0 -1
  359. package/dist/adapters/kysely/kysely-query.js +0 -223
  360. package/dist/adapters/kysely/kysely-query.js.map +0 -1
  361. package/dist/adapters/kysely/kysely-shared.d.ts.map +0 -1
  362. package/dist/adapters/kysely/kysely-shared.js +0 -18
  363. package/dist/adapters/kysely/kysely-shared.js.map +0 -1
  364. package/dist/adapters/kysely/kysely-uow-compiler.js +0 -170
  365. package/dist/adapters/kysely/kysely-uow-compiler.js.map +0 -1
  366. package/dist/adapters/kysely/kysely-uow-executor.js +0 -89
  367. package/dist/adapters/kysely/kysely-uow-executor.js.map +0 -1
  368. package/dist/adapters/kysely/migration/execute-base.js +0 -128
  369. package/dist/adapters/kysely/migration/execute-base.js.map +0 -1
  370. package/dist/adapters/kysely/migration/execute-factory.js +0 -34
  371. package/dist/adapters/kysely/migration/execute-factory.js.map +0 -1
  372. package/dist/adapters/kysely/migration/execute-mssql.js +0 -112
  373. package/dist/adapters/kysely/migration/execute-mssql.js.map +0 -1
  374. package/dist/adapters/kysely/migration/execute-mysql.js +0 -93
  375. package/dist/adapters/kysely/migration/execute-mysql.js.map +0 -1
  376. package/dist/adapters/kysely/migration/execute-postgres.js +0 -104
  377. package/dist/adapters/kysely/migration/execute-postgres.js.map +0 -1
  378. package/dist/adapters/kysely/migration/execute-sqlite.js +0 -123
  379. package/dist/adapters/kysely/migration/execute-sqlite.js.map +0 -1
  380. package/dist/adapters/kysely/migration/execute.js +0 -34
  381. package/dist/adapters/kysely/migration/execute.js.map +0 -1
  382. package/dist/bind-services.d.ts +0 -7
  383. package/dist/bind-services.d.ts.map +0 -1
  384. package/dist/bind-services.js +0 -14
  385. package/dist/bind-services.js.map +0 -1
  386. package/dist/fragment.d.ts +0 -173
  387. package/dist/fragment.d.ts.map +0 -1
  388. package/dist/fragment.js +0 -191
  389. package/dist/fragment.js.map +0 -1
  390. package/dist/migration-engine/create.d.ts +0 -37
  391. package/dist/migration-engine/create.d.ts.map +0 -1
  392. package/dist/migration-engine/create.js +0 -58
  393. package/dist/migration-engine/create.js.map +0 -1
  394. package/dist/migration-engine/shared.d.ts +0 -112
  395. package/dist/migration-engine/shared.d.ts.map +0 -1
  396. package/dist/query/query.d.ts.map +0 -1
  397. package/dist/query/result-transform.js +0 -168
  398. package/dist/query/result-transform.js.map +0 -1
  399. package/dist/query/unit-of-work.d.ts.map +0 -1
  400. package/dist/query/unit-of-work.js.map +0 -1
  401. package/dist/schema/serialize.js +0 -106
  402. package/dist/schema/serialize.js.map +0 -1
  403. package/dist/shared/settings-schema.js +0 -36
  404. package/dist/shared/settings-schema.js.map +0 -1
  405. package/src/adapters/drizzle/drizzle-adapter.test.ts +0 -170
  406. package/src/adapters/drizzle/drizzle-connection-pool.ts +0 -66
  407. package/src/adapters/drizzle/drizzle-query.test.ts +0 -499
  408. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +0 -1383
  409. package/src/adapters/drizzle/drizzle-uow-compiler.ts +0 -636
  410. package/src/adapters/drizzle/drizzle-uow-decoder.ts +0 -218
  411. package/src/adapters/drizzle/drizzle-uow-executor.ts +0 -276
  412. package/src/adapters/drizzle/join-column-utils.test.ts +0 -79
  413. package/src/adapters/drizzle/join-column-utils.ts +0 -39
  414. package/src/adapters/kysely/kysely-connection-pool.ts +0 -70
  415. package/src/adapters/kysely/kysely-query-builder.test.ts +0 -1344
  416. package/src/adapters/kysely/kysely-query-builder.ts +0 -666
  417. package/src/adapters/kysely/kysely-query-compiler.ts +0 -132
  418. package/src/adapters/kysely/kysely-query.test.ts +0 -498
  419. package/src/adapters/kysely/kysely-query.ts +0 -390
  420. package/src/adapters/kysely/kysely-shared.ts +0 -23
  421. package/src/adapters/kysely/kysely-uow-compiler.test.ts +0 -998
  422. package/src/adapters/kysely/kysely-uow-compiler.ts +0 -318
  423. package/src/adapters/kysely/kysely-uow-executor.ts +0 -145
  424. package/src/adapters/kysely/kysely-uow-joins.test.ts +0 -811
  425. package/src/adapters/kysely/migration/execute-base.ts +0 -256
  426. package/src/adapters/kysely/migration/execute-factory.ts +0 -53
  427. package/src/adapters/kysely/migration/execute-mssql.ts +0 -250
  428. package/src/adapters/kysely/migration/execute-mysql.ts +0 -211
  429. package/src/adapters/kysely/migration/execute-postgres.test.ts +0 -2657
  430. package/src/adapters/kysely/migration/execute-postgres.ts +0 -234
  431. package/src/adapters/kysely/migration/execute-sqlite.ts +0 -247
  432. package/src/adapters/kysely/migration/execute.ts +0 -50
  433. package/src/adapters/kysely/migration/kysely-migrator.test.ts +0 -261
  434. package/src/bind-services.test.ts +0 -214
  435. package/src/bind-services.ts +0 -37
  436. package/src/db-fragment.test.ts +0 -800
  437. package/src/fragment.ts +0 -727
  438. package/src/query/result-transform.ts +0 -271
  439. package/src/query/unit-of-work-multi-schema.test.ts +0 -64
  440. package/src/query/unit-of-work.test.ts +0 -943
  441. package/src/schema/serialize.ts +0 -396
  442. package/src/shared/settings-schema.ts +0 -61
  443. package/src/uow-context-integration.test.ts +0 -102
  444. package/src/uow-context.test.ts +0 -182
  445. /package/dist/query/{query.js → simple-query-interface.js} +0 -0
@@ -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, UnitOfWork, 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
  */
@@ -93,8 +93,8 @@ interface AbstractQuery<TSchema extends AnySchema, TUOWConfig = void> {
93
93
  /**
94
94
  * Create a Unit of Work bound to this query engine
95
95
  */
96
- createUnitOfWork: (name?: string, config?: TUOWConfig) => UnitOfWork<TSchema, []>;
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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"}
@@ -0,0 +1,133 @@
1
+ import { AnySchema, FragnoId } from "../../schema/create.js";
2
+ import { RetryPolicy } from "./retry-policy.js";
3
+ import { IUnitOfWork, TypedUnitOfWork } from "./unit-of-work.js";
4
+
5
+ //#region src/query/unit-of-work/execute-unit-of-work.d.ts
6
+
7
+ /**
8
+ * Type utility that unwraps promises 1 level deep in objects, arrays, or direct promises
9
+ * Handles tuples, arrays, objects, and direct promises
10
+ */
11
+ type AwaitedPromisesInObject<T> = T extends Promise<infer U> ? Awaited<U> : T extends readonly [unknown, ...unknown[]] ? { [K in keyof T]: AwaitedPromisesInObject<T[K]> } : T extends [unknown, ...unknown[]] ? { [K in keyof T]: AwaitedPromisesInObject<T[K]> } : T extends (infer U)[] ? Awaited<U>[] : T extends readonly (infer U)[] ? readonly Awaited<U>[] : T extends Record<string, unknown> ? { [K in keyof T]: T[K] extends Promise<infer U> ? Awaited<U> : T[K] } : T;
12
+ /**
13
+ * Result of executing a Unit of Work with retry support
14
+ * Promises in mutationResult are unwrapped 1 level deep
15
+ */
16
+ type ExecuteUnitOfWorkResult<TRetrievalResults, TMutationResult> = {
17
+ success: true;
18
+ results: TRetrievalResults;
19
+ mutationResult: AwaitedPromisesInObject<TMutationResult>;
20
+ createdIds: FragnoId[];
21
+ nonce: string;
22
+ } | {
23
+ success: false;
24
+ reason: "conflict";
25
+ } | {
26
+ success: false;
27
+ reason: "aborted";
28
+ } | {
29
+ success: false;
30
+ reason: "error";
31
+ error: unknown;
32
+ };
33
+ /**
34
+ * Callbacks for executing a Unit of Work
35
+ */
36
+ interface ExecuteUnitOfWorkCallbacks<TSchema extends AnySchema, TRetrievalResults extends unknown[], TMutationResult, TRawInput> {
37
+ /**
38
+ * Retrieval phase callback - adds retrieval operations to the UOW
39
+ */
40
+ retrieve?: (uow: TypedUnitOfWork<TSchema, [], TRawInput>) => TypedUnitOfWork<TSchema, TRetrievalResults, TRawInput>;
41
+ /**
42
+ * Mutation phase callback - receives UOW and retrieval results, adds mutation operations
43
+ */
44
+ mutate?: (uow: TypedUnitOfWork<TSchema, TRetrievalResults, TRawInput>, results: TRetrievalResults) => TMutationResult | Promise<TMutationResult>;
45
+ /**
46
+ * Success callback - invoked after successful execution
47
+ * Promises in mutationResult are already unwrapped 1 level deep
48
+ */
49
+ onSuccess?: (result: {
50
+ results: TRetrievalResults;
51
+ mutationResult: AwaitedPromisesInObject<TMutationResult>;
52
+ createdIds: FragnoId[];
53
+ nonce: string;
54
+ }) => void | Promise<void>;
55
+ }
56
+ /**
57
+ * Options for executing a Unit of Work
58
+ */
59
+ interface ExecuteUnitOfWorkOptions<TSchema extends AnySchema, TRawInput> {
60
+ /**
61
+ * Factory function that creates or resets a UOW instance for each attempt
62
+ */
63
+ createUnitOfWork: () => TypedUnitOfWork<TSchema, [], TRawInput>;
64
+ /**
65
+ * Retry policy for handling optimistic concurrency conflicts
66
+ */
67
+ retryPolicy?: RetryPolicy;
68
+ /**
69
+ * Abort signal to cancel execution
70
+ */
71
+ signal?: AbortSignal;
72
+ }
73
+ /**
74
+ * Execute a Unit of Work with automatic retry support for optimistic concurrency conflicts.
75
+ *
76
+ * This function orchestrates the two-phase execution (retrieval + mutation) with retry logic.
77
+ * It creates fresh UOW instances for each attempt.
78
+ *
79
+ * @param callbacks - Object containing retrieve, mutate, and onSuccess callbacks
80
+ * @param options - Configuration including UOW factory, retry policy, and abort signal
81
+ * @returns Promise resolving to the execution result
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * const result = await executeUnitOfWork(
86
+ * {
87
+ * retrieve: (uow) => uow.find("users", (b) => b.whereIndex("primary")),
88
+ * mutate: (uow, [users]) => {
89
+ * const user = users[0];
90
+ * uow.update("users", user.id, (b) => b.set({ balance: newBalance }));
91
+ * },
92
+ * onSuccess: async ({ results, mutationResult }) => {
93
+ * console.log("Update successful!");
94
+ * }
95
+ * },
96
+ * {
97
+ * createUnitOfWork: () => queryEngine.createUnitOfWork(),
98
+ * retryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 })
99
+ * }
100
+ * );
101
+ * ```
102
+ */
103
+ declare function executeUnitOfWork<TSchema extends AnySchema, TRetrievalResults extends unknown[], TMutationResult = void, TRawInput = unknown>(callbacks: ExecuteUnitOfWorkCallbacks<TSchema, TRetrievalResults, TMutationResult, TRawInput>, options: ExecuteUnitOfWorkOptions<TSchema, TRawInput>): Promise<ExecuteUnitOfWorkResult<TRetrievalResults, TMutationResult>>;
104
+ /**
105
+ * Options for executing a Unit of Work with restricted access
106
+ */
107
+ interface ExecuteRestrictedUnitOfWorkOptions {
108
+ /**
109
+ * Factory function that creates or resets a UOW instance for each attempt
110
+ */
111
+ createUnitOfWork: () => IUnitOfWork;
112
+ /**
113
+ * Retry policy for handling optimistic concurrency conflicts
114
+ */
115
+ retryPolicy?: RetryPolicy;
116
+ /**
117
+ * Abort signal to cancel execution
118
+ */
119
+ signal?: AbortSignal;
120
+ /**
121
+ * Callback invoked before mutations are executed.
122
+ * Use this to add additional mutation operations (e.g., hook event records).
123
+ */
124
+ onBeforeMutate?: (uow: IUnitOfWork) => void;
125
+ /**
126
+ * Callback invoked after successful mutation phase.
127
+ * Use this for post-mutation processing like hook execution.
128
+ */
129
+ onSuccess?: (uow: IUnitOfWork) => Promise<void>;
130
+ }
131
+ //#endregion
132
+ export { AwaitedPromisesInObject, ExecuteRestrictedUnitOfWorkOptions, ExecuteUnitOfWorkCallbacks, ExecuteUnitOfWorkOptions, ExecuteUnitOfWorkResult, executeUnitOfWork };
133
+ //# 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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"}
@@ -0,0 +1,197 @@
1
+ import { ExponentialBackoffRetryPolicy, NoRetryPolicy } from "./retry-policy.js";
2
+
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
+ };
14
+ /**
15
+ * Await promises in an object 1 level deep
16
+ */
17
+ async function awaitPromisesInObject(obj) {
18
+ if (obj === null || obj === void 0) return obj;
19
+ if (typeof obj !== "object") return obj;
20
+ if (obj instanceof Promise) return await obj;
21
+ if (Array.isArray(obj)) return await Promise.all(obj.map((item) => item instanceof Promise ? item : Promise.resolve(item)));
22
+ const result = {};
23
+ const entries = Object.entries(obj);
24
+ const awaitedEntries = await Promise.all(entries.map(async ([key, value]) => {
25
+ return [key, value instanceof Promise ? await value : value];
26
+ }));
27
+ for (const [key, value] of awaitedEntries) result[key] = value;
28
+ return result;
29
+ }
30
+ /**
31
+ * Execute a Unit of Work with automatic retry support for optimistic concurrency conflicts.
32
+ *
33
+ * This function orchestrates the two-phase execution (retrieval + mutation) with retry logic.
34
+ * It creates fresh UOW instances for each attempt.
35
+ *
36
+ * @param callbacks - Object containing retrieve, mutate, and onSuccess callbacks
37
+ * @param options - Configuration including UOW factory, retry policy, and abort signal
38
+ * @returns Promise resolving to the execution result
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * const result = await executeUnitOfWork(
43
+ * {
44
+ * retrieve: (uow) => uow.find("users", (b) => b.whereIndex("primary")),
45
+ * mutate: (uow, [users]) => {
46
+ * const user = users[0];
47
+ * uow.update("users", user.id, (b) => b.set({ balance: newBalance }));
48
+ * },
49
+ * onSuccess: async ({ results, mutationResult }) => {
50
+ * console.log("Update successful!");
51
+ * }
52
+ * },
53
+ * {
54
+ * createUnitOfWork: () => queryEngine.createUnitOfWork(),
55
+ * retryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 })
56
+ * }
57
+ * );
58
+ * ```
59
+ */
60
+ async function executeUnitOfWork(callbacks, options) {
61
+ if (!callbacks.retrieve && !callbacks.mutate) throw new Error("At least one of 'retrieve' or 'mutate' callbacks must be provided");
62
+ const retryPolicy = options.retryPolicy ?? new NoRetryPolicy();
63
+ const signal = options.signal;
64
+ let attempt = 0;
65
+ while (true) {
66
+ if (signal?.aborted) return {
67
+ success: false,
68
+ reason: "aborted"
69
+ };
70
+ try {
71
+ const uow = options.createUnitOfWork();
72
+ let retrievalUow;
73
+ if (callbacks.retrieve) retrievalUow = callbacks.retrieve(uow);
74
+ else retrievalUow = uow;
75
+ const results = await retrievalUow.executeRetrieve();
76
+ let mutationResult;
77
+ if (callbacks.mutate) mutationResult = await callbacks.mutate(retrievalUow, results);
78
+ else mutationResult = void 0;
79
+ const { success } = await retrievalUow.executeMutations();
80
+ if (success) {
81
+ const createdIds = retrievalUow.getCreatedIds();
82
+ const nonce = retrievalUow.nonce;
83
+ const awaitedMutationResult = await awaitPromisesInObject(mutationResult);
84
+ if (callbacks.onSuccess) await callbacks.onSuccess({
85
+ results,
86
+ mutationResult: awaitedMutationResult,
87
+ createdIds,
88
+ nonce
89
+ });
90
+ return {
91
+ success: true,
92
+ results,
93
+ mutationResult: awaitedMutationResult,
94
+ createdIds,
95
+ nonce
96
+ };
97
+ }
98
+ if (!retryPolicy.shouldRetry(attempt, void 0, signal)) return {
99
+ success: false,
100
+ reason: "conflict"
101
+ };
102
+ const delayMs = retryPolicy.getDelayMs(attempt);
103
+ if (delayMs > 0) await new Promise((resolve) => setTimeout(resolve, delayMs));
104
+ attempt++;
105
+ } catch (error) {
106
+ return {
107
+ success: false,
108
+ reason: "error",
109
+ error
110
+ };
111
+ }
112
+ }
113
+ }
114
+ /**
115
+ * Execute a Unit of Work with explicit phase control and automatic retry support.
116
+ *
117
+ * This function provides an alternative API where users write a single callback that receives
118
+ * a context object with forSchema, executeRetrieve, and executeMutate methods. The user can
119
+ * create schema-specific UOWs via forSchema, then call executeRetrieve() and executeMutate()
120
+ * to execute the retrieval and mutation phases. The entire callback is re-executed on optimistic
121
+ * concurrency conflicts, ensuring retries work properly.
122
+ *
123
+ * @param callback - Async function that receives a context with forSchema, executeRetrieve, executeMutate, nonce, and currentAttempt
124
+ * @param options - Configuration including UOW factory, retry policy, and abort signal
125
+ * @returns Promise resolving to the callback's return value
126
+ * @throws Error if retries are exhausted or callback throws an error
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * const { userId, profileId } = await executeRestrictedUnitOfWork(
131
+ * async ({ forSchema, executeRetrieve, executeMutate, nonce, currentAttempt }) => {
132
+ * const uow = forSchema(schema);
133
+ * const userId = uow.create("users", { name: "John" });
134
+ *
135
+ * // Execute retrieval phase
136
+ * await executeRetrieve();
137
+ *
138
+ * const profileId = uow.create("profiles", { userId });
139
+ *
140
+ * // Execute mutation phase
141
+ * await executeMutate();
142
+ *
143
+ * return { userId, profileId };
144
+ * },
145
+ * {
146
+ * createUnitOfWork: () => db.createUnitOfWork(),
147
+ * retryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 5 })
148
+ * }
149
+ * );
150
+ * ```
151
+ */
152
+ async function executeRestrictedUnitOfWork(callback, options) {
153
+ const retryPolicy = options.retryPolicy ?? new ExponentialBackoffRetryPolicy({
154
+ maxRetries: 5,
155
+ initialDelayMs: 10,
156
+ maxDelayMs: 100
157
+ });
158
+ const signal = options.signal;
159
+ let attempt = 0;
160
+ while (true) {
161
+ if (signal?.aborted) throw new Error("Unit of Work execution aborted");
162
+ try {
163
+ const baseUow = options.createUnitOfWork();
164
+ return await awaitPromisesInObject(await callback({
165
+ forSchema: (schema, hooks) => {
166
+ return baseUow.forSchema(schema, hooks);
167
+ },
168
+ executeRetrieve: async () => {
169
+ await baseUow.executeRetrieve();
170
+ },
171
+ executeMutate: async () => {
172
+ if (baseUow.state === "executed") return;
173
+ if (baseUow.state === "building-retrieval") await baseUow.executeRetrieve();
174
+ if (options.onBeforeMutate) options.onBeforeMutate(baseUow);
175
+ if (!(await baseUow.executeMutations()).success) throw new ConcurrencyConflictError();
176
+ if (options.onSuccess) await options.onSuccess(baseUow);
177
+ },
178
+ nonce: baseUow.nonce,
179
+ currentAttempt: attempt
180
+ }));
181
+ } catch (error) {
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
+ //#endregion
196
+ export { executeRestrictedUnitOfWork, executeUnitOfWork };
197
+ //# 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"],"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 // Wait before retrying\n const delayMs = retryPolicy.getDelayMs(attempt);\n if (delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n // Increment attempt counter for next iteration\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 * 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 // Wait before retrying\n const delayMs = retryPolicy.getDelayMs(attempt);\n if (delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n // Increment attempt counter for next iteration\n attempt++;\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ //#region src/query/unit-of-work/retry-policy.d.ts
2
+ /**
3
+ * Policy for retrying failed Unit of Work operations
4
+ */
5
+ interface RetryPolicy {
6
+ /**
7
+ * Determines if the operation should be retried
8
+ * @param attempt - The current attempt number (0-indexed)
9
+ * @param error - Optional error from the previous attempt
10
+ * @param signal - Optional AbortSignal to check for cancellation
11
+ * @returns true if the operation should be retried, false otherwise
12
+ */
13
+ shouldRetry(attempt: number, error?: unknown, signal?: AbortSignal): boolean;
14
+ /**
15
+ * Gets the delay in milliseconds before the next retry attempt
16
+ * @param attempt - The current attempt number (0-indexed)
17
+ * @returns Delay in milliseconds
18
+ */
19
+ getDelayMs(attempt: number): number;
20
+ }
21
+ /**
22
+ * Options for exponential backoff retry policy
23
+ */
24
+ interface ExponentialBackoffRetryPolicyOptions {
25
+ /**
26
+ * Maximum number of retry attempts (default: 3)
27
+ */
28
+ maxRetries?: number;
29
+ /**
30
+ * Initial delay in milliseconds (default: 100)
31
+ */
32
+ initialDelayMs?: number;
33
+ /**
34
+ * Maximum delay in milliseconds (default: 10000)
35
+ */
36
+ maxDelayMs?: number;
37
+ /**
38
+ * Multiplier for exponential backoff (default: 2)
39
+ */
40
+ backoffMultiplier?: number;
41
+ }
42
+ /**
43
+ * Exponential backoff retry policy
44
+ * Delay increases exponentially: initialDelay * (multiplier ^ attempt)
45
+ */
46
+ declare class ExponentialBackoffRetryPolicy implements RetryPolicy {
47
+ #private;
48
+ constructor(options?: ExponentialBackoffRetryPolicyOptions);
49
+ shouldRetry(attempt: number, _error?: unknown, signal?: AbortSignal): boolean;
50
+ getDelayMs(attempt: number): number;
51
+ }
52
+ /**
53
+ * Options for linear backoff retry policy
54
+ */
55
+ interface LinearBackoffRetryPolicyOptions {
56
+ /**
57
+ * Maximum number of retry attempts (default: 3)
58
+ */
59
+ maxRetries?: number;
60
+ /**
61
+ * Base delay in milliseconds (default: 100)
62
+ */
63
+ delayMs?: number;
64
+ /**
65
+ * Increment added to delay for each attempt in milliseconds (default: 100)
66
+ */
67
+ incrementMs?: number;
68
+ }
69
+ /**
70
+ * Linear backoff retry policy
71
+ * Delay increases linearly: delayMs + (attempt * incrementMs)
72
+ */
73
+ declare class LinearBackoffRetryPolicy implements RetryPolicy {
74
+ #private;
75
+ constructor(options?: LinearBackoffRetryPolicyOptions);
76
+ shouldRetry(attempt: number, _error?: unknown, signal?: AbortSignal): boolean;
77
+ getDelayMs(attempt: number): number;
78
+ }
79
+ /**
80
+ * No retry policy - never retries failed operations
81
+ */
82
+ declare class NoRetryPolicy implements RetryPolicy {
83
+ shouldRetry(_attempt: number, _error?: unknown, _signal?: AbortSignal): boolean;
84
+ getDelayMs(_attempt: number): number;
85
+ }
86
+ //#endregion
87
+ export { ExponentialBackoffRetryPolicy, LinearBackoffRetryPolicy, NoRetryPolicy, RetryPolicy };
88
+ //# sourceMappingURL=retry-policy.d.ts.map
@@ -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"}
@@ -0,0 +1,61 @@
1
+ //#region src/query/unit-of-work/retry-policy.ts
2
+ /**
3
+ * Exponential backoff retry policy
4
+ * Delay increases exponentially: initialDelay * (multiplier ^ attempt)
5
+ */
6
+ var ExponentialBackoffRetryPolicy = class {
7
+ #maxRetries;
8
+ #initialDelayMs;
9
+ #maxDelayMs;
10
+ #backoffMultiplier;
11
+ constructor(options = {}) {
12
+ this.#maxRetries = options.maxRetries ?? 3;
13
+ this.#initialDelayMs = options.initialDelayMs ?? 100;
14
+ this.#maxDelayMs = options.maxDelayMs ?? 1e4;
15
+ this.#backoffMultiplier = options.backoffMultiplier ?? 2;
16
+ }
17
+ shouldRetry(attempt, _error, signal) {
18
+ if (signal?.aborted) return false;
19
+ return attempt < this.#maxRetries;
20
+ }
21
+ getDelayMs(attempt) {
22
+ const delay = this.#initialDelayMs * Math.pow(this.#backoffMultiplier, attempt);
23
+ return Math.min(delay, this.#maxDelayMs);
24
+ }
25
+ };
26
+ /**
27
+ * Linear backoff retry policy
28
+ * Delay increases linearly: delayMs + (attempt * incrementMs)
29
+ */
30
+ var LinearBackoffRetryPolicy = class {
31
+ #maxRetries;
32
+ #delayMs;
33
+ #incrementMs;
34
+ constructor(options = {}) {
35
+ this.#maxRetries = options.maxRetries ?? 3;
36
+ this.#delayMs = options.delayMs ?? 100;
37
+ this.#incrementMs = options.incrementMs ?? 100;
38
+ }
39
+ shouldRetry(attempt, _error, signal) {
40
+ if (signal?.aborted) return false;
41
+ return attempt < this.#maxRetries;
42
+ }
43
+ getDelayMs(attempt) {
44
+ return this.#delayMs + attempt * this.#incrementMs;
45
+ }
46
+ };
47
+ /**
48
+ * No retry policy - never retries failed operations
49
+ */
50
+ var NoRetryPolicy = class {
51
+ shouldRetry(_attempt, _error, _signal) {
52
+ return false;
53
+ }
54
+ getDelayMs(_attempt) {
55
+ return 0;
56
+ }
57
+ };
58
+
59
+ //#endregion
60
+ export { ExponentialBackoffRetryPolicy, LinearBackoffRetryPolicy, NoRetryPolicy };
61
+ //# sourceMappingURL=retry-policy.js.map
@@ -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"}