@fragno-dev/db 0.1.15 → 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 (407) hide show
  1. package/.turbo/turbo-build.log +242 -179
  2. package/CHANGELOG.md +23 -0
  3. package/README.md +123 -8
  4. package/dist/adapters/adapters.d.ts +5 -5
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/drizzle/drizzle-adapter.d.ts +6 -21
  8. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
  9. package/dist/adapters/drizzle/drizzle-adapter.js +7 -54
  10. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
  11. package/dist/adapters/drizzle/generate.d.ts +3 -0
  12. package/dist/adapters/drizzle/generate.d.ts.map +1 -1
  13. package/dist/adapters/drizzle/generate.js +36 -28
  14. package/dist/adapters/drizzle/generate.js.map +1 -1
  15. package/dist/adapters/generic-sql/driver-config.d.ts +74 -0
  16. package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -0
  17. package/dist/adapters/generic-sql/driver-config.js +94 -0
  18. package/dist/adapters/generic-sql/driver-config.js.map +1 -0
  19. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +43 -0
  20. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -0
  21. package/dist/adapters/generic-sql/generic-sql-adapter.js +87 -0
  22. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -0
  23. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +67 -0
  24. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -0
  25. package/dist/adapters/generic-sql/migration/cold-kysely.js +33 -0
  26. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -0
  27. package/dist/adapters/generic-sql/migration/dialect/mysql.js +60 -0
  28. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -0
  29. package/dist/adapters/generic-sql/migration/dialect/postgres.js +59 -0
  30. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -0
  31. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +96 -0
  32. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -0
  33. package/dist/adapters/generic-sql/migration/executor.d.ts +15 -0
  34. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  35. package/dist/adapters/generic-sql/migration/executor.js +18 -0
  36. package/dist/adapters/generic-sql/migration/executor.js.map +1 -0
  37. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  38. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  39. package/dist/adapters/generic-sql/migration/prepared-migrations.js +68 -0
  40. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -0
  41. package/dist/adapters/generic-sql/migration/sql-generator.js +212 -0
  42. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -0
  43. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +32 -0
  44. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -0
  45. package/dist/adapters/generic-sql/query/cursor-utils.js +37 -0
  46. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -0
  47. package/dist/adapters/generic-sql/query/dialect/mysql.js +33 -0
  48. package/dist/adapters/generic-sql/query/dialect/mysql.js.map +1 -0
  49. package/dist/adapters/generic-sql/query/dialect/postgres.js +32 -0
  50. package/dist/adapters/generic-sql/query/dialect/postgres.js.map +1 -0
  51. package/dist/adapters/generic-sql/query/dialect/sqlite.js +32 -0
  52. package/dist/adapters/generic-sql/query/dialect/sqlite.js.map +1 -0
  53. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +152 -0
  54. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -0
  55. package/dist/adapters/generic-sql/query/select-builder.js +69 -0
  56. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -0
  57. package/dist/adapters/generic-sql/query/sql-query-compiler.js +145 -0
  58. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -0
  59. package/dist/adapters/generic-sql/query/where-builder.js +129 -0
  60. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -0
  61. package/dist/adapters/generic-sql/result-interpreter.js +74 -0
  62. package/dist/adapters/generic-sql/result-interpreter.js.map +1 -0
  63. package/dist/adapters/generic-sql/uow-decoder.js +105 -0
  64. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -0
  65. package/dist/adapters/generic-sql/uow-encoder.js +93 -0
  66. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -0
  67. package/dist/adapters/kysely/kysely-adapter.d.ts +5 -18
  68. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
  69. package/dist/adapters/kysely/kysely-adapter.js +6 -165
  70. package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
  71. package/dist/adapters/{drizzle/drizzle-query.js → shared/from-unit-of-work-compiler.js} +47 -61
  72. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -0
  73. package/dist/adapters/{drizzle/shared.d.ts → shared/table-name-mapper.d.ts} +2 -4
  74. package/dist/adapters/shared/table-name-mapper.d.ts.map +1 -0
  75. package/dist/adapters/shared/table-name-mapper.js +43 -0
  76. package/dist/adapters/shared/table-name-mapper.js.map +1 -0
  77. package/dist/adapters/shared/uow-operation-compiler.js +105 -0
  78. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -0
  79. package/dist/db-fragment-definition-builder.d.ts +53 -19
  80. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  81. package/dist/db-fragment-definition-builder.js +89 -19
  82. package/dist/db-fragment-definition-builder.js.map +1 -1
  83. package/dist/fragments/internal-fragment.d.ts +39 -5
  84. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  85. package/dist/fragments/internal-fragment.js +82 -10
  86. package/dist/fragments/internal-fragment.js.map +1 -1
  87. package/dist/hooks/hooks.d.ts +51 -0
  88. package/dist/hooks/hooks.d.ts.map +1 -0
  89. package/dist/hooks/hooks.js +88 -0
  90. package/dist/hooks/hooks.js.map +1 -0
  91. package/dist/migration-engine/generation-engine.d.ts +0 -2
  92. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  93. package/dist/migration-engine/generation-engine.js +23 -61
  94. package/dist/migration-engine/generation-engine.js.map +1 -1
  95. package/dist/mod.d.ts +34 -10
  96. package/dist/mod.d.ts.map +1 -1
  97. package/dist/mod.js +47 -16
  98. package/dist/mod.js.map +1 -1
  99. package/dist/node_modules/.pnpm/{rou3@0.7.8 → rou3@0.7.10}/node_modules/rou3/dist/index.js +1 -1
  100. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +1 -0
  101. package/dist/packages/fragno/dist/api/fragment-instantiator.js +69 -31
  102. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -1
  103. package/dist/query/column-defaults.js +27 -0
  104. package/dist/query/column-defaults.js.map +1 -0
  105. package/dist/query/cursor.d.ts +4 -4
  106. package/dist/query/cursor.d.ts.map +1 -1
  107. package/dist/query/cursor.js +8 -6
  108. package/dist/query/cursor.js.map +1 -1
  109. package/dist/query/orm/orm.d.ts +1 -1
  110. package/dist/query/orm/orm.js.map +1 -1
  111. package/dist/query/serialize/create-sql-serializer.js +30 -0
  112. package/dist/query/serialize/create-sql-serializer.js.map +1 -0
  113. package/dist/query/serialize/dialect/mysql-serializer.js +87 -0
  114. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -0
  115. package/dist/query/serialize/dialect/postgres-serializer.js +80 -0
  116. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -0
  117. package/dist/query/serialize/dialect/sqlite-serializer.js +93 -0
  118. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -0
  119. package/dist/query/serialize/sql-serializer.js +67 -0
  120. package/dist/query/serialize/sql-serializer.js.map +1 -0
  121. package/dist/query/{query.d.ts → simple-query-interface.d.ts} +5 -5
  122. package/dist/query/simple-query-interface.d.ts.map +1 -0
  123. package/dist/query/{execute-unit-of-work.d.ts → unit-of-work/execute-unit-of-work.d.ts} +13 -3
  124. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  125. package/dist/query/{execute-unit-of-work.js → unit-of-work/execute-unit-of-work.js} +17 -4
  126. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  127. package/dist/query/{retry-policy.d.ts → unit-of-work/retry-policy.d.ts} +1 -1
  128. package/dist/query/unit-of-work/retry-policy.d.ts.map +1 -0
  129. package/dist/query/{retry-policy.js → unit-of-work/retry-policy.js} +1 -1
  130. package/dist/query/unit-of-work/retry-policy.js.map +1 -0
  131. package/dist/query/{unit-of-work.d.ts → unit-of-work/unit-of-work.d.ts} +51 -18
  132. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  133. package/dist/query/{unit-of-work.js → unit-of-work/unit-of-work.js} +58 -11
  134. package/dist/query/unit-of-work/unit-of-work.js.map +1 -0
  135. package/dist/query/value-decoding.js +71 -0
  136. package/dist/query/value-decoding.js.map +1 -0
  137. package/dist/query/value-encoding.js +124 -0
  138. package/dist/query/value-encoding.js.map +1 -0
  139. package/dist/schema/create.d.ts +3 -0
  140. package/dist/schema/create.d.ts.map +1 -1
  141. package/dist/schema/create.js +4 -0
  142. package/dist/schema/create.js.map +1 -1
  143. package/dist/schema/type-conversion/create-sql-type-mapper.js +29 -0
  144. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -0
  145. package/dist/schema/type-conversion/dialect/mysql.js +57 -0
  146. package/dist/schema/type-conversion/dialect/mysql.js.map +1 -0
  147. package/dist/schema/type-conversion/dialect/postgres.js +56 -0
  148. package/dist/schema/type-conversion/dialect/postgres.js.map +1 -0
  149. package/dist/schema/type-conversion/dialect/sqlite.js +52 -0
  150. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -0
  151. package/dist/schema/type-conversion/type-mapping.js +63 -0
  152. package/dist/schema/type-conversion/type-mapping.js.map +1 -0
  153. package/dist/sql-driver/connection/connection-provider.d.ts +13 -0
  154. package/dist/sql-driver/connection/connection-provider.d.ts.map +1 -0
  155. package/dist/sql-driver/connection/connection-provider.js +19 -0
  156. package/dist/sql-driver/connection/connection-provider.js.map +1 -0
  157. package/dist/sql-driver/connection/single-connection-provider.js +23 -0
  158. package/dist/sql-driver/connection/single-connection-provider.js.map +1 -0
  159. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  160. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  161. package/dist/sql-driver/dialects/dialects.d.ts +2 -0
  162. package/dist/sql-driver/dialects/dialects.js +3 -0
  163. package/dist/sql-driver/dialects/durable-object-dialect.d.ts +72 -0
  164. package/dist/sql-driver/dialects/durable-object-dialect.d.ts.map +1 -0
  165. package/dist/sql-driver/dialects/durable-object-dialect.js +130 -0
  166. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -0
  167. package/dist/sql-driver/driver/runtime-driver.d.ts +23 -0
  168. package/dist/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  169. package/dist/sql-driver/driver/runtime-driver.js +56 -0
  170. package/dist/sql-driver/driver/runtime-driver.js.map +1 -0
  171. package/dist/sql-driver/query-executor/default-query-executor.js +26 -0
  172. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -0
  173. package/dist/sql-driver/query-executor/plugin.d.ts +17 -0
  174. package/dist/sql-driver/query-executor/plugin.d.ts.map +1 -0
  175. package/dist/sql-driver/query-executor/query-executor-base.js +25 -0
  176. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -0
  177. package/dist/sql-driver/query-executor/query-executor.d.ts +36 -0
  178. package/dist/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  179. package/dist/sql-driver/sql-driver-adapter.d.ts +29 -0
  180. package/dist/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  181. package/dist/sql-driver/sql-driver-adapter.js +68 -0
  182. package/dist/sql-driver/sql-driver-adapter.js.map +1 -0
  183. package/dist/sql-driver/sql-driver.d.ts +38 -0
  184. package/dist/sql-driver/sql-driver.d.ts.map +1 -0
  185. package/dist/sql-driver/sql-driver.js +1 -0
  186. package/dist/sql-driver/sql.js +50 -0
  187. package/dist/sql-driver/sql.js.map +1 -0
  188. package/dist/with-database.d.ts +6 -2
  189. package/dist/with-database.d.ts.map +1 -1
  190. package/dist/with-database.js +1 -1
  191. package/dist/with-database.js.map +1 -1
  192. package/package.json +37 -10
  193. package/src/adapters/adapters.ts +8 -5
  194. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +60 -169
  195. package/src/adapters/drizzle/{drizzle-adapter-sqlite.test.ts → drizzle-adapter-sqlite3.test.ts} +31 -55
  196. package/src/adapters/drizzle/drizzle-adapter.ts +15 -107
  197. package/src/adapters/drizzle/generate.test.ts +2 -2
  198. package/src/adapters/drizzle/generate.ts +78 -34
  199. package/src/adapters/drizzle/migrate-drizzle.test.ts +19 -0
  200. package/src/adapters/drizzle/shared.ts +0 -34
  201. package/src/adapters/drizzle/test-utils.ts +3 -3
  202. package/src/adapters/generic-sql/README.md +14 -0
  203. package/src/adapters/generic-sql/driver-config.ts +144 -0
  204. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +50 -0
  205. package/src/adapters/generic-sql/generic-sql-adapter.ts +146 -0
  206. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +130 -0
  207. package/src/adapters/generic-sql/migration/cold-kysely.ts +55 -0
  208. package/src/adapters/{kysely/migration/execute-mysql.test.ts → generic-sql/migration/dialect/mysql.test.ts} +342 -484
  209. package/src/adapters/generic-sql/migration/dialect/mysql.ts +104 -0
  210. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +1008 -0
  211. package/src/adapters/generic-sql/migration/dialect/postgres.ts +113 -0
  212. package/src/adapters/{kysely/migration/execute-sqlite.test.ts → generic-sql/migration/dialect/sqlite.test.ts} +307 -510
  213. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +189 -0
  214. package/src/adapters/generic-sql/migration/executor.ts +33 -0
  215. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +661 -0
  216. package/src/adapters/generic-sql/migration/prepared-migrations.ts +214 -0
  217. package/src/adapters/generic-sql/migration/sql-generator.ts +413 -0
  218. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +36 -0
  219. package/src/adapters/generic-sql/query/cursor-utils.ts +56 -0
  220. package/src/adapters/generic-sql/query/dialect/mysql.ts +34 -0
  221. package/src/adapters/generic-sql/query/dialect/postgres.ts +32 -0
  222. package/src/adapters/generic-sql/query/dialect/sqlite.ts +32 -0
  223. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +1568 -0
  224. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +314 -0
  225. package/src/adapters/generic-sql/query/select-builder.test.ts +256 -0
  226. package/src/adapters/generic-sql/query/select-builder.ts +137 -0
  227. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +195 -0
  228. package/src/adapters/generic-sql/query/sql-query-compiler.ts +367 -0
  229. package/src/adapters/generic-sql/query/where-builder.test.ts +744 -0
  230. package/src/adapters/generic-sql/query/where-builder.ts +211 -0
  231. package/src/adapters/generic-sql/result-interpreter.ts +102 -0
  232. package/src/adapters/generic-sql/test/generic-drizzle-adapter-sqlite3.test.ts +899 -0
  233. package/src/adapters/generic-sql/uow-decoder.test.ts +399 -0
  234. package/src/adapters/generic-sql/uow-decoder.ts +152 -0
  235. package/src/adapters/generic-sql/uow-encoder.test.ts +183 -0
  236. package/src/adapters/generic-sql/uow-encoder.ts +131 -0
  237. package/src/adapters/kysely/kysely-adapter-pglite.test.ts +26 -76
  238. package/src/adapters/kysely/{kysely-adapter-sqlite.test.ts → kysely-adapter-sqlocal.test.ts} +76 -17
  239. package/src/adapters/kysely/kysely-adapter.ts +10 -250
  240. package/src/adapters/{drizzle/drizzle-query.ts → shared/from-unit-of-work-compiler.ts} +110 -104
  241. package/src/adapters/shared/table-name-mapper.ts +50 -0
  242. package/src/adapters/shared/uow-operation-compiler.ts +211 -0
  243. package/src/db-fragment-definition-builder.test.ts +2 -2
  244. package/src/db-fragment-definition-builder.ts +281 -50
  245. package/src/db-fragment-instantiator.test.ts +78 -2
  246. package/src/db-fragment-integration.test.ts +14 -16
  247. package/src/fragments/internal-fragment.test.ts +434 -45
  248. package/src/fragments/internal-fragment.ts +184 -20
  249. package/src/hooks/hooks.test.ts +575 -0
  250. package/src/hooks/hooks.ts +179 -0
  251. package/src/migration-engine/generation-engine.test.ts +44 -54
  252. package/src/migration-engine/generation-engine.ts +48 -94
  253. package/src/mod.ts +117 -29
  254. package/src/query/column-defaults.ts +49 -0
  255. package/src/query/cursor.test.ts +31 -6
  256. package/src/query/cursor.ts +11 -7
  257. package/src/query/orm/orm.ts +1 -1
  258. package/src/query/query-type.test.ts +9 -9
  259. package/src/query/serialize/create-sql-serializer.ts +34 -0
  260. package/src/query/serialize/dialect/mysql-serializer.ts +142 -0
  261. package/src/query/serialize/dialect/postgres-serializer.ts +129 -0
  262. package/src/query/serialize/dialect/sqlite-serializer.test.ts +251 -0
  263. package/src/query/serialize/dialect/sqlite-serializer.ts +156 -0
  264. package/src/query/serialize/sql-serializer.ts +143 -0
  265. package/src/query/{query.ts → simple-query-interface.ts} +2 -2
  266. package/src/query/{execute-unit-of-work.test.ts → unit-of-work/execute-unit-of-work.test.ts} +16 -16
  267. package/src/query/{execute-unit-of-work.ts → unit-of-work/execute-unit-of-work.ts} +49 -8
  268. package/src/query/{unit-of-work-coordinator.test.ts → unit-of-work/unit-of-work-coordinator.test.ts} +41 -43
  269. package/src/query/{unit-of-work-types.test.ts → unit-of-work/unit-of-work-types.test.ts} +5 -3
  270. package/src/query/{unit-of-work.test.ts → unit-of-work/unit-of-work.test.ts} +100 -9
  271. package/src/query/{unit-of-work.ts → unit-of-work/unit-of-work.ts} +135 -32
  272. package/src/query/{result-transform.test.ts → value-decoding.test.ts} +45 -427
  273. package/src/query/value-decoding.ts +113 -0
  274. package/src/query/value-encoding.test.ts +390 -0
  275. package/src/query/value-encoding.ts +168 -0
  276. package/src/schema/create.test.ts +5 -1
  277. package/src/schema/create.ts +5 -0
  278. package/src/schema/serialize.test.ts +165 -407
  279. package/src/schema/type-conversion/create-sql-type-mapper.ts +28 -0
  280. package/src/schema/type-conversion/dialect/mysql.ts +64 -0
  281. package/src/schema/type-conversion/dialect/postgres.ts +62 -0
  282. package/src/schema/type-conversion/dialect/sqlite.ts +63 -0
  283. package/src/schema/type-conversion/type-mapping.test.ts +137 -0
  284. package/src/schema/type-conversion/type-mapping.ts +153 -0
  285. package/src/shared/connection-pool.ts +5 -5
  286. package/src/sql-driver/better-sqlite3.test.ts +126 -0
  287. package/src/sql-driver/connection/connection-provider.ts +27 -0
  288. package/src/sql-driver/connection/single-connection-provider.ts +42 -0
  289. package/src/sql-driver/dialect-adapter/dialect-adapter.ts +9 -0
  290. package/src/sql-driver/dialect-adapter/sqlite-dialect-adapter.ts +7 -0
  291. package/src/sql-driver/dialects/dialects.ts +1 -0
  292. package/src/sql-driver/dialects/durable-object-dialect.ts +260 -0
  293. package/src/sql-driver/driver/runtime-driver.ts +91 -0
  294. package/src/sql-driver/query-executor/default-query-executor.ts +38 -0
  295. package/src/sql-driver/query-executor/plugin.ts +22 -0
  296. package/src/sql-driver/query-executor/query-executor-base.ts +53 -0
  297. package/src/sql-driver/query-executor/query-executor.ts +44 -0
  298. package/src/sql-driver/sql-driver-adapter.ts +96 -0
  299. package/src/sql-driver/sql-driver.ts +53 -0
  300. package/src/sql-driver/sql.ts +57 -0
  301. package/src/sql-driver/sqlocal.test.ts +117 -0
  302. package/src/with-database.ts +35 -23
  303. package/tsdown.config.ts +7 -2
  304. package/dist/adapters/drizzle/drizzle-connection-pool.js +0 -40
  305. package/dist/adapters/drizzle/drizzle-connection-pool.js.map +0 -1
  306. package/dist/adapters/drizzle/drizzle-query.d.ts +0 -23
  307. package/dist/adapters/drizzle/drizzle-query.d.ts.map +0 -1
  308. package/dist/adapters/drizzle/drizzle-query.js.map +0 -1
  309. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +0 -10
  310. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +0 -1
  311. package/dist/adapters/drizzle/drizzle-uow-compiler.js +0 -334
  312. package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +0 -1
  313. package/dist/adapters/drizzle/drizzle-uow-decoder.js +0 -123
  314. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +0 -1
  315. package/dist/adapters/drizzle/drizzle-uow-executor.js +0 -160
  316. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +0 -1
  317. package/dist/adapters/drizzle/join-column-utils.js +0 -28
  318. package/dist/adapters/drizzle/join-column-utils.js.map +0 -1
  319. package/dist/adapters/drizzle/shared.d.ts.map +0 -1
  320. package/dist/adapters/drizzle/shared.js +0 -35
  321. package/dist/adapters/drizzle/shared.js.map +0 -1
  322. package/dist/adapters/kysely/kysely-connection-pool.js +0 -41
  323. package/dist/adapters/kysely/kysely-connection-pool.js.map +0 -1
  324. package/dist/adapters/kysely/kysely-query-builder.js +0 -321
  325. package/dist/adapters/kysely/kysely-query-builder.js.map +0 -1
  326. package/dist/adapters/kysely/kysely-query-compiler.js +0 -67
  327. package/dist/adapters/kysely/kysely-query-compiler.js.map +0 -1
  328. package/dist/adapters/kysely/kysely-query.d.ts +0 -23
  329. package/dist/adapters/kysely/kysely-query.d.ts.map +0 -1
  330. package/dist/adapters/kysely/kysely-query.js +0 -230
  331. package/dist/adapters/kysely/kysely-query.js.map +0 -1
  332. package/dist/adapters/kysely/kysely-shared.d.ts +0 -14
  333. package/dist/adapters/kysely/kysely-shared.d.ts.map +0 -1
  334. package/dist/adapters/kysely/kysely-shared.js +0 -33
  335. package/dist/adapters/kysely/kysely-shared.js.map +0 -1
  336. package/dist/adapters/kysely/kysely-uow-compiler.js +0 -193
  337. package/dist/adapters/kysely/kysely-uow-compiler.js.map +0 -1
  338. package/dist/adapters/kysely/kysely-uow-executor.js +0 -93
  339. package/dist/adapters/kysely/kysely-uow-executor.js.map +0 -1
  340. package/dist/adapters/kysely/migration/execute-base.js +0 -128
  341. package/dist/adapters/kysely/migration/execute-base.js.map +0 -1
  342. package/dist/adapters/kysely/migration/execute-factory.js +0 -34
  343. package/dist/adapters/kysely/migration/execute-factory.js.map +0 -1
  344. package/dist/adapters/kysely/migration/execute-mssql.js +0 -112
  345. package/dist/adapters/kysely/migration/execute-mssql.js.map +0 -1
  346. package/dist/adapters/kysely/migration/execute-mysql.js +0 -93
  347. package/dist/adapters/kysely/migration/execute-mysql.js.map +0 -1
  348. package/dist/adapters/kysely/migration/execute-postgres.js +0 -104
  349. package/dist/adapters/kysely/migration/execute-postgres.js.map +0 -1
  350. package/dist/adapters/kysely/migration/execute-sqlite.js +0 -123
  351. package/dist/adapters/kysely/migration/execute-sqlite.js.map +0 -1
  352. package/dist/adapters/kysely/migration/execute.js +0 -34
  353. package/dist/adapters/kysely/migration/execute.js.map +0 -1
  354. package/dist/migration-engine/create.d.ts +0 -37
  355. package/dist/migration-engine/create.d.ts.map +0 -1
  356. package/dist/migration-engine/create.js +0 -58
  357. package/dist/migration-engine/create.js.map +0 -1
  358. package/dist/migration-engine/shared.d.ts +0 -112
  359. package/dist/migration-engine/shared.d.ts.map +0 -1
  360. package/dist/node_modules/.pnpm/rou3@0.7.8/node_modules/rou3/dist/index.js.map +0 -1
  361. package/dist/query/execute-unit-of-work.d.ts.map +0 -1
  362. package/dist/query/execute-unit-of-work.js.map +0 -1
  363. package/dist/query/query.d.ts.map +0 -1
  364. package/dist/query/result-transform.js +0 -170
  365. package/dist/query/result-transform.js.map +0 -1
  366. package/dist/query/retry-policy.d.ts.map +0 -1
  367. package/dist/query/retry-policy.js.map +0 -1
  368. package/dist/query/unit-of-work.d.ts.map +0 -1
  369. package/dist/query/unit-of-work.js.map +0 -1
  370. package/dist/schema/serialize.js +0 -111
  371. package/dist/schema/serialize.js.map +0 -1
  372. package/src/adapters/drizzle/drizzle-adapter.test.ts +0 -122
  373. package/src/adapters/drizzle/drizzle-connection-pool.ts +0 -66
  374. package/src/adapters/drizzle/drizzle-query.test.ts +0 -499
  375. package/src/adapters/drizzle/drizzle-uow-compiler-mysql.test.ts +0 -1442
  376. package/src/adapters/drizzle/drizzle-uow-compiler-sqlite.test.ts +0 -1414
  377. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +0 -1400
  378. package/src/adapters/drizzle/drizzle-uow-compiler.ts +0 -677
  379. package/src/adapters/drizzle/drizzle-uow-decoder.ts +0 -228
  380. package/src/adapters/drizzle/drizzle-uow-executor.ts +0 -309
  381. package/src/adapters/drizzle/join-column-utils.test.ts +0 -79
  382. package/src/adapters/drizzle/join-column-utils.ts +0 -39
  383. package/src/adapters/kysely/kysely-connection-pool.ts +0 -70
  384. package/src/adapters/kysely/kysely-query-builder.test.ts +0 -1344
  385. package/src/adapters/kysely/kysely-query-builder.ts +0 -666
  386. package/src/adapters/kysely/kysely-query-compiler.ts +0 -127
  387. package/src/adapters/kysely/kysely-query.test.ts +0 -498
  388. package/src/adapters/kysely/kysely-query.ts +0 -399
  389. package/src/adapters/kysely/kysely-shared.ts +0 -57
  390. package/src/adapters/kysely/kysely-uow-compiler.test.ts +0 -986
  391. package/src/adapters/kysely/kysely-uow-compiler.ts +0 -350
  392. package/src/adapters/kysely/kysely-uow-executor.ts +0 -164
  393. package/src/adapters/kysely/kysely-uow-joins.test.ts +0 -794
  394. package/src/adapters/kysely/migration/execute-base.ts +0 -256
  395. package/src/adapters/kysely/migration/execute-factory.ts +0 -53
  396. package/src/adapters/kysely/migration/execute-mssql.ts +0 -250
  397. package/src/adapters/kysely/migration/execute-mysql.ts +0 -211
  398. package/src/adapters/kysely/migration/execute-postgres.test.ts +0 -2657
  399. package/src/adapters/kysely/migration/execute-postgres.ts +0 -234
  400. package/src/adapters/kysely/migration/execute-sqlite.ts +0 -247
  401. package/src/adapters/kysely/migration/execute.ts +0 -50
  402. package/src/adapters/kysely/migration/kysely-migrator.test.ts +0 -261
  403. package/src/query/result-transform.ts +0 -274
  404. package/src/schema/serialize.ts +0 -407
  405. /package/dist/query/{query.js → simple-query-interface.js} +0 -0
  406. /package/src/query/{retry-policy.test.ts → unit-of-work/retry-policy.test.ts} +0 -0
  407. /package/src/query/{retry-policy.ts → unit-of-work/retry-policy.ts} +0 -0
