@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,105 @@
1
+ import "../../query/cursor.js";
2
+ import { createTableNameMapper } from "./table-name-mapper.js";
3
+
4
+ //#region src/adapters/shared/uow-operation-compiler.ts
5
+ /**
6
+ * Abstract base class for Unit of Work operation compilers
7
+ *
8
+ * This class provides a structure and utilities for implementing UOW compilers
9
+ * for different ORM/query builders (Kysely, Drizzle, etc.).
10
+ *
11
+ * Subclasses must implement the abstract methods for each operation type,
12
+ * and can use the provided utility methods for common tasks.
13
+ *
14
+ * @template TCompiledQuery - The type of compiled query for the target ORM
15
+ */
16
+ var UOWOperationCompiler = class {
17
+ #driverConfig;
18
+ #mapperFactory;
19
+ constructor(driverConfig, mapperFactory) {
20
+ this.#driverConfig = driverConfig;
21
+ this.#mapperFactory = mapperFactory;
22
+ }
23
+ get driverConfig() {
24
+ return this.#driverConfig;
25
+ }
26
+ get mapperFactory() {
27
+ return this.#mapperFactory;
28
+ }
29
+ /**
30
+ * Get the mapper for a specific operation based on its namespace
31
+ */
32
+ getMapperForOperation(namespace) {
33
+ return this.#mapperFactory ? this.#mapperFactory(namespace) : namespace ? createTableNameMapper(namespace) : void 0;
34
+ }
35
+ /**
36
+ * Get a table from a schema by name
37
+ * @throws Error if table is not found
38
+ */
39
+ getTable(schema, tableName) {
40
+ const table = schema.tables[tableName];
41
+ if (!table) throw new Error(`Invalid table name ${tableName}.`);
42
+ return table;
43
+ }
44
+ /**
45
+ * Get the version to check for a given ID and checkVersion flag
46
+ * @returns The version to check or undefined if no check is required
47
+ * @throws Error if the ID is a string and checkVersion is true
48
+ */
49
+ getVersionToCheck(id, checkVersion) {
50
+ if (!checkVersion) return;
51
+ if (typeof id === "string") throw new Error(`Cannot use checkVersion with a string ID. Version checking requires a FragnoId with version information.`);
52
+ return id.version;
53
+ }
54
+ /**
55
+ * Extract external ID from FragnoId or string
56
+ */
57
+ getExternalId(id) {
58
+ return typeof id === "string" ? id : id.externalId;
59
+ }
60
+ /**
61
+ * Get the physical table name for an operation, applying namespace mapping if needed
62
+ */
63
+ getPhysicalTableName(logicalName, namespace) {
64
+ const mapper = this.getMapperForOperation(namespace);
65
+ return mapper ? mapper.toPhysical(logicalName) : logicalName;
66
+ }
67
+ };
68
+ /**
69
+ * Creates a UOWCompiler from a UOWOperationCompiler by dispatching operations
70
+ * to the appropriate specific compilation methods based on operation type.
71
+ *
72
+ * @template TCompiledQuery - The type of compiled query for the target ORM
73
+ * @param operationCompiler - The operation compiler to wrap
74
+ * @returns A UOWCompiler instance that delegates to the operation compiler
75
+ */
76
+ function createUOWCompilerFromOperationCompiler(operationCompiler) {
77
+ return {
78
+ compileRetrievalOperation(op) {
79
+ switch (op.type) {
80
+ case "count": return operationCompiler.compileCount(op);
81
+ case "find": return operationCompiler.compileFind(op);
82
+ default: {
83
+ const exhaustiveCheck = op;
84
+ throw new Error(`Unknown retrieval operation type: ${exhaustiveCheck.type}`);
85
+ }
86
+ }
87
+ },
88
+ compileMutationOperation(op) {
89
+ switch (op.type) {
90
+ case "create": return operationCompiler.compileCreate(op);
91
+ case "update": return operationCompiler.compileUpdate(op);
92
+ case "delete": return operationCompiler.compileDelete(op);
93
+ case "check": return operationCompiler.compileCheck(op);
94
+ default: {
95
+ const exhaustiveCheck = op;
96
+ throw new Error(`Unknown mutation operation type: ${exhaustiveCheck.type}`);
97
+ }
98
+ }
99
+ }
100
+ };
101
+ }
102
+
103
+ //#endregion
104
+ export { UOWOperationCompiler, createUOWCompilerFromOperationCompiler };
105
+ //# sourceMappingURL=uow-operation-compiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uow-operation-compiler.js","names":["#driverConfig","#mapperFactory","exhaustiveCheck: never"],"sources":["../../../src/adapters/shared/uow-operation-compiler.ts"],"sourcesContent":["import type { AnyColumn, AnySchema, AnyTable, FragnoId } from \"../../schema/create\";\nimport type { Condition } from \"../../query/condition-builder\";\nimport type {\n CompiledMutation,\n RetrievalOperation,\n MutationOperation,\n UOWCompiler,\n} from \"../../query/unit-of-work/unit-of-work\";\nimport { Cursor } from \"../../query/cursor\";\nimport type { DriverConfig } from \"../generic-sql/driver-config\";\nimport { createTableNameMapper, type TableNameMapper } from \"./table-name-mapper\";\n\n/**\n * Options for compiling a find operation with cursor pagination\n */\nexport interface FindCompilationOptions {\n /** Index columns used for ordering */\n indexColumns: AnyColumn[];\n /** Order direction for the index */\n orderDirection: \"asc\" | \"desc\";\n /** User-provided where condition */\n userWhere: Condition | boolean | undefined;\n /** Cursor string or Cursor object for pagination (after) */\n after?: string | Cursor;\n /** Cursor string or Cursor object for pagination (before) */\n before?: string | Cursor;\n /** Page size for pagination */\n pageSize?: number;\n /** Whether this is a high-level cursor API call (affects limit calculation) */\n withCursor?: boolean;\n /** Driver config for cursor serialization */\n driverConfig: DriverConfig;\n}\n\n/**\n * Result of cursor condition building\n */\nexport interface CursorConditionResult {\n /** The combined where condition (user where + cursor condition) */\n where: Condition | undefined;\n /** The effective limit to use (may be pageSize + 1 for cursor detection) */\n limit: number | undefined;\n}\n\n/**\n * Abstract base class for Unit of Work operation compilers\n *\n * This class provides a structure and utilities for implementing UOW compilers\n * for different ORM/query builders (Kysely, Drizzle, etc.).\n *\n * Subclasses must implement the abstract methods for each operation type,\n * and can use the provided utility methods for common tasks.\n *\n * @template TCompiledQuery - The type of compiled query for the target ORM\n */\nexport abstract class UOWOperationCompiler<TCompiledQuery> {\n #driverConfig: DriverConfig;\n #mapperFactory?: (namespace: string | undefined) => TableNameMapper | undefined;\n\n constructor(\n driverConfig: DriverConfig,\n mapperFactory?: (namespace: string | undefined) => TableNameMapper | undefined,\n ) {\n this.#driverConfig = driverConfig;\n this.#mapperFactory = mapperFactory;\n }\n\n protected get driverConfig(): DriverConfig {\n return this.#driverConfig;\n }\n\n protected get mapperFactory():\n | ((namespace: string | undefined) => TableNameMapper | undefined)\n | undefined {\n return this.#mapperFactory;\n }\n\n abstract compileCount(\n op: RetrievalOperation<AnySchema> & { type: \"count\" },\n ): TCompiledQuery | null;\n\n abstract compileFind(op: RetrievalOperation<AnySchema> & { type: \"find\" }): TCompiledQuery | null;\n\n /**\n * Compile a create operation\n */\n abstract compileCreate(\n op: MutationOperation<AnySchema> & { type: \"create\" },\n ): CompiledMutation<TCompiledQuery> | null;\n\n abstract compileUpdate(\n op: MutationOperation<AnySchema> & { type: \"update\" },\n ): CompiledMutation<TCompiledQuery> | null;\n\n abstract compileDelete(\n op: MutationOperation<AnySchema> & { type: \"delete\" },\n ): CompiledMutation<TCompiledQuery> | null;\n\n abstract compileCheck(\n op: MutationOperation<AnySchema> & { type: \"check\" },\n ): CompiledMutation<TCompiledQuery> | null;\n\n // ==================== Utility Methods ====================\n\n /**\n * Get the mapper for a specific operation based on its namespace\n */\n protected getMapperForOperation(namespace: string | undefined): TableNameMapper | undefined {\n return this.#mapperFactory\n ? this.#mapperFactory(namespace)\n : namespace\n ? createTableNameMapper(namespace)\n : undefined;\n }\n\n /**\n * Get a table from a schema by name\n * @throws Error if table is not found\n */\n protected getTable(schema: AnySchema, tableName: string): AnyTable {\n const table = schema.tables[tableName];\n if (!table) {\n throw new Error(`Invalid table name ${tableName}.`);\n }\n return table;\n }\n\n /**\n * Get the version to check for a given ID and checkVersion flag\n * @returns The version to check or undefined if no check is required\n * @throws Error if the ID is a string and checkVersion is true\n */\n protected getVersionToCheck(id: FragnoId | string, checkVersion: boolean): number | undefined {\n if (!checkVersion) {\n return undefined;\n }\n\n if (typeof id === \"string\") {\n throw new Error(\n `Cannot use checkVersion with a string ID. Version checking requires a FragnoId with version information.`,\n );\n }\n\n return id.version;\n }\n\n /**\n * Extract external ID from FragnoId or string\n */\n protected getExternalId(id: FragnoId | string): string {\n return typeof id === \"string\" ? id : id.externalId;\n }\n\n /**\n * Get the physical table name for an operation, applying namespace mapping if needed\n */\n protected getPhysicalTableName(logicalName: string, namespace: string | undefined): string {\n const mapper = this.getMapperForOperation(namespace);\n return mapper ? mapper.toPhysical(logicalName) : logicalName;\n }\n}\n\n/**\n * Creates a UOWCompiler from a UOWOperationCompiler by dispatching operations\n * to the appropriate specific compilation methods based on operation type.\n *\n * @template TCompiledQuery - The type of compiled query for the target ORM\n * @param operationCompiler - The operation compiler to wrap\n * @returns A UOWCompiler instance that delegates to the operation compiler\n */\nexport function createUOWCompilerFromOperationCompiler<TCompiledQuery>(\n operationCompiler: UOWOperationCompiler<TCompiledQuery>,\n): UOWCompiler<TCompiledQuery> {\n return {\n compileRetrievalOperation(op: RetrievalOperation<AnySchema>): TCompiledQuery | null {\n switch (op.type) {\n case \"count\":\n return operationCompiler.compileCount(op);\n case \"find\":\n return operationCompiler.compileFind(op);\n default: {\n const exhaustiveCheck: never = op;\n throw new Error(\n `Unknown retrieval operation type: ${(exhaustiveCheck as RetrievalOperation<AnySchema>).type}`,\n );\n }\n }\n },\n\n compileMutationOperation(\n op: MutationOperation<AnySchema>,\n ): CompiledMutation<TCompiledQuery> | null {\n switch (op.type) {\n case \"create\":\n return operationCompiler.compileCreate(op);\n case \"update\":\n return operationCompiler.compileUpdate(op);\n case \"delete\":\n return operationCompiler.compileDelete(op);\n case \"check\":\n return operationCompiler.compileCheck(op);\n default: {\n const exhaustiveCheck: never = op;\n throw new Error(\n `Unknown mutation operation type: ${(exhaustiveCheck as MutationOperation<AnySchema>).type}`,\n );\n }\n }\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;AAuDA,IAAsB,uBAAtB,MAA2D;CACzD;CACA;CAEA,YACE,cACA,eACA;AACA,QAAKA,eAAgB;AACrB,QAAKC,gBAAiB;;CAGxB,IAAc,eAA6B;AACzC,SAAO,MAAKD;;CAGd,IAAc,gBAEA;AACZ,SAAO,MAAKC;;;;;CAiCd,AAAU,sBAAsB,WAA4D;AAC1F,SAAO,MAAKA,gBACR,MAAKA,cAAe,UAAU,GAC9B,YACE,sBAAsB,UAAU,GAChC;;;;;;CAOR,AAAU,SAAS,QAAmB,WAA6B;EACjE,MAAM,QAAQ,OAAO,OAAO;AAC5B,MAAI,CAAC,MACH,OAAM,IAAI,MAAM,sBAAsB,UAAU,GAAG;AAErD,SAAO;;;;;;;CAQT,AAAU,kBAAkB,IAAuB,cAA2C;AAC5F,MAAI,CAAC,aACH;AAGF,MAAI,OAAO,OAAO,SAChB,OAAM,IAAI,MACR,2GACD;AAGH,SAAO,GAAG;;;;;CAMZ,AAAU,cAAc,IAA+B;AACrD,SAAO,OAAO,OAAO,WAAW,KAAK,GAAG;;;;;CAM1C,AAAU,qBAAqB,aAAqB,WAAuC;EACzF,MAAM,SAAS,KAAK,sBAAsB,UAAU;AACpD,SAAO,SAAS,OAAO,WAAW,YAAY,GAAG;;;;;;;;;;;AAYrD,SAAgB,uCACd,mBAC6B;AAC7B,QAAO;EACL,0BAA0B,IAA0D;AAClF,WAAQ,GAAG,MAAX;IACE,KAAK,QACH,QAAO,kBAAkB,aAAa,GAAG;IAC3C,KAAK,OACH,QAAO,kBAAkB,YAAY,GAAG;IAC1C,SAAS;KACP,MAAMC,kBAAyB;AAC/B,WAAM,IAAI,MACR,qCAAsC,gBAAkD,OACzF;;;;EAKP,yBACE,IACyC;AACzC,WAAQ,GAAG,MAAX;IACE,KAAK,SACH,QAAO,kBAAkB,cAAc,GAAG;IAC5C,KAAK,SACH,QAAO,kBAAkB,cAAc,GAAG;IAC5C,KAAK,SACH,QAAO,kBAAkB,cAAc,GAAG;IAC5C,KAAK,QACH,QAAO,kBAAkB,aAAa,GAAG;IAC3C,SAAS;KACP,MAAMA,kBAAyB;AAC/B,WAAM,IAAI,MACR,oCAAqC,gBAAiD,OACvF;;;;EAIR"}
@@ -0,0 +1,186 @@
1
+ import { AnySchema } from "./schema/create.js";
2
+ import { AwaitedPromisesInObject, ExecuteRestrictedUnitOfWorkOptions } from "./query/unit-of-work/execute-unit-of-work.js";
3
+ import { HookContext, HookFn, HooksMap } from "./hooks/hooks.js";
4
+ import { IUnitOfWork, TypedUnitOfWork } from "./query/unit-of-work/unit-of-work.js";
5
+ import { SimpleQueryInterface } from "./query/simple-query-interface.js";
6
+ import { DatabaseAdapter } from "./adapters/adapters.js";
7
+ import { AnyFragnoInstantiatedFragment, FragmentDefinition, FragmentDefinitionBuilder, FragnoPublicConfig, RequestThisContext, ServiceConstructorFn } from "@fragno-dev/core";
8
+
9
+ //#region src/db-fragment-definition-builder.d.ts
10
+
11
+ /**
12
+ * Extended FragnoPublicConfig that includes a database adapter.
13
+ * Use this type when creating fragments with database support.
14
+ */
15
+ type FragnoPublicConfigWithDatabase = FragnoPublicConfig & {
16
+ databaseAdapter: DatabaseAdapter<any>;
17
+ };
18
+ /**
19
+ * Implicit dependencies that database fragments get automatically.
20
+ * These are injected without requiring explicit configuration.
21
+ */
22
+ type ImplicitDatabaseDependencies<TSchema extends AnySchema> = {
23
+ /**
24
+ * Database query engine for the fragment's schema.
25
+ */
26
+ db: SimpleQueryInterface<TSchema>;
27
+ /**
28
+ * The schema definition for this fragment.
29
+ */
30
+ schema: TSchema;
31
+ /**
32
+ * The database namespace for this fragment.
33
+ */
34
+ namespace: string;
35
+ /**
36
+ * Create a new Unit of Work for database operations.
37
+ */
38
+ createUnitOfWork: () => IUnitOfWork;
39
+ };
40
+ /**
41
+ * Service context for database fragments - provides restricted UOW access without execute methods.
42
+ */
43
+ type DatabaseServiceContext<THooks extends HooksMap> = RequestThisContext & {
44
+ /**
45
+ * Get a typed, restricted Unit of Work for the given schema.
46
+ * @param schema - Schema to get a typed view for
47
+ * @returns TypedUnitOfWork (restricted version without execute methods)
48
+ */
49
+ uow<TSchema extends AnySchema>(schema: TSchema): TypedUnitOfWork<TSchema, [], unknown, THooks>;
50
+ };
51
+ /**
52
+ * Handler context for database fragments - provides UOW execution with automatic retry support.
53
+ */
54
+ type DatabaseHandlerContext<THooks extends HooksMap = {}> = RequestThisContext & {
55
+ /**
56
+ * Execute a Unit of Work with explicit phase control and automatic retry support.
57
+ * This method provides an API where users call forSchema to create a schema-specific
58
+ * UOW, then call executeRetrieve() and executeMutate() to execute the phases. The entire
59
+ * callback is re-executed on optimistic concurrency conflicts, ensuring retries work properly.
60
+ * Automatically provides the UOW factory from context.
61
+ * Promises in the returned object are awaited 1 level deep.
62
+ *
63
+ * @param callback - Async function that receives a context with forSchema, executeRetrieve, executeMutate, nonce, and currentAttempt
64
+ * @param options - Optional configuration for retry policy and abort signal
65
+ * @returns Promise resolving to the callback's return value with promises awaited 1 level deep
66
+ * @throws Error if retries are exhausted or callback throws an error
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * const result = await this.uow(async ({ forSchema, executeRetrieve, executeMutate, nonce, currentAttempt }) => {
71
+ * const uow = forSchema(schema);
72
+ * const userId = uow.create("users", { name: "John" });
73
+ *
74
+ * // Execute retrieval phase
75
+ * await executeRetrieve();
76
+ *
77
+ * const profileId = uow.create("profiles", { userId });
78
+ *
79
+ * // Execute mutation phase
80
+ * await executeMutate();
81
+ *
82
+ * return { userId, profileId };
83
+ * });
84
+ * ```
85
+ */
86
+ uow<TResult>(callback: (context: {
87
+ forSchema: <TSchema extends AnySchema, H extends HooksMap = THooks>(schema: TSchema, hooks?: H) => TypedUnitOfWork<TSchema, [], unknown, H>;
88
+ executeRetrieve: () => Promise<void>;
89
+ executeMutate: () => Promise<void>;
90
+ nonce: string;
91
+ currentAttempt: number;
92
+ }) => Promise<TResult> | TResult, options?: Omit<ExecuteRestrictedUnitOfWorkOptions, "createUnitOfWork">): Promise<AwaitedPromisesInObject<TResult>>;
93
+ };
94
+ /**
95
+ * Database fragment context provided to user callbacks.
96
+ */
97
+ type DatabaseFragmentContext<TSchema extends AnySchema> = {
98
+ /**
99
+ * Database adapter instance.
100
+ */
101
+ databaseAdapter: DatabaseAdapter<any>;
102
+ /**
103
+ * ORM query engine for the fragment's schema.
104
+ */
105
+ db: SimpleQueryInterface<TSchema>;
106
+ };
107
+ /**
108
+ * Storage type for database fragments - stores the Unit of Work.
109
+ */
110
+ type DatabaseRequestStorage = {
111
+ uow: IUnitOfWork;
112
+ };
113
+ /**
114
+ * Builder for database fragments that wraps the core fragment builder
115
+ * and provides database-specific functionality.
116
+ *
117
+ * Database fragments always require FragnoPublicConfigWithDatabase (which includes databaseAdapter).
118
+ */
119
+ declare class DatabaseFragmentDefinitionBuilder<TSchema extends AnySchema, TConfig, TDeps, TBaseServices, TServices, TServiceDependencies, TPrivateServices, THooks extends HooksMap = {}, TServiceThisContext extends RequestThisContext = DatabaseHandlerContext, THandlerThisContext extends RequestThisContext = DatabaseHandlerContext, TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment> = {}> {
120
+ #private;
121
+ constructor(baseBuilder: FragmentDefinitionBuilder<TConfig, FragnoPublicConfigWithDatabase, TDeps, TBaseServices, TServices, TServiceDependencies, TPrivateServices, TServiceThisContext, THandlerThisContext, DatabaseRequestStorage, TLinkedFragments>, schema: TSchema, namespace?: string, hooksFactory?: (context: {
122
+ config: TConfig;
123
+ options: FragnoPublicConfigWithDatabase;
124
+ }) => THooks);
125
+ /**
126
+ * Define dependencies for this database fragment.
127
+ * The context includes database adapter and ORM instance.
128
+ */
129
+ withDependencies<TNewDeps>(fn: (context: {
130
+ config: TConfig;
131
+ options: FragnoPublicConfigWithDatabase;
132
+ db: SimpleQueryInterface<TSchema>;
133
+ databaseAdapter: DatabaseAdapter<any>;
134
+ }) => TNewDeps): DatabaseFragmentDefinitionBuilder<TSchema, TConfig, TNewDeps & ImplicitDatabaseDependencies<TSchema>, {}, {}, TServiceDependencies, {}, THooks, TServiceThisContext, THandlerThisContext, TLinkedFragments>;
135
+ providesBaseService<TNewService>(fn: ServiceConstructorFn<TConfig, FragnoPublicConfigWithDatabase, TDeps, TServiceDependencies, TPrivateServices, TNewService, TServiceThisContext>): DatabaseFragmentDefinitionBuilder<TSchema, TConfig, TDeps, TNewService, TServices, TServiceDependencies, TPrivateServices, THooks, TServiceThisContext, THandlerThisContext, TLinkedFragments>;
136
+ providesService<TServiceName extends string, TService>(serviceName: TServiceName, fn: ServiceConstructorFn<TConfig, FragnoPublicConfigWithDatabase, TDeps, TServiceDependencies, TPrivateServices, TService, TServiceThisContext>): DatabaseFragmentDefinitionBuilder<TSchema, TConfig, TDeps, TBaseServices, TServices & { [K in TServiceName]: TService }, TServiceDependencies, TPrivateServices, THooks, TServiceThisContext, THandlerThisContext, TLinkedFragments>;
137
+ /**
138
+ * Provide a private service that is only accessible to the fragment author.
139
+ * Private services are NOT exposed on the fragment instance, but can be used
140
+ * when defining other services (baseServices, namedServices, and other privateServices).
141
+ * Private services are instantiated in order, so earlier private services are available
142
+ * to later ones.
143
+ */
144
+ providesPrivateService<TServiceName extends string, TService>(serviceName: TServiceName, fn: ServiceConstructorFn<TConfig, FragnoPublicConfigWithDatabase, TDeps, TServiceDependencies, TPrivateServices, TService, TServiceThisContext>): DatabaseFragmentDefinitionBuilder<TSchema, TConfig, TDeps, TBaseServices, TServices, TServiceDependencies, TPrivateServices & { [K in TServiceName]: TService }, THooks, TServiceThisContext, THandlerThisContext, TLinkedFragments>;
145
+ /**
146
+ * Define durable hooks for this fragment.
147
+ * Hooks are automatically persisted and retried on failure.
148
+ *
149
+ * @param fn - Function that receives defineHook helper and returns a hooks map
150
+ * @returns Builder with hooks type set
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * .provideHooks(({ defineHook, config }) => ({
155
+ * onSubscribe: defineHook(async function (payload: { email: string }) {
156
+ * // 'this' context available (HookServiceContext with nonce)
157
+ * await config.onSubscribe?.(payload.email);
158
+ * }),
159
+ * }))
160
+ * ```
161
+ */
162
+ provideHooks<TNewHooks extends HooksMap>(fn: (context: {
163
+ config: TConfig;
164
+ options: FragnoPublicConfigWithDatabase;
165
+ defineHook: <TPayload>(hook: (this: HookContext, payload: TPayload) => void | Promise<void>) => HookFn<TPayload>;
166
+ }) => TNewHooks): DatabaseFragmentDefinitionBuilder<TSchema, TConfig, TDeps, TBaseServices, TServices, TServiceDependencies, TPrivateServices, TNewHooks, DatabaseServiceContext<TNewHooks>, THandlerThisContext, TLinkedFragments>;
167
+ /**
168
+ * Declare that this fragment uses a required service provided by the runtime.
169
+ * Delegates to the base builder.
170
+ */
171
+ usesService<TServiceName extends string, TService>(serviceName: TServiceName): DatabaseFragmentDefinitionBuilder<TSchema, TConfig, TDeps, TBaseServices, TServices, TServiceDependencies & { [K in TServiceName]: TService }, TPrivateServices, THooks, TServiceThisContext, THandlerThisContext, TLinkedFragments>;
172
+ /**
173
+ * Declare that this fragment uses an optional service provided by the runtime.
174
+ * Delegates to the base builder.
175
+ */
176
+ usesOptionalService<TServiceName extends string, TService>(serviceName: TServiceName): DatabaseFragmentDefinitionBuilder<TSchema, TConfig, TDeps, TBaseServices, TServices, TServiceDependencies & { [K in TServiceName]: TService | undefined }, TPrivateServices, THooks, TServiceThisContext, THandlerThisContext, TLinkedFragments>;
177
+ /**
178
+ * Build the final database fragment definition.
179
+ * This includes the request context setup for UnitOfWork management.
180
+ * Note: TDeps already includes ImplicitDatabaseDependencies from withDatabase().
181
+ */
182
+ build(): FragmentDefinition<TConfig, FragnoPublicConfigWithDatabase, TDeps, TBaseServices, TServices, TServiceDependencies, TPrivateServices, DatabaseServiceContext<THooks>, DatabaseHandlerContext<THooks>, DatabaseRequestStorage, TLinkedFragments>;
183
+ }
184
+ //#endregion
185
+ export { DatabaseFragmentContext, DatabaseFragmentDefinitionBuilder, DatabaseHandlerContext, DatabaseRequestStorage, DatabaseServiceContext, FragnoPublicConfigWithDatabase, ImplicitDatabaseDependencies };
186
+ //# sourceMappingURL=db-fragment-definition-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-fragment-definition-builder.d.ts","names":[],"sources":["../src/db-fragment-definition-builder.ts"],"sourcesContent":[],"mappings":"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"}
@@ -0,0 +1,207 @@
1
+ import "./query/unit-of-work/unit-of-work.js";
2
+ import { executeRestrictedUnitOfWork } from "./query/unit-of-work/execute-unit-of-work.js";
3
+ import { prepareHookMutations, processHooks } from "./hooks/hooks.js";
4
+
5
+ //#region src/db-fragment-definition-builder.ts
6
+ /**
7
+ * Create database context from options.
8
+ * This extracts the database adapter and creates the ORM instance.
9
+ */
10
+ function createDatabaseContext(options, schema, namespace) {
11
+ const databaseAdapter = options.databaseAdapter;
12
+ if (!databaseAdapter) throw new Error("Database fragment requires a database adapter to be provided in options.databaseAdapter");
13
+ return {
14
+ databaseAdapter,
15
+ db: databaseAdapter.createQueryEngine(schema, namespace)
16
+ };
17
+ }
18
+ /**
19
+ * Builder for database fragments that wraps the core fragment builder
20
+ * and provides database-specific functionality.
21
+ *
22
+ * Database fragments always require FragnoPublicConfigWithDatabase (which includes databaseAdapter).
23
+ */
24
+ var DatabaseFragmentDefinitionBuilder = class DatabaseFragmentDefinitionBuilder {
25
+ #baseBuilder;
26
+ #schema;
27
+ #namespace;
28
+ #hooksFactory;
29
+ constructor(baseBuilder, schema, namespace, hooksFactory) {
30
+ this.#baseBuilder = baseBuilder;
31
+ this.#schema = schema;
32
+ this.#namespace = namespace ?? baseBuilder.name;
33
+ this.#hooksFactory = hooksFactory;
34
+ }
35
+ /**
36
+ * Define dependencies for this database fragment.
37
+ * The context includes database adapter and ORM instance.
38
+ */
39
+ withDependencies(fn) {
40
+ const wrappedFn = (context) => {
41
+ const dbContext = createDatabaseContext(context.options, this.#schema, this.#namespace);
42
+ const userDeps = fn({
43
+ config: context.config,
44
+ options: context.options,
45
+ db: dbContext.db,
46
+ databaseAdapter: dbContext.databaseAdapter
47
+ });
48
+ const createUow = () => dbContext.db.createUnitOfWork();
49
+ const implicitDeps = {
50
+ db: dbContext.db,
51
+ schema: this.#schema,
52
+ namespace: this.#namespace,
53
+ createUnitOfWork: createUow
54
+ };
55
+ return {
56
+ ...userDeps,
57
+ ...implicitDeps
58
+ };
59
+ };
60
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.withDependencies(wrappedFn), this.#schema, this.#namespace, this.#hooksFactory);
61
+ }
62
+ providesBaseService(fn) {
63
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.providesBaseService(fn), this.#schema, this.#namespace, this.#hooksFactory);
64
+ }
65
+ providesService(serviceName, fn) {
66
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.providesService(serviceName, fn), this.#schema, this.#namespace, this.#hooksFactory);
67
+ }
68
+ /**
69
+ * Provide a private service that is only accessible to the fragment author.
70
+ * Private services are NOT exposed on the fragment instance, but can be used
71
+ * when defining other services (baseServices, namedServices, and other privateServices).
72
+ * Private services are instantiated in order, so earlier private services are available
73
+ * to later ones.
74
+ */
75
+ providesPrivateService(serviceName, fn) {
76
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.providesPrivateService(serviceName, fn), this.#schema, this.#namespace, this.#hooksFactory);
77
+ }
78
+ /**
79
+ * Define durable hooks for this fragment.
80
+ * Hooks are automatically persisted and retried on failure.
81
+ *
82
+ * @param fn - Function that receives defineHook helper and returns a hooks map
83
+ * @returns Builder with hooks type set
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * .provideHooks(({ defineHook, config }) => ({
88
+ * onSubscribe: defineHook(async function (payload: { email: string }) {
89
+ * // 'this' context available (HookServiceContext with nonce)
90
+ * await config.onSubscribe?.(payload.email);
91
+ * }),
92
+ * }))
93
+ * ```
94
+ */
95
+ provideHooks(fn) {
96
+ const defineHook = (hook) => {
97
+ return hook;
98
+ };
99
+ const hooksFactory = (context) => {
100
+ return fn({
101
+ config: context.config,
102
+ options: context.options,
103
+ defineHook
104
+ });
105
+ };
106
+ const newBuilder = new DatabaseFragmentDefinitionBuilder(this.#baseBuilder, this.#schema, this.#namespace);
107
+ newBuilder.#hooksFactory = hooksFactory;
108
+ return newBuilder;
109
+ }
110
+ /**
111
+ * Declare that this fragment uses a required service provided by the runtime.
112
+ * Delegates to the base builder.
113
+ */
114
+ usesService(serviceName) {
115
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.usesService(serviceName), this.#schema, this.#namespace, this.#hooksFactory);
116
+ }
117
+ /**
118
+ * Declare that this fragment uses an optional service provided by the runtime.
119
+ * Delegates to the base builder.
120
+ */
121
+ usesOptionalService(serviceName) {
122
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.usesOptionalService(serviceName), this.#schema, this.#namespace, this.#hooksFactory);
123
+ }
124
+ /**
125
+ * Build the final database fragment definition.
126
+ * This includes the request context setup for UnitOfWork management.
127
+ * Note: TDeps already includes ImplicitDatabaseDependencies from withDatabase().
128
+ */
129
+ build() {
130
+ const baseDef = this.#baseBuilder.build();
131
+ const dependencies = (context) => {
132
+ let userDeps;
133
+ try {
134
+ userDeps = baseDef.dependencies?.(context);
135
+ } catch (error) {
136
+ if (process.env["FRAGNO_INIT_DRY_RUN"] === "true") {
137
+ console.warn("Warning: Failed to initialize user dependencies in dry run mode:", error instanceof Error ? error.message : String(error));
138
+ userDeps = {};
139
+ } else throw error;
140
+ }
141
+ const { db } = createDatabaseContext(context.options, this.#schema, this.#namespace);
142
+ const implicitDeps = {
143
+ db,
144
+ schema: this.#schema,
145
+ namespace: this.#namespace,
146
+ createUnitOfWork: () => db.createUnitOfWork()
147
+ };
148
+ return {
149
+ ...userDeps,
150
+ ...implicitDeps
151
+ };
152
+ };
153
+ const builderWithStorage = this.#baseBuilder.withExternalRequestStorage(({ options }) => {
154
+ return createDatabaseContext(options, this.#schema, this.#namespace).databaseAdapter.contextStorage;
155
+ }).withRequestStorage(({ options }) => {
156
+ return { uow: createDatabaseContext(options, this.#schema, this.#namespace).db.createUnitOfWork() };
157
+ });
158
+ const internalFragmentFactory = baseDef.linkedFragments?.["_fragno_internal"];
159
+ return {
160
+ ...builderWithStorage.withThisContext(({ storage, config, options }) => {
161
+ const hooksConfig = this.#hooksFactory ? {
162
+ hooks: this.#hooksFactory({
163
+ config,
164
+ options
165
+ }),
166
+ namespace: this.#namespace,
167
+ internalFragment: internalFragmentFactory({
168
+ config,
169
+ options
170
+ })
171
+ } : void 0;
172
+ function forSchema(schema) {
173
+ const uow$1 = storage.getStore()?.uow;
174
+ if (!uow$1) throw new Error("No UnitOfWork in context. Service must be called within a route handler OR using `withUnitOfWork`.");
175
+ return uow$1.restrict().forSchema(schema);
176
+ }
177
+ const serviceContext = { uow: forSchema };
178
+ async function uow(callback, execOptions) {
179
+ const currentStorage = storage.getStore();
180
+ if (!currentStorage) throw new Error("No storage in context. Handler must be called within a request context.");
181
+ const wrappedCallback = async (context) => {
182
+ return callback(context);
183
+ };
184
+ return executeRestrictedUnitOfWork(wrappedCallback, {
185
+ ...execOptions,
186
+ createUnitOfWork: () => {
187
+ currentStorage.uow.reset();
188
+ if (hooksConfig) currentStorage.uow.registerSchema(hooksConfig.internalFragment.$internal.deps.schema, hooksConfig.internalFragment.$internal.deps.namespace);
189
+ return currentStorage.uow;
190
+ },
191
+ onBeforeMutate: hooksConfig ? (uow$1) => prepareHookMutations(uow$1, hooksConfig) : void 0,
192
+ onSuccess: hooksConfig ? () => processHooks(hooksConfig) : void 0
193
+ });
194
+ }
195
+ return {
196
+ serviceContext,
197
+ handlerContext: { uow }
198
+ };
199
+ }).build(),
200
+ dependencies
201
+ };
202
+ }
203
+ };
204
+
205
+ //#endregion
206
+ export { DatabaseFragmentDefinitionBuilder };
207
+ //# sourceMappingURL=db-fragment-definition-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-fragment-definition-builder.js","names":["#baseBuilder","#schema","#namespace","#hooksFactory","implicitDeps: ImplicitDatabaseDependencies<TSchema>","uow","serviceContext: DatabaseServiceContext<THooks>"],"sources":["../src/db-fragment-definition-builder.ts"],"sourcesContent":["import type { AnySchema } from \"./schema/create\";\nimport type { SimpleQueryInterface } from \"./query/simple-query-interface\";\nimport type { DatabaseAdapter } from \"./adapters/adapters\";\nimport type { IUnitOfWork } from \"./query/unit-of-work/unit-of-work\";\nimport { TypedUnitOfWork, UnitOfWork } from \"./query/unit-of-work/unit-of-work\";\nimport type {\n RequestThisContext,\n FragnoPublicConfig,\n AnyFragnoInstantiatedFragment,\n} from \"@fragno-dev/core\";\nimport {\n FragmentDefinitionBuilder,\n type FragmentDefinition,\n type ServiceConstructorFn,\n} from \"@fragno-dev/core\";\nimport {\n executeRestrictedUnitOfWork,\n type AwaitedPromisesInObject,\n type ExecuteRestrictedUnitOfWorkOptions,\n} from \"./query/unit-of-work/execute-unit-of-work\";\nimport {\n prepareHookMutations,\n processHooks,\n type HooksMap,\n type HookFn,\n type HookContext,\n} from \"./hooks/hooks\";\nimport type { InternalFragmentInstance } from \"./fragments/internal-fragment\";\n\n/**\n * Extended FragnoPublicConfig that includes a database adapter.\n * Use this type when creating fragments with database support.\n */\nexport type FragnoPublicConfigWithDatabase = FragnoPublicConfig & {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n databaseAdapter: DatabaseAdapter<any>;\n};\n\n/**\n * Implicit dependencies that database fragments get automatically.\n * These are injected without requiring explicit configuration.\n */\nexport type ImplicitDatabaseDependencies<TSchema extends AnySchema> = {\n /**\n * Database query engine for the fragment's schema.\n */\n db: SimpleQueryInterface<TSchema>;\n /**\n * The schema definition for this fragment.\n */\n schema: TSchema;\n /**\n * The database namespace for this fragment.\n */\n namespace: string;\n /**\n * Create a new Unit of Work for database operations.\n */\n createUnitOfWork: () => IUnitOfWork;\n};\n\n/**\n * Service context for database fragments - provides restricted UOW access without execute methods.\n */\nexport type DatabaseServiceContext<THooks extends HooksMap> = RequestThisContext & {\n /**\n * Get a typed, restricted Unit of Work for the given schema.\n * @param schema - Schema to get a typed view for\n * @returns TypedUnitOfWork (restricted version without execute methods)\n */\n uow<TSchema extends AnySchema>(schema: TSchema): TypedUnitOfWork<TSchema, [], unknown, THooks>;\n};\n\n/**\n * Handler context for database fragments - provides UOW execution with automatic retry support.\n */\nexport type DatabaseHandlerContext<THooks extends HooksMap = {}> = RequestThisContext & {\n /**\n * Execute a Unit of Work with explicit phase control and automatic retry support.\n * This method provides an API where users call forSchema to create a schema-specific\n * UOW, then call executeRetrieve() and executeMutate() to execute the phases. The entire\n * callback is re-executed on optimistic concurrency conflicts, ensuring retries work properly.\n * Automatically provides the UOW factory from context.\n * Promises in the returned object are awaited 1 level deep.\n *\n * @param callback - Async function that receives a context with forSchema, executeRetrieve, executeMutate, nonce, and currentAttempt\n * @param options - Optional configuration for retry policy and abort signal\n * @returns Promise resolving to the callback's return value with promises awaited 1 level deep\n * @throws Error if retries are exhausted or callback throws an error\n *\n * @example\n * ```ts\n * const result = await this.uow(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 */\n uow<TResult>(\n callback: (context: {\n forSchema: <TSchema extends AnySchema, H extends HooksMap = THooks>(\n schema: TSchema,\n hooks?: H,\n ) => TypedUnitOfWork<TSchema, [], unknown, H>;\n executeRetrieve: () => Promise<void>;\n executeMutate: () => Promise<void>;\n nonce: string;\n currentAttempt: number;\n }) => Promise<TResult> | TResult,\n options?: Omit<ExecuteRestrictedUnitOfWorkOptions, \"createUnitOfWork\">,\n ): Promise<AwaitedPromisesInObject<TResult>>;\n};\n\n/**\n * Database fragment context provided to user callbacks.\n */\nexport type DatabaseFragmentContext<TSchema extends AnySchema> = {\n /**\n * Database adapter instance.\n */\n databaseAdapter: DatabaseAdapter<any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n /**\n * ORM query engine for the fragment's schema.\n */\n db: SimpleQueryInterface<TSchema>;\n};\n\n/**\n * Create database context from options.\n * This extracts the database adapter and creates the ORM instance.\n */\nfunction createDatabaseContext<TSchema extends AnySchema>(\n options: FragnoPublicConfigWithDatabase,\n schema: TSchema,\n namespace: string,\n): DatabaseFragmentContext<TSchema> {\n const databaseAdapter = options.databaseAdapter;\n\n if (!databaseAdapter) {\n throw new Error(\n \"Database fragment requires a database adapter to be provided in options.databaseAdapter\",\n );\n }\n\n const db = databaseAdapter.createQueryEngine(schema, namespace);\n\n return { databaseAdapter, db };\n}\n\n/**\n * Storage type for database fragments - stores the Unit of Work.\n */\nexport type DatabaseRequestStorage = {\n uow: IUnitOfWork;\n};\n\n/**\n * Builder for database fragments that wraps the core fragment builder\n * and provides database-specific functionality.\n *\n * Database fragments always require FragnoPublicConfigWithDatabase (which includes databaseAdapter).\n */\nexport class DatabaseFragmentDefinitionBuilder<\n TSchema extends AnySchema,\n TConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDependencies,\n TPrivateServices,\n THooks extends HooksMap = {},\n TServiceThisContext extends RequestThisContext = DatabaseHandlerContext,\n THandlerThisContext extends RequestThisContext = DatabaseHandlerContext,\n TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment> = {},\n> {\n // Store the base builder - we'll replace its storage and context setup when building\n #baseBuilder: FragmentDefinitionBuilder<\n TConfig,\n FragnoPublicConfigWithDatabase,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDependencies,\n TPrivateServices,\n TServiceThisContext,\n THandlerThisContext,\n DatabaseRequestStorage,\n TLinkedFragments\n >;\n #schema: TSchema;\n #namespace: string;\n #hooksFactory?: (context: { config: TConfig; options: FragnoPublicConfigWithDatabase }) => THooks;\n\n constructor(\n baseBuilder: FragmentDefinitionBuilder<\n TConfig,\n FragnoPublicConfigWithDatabase,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDependencies,\n TPrivateServices,\n TServiceThisContext,\n THandlerThisContext,\n DatabaseRequestStorage,\n TLinkedFragments\n >,\n schema: TSchema,\n namespace?: string,\n hooksFactory?: (context: {\n config: TConfig;\n options: FragnoPublicConfigWithDatabase;\n }) => THooks,\n ) {\n this.#baseBuilder = baseBuilder;\n this.#schema = schema;\n this.#namespace = namespace ?? baseBuilder.name;\n this.#hooksFactory = hooksFactory;\n }\n\n /**\n * Define dependencies for this database fragment.\n * The context includes database adapter and ORM instance.\n */\n withDependencies<TNewDeps>(\n fn: (context: {\n config: TConfig;\n options: FragnoPublicConfigWithDatabase;\n db: SimpleQueryInterface<TSchema>;\n databaseAdapter: DatabaseAdapter<any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n }) => TNewDeps,\n ): DatabaseFragmentDefinitionBuilder<\n TSchema,\n TConfig,\n TNewDeps & ImplicitDatabaseDependencies<TSchema>,\n {},\n {},\n TServiceDependencies,\n {},\n THooks,\n TServiceThisContext,\n THandlerThisContext,\n TLinkedFragments\n > {\n // Wrap user function to inject DB context\n const wrappedFn = (context: { config: TConfig; options: FragnoPublicConfigWithDatabase }) => {\n const dbContext = createDatabaseContext(context.options, this.#schema, this.#namespace);\n\n // Call user function with enriched context\n const userDeps = fn({\n config: context.config,\n options: context.options,\n db: dbContext.db,\n databaseAdapter: dbContext.databaseAdapter,\n });\n\n // Create implicit dependencies\n const createUow = () => dbContext.db.createUnitOfWork();\n const implicitDeps: ImplicitDatabaseDependencies<TSchema> = {\n db: dbContext.db,\n schema: this.#schema,\n namespace: this.#namespace,\n createUnitOfWork: createUow,\n };\n\n return {\n ...userDeps,\n ...implicitDeps,\n };\n };\n\n // Create new base builder with wrapped function\n const newBaseBuilder = this.#baseBuilder.withDependencies(wrappedFn);\n\n return new DatabaseFragmentDefinitionBuilder(\n newBaseBuilder,\n this.#schema,\n this.#namespace,\n this.#hooksFactory,\n );\n }\n\n providesBaseService<TNewService>(\n fn: ServiceConstructorFn<\n TConfig,\n FragnoPublicConfigWithDatabase,\n TDeps,\n TServiceDependencies,\n TPrivateServices,\n TNewService,\n TServiceThisContext\n >,\n ): DatabaseFragmentDefinitionBuilder<\n TSchema,\n TConfig,\n TDeps,\n TNewService,\n TServices,\n TServiceDependencies,\n TPrivateServices,\n THooks,\n TServiceThisContext,\n THandlerThisContext,\n TLinkedFragments\n > {\n const newBaseBuilder = this.#baseBuilder.providesBaseService<TNewService>(fn);\n\n return new DatabaseFragmentDefinitionBuilder(\n newBaseBuilder,\n this.#schema,\n this.#namespace,\n this.#hooksFactory,\n );\n }\n\n providesService<TServiceName extends string, TService>(\n serviceName: TServiceName,\n fn: ServiceConstructorFn<\n TConfig,\n FragnoPublicConfigWithDatabase,\n TDeps,\n TServiceDependencies,\n TPrivateServices,\n TService,\n TServiceThisContext\n >,\n ): DatabaseFragmentDefinitionBuilder<\n TSchema,\n TConfig,\n TDeps,\n TBaseServices,\n TServices & { [K in TServiceName]: TService },\n TServiceDependencies,\n TPrivateServices,\n THooks,\n TServiceThisContext,\n THandlerThisContext,\n TLinkedFragments\n > {\n const newBaseBuilder = this.#baseBuilder.providesService<TServiceName, TService>(\n serviceName,\n fn,\n );\n\n return new DatabaseFragmentDefinitionBuilder(\n newBaseBuilder,\n this.#schema,\n this.#namespace,\n this.#hooksFactory,\n );\n }\n\n /**\n * Provide a private service that is only accessible to the fragment author.\n * Private services are NOT exposed on the fragment instance, but can be used\n * when defining other services (baseServices, namedServices, and other privateServices).\n * Private services are instantiated in order, so earlier private services are available\n * to later ones.\n */\n providesPrivateService<TServiceName extends string, TService>(\n serviceName: TServiceName,\n fn: ServiceConstructorFn<\n TConfig,\n FragnoPublicConfigWithDatabase,\n TDeps,\n TServiceDependencies,\n TPrivateServices,\n TService,\n TServiceThisContext\n >,\n ): DatabaseFragmentDefinitionBuilder<\n TSchema,\n TConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDependencies,\n TPrivateServices & { [K in TServiceName]: TService },\n THooks,\n TServiceThisContext,\n THandlerThisContext,\n TLinkedFragments\n > {\n const newBaseBuilder = this.#baseBuilder.providesPrivateService<TServiceName, TService>(\n serviceName,\n fn,\n );\n\n return new DatabaseFragmentDefinitionBuilder(\n newBaseBuilder,\n this.#schema,\n this.#namespace,\n this.#hooksFactory,\n );\n }\n\n /**\n * Define durable hooks for this fragment.\n * Hooks are automatically persisted and retried on failure.\n *\n * @param fn - Function that receives defineHook helper and returns a hooks map\n * @returns Builder with hooks type set\n *\n * @example\n * ```ts\n * .provideHooks(({ defineHook, config }) => ({\n * onSubscribe: defineHook(async function (payload: { email: string }) {\n * // 'this' context available (HookServiceContext with nonce)\n * await config.onSubscribe?.(payload.email);\n * }),\n * }))\n * ```\n */\n provideHooks<TNewHooks extends HooksMap>(\n fn: (context: {\n config: TConfig;\n options: FragnoPublicConfigWithDatabase;\n defineHook: <TPayload>(\n hook: (this: HookContext, payload: TPayload) => void | Promise<void>,\n ) => HookFn<TPayload>;\n }) => TNewHooks,\n ): DatabaseFragmentDefinitionBuilder<\n TSchema,\n TConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDependencies,\n TPrivateServices,\n TNewHooks,\n DatabaseServiceContext<TNewHooks>,\n THandlerThisContext,\n TLinkedFragments\n > {\n const defineHook = <TPayload>(\n hook: (this: HookContext, payload: TPayload) => void | Promise<void>,\n ): HookFn<TPayload> => {\n return hook;\n };\n\n // Store the hooks factory - it will be called in build() with config/options\n const hooksFactory = (context: {\n config: TConfig;\n options: FragnoPublicConfigWithDatabase;\n }) => {\n return fn({\n config: context.config,\n options: context.options,\n defineHook,\n });\n };\n\n // Create new builder with hooks factory stored\n // Cast is safe: we're only changing THooks and TServiceThisContext type parameters\n const newBuilder = new DatabaseFragmentDefinitionBuilder(\n this.#baseBuilder,\n this.#schema,\n this.#namespace,\n ) as unknown as DatabaseFragmentDefinitionBuilder<\n TSchema,\n TConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDependencies,\n TPrivateServices,\n TNewHooks,\n DatabaseServiceContext<TNewHooks>,\n THandlerThisContext,\n TLinkedFragments\n >;\n\n newBuilder.#hooksFactory = hooksFactory;\n\n return newBuilder;\n }\n\n /**\n * Declare that this fragment uses a required service provided by the runtime.\n * Delegates to the base builder.\n */\n usesService<TServiceName extends string, TService>(\n serviceName: TServiceName,\n ): DatabaseFragmentDefinitionBuilder<\n TSchema,\n TConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDependencies & { [K in TServiceName]: TService },\n TPrivateServices,\n THooks,\n TServiceThisContext,\n THandlerThisContext,\n TLinkedFragments\n > {\n const newBaseBuilder = this.#baseBuilder.usesService<TServiceName, TService>(serviceName);\n\n return new DatabaseFragmentDefinitionBuilder(\n newBaseBuilder,\n this.#schema,\n this.#namespace,\n this.#hooksFactory,\n );\n }\n\n /**\n * Declare that this fragment uses an optional service provided by the runtime.\n * Delegates to the base builder.\n */\n usesOptionalService<TServiceName extends string, TService>(\n serviceName: TServiceName,\n ): DatabaseFragmentDefinitionBuilder<\n TSchema,\n TConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDependencies & { [K in TServiceName]: TService | undefined },\n TPrivateServices,\n THooks,\n TServiceThisContext,\n THandlerThisContext,\n TLinkedFragments\n > {\n const newBaseBuilder = this.#baseBuilder.usesOptionalService<TServiceName, TService>(\n serviceName,\n );\n\n return new DatabaseFragmentDefinitionBuilder(\n newBaseBuilder,\n this.#schema,\n this.#namespace,\n this.#hooksFactory,\n );\n }\n\n /**\n * Build the final database fragment definition.\n * This includes the request context setup for UnitOfWork management.\n * Note: TDeps already includes ImplicitDatabaseDependencies from withDatabase().\n */\n build(): FragmentDefinition<\n TConfig,\n FragnoPublicConfigWithDatabase,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDependencies,\n TPrivateServices,\n DatabaseServiceContext<THooks>,\n DatabaseHandlerContext<THooks>,\n DatabaseRequestStorage,\n TLinkedFragments\n > {\n const baseDef = this.#baseBuilder.build();\n\n // Ensure dependencies callback always exists for database fragments\n // If no user dependencies were defined, create a minimal one that only adds implicit deps\n const dependencies = (context: {\n config: TConfig;\n options: FragnoPublicConfigWithDatabase;\n }): TDeps => {\n // In dry run mode, allow user deps to fail gracefully.\n // This is critical for database fragments because the CLI needs access to the schema\n // even when user dependencies (like API clients) can't be initialized.\n // Without this, if user deps fail, we'd lose the implicit database dependencies\n // (including schema), and the CLI couldn't extract schema information.\n let userDeps;\n try {\n userDeps = baseDef.dependencies?.(context);\n } catch (error) {\n if (process.env[\"FRAGNO_INIT_DRY_RUN\"] === \"true\") {\n console.warn(\n \"Warning: Failed to initialize user dependencies in dry run mode:\",\n error instanceof Error ? error.message : String(error),\n );\n userDeps = {};\n } else {\n throw error;\n }\n }\n\n const { db } = createDatabaseContext(context.options, this.#schema, this.#namespace);\n\n const implicitDeps: ImplicitDatabaseDependencies<TSchema> = {\n db,\n schema: this.#schema,\n namespace: this.#namespace,\n createUnitOfWork: () => db.createUnitOfWork(),\n };\n\n return {\n ...userDeps,\n ...implicitDeps,\n } as TDeps;\n };\n\n // Use the adapter's shared context storage (all fragments using the same adapter share this storage)\n const builderWithExternalStorage = this.#baseBuilder.withExternalRequestStorage(\n ({ options }) => {\n const dbContext = createDatabaseContext(options, this.#schema, this.#namespace);\n return dbContext.databaseAdapter.contextStorage;\n },\n );\n\n // Set up request storage to initialize the Unit of Work\n const builderWithStorage = builderWithExternalStorage.withRequestStorage(\n ({ options }): DatabaseRequestStorage => {\n // Create database context - needed here to create the UOW\n const dbContextForStorage = createDatabaseContext(options, this.#schema, this.#namespace);\n\n // Create a new Unit of Work for this request\n const uow: IUnitOfWork = dbContextForStorage.db.createUnitOfWork();\n\n return { uow };\n },\n );\n\n // Get the internal fragment factory from linked fragments (added by withDatabase)\n // Cast is safe: withDatabase() guarantees this fragment exists and has the correct type\n const internalFragmentFactory = baseDef.linkedFragments?.[\"_fragno_internal\"] as (context: {\n config: TConfig;\n options: FragnoPublicConfigWithDatabase;\n }) => InternalFragmentInstance;\n\n const builderWithContext = builderWithStorage.withThisContext<\n DatabaseServiceContext<THooks>,\n DatabaseHandlerContext<THooks>\n >(({ storage, config, options }) => {\n // Create hooks config if hooks factory is defined\n const hooksConfig = this.#hooksFactory\n ? {\n hooks: this.#hooksFactory({ config, options }),\n namespace: this.#namespace,\n internalFragment: internalFragmentFactory({ config, options }),\n }\n : undefined;\n\n function forSchema<TSchema extends AnySchema>(\n schema: TSchema,\n ): TypedUnitOfWork<TSchema, [], unknown, THooks> {\n const uow = storage.getStore()?.uow;\n if (!uow) {\n throw new Error(\n \"No UnitOfWork in context. Service must be called within a route handler OR using `withUnitOfWork`.\",\n );\n }\n\n return uow.restrict().forSchema<TSchema, THooks>(schema);\n }\n\n const serviceContext: DatabaseServiceContext<THooks> = {\n uow: forSchema,\n };\n\n async function uow<TResult>(\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> | TResult,\n execOptions?: Omit<\n ExecuteRestrictedUnitOfWorkOptions,\n \"createUnitOfWork\" | \"onBeforeMutate\" | \"onSuccess\"\n >,\n ): Promise<AwaitedPromisesInObject<TResult>> {\n const currentStorage = storage.getStore();\n if (!currentStorage) {\n throw new Error(\n \"No storage in context. Handler must be called within a request context.\",\n );\n }\n\n const wrappedCallback = async (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 return callback(context);\n };\n\n return executeRestrictedUnitOfWork(wrappedCallback, {\n ...execOptions,\n createUnitOfWork: () => {\n currentStorage.uow.reset();\n // Register internal schema for hook mutations\n if (hooksConfig) {\n currentStorage.uow.registerSchema(\n hooksConfig.internalFragment.$internal.deps.schema,\n hooksConfig.internalFragment.$internal.deps.namespace,\n );\n }\n return currentStorage.uow as UnitOfWork;\n },\n onBeforeMutate: hooksConfig ? (uow) => prepareHookMutations(uow, hooksConfig) : undefined,\n onSuccess: hooksConfig ? () => processHooks(hooksConfig) : undefined,\n });\n }\n\n const handlerContext: DatabaseHandlerContext<THooks> = {\n uow,\n };\n\n return { serviceContext, handlerContext };\n });\n\n // Build the final definition\n const finalDef = builderWithContext.build();\n\n // Return the complete definition with proper typing and dependencies\n return {\n ...finalDef,\n dependencies,\n };\n }\n}\n"],"mappings":";;;;;;;;;AA6IA,SAAS,sBACP,SACA,QACA,WACkC;CAClC,MAAM,kBAAkB,QAAQ;AAEhC,KAAI,CAAC,gBACH,OAAM,IAAI,MACR,0FACD;AAKH,QAAO;EAAE;EAAiB,IAFf,gBAAgB,kBAAkB,QAAQ,UAAU;EAEjC;;;;;;;;AAgBhC,IAAa,oCAAb,MAAa,kCAYX;CAEA;CAaA;CACA;CACA;CAEA,YACE,aAaA,QACA,WACA,cAIA;AACA,QAAKA,cAAe;AACpB,QAAKC,SAAU;AACf,QAAKC,YAAa,aAAa,YAAY;AAC3C,QAAKC,eAAgB;;;;;;CAOvB,iBACE,IAkBA;EAEA,MAAM,aAAa,YAA0E;GAC3F,MAAM,YAAY,sBAAsB,QAAQ,SAAS,MAAKF,QAAS,MAAKC,UAAW;GAGvF,MAAM,WAAW,GAAG;IAClB,QAAQ,QAAQ;IAChB,SAAS,QAAQ;IACjB,IAAI,UAAU;IACd,iBAAiB,UAAU;IAC5B,CAAC;GAGF,MAAM,kBAAkB,UAAU,GAAG,kBAAkB;GACvD,MAAME,eAAsD;IAC1D,IAAI,UAAU;IACd,QAAQ,MAAKH;IACb,WAAW,MAAKC;IAChB,kBAAkB;IACnB;AAED,UAAO;IACL,GAAG;IACH,GAAG;IACJ;;AAMH,SAAO,IAAI,kCAFY,MAAKF,YAAa,iBAAiB,UAAU,EAIlE,MAAKC,QACL,MAAKC,WACL,MAAKC,aACN;;CAGH,oBACE,IAqBA;AAGA,SAAO,IAAI,kCAFY,MAAKH,YAAa,oBAAiC,GAAG,EAI3E,MAAKC,QACL,MAAKC,WACL,MAAKC,aACN;;CAGH,gBACE,aACA,IAqBA;AAMA,SAAO,IAAI,kCALY,MAAKH,YAAa,gBACvC,aACA,GACD,EAIC,MAAKC,QACL,MAAKC,WACL,MAAKC,aACN;;;;;;;;;CAUH,uBACE,aACA,IAqBA;AAMA,SAAO,IAAI,kCALY,MAAKH,YAAa,uBACvC,aACA,GACD,EAIC,MAAKC,QACL,MAAKC,WACL,MAAKC,aACN;;;;;;;;;;;;;;;;;;;CAoBH,aACE,IAmBA;EACA,MAAM,cACJ,SACqB;AACrB,UAAO;;EAIT,MAAM,gBAAgB,YAGhB;AACJ,UAAO,GAAG;IACR,QAAQ,QAAQ;IAChB,SAAS,QAAQ;IACjB;IACD,CAAC;;EAKJ,MAAM,aAAa,IAAI,kCACrB,MAAKH,aACL,MAAKC,QACL,MAAKC,UACN;AAcD,cAAWC,eAAgB;AAE3B,SAAO;;;;;;CAOT,YACE,aAaA;AAGA,SAAO,IAAI,kCAFY,MAAKH,YAAa,YAAoC,YAAY,EAIvF,MAAKC,QACL,MAAKC,WACL,MAAKC,aACN;;;;;;CAOH,oBACE,aAaA;AAKA,SAAO,IAAI,kCAJY,MAAKH,YAAa,oBACvC,YACD,EAIC,MAAKC,QACL,MAAKC,WACL,MAAKC,aACN;;;;;;;CAQH,QAYE;EACA,MAAM,UAAU,MAAKH,YAAa,OAAO;EAIzC,MAAM,gBAAgB,YAGT;GAMX,IAAI;AACJ,OAAI;AACF,eAAW,QAAQ,eAAe,QAAQ;YACnC,OAAO;AACd,QAAI,QAAQ,IAAI,2BAA2B,QAAQ;AACjD,aAAQ,KACN,oEACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CACvD;AACD,gBAAW,EAAE;UAEb,OAAM;;GAIV,MAAM,EAAE,OAAO,sBAAsB,QAAQ,SAAS,MAAKC,QAAS,MAAKC,UAAW;GAEpF,MAAME,eAAsD;IAC1D;IACA,QAAQ,MAAKH;IACb,WAAW,MAAKC;IAChB,wBAAwB,GAAG,kBAAkB;IAC9C;AAED,UAAO;IACL,GAAG;IACH,GAAG;IACJ;;EAYH,MAAM,qBAR6B,MAAKF,YAAa,4BAClD,EAAE,cAAc;AAEf,UADkB,sBAAsB,SAAS,MAAKC,QAAS,MAAKC,UAAW,CAC9D,gBAAgB;IAEpC,CAGqD,oBACnD,EAAE,cAAsC;AAOvC,UAAO,EAAE,KALmB,sBAAsB,SAAS,MAAKD,QAAS,MAAKC,UAAW,CAG5C,GAAG,kBAAkB,EAEpD;IAEjB;EAID,MAAM,0BAA0B,QAAQ,kBAAkB;AAoG1D,SAAO;GACL,GAhGyB,mBAAmB,iBAG3C,EAAE,SAAS,QAAQ,cAAc;IAElC,MAAM,cAAc,MAAKC,eACrB;KACE,OAAO,MAAKA,aAAc;MAAE;MAAQ;MAAS,CAAC;KAC9C,WAAW,MAAKD;KAChB,kBAAkB,wBAAwB;MAAE;MAAQ;MAAS,CAAC;KAC/D,GACD;IAEJ,SAAS,UACP,QAC+C;KAC/C,MAAMG,QAAM,QAAQ,UAAU,EAAE;AAChC,SAAI,CAACA,MACH,OAAM,IAAI,MACR,qGACD;AAGH,YAAOA,MAAI,UAAU,CAAC,UAA2B,OAAO;;IAG1D,MAAMC,iBAAiD,EACrD,KAAK,WACN;IAED,eAAe,IACb,UAUA,aAI2C;KAC3C,MAAM,iBAAiB,QAAQ,UAAU;AACzC,SAAI,CAAC,eACH,OAAM,IAAI,MACR,0EACD;KAGH,MAAM,kBAAkB,OAAO,YASP;AACtB,aAAO,SAAS,QAAQ;;AAG1B,YAAO,4BAA4B,iBAAiB;MAClD,GAAG;MACH,wBAAwB;AACtB,sBAAe,IAAI,OAAO;AAE1B,WAAI,YACF,gBAAe,IAAI,eACjB,YAAY,iBAAiB,UAAU,KAAK,QAC5C,YAAY,iBAAiB,UAAU,KAAK,UAC7C;AAEH,cAAO,eAAe;;MAExB,gBAAgB,eAAe,UAAQ,qBAAqBD,OAAK,YAAY,GAAG;MAChF,WAAW,oBAAoB,aAAa,YAAY,GAAG;MAC5D,CAAC;;AAOJ,WAAO;KAAE;KAAgB,gBAJ8B,EACrD,KACD;KAEwC;KACzC,CAGkC,OAAO;GAKzC;GACD"}
@@ -0,0 +1,53 @@
1
+ import { AnyColumn, AnyRelation, Column, FragnoId, IdColumn, Index, Schema, Table } from "../schema/create.js";
2
+ import { RetryPolicy } from "../query/unit-of-work/retry-policy.js";
3
+ import { DatabaseHandlerContext, DatabaseRequestStorage, DatabaseServiceContext, FragnoPublicConfigWithDatabase, ImplicitDatabaseDependencies } from "../db-fragment-definition-builder.js";
4
+ import * as _fragno_dev_core0 from "@fragno-dev/core";
5
+ import { InstantiatedFragmentFromDefinition } from "@fragno-dev/core";
6
+
7
+ //#region src/fragments/internal-fragment.d.ts
8
+ declare const internalFragmentDef: _fragno_dev_core0.FragmentDefinition<{}, FragnoPublicConfigWithDatabase, ImplicitDatabaseDependencies<Schema<Record<"fragno_db_settings", Table<Record<string, AnyColumn> & Record<"id", IdColumn<"varchar(30)", string | FragnoId | null, FragnoId>> & Record<"key", Column<"string", string, string>> & Record<"value", Column<"string", string, string>>, Record<string, AnyRelation>, Record<string, Index<AnyColumn[], readonly string[]>> & Record<"unique_key", Index<readonly [Column<"string", string, string>] & AnyColumn[], readonly ["key"]>>>> & Record<"fragno_hooks", Table<Record<string, AnyColumn> & Record<"id", IdColumn<"varchar(30)", string | FragnoId | null, FragnoId>> & Record<"namespace", Column<"string", string, string>> & Record<"hookName", Column<"string", string, string>> & Record<"payload", Column<"json", unknown, unknown>> & Record<"status", Column<"string", string, string>> & Record<"attempts", Column<"integer", number | null, number>> & Record<"maxAttempts", Column<"integer", number | null, number>> & Record<"lastAttemptAt", Column<"timestamp", Date | null, Date | null>> & Record<"nextRetryAt", Column<"timestamp", Date | null, Date | null>> & Record<"error", Column<"string", string | null, string | null>> & Record<"createdAt", Column<"timestamp", Date | null, Date>> & Record<"nonce", Column<"string", string, string>>, Record<string, AnyRelation>, Record<string, Index<AnyColumn[], readonly string[]>> & Record<"idx_namespace_status_retry", Index<readonly [Column<"string", string, string>, Column<"string", string, string>, Column<"timestamp", Date | null, Date | null>] & AnyColumn[], readonly ["namespace", "status", "nextRetryAt"]>> & Record<"idx_nonce", Index<readonly [Column<"string", string, string>] & AnyColumn[], readonly ["nonce"]>>>>>>, {}, {
9
+ settingsService: {
10
+ get(namespace: string, key: string): Promise<{
11
+ id: FragnoId;
12
+ key: string;
13
+ value: string;
14
+ } | undefined>;
15
+ set(namespace: string, key: string, value: string): Promise<void>;
16
+ delete(id: FragnoId): Promise<void>;
17
+ };
18
+ } & {
19
+ hookService: {
20
+ /**
21
+ * Get pending hook events for processing.
22
+ * Returns all pending events for the given namespace that are ready to be processed.
23
+ */
24
+ getPendingHookEvents(namespace: string): Promise<{
25
+ id: FragnoId;
26
+ hookName: string;
27
+ payload: unknown;
28
+ attempts: number;
29
+ maxAttempts: number;
30
+ nonce: string;
31
+ }[]>;
32
+ /**
33
+ * Mark a hook event as completed.
34
+ */
35
+ markHookCompleted(eventId: FragnoId): void;
36
+ /**
37
+ * Mark a hook event as failed and schedule next retry.
38
+ */
39
+ markHookFailed(eventId: FragnoId, error: string, attempts: number, retryPolicy: RetryPolicy): void;
40
+ /**
41
+ * Mark a hook event as processing (to prevent concurrent execution).
42
+ */
43
+ markHookProcessing(eventId: FragnoId): void;
44
+ };
45
+ }, {}, {}, DatabaseServiceContext<{}>, DatabaseHandlerContext<{}>, DatabaseRequestStorage, {}>;
46
+ /**
47
+ * Type representing an instantiated internal fragment.
48
+ * This is the fragment that manages Fragno's internal settings table.
49
+ */
50
+ type InternalFragmentInstance = InstantiatedFragmentFromDefinition<typeof internalFragmentDef>;
51
+ //#endregion
52
+ export { InternalFragmentInstance, internalFragmentDef };
53
+ //# sourceMappingURL=internal-fragment.d.ts.map