@@ -1,9 +1,13 @@
1
1
  import type { AnySchema } from "./schema/create";
2
- import type { AbstractQuery } from "./query/query";
2
+ import type { SimpleQueryInterface } from "./query/simple-query-interface";
3
3
  import type { DatabaseAdapter } from "./adapters/adapters";
4
- import type { IUnitOfWork } from "./query/unit-of-work";
5
- import { TypedUnitOfWork, UnitOfWork } from "./query/unit-of-work";
6
- import type { RequestThisContext, FragnoPublicConfig } from "@fragno-dev/core";
4
+ import type { IUnitOfWork } from "./query/unit-of-work/unit-of-work";
5
+ import { TypedUnitOfWork, UnitOfWork } from "./query/unit-of-work/unit-of-work";
6
+ import type {
7
+ RequestThisContext,
8
+ FragnoPublicConfig,
9
+ AnyFragnoInstantiatedFragment,
10
+ } from "@fragno-dev/core";
7
11
  import {
8
12
  FragmentDefinitionBuilder,
9
13
  type FragmentDefinition,
@@ -13,7 +17,15 @@ import {
13
17
  executeRestrictedUnitOfWork,
14
18
  type AwaitedPromisesInObject,
15
19
  type ExecuteRestrictedUnitOfWorkOptions,
16
- } from "./query/execute-unit-of-work";
20
+ } from "./query/unit-of-work/execute-unit-of-work";
21
+ import {
22
+ prepareHookMutations,
23
+ processHooks,
24
+ type HooksMap,
25
+ type HookFn,
26
+ type HookContext,
27
+ } from "./hooks/hooks";
28
+ import type { InternalFragmentInstance } from "./fragments/internal-fragment";
17
29
 
18
30
  /**
19
31
  * Extended FragnoPublicConfig that includes a database adapter.
@@ -32,7 +44,7 @@ export type ImplicitDatabaseDependencies<TSchema extends AnySchema> = {
32
44
  /**
33
45
  * Database query engine for the fragment's schema.
34
46
  */
35
- db: AbstractQuery<TSchema>;
47
+ db: SimpleQueryInterface<TSchema>;
36
48
  /**
37
49
  * The schema definition for this fragment.
38
50
  */
@@ -50,19 +62,19 @@ export type ImplicitDatabaseDependencies<TSchema extends AnySchema> = {
50
62
  /**
51
63
  * Service context for database fragments - provides restricted UOW access without execute methods.
52
64
  */
53
- export type DatabaseServiceContext = RequestThisContext & {
65
+ export type DatabaseServiceContext<THooks extends HooksMap> = RequestThisContext & {
54
66
  /**
55
67
  * Get a typed, restricted Unit of Work for the given schema.
56
68
  * @param schema - Schema to get a typed view for
57
69
  * @returns TypedUnitOfWork (restricted version without execute methods)
58
70
  */
59
- uow<TSchema extends AnySchema>(schema: TSchema): TypedUnitOfWork<TSchema, [], unknown>;
71
+ uow<TSchema extends AnySchema>(schema: TSchema): TypedUnitOfWork<TSchema, [], unknown, THooks>;
60
72
  };
61
73
 
62
74
  /**
63
75
  * Handler context for database fragments - provides UOW execution with automatic retry support.
64
76
  */
65
- export type DatabaseHandlerContext = RequestThisContext & {
77
+ export type DatabaseHandlerContext<THooks extends HooksMap = {}> = RequestThisContext & {
66
78
  /**
67
79
  * Execute a Unit of Work with explicit phase control and automatic retry support.
68
80
  * This method provides an API where users call forSchema to create a schema-specific
@@ -96,7 +108,10 @@ export type DatabaseHandlerContext = RequestThisContext & {
96
108
  */
97
109
  uow<TResult>(
98
110
  callback: (context: {
99
- forSchema: <S extends AnySchema>(schema: S) => TypedUnitOfWork<S, [], unknown>;
111
+ forSchema: <TSchema extends AnySchema, H extends HooksMap = THooks>(
112
+ schema: TSchema,
113
+ hooks?: H,
114
+ ) => TypedUnitOfWork<TSchema, [], unknown, H>;
100
115
  executeRetrieve: () => Promise<void>;
101
116
  executeMutate: () => Promise<void>;
102
117
  nonce: string;
@@ -117,7 +132,7 @@ export type DatabaseFragmentContext<TSchema extends AnySchema> = {
117
132
  /**
118
133
  * ORM query engine for the fragment's schema.
119
134
  */
120
- db: AbstractQuery<TSchema>;
135
+ db: SimpleQueryInterface<TSchema>;
121
136
  };
122
137
 
123
138
  /**
@@ -163,8 +178,10 @@ export class DatabaseFragmentDefinitionBuilder<
163
178
  TServices,
164
179
  TServiceDependencies,
165
180
  TPrivateServices,
181
+ THooks extends HooksMap = {},
166
182
  TServiceThisContext extends RequestThisContext = DatabaseHandlerContext,
167
183
  THandlerThisContext extends RequestThisContext = DatabaseHandlerContext,
184
+ TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment> = {},
168
185
  > {
169
186
  // Store the base builder - we'll replace its storage and context setup when building
170
187
  #baseBuilder: FragmentDefinitionBuilder<
@@ -177,10 +194,12 @@ export class DatabaseFragmentDefinitionBuilder<
177
194
  TPrivateServices,
178
195
  TServiceThisContext,
179
196
  THandlerThisContext,
180
- DatabaseRequestStorage
197
+ DatabaseRequestStorage,
198
+ TLinkedFragments
181
199
  >;
182
200
  #schema: TSchema;
183
201
  #namespace: string;
202
+ #hooksFactory?: (context: { config: TConfig; options: FragnoPublicConfigWithDatabase }) => THooks;
184
203
 
185
204
  constructor(
186
205
  baseBuilder: FragmentDefinitionBuilder<
@@ -193,14 +212,20 @@ export class DatabaseFragmentDefinitionBuilder<
193
212
  TPrivateServices,
194
213
  TServiceThisContext,
195
214
  THandlerThisContext,
196
- DatabaseRequestStorage
215
+ DatabaseRequestStorage,
216
+ TLinkedFragments
197
217
  >,
198
218
  schema: TSchema,
199
219
  namespace?: string,
220
+ hooksFactory?: (context: {
221
+ config: TConfig;
222
+ options: FragnoPublicConfigWithDatabase;
223
+ }) => THooks,
200
224
  ) {
201
225
  this.#baseBuilder = baseBuilder;
202
226
  this.#schema = schema;
203
- this.#namespace = namespace ?? baseBuilder.name + "-db";
227
+ this.#namespace = namespace ?? baseBuilder.name;
228
+ this.#hooksFactory = hooksFactory;
204
229
  }
205
230
 
206
231
  /**
@@ -211,7 +236,7 @@ export class DatabaseFragmentDefinitionBuilder<
211
236
  fn: (context: {
212
237
  config: TConfig;
213
238
  options: FragnoPublicConfigWithDatabase;
214
- db: AbstractQuery<TSchema>;
239
+ db: SimpleQueryInterface<TSchema>;
215
240
  databaseAdapter: DatabaseAdapter<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
216
241
  }) => TNewDeps,
217
242
  ): DatabaseFragmentDefinitionBuilder<
@@ -222,8 +247,10 @@ export class DatabaseFragmentDefinitionBuilder<
222
247
  {},
223
248
  TServiceDependencies,
224
249
  {},
250
+ THooks,
225
251
  TServiceThisContext,
226
- THandlerThisContext
252
+ THandlerThisContext,
253
+ TLinkedFragments
227
254
  > {
228
255
  // Wrap user function to inject DB context
229
256
  const wrappedFn = (context: { config: TConfig; options: FragnoPublicConfigWithDatabase }) => {
@@ -255,8 +282,12 @@ export class DatabaseFragmentDefinitionBuilder<
255
282
  // Create new base builder with wrapped function
256
283
  const newBaseBuilder = this.#baseBuilder.withDependencies(wrappedFn);
257
284
 
258
- // Return new database builder with updated base
259
- return new DatabaseFragmentDefinitionBuilder(newBaseBuilder, this.#schema, this.#namespace);
285
+ return new DatabaseFragmentDefinitionBuilder(
286
+ newBaseBuilder,
287
+ this.#schema,
288
+ this.#namespace,
289
+ this.#hooksFactory,
290
+ );
260
291
  }
261
292
 
262
293
  providesBaseService<TNewService>(
@@ -277,12 +308,19 @@ export class DatabaseFragmentDefinitionBuilder<
277
308
  TServices,
278
309
  TServiceDependencies,
279
310
  TPrivateServices,
311
+ THooks,
280
312
  TServiceThisContext,
281
- THandlerThisContext
313
+ THandlerThisContext,
314
+ TLinkedFragments
282
315
  > {
283
316
  const newBaseBuilder = this.#baseBuilder.providesBaseService<TNewService>(fn);
284
317
 
285
- return new DatabaseFragmentDefinitionBuilder(newBaseBuilder, this.#schema, this.#namespace);
318
+ return new DatabaseFragmentDefinitionBuilder(
319
+ newBaseBuilder,
320
+ this.#schema,
321
+ this.#namespace,
322
+ this.#hooksFactory,
323
+ );
286
324
  }
287
325
 
288
326
  providesService<TServiceName extends string, TService>(
@@ -304,15 +342,147 @@ export class DatabaseFragmentDefinitionBuilder<
304
342
  TServices & { [K in TServiceName]: TService },
305
343
  TServiceDependencies,
306
344
  TPrivateServices,
345
+ THooks,
307
346
  TServiceThisContext,
308
- THandlerThisContext
347
+ THandlerThisContext,
348
+ TLinkedFragments
309
349
  > {
310
350
  const newBaseBuilder = this.#baseBuilder.providesService<TServiceName, TService>(
311
351
  serviceName,
312
352
  fn,
313
353
  );
314
354
 
315
- return new DatabaseFragmentDefinitionBuilder(newBaseBuilder, this.#schema, this.#namespace);
355
+ return new DatabaseFragmentDefinitionBuilder(
356
+ newBaseBuilder,
357
+ this.#schema,
358
+ this.#namespace,
359
+ this.#hooksFactory,
360
+ );
361
+ }
362
+
363
+ /**
364
+ * Provide a private service that is only accessible to the fragment author.
365
+ * Private services are NOT exposed on the fragment instance, but can be used
366
+ * when defining other services (baseServices, namedServices, and other privateServices).
367
+ * Private services are instantiated in order, so earlier private services are available
368
+ * to later ones.
369
+ */
370
+ providesPrivateService<TServiceName extends string, TService>(
371
+ serviceName: TServiceName,
372
+ fn: ServiceConstructorFn<
373
+ TConfig,
374
+ FragnoPublicConfigWithDatabase,
375
+ TDeps,
376
+ TServiceDependencies,
377
+ TPrivateServices,
378
+ TService,
379
+ TServiceThisContext
380
+ >,
381
+ ): DatabaseFragmentDefinitionBuilder<
382
+ TSchema,
383
+ TConfig,
384
+ TDeps,
385
+ TBaseServices,
386
+ TServices,
387
+ TServiceDependencies,
388
+ TPrivateServices & { [K in TServiceName]: TService },
389
+ THooks,
390
+ TServiceThisContext,
391
+ THandlerThisContext,
392
+ TLinkedFragments
393
+ > {
394
+ const newBaseBuilder = this.#baseBuilder.providesPrivateService<TServiceName, TService>(
395
+ serviceName,
396
+ fn,
397
+ );
398
+
399
+ return new DatabaseFragmentDefinitionBuilder(
400
+ newBaseBuilder,
401
+ this.#schema,
402
+ this.#namespace,
403
+ this.#hooksFactory,
404
+ );
405
+ }
406
+
407
+ /**
408
+ * Define durable hooks for this fragment.
409
+ * Hooks are automatically persisted and retried on failure.
410
+ *
411
+ * @param fn - Function that receives defineHook helper and returns a hooks map
412
+ * @returns Builder with hooks type set
413
+ *
414
+ * @example
415
+ * ```ts
416
+ * .provideHooks(({ defineHook, config }) => ({
417
+ * onSubscribe: defineHook(async function (payload: { email: string }) {
418
+ * // 'this' context available (HookServiceContext with nonce)
419
+ * await config.onSubscribe?.(payload.email);
420
+ * }),
421
+ * }))
422
+ * ```
423
+ */
424
+ provideHooks<TNewHooks extends HooksMap>(
425
+ fn: (context: {
426
+ config: TConfig;
427
+ options: FragnoPublicConfigWithDatabase;
428
+ defineHook: <TPayload>(
429
+ hook: (this: HookContext, payload: TPayload) => void | Promise<void>,
430
+ ) => HookFn<TPayload>;
431
+ }) => TNewHooks,
432
+ ): DatabaseFragmentDefinitionBuilder<
433
+ TSchema,
434
+ TConfig,
435
+ TDeps,
436
+ TBaseServices,
437
+ TServices,
438
+ TServiceDependencies,
439
+ TPrivateServices,
440
+ TNewHooks,
441
+ DatabaseServiceContext<TNewHooks>,
442
+ THandlerThisContext,
443
+ TLinkedFragments
444
+ > {
445
+ const defineHook = <TPayload>(
446
+ hook: (this: HookContext, payload: TPayload) => void | Promise<void>,
447
+ ): HookFn<TPayload> => {
448
+ return hook;
449
+ };
450
+
451
+ // Store the hooks factory - it will be called in build() with config/options
452
+ const hooksFactory = (context: {
453
+ config: TConfig;
454
+ options: FragnoPublicConfigWithDatabase;
455
+ }) => {
456
+ return fn({
457
+ config: context.config,
458
+ options: context.options,
459
+ defineHook,
460
+ });
461
+ };
462
+
463
+ // Create new builder with hooks factory stored
464
+ // Cast is safe: we're only changing THooks and TServiceThisContext type parameters
465
+ const newBuilder = new DatabaseFragmentDefinitionBuilder(
466
+ this.#baseBuilder,
467
+ this.#schema,
468
+ this.#namespace,
469
+ ) as unknown as DatabaseFragmentDefinitionBuilder<
470
+ TSchema,
471
+ TConfig,
472
+ TDeps,
473
+ TBaseServices,
474
+ TServices,
475
+ TServiceDependencies,
476
+ TPrivateServices,
477
+ TNewHooks,
478
+ DatabaseServiceContext<TNewHooks>,
479
+ THandlerThisContext,
480
+ TLinkedFragments
481
+ >;
482
+
483
+ newBuilder.#hooksFactory = hooksFactory;
484
+
485
+ return newBuilder;
316
486
  }
317
487
 
318
488
  /**
@@ -329,12 +499,19 @@ export class DatabaseFragmentDefinitionBuilder<
329
499
  TServices,
330
500
  TServiceDependencies & { [K in TServiceName]: TService },
331
501
  TPrivateServices,
502
+ THooks,
332
503
  TServiceThisContext,
333
- THandlerThisContext
504
+ THandlerThisContext,
505
+ TLinkedFragments
334
506
  > {
335
507
  const newBaseBuilder = this.#baseBuilder.usesService<TServiceName, TService>(serviceName);
336
508
 
337
- return new DatabaseFragmentDefinitionBuilder(newBaseBuilder, this.#schema, this.#namespace);
509
+ return new DatabaseFragmentDefinitionBuilder(
510
+ newBaseBuilder,
511
+ this.#schema,
512
+ this.#namespace,
513
+ this.#hooksFactory,
514
+ );
338
515
  }
339
516
 
340
517
  /**
@@ -351,14 +528,21 @@ export class DatabaseFragmentDefinitionBuilder<
351
528
  TServices,
352
529
  TServiceDependencies & { [K in TServiceName]: TService | undefined },
353
530
  TPrivateServices,
531
+ THooks,
354
532
  TServiceThisContext,
355
- THandlerThisContext
533
+ THandlerThisContext,
534
+ TLinkedFragments
356
535
  > {
357
536
  const newBaseBuilder = this.#baseBuilder.usesOptionalService<TServiceName, TService>(
358
537
  serviceName,
359
538
  );
360
539
 
361
- return new DatabaseFragmentDefinitionBuilder(newBaseBuilder, this.#schema, this.#namespace);
540
+ return new DatabaseFragmentDefinitionBuilder(
541
+ newBaseBuilder,
542
+ this.#schema,
543
+ this.#namespace,
544
+ this.#hooksFactory,
545
+ );
362
546
  }
363
547
 
364
548
  /**
@@ -374,18 +558,38 @@ export class DatabaseFragmentDefinitionBuilder<
374
558
  TServices,
375
559
  TServiceDependencies,
376
560
  TPrivateServices,
377
- DatabaseServiceContext,
378
- DatabaseHandlerContext,
379
- DatabaseRequestStorage
561
+ DatabaseServiceContext<THooks>,
562
+ DatabaseHandlerContext<THooks>,
563
+ DatabaseRequestStorage,
564
+ TLinkedFragments
380
565
  > {
566
+ const baseDef = this.#baseBuilder.build();
567
+
381
568
  // Ensure dependencies callback always exists for database fragments
382
569
  // If no user dependencies were defined, create a minimal one that only adds implicit deps
383
570
  const dependencies = (context: {
384
571
  config: TConfig;
385
572
  options: FragnoPublicConfigWithDatabase;
386
573
  }): TDeps => {
387
- const baseDef = this.#baseBuilder.build();
388
- const userDeps = baseDef.dependencies?.(context);
574
+ // In dry run mode, allow user deps to fail gracefully.
575
+ // This is critical for database fragments because the CLI needs access to the schema
576
+ // even when user dependencies (like API clients) can't be initialized.
577
+ // Without this, if user deps fail, we'd lose the implicit database dependencies
578
+ // (including schema), and the CLI couldn't extract schema information.
579
+ let userDeps;
580
+ try {
581
+ userDeps = baseDef.dependencies?.(context);
582
+ } catch (error) {
583
+ if (process.env["FRAGNO_INIT_DRY_RUN"] === "true") {
584
+ console.warn(
585
+ "Warning: Failed to initialize user dependencies in dry run mode:",
586
+ error instanceof Error ? error.message : String(error),
587
+ );
588
+ userDeps = {};
589
+ } else {
590
+ throw error;
591
+ }
592
+ }
389
593
 
390
594
  const { db } = createDatabaseContext(context.options, this.#schema, this.#namespace);
391
595
 
@@ -423,15 +627,29 @@ export class DatabaseFragmentDefinitionBuilder<
423
627
  },
424
628
  );
425
629
 
426
- // Services get restricted context (no execute methods), handlers get execution context
630
+ // Get the internal fragment factory from linked fragments (added by withDatabase)
631
+ // Cast is safe: withDatabase() guarantees this fragment exists and has the correct type
632
+ const internalFragmentFactory = baseDef.linkedFragments?.["_fragno_internal"] as (context: {
633
+ config: TConfig;
634
+ options: FragnoPublicConfigWithDatabase;
635
+ }) => InternalFragmentInstance;
636
+
427
637
  const builderWithContext = builderWithStorage.withThisContext<
428
- DatabaseServiceContext,
429
- DatabaseHandlerContext
430
- >(({ storage }) => {
431
- // Service context - forSchema method to get restricted typed UOW
638
+ DatabaseServiceContext<THooks>,
639
+ DatabaseHandlerContext<THooks>
640
+ >(({ storage, config, options }) => {
641
+ // Create hooks config if hooks factory is defined
642
+ const hooksConfig = this.#hooksFactory
643
+ ? {
644
+ hooks: this.#hooksFactory({ config, options }),
645
+ namespace: this.#namespace,
646
+ internalFragment: internalFragmentFactory({ config, options }),
647
+ }
648
+ : undefined;
649
+
432
650
  function forSchema<TSchema extends AnySchema>(
433
651
  schema: TSchema,
434
- ): TypedUnitOfWork<TSchema, [], unknown> {
652
+ ): TypedUnitOfWork<TSchema, [], unknown, THooks> {
435
653
  const uow = storage.getStore()?.uow;
436
654
  if (!uow) {
437
655
  throw new Error(
@@ -439,24 +657,28 @@ export class DatabaseFragmentDefinitionBuilder<
439
657
  );
440
658
  }
441
659
 
442
- // Return typed view of restricted UOW
443
- return uow.restrict().forSchema(schema);
660
+ return uow.restrict().forSchema<TSchema, THooks>(schema);
444
661
  }
445
662
 
446
- const serviceContext: DatabaseServiceContext = {
663
+ const serviceContext: DatabaseServiceContext<THooks> = {
447
664
  uow: forSchema,
448
665
  };
449
666
 
450
- // Handler context - only executeRestrictedUnitOfWork
451
667
  async function uow<TResult>(
452
668
  callback: (context: {
453
- forSchema: <S extends AnySchema>(schema: S) => TypedUnitOfWork<S, [], unknown>;
669
+ forSchema: <S extends AnySchema, H extends HooksMap = THooks>(
670
+ schema: S,
671
+ hooks?: H,
672
+ ) => TypedUnitOfWork<S, [], unknown, H>;
454
673
  executeRetrieve: () => Promise<void>;
455
674
  executeMutate: () => Promise<void>;
456
675
  nonce: string;
457
676
  currentAttempt: number;
458
677
  }) => Promise<TResult> | TResult,
459
- options?: Omit<ExecuteRestrictedUnitOfWorkOptions, "createUnitOfWork">,
678
+ execOptions?: Omit<
679
+ ExecuteRestrictedUnitOfWorkOptions,
680
+ "createUnitOfWork" | "onBeforeMutate" | "onSuccess"
681
+ >,
460
682
  ): Promise<AwaitedPromisesInObject<TResult>> {
461
683
  const currentStorage = storage.getStore();
462
684
  if (!currentStorage) {
@@ -465,29 +687,38 @@ export class DatabaseFragmentDefinitionBuilder<
465
687
  );
466
688
  }
467
689
 
468
- // Wrap callback to ensure it always returns a Promise
469
690
  const wrappedCallback = async (context: {
470
- forSchema: <S extends AnySchema>(schema: S) => TypedUnitOfWork<S, [], unknown>;
691
+ forSchema: <S extends AnySchema, H extends HooksMap = THooks>(
692
+ schema: S,
693
+ hooks?: H,
694
+ ) => TypedUnitOfWork<S, [], unknown, H>;
471
695
  executeRetrieve: () => Promise<void>;
472
696
  executeMutate: () => Promise<void>;
473
697
  nonce: string;
474
698
  currentAttempt: number;
475
699
  }): Promise<TResult> => {
476
- return await callback(context);
700
+ return callback(context);
477
701
  };
478
702
 
479
- // Use the UOW from storage - reset it before each attempt for retry support
480
- // Cast is safe because IUnitOfWork is actually implemented by UnitOfWork
481
703
  return executeRestrictedUnitOfWork(wrappedCallback, {
482
- ...options,
704
+ ...execOptions,
483
705
  createUnitOfWork: () => {
484
706
  currentStorage.uow.reset();
707
+ // Register internal schema for hook mutations
708
+ if (hooksConfig) {
709
+ currentStorage.uow.registerSchema(
710
+ hooksConfig.internalFragment.$internal.deps.schema,
711
+ hooksConfig.internalFragment.$internal.deps.namespace,
712
+ );
713
+ }
485
714
  return currentStorage.uow as UnitOfWork;
486
715
  },
716
+ onBeforeMutate: hooksConfig ? (uow) => prepareHookMutations(uow, hooksConfig) : undefined,
717
+ onSuccess: hooksConfig ? () => processHooks(hooksConfig) : undefined,
487
718
  });
488
719
  }
489
720
 
490
- const handlerContext: DatabaseHandlerContext = {
721
+ const handlerContext: DatabaseHandlerContext<THooks> = {
491
722
  uow,
492
723
  };
493
724
 
@@ -4,7 +4,7 @@ import { defineRoutes } from "@fragno-dev/core/route";
4
4
  import { withDatabase } from "./with-database";
5
5
  import { schema, idColumn, column } from "./schema/create";
6
6
  import type { DatabaseAdapter } from "./adapters/adapters";
7
- import type { AbstractQuery } from "./query/query";
7
+ import type { SimpleQueryInterface } from "./query/simple-query-interface";
8
8
  import { RequestContextStorage } from "@fragno-dev/core/internal/request-context-storage";
9
9
  import { z } from "zod";
10
10
 
@@ -56,7 +56,7 @@ function createMockAdapter(): DatabaseAdapter {
56
56
  };
57
57
  }),
58
58
  type: "mock",
59
- } as unknown as AbstractQuery<TestSchema>;
59
+ } as unknown as SimpleQueryInterface<TestSchema>;
60
60
 
61
61
  return {
62
62
  createQueryEngine: vi.fn(() => mockdb),
@@ -428,6 +428,82 @@ describe("db-fragment-instantiator", () => {
428
428
  });
429
429
  });
430
430
 
431
+ describe("$internal object", () => {
432
+ it("should populate $internal.deps with database dependencies", () => {
433
+ const definition = defineFragment("test-db-fragment")
434
+ .extend(withDatabase(testSchema))
435
+ .build();
436
+
437
+ const mockAdapter = createMockAdapter();
438
+ const fragment = instantiate(definition)
439
+ .withOptions({ mountRoute: "/api", databaseAdapter: mockAdapter })
440
+ .build();
441
+
442
+ expect(fragment.$internal.deps).toBeDefined();
443
+ expect(fragment.$internal.deps).toHaveProperty("db");
444
+ expect(fragment.$internal.deps).toHaveProperty("schema");
445
+ expect(fragment.$internal.deps).toHaveProperty("namespace");
446
+ expect(fragment.$internal.deps).toHaveProperty("createUnitOfWork");
447
+ });
448
+
449
+ it("should populate $internal.options with database adapter", () => {
450
+ const definition = defineFragment("test-db-fragment")
451
+ .extend(withDatabase(testSchema))
452
+ .build();
453
+
454
+ const mockAdapter = createMockAdapter();
455
+ const fragment = instantiate(definition)
456
+ .withOptions({ mountRoute: "/api", databaseAdapter: mockAdapter })
457
+ .build();
458
+
459
+ expect(fragment.$internal.options).toBeDefined();
460
+ expect(fragment.$internal.options).toHaveProperty("databaseAdapter");
461
+ expect(fragment.$internal.options.databaseAdapter).toBe(mockAdapter);
462
+ expect(fragment.$internal.options).toHaveProperty("mountRoute", "/api");
463
+ });
464
+
465
+ it("should have correct schema and namespace in $internal.deps", () => {
466
+ const definition = defineFragment("test-db-fragment")
467
+ .extend(withDatabase(testSchema))
468
+ .build();
469
+
470
+ const mockAdapter = createMockAdapter();
471
+ const fragment = instantiate(definition)
472
+ .withOptions({ mountRoute: "/api", databaseAdapter: mockAdapter })
473
+ .build();
474
+
475
+ expect(fragment.$internal.deps.schema).toBe(testSchema);
476
+ expect(fragment.$internal.deps.namespace).toBe("test-db-fragment");
477
+ });
478
+
479
+ it("should populate $internal when using providesBaseService without withDependencies", () => {
480
+ const definition = defineFragment("test-db-fragment")
481
+ .extend(withDatabase(testSchema))
482
+ .providesBaseService(({ defineService }) =>
483
+ defineService({
484
+ testMethod: function () {
485
+ return "test";
486
+ },
487
+ }),
488
+ )
489
+ .build();
490
+
491
+ const mockAdapter = createMockAdapter();
492
+ const fragment = instantiate(definition)
493
+ .withOptions({ mountRoute: "/api", databaseAdapter: mockAdapter })
494
+ .build();
495
+
496
+ expect(fragment.$internal.deps).toBeDefined();
497
+ expect(fragment.$internal.deps).toHaveProperty("db");
498
+ expect(fragment.$internal.deps).toHaveProperty("schema");
499
+ expect(fragment.$internal.deps).toHaveProperty("namespace");
500
+ expect(fragment.$internal.deps).toHaveProperty("createUnitOfWork");
501
+ expect(fragment.$internal.options).toBeDefined();
502
+ expect(fragment.$internal.options).toHaveProperty("databaseAdapter");
503
+ expect(fragment.$internal.options.databaseAdapter).toBe(mockAdapter);
504
+ });
505
+ });
506
+
431
507
  describe("error handling", () => {
432
508
  it("should throw when databaseAdapter is not provided", () => {
433
509
  const definition = defineFragment("test-db-fragment")