@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
@@ -0,0 +1,575 @@
1
+ import SQLite from "better-sqlite3";
2
+ import { SqliteDialect } from "kysely";
3
+ import { beforeAll, describe, expect, it, vi } from "vitest";
4
+ import { instantiate } from "@fragno-dev/core";
5
+ import { prepareHookMutations, processHooks, type HooksMap, type HookContext } from "./hooks";
6
+ import { internalFragmentDef, internalSchema } from "../fragments/internal-fragment";
7
+ import type { FragnoPublicConfigWithDatabase } from "../db-fragment-definition-builder";
8
+ import { DrizzleAdapter } from "../adapters/drizzle/drizzle-adapter";
9
+ import { BetterSQLite3DriverConfig } from "../adapters/generic-sql/driver-config";
10
+ import { ExponentialBackoffRetryPolicy, NoRetryPolicy } from "../query/unit-of-work/retry-policy";
11
+ import type { FragnoId } from "../schema/create";
12
+
13
+ describe("Hook System", () => {
14
+ let sqliteDatabase: SQLite.Database;
15
+ let adapter: DrizzleAdapter;
16
+ let internalFragment: ReturnType<typeof instantiateFragment>;
17
+
18
+ function instantiateFragment(options: FragnoPublicConfigWithDatabase) {
19
+ return instantiate(internalFragmentDef).withConfig({}).withOptions(options).build();
20
+ }
21
+
22
+ beforeAll(async () => {
23
+ sqliteDatabase = new SQLite(":memory:");
24
+
25
+ const dialect = new SqliteDialect({
26
+ database: sqliteDatabase,
27
+ });
28
+
29
+ adapter = new DrizzleAdapter({
30
+ dialect,
31
+ driverConfig: new BetterSQLite3DriverConfig(),
32
+ });
33
+
34
+ {
35
+ const migrations = adapter.prepareMigrations(internalSchema, "");
36
+ await migrations.executeWithDriver(adapter.driver, 0);
37
+ }
38
+
39
+ const options: FragnoPublicConfigWithDatabase = {
40
+ databaseAdapter: adapter,
41
+ };
42
+
43
+ internalFragment = instantiateFragment(options);
44
+
45
+ return async () => {
46
+ await adapter.close();
47
+ };
48
+ }, 12000);
49
+
50
+ describe("prepareHookMutations", () => {
51
+ it("should create hook records for triggered hooks", async () => {
52
+ const namespace = "test-namespace";
53
+ const hooks: HooksMap = {
54
+ onTest: vi.fn(),
55
+ };
56
+
57
+ await internalFragment.inContext(async function () {
58
+ await this.uow(async ({ forSchema, executeMutate }) => {
59
+ const uow = forSchema(internalSchema, hooks);
60
+
61
+ // Trigger a hook
62
+ uow.triggerHook("onTest", { data: "test" });
63
+
64
+ // Prepare hook mutations
65
+ prepareHookMutations(uow, {
66
+ hooks,
67
+ namespace,
68
+ internalFragment,
69
+ defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 5 }),
70
+ });
71
+
72
+ await executeMutate();
73
+ });
74
+ });
75
+
76
+ // Verify hook was created
77
+ const events = await internalFragment.inContext(async function () {
78
+ return await this.uow(async ({ executeRetrieve }) => {
79
+ const result = internalFragment.services.hookService.getPendingHookEvents(namespace);
80
+ await executeRetrieve();
81
+ return result;
82
+ });
83
+ });
84
+
85
+ expect(events).toHaveLength(1);
86
+ expect(events[0]).toMatchObject({
87
+ hookName: "onTest",
88
+ payload: { data: "test" },
89
+ attempts: 0,
90
+ maxAttempts: 5,
91
+ });
92
+ });
93
+
94
+ it("should set maxAttempts to 1 when retry policy does not retry", async () => {
95
+ const namespace = "test-no-retry";
96
+ const hooks: HooksMap = {
97
+ onNoRetry: vi.fn(),
98
+ };
99
+
100
+ await internalFragment.inContext(async function () {
101
+ await this.uow(async ({ forSchema, executeMutate }) => {
102
+ const uow = forSchema(internalSchema, hooks);
103
+
104
+ uow.triggerHook("onNoRetry", { data: "test" });
105
+
106
+ prepareHookMutations(uow, {
107
+ hooks,
108
+ namespace,
109
+ internalFragment,
110
+ defaultRetryPolicy: new NoRetryPolicy(),
111
+ });
112
+
113
+ await executeMutate();
114
+ });
115
+ });
116
+
117
+ const events = await internalFragment.inContext(async function () {
118
+ return await this.uow(async ({ executeRetrieve }) => {
119
+ const result = internalFragment.services.hookService.getPendingHookEvents(namespace);
120
+ await executeRetrieve();
121
+ return result;
122
+ });
123
+ });
124
+
125
+ expect(events).toHaveLength(1);
126
+ expect(events[0]?.maxAttempts).toBe(1);
127
+ });
128
+
129
+ it("should use custom retry policy from trigger options", async () => {
130
+ const namespace = "test-custom-retry";
131
+ const hooks: HooksMap = {
132
+ onCustomRetry: vi.fn(),
133
+ };
134
+
135
+ await internalFragment.inContext(async function () {
136
+ await this.uow(async ({ forSchema, executeMutate }) => {
137
+ const uow = forSchema(internalSchema, hooks);
138
+
139
+ uow.triggerHook(
140
+ "onCustomRetry",
141
+ { data: "test" },
142
+ {
143
+ retryPolicy: new NoRetryPolicy(),
144
+ },
145
+ );
146
+
147
+ prepareHookMutations(uow, {
148
+ hooks,
149
+ namespace,
150
+ internalFragment,
151
+ defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 10 }),
152
+ });
153
+
154
+ await executeMutate();
155
+ });
156
+ });
157
+
158
+ const events = await internalFragment.inContext(async function () {
159
+ return await this.uow(async ({ executeRetrieve }) => {
160
+ const result = internalFragment.services.hookService.getPendingHookEvents(namespace);
161
+ await executeRetrieve();
162
+ return result;
163
+ });
164
+ });
165
+
166
+ expect(events[0]?.maxAttempts).toBe(1);
167
+ });
168
+ });
169
+
170
+ describe("processHooks", () => {
171
+ it("should execute hooks and mark them as completed", async () => {
172
+ const namespace = "test-success";
173
+ const hookFn = vi.fn();
174
+ const hooks: HooksMap = {
175
+ onSuccess: hookFn,
176
+ };
177
+
178
+ let eventId: FragnoId;
179
+
180
+ // Create a pending hook event
181
+ await internalFragment.inContext(async function () {
182
+ await this.uow(async ({ forSchema, executeMutate }) => {
183
+ const uow = forSchema(internalSchema);
184
+ eventId = uow.create("fragno_hooks", {
185
+ namespace,
186
+ hookName: "onSuccess",
187
+ payload: { email: "test@example.com" },
188
+ status: "pending",
189
+ attempts: 0,
190
+ maxAttempts: 5,
191
+ lastAttemptAt: null,
192
+ nextRetryAt: null,
193
+ error: null,
194
+ nonce: "test-nonce",
195
+ });
196
+ await executeMutate();
197
+ });
198
+ });
199
+
200
+ // Process hooks
201
+ await processHooks({
202
+ hooks,
203
+ namespace,
204
+ internalFragment,
205
+ defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 }),
206
+ });
207
+
208
+ // Verify hook was called
209
+ expect(hookFn).toHaveBeenCalledOnce();
210
+ expect(hookFn).toHaveBeenCalledWith({ email: "test@example.com" });
211
+
212
+ // Verify hook context (this)
213
+ const hookContext = hookFn.mock.contexts[0] as HookContext;
214
+ expect(hookContext.nonce).toBe("test-nonce");
215
+
216
+ // Verify event was marked as completed
217
+ const result = await internalFragment.inContext(async function () {
218
+ return await this.uow(async ({ forSchema, executeRetrieve }) => {
219
+ const uow = forSchema(internalSchema);
220
+ const findUow = uow.find("fragno_hooks", (b) =>
221
+ b.whereIndex("primary", (eb) => eb("id", "=", eventId)),
222
+ );
223
+ await executeRetrieve();
224
+ const [events] = await findUow.retrievalPhase;
225
+ return events?.[0];
226
+ });
227
+ });
228
+
229
+ expect(result?.status).toBe("completed");
230
+ expect(result?.lastAttemptAt).toBeInstanceOf(Date);
231
+ });
232
+
233
+ it("should mark failed hooks for retry", async () => {
234
+ const namespace = "test-failure";
235
+ const hookFn = vi.fn().mockRejectedValue(new Error("Hook failed"));
236
+ const hooks: HooksMap = {
237
+ onFailure: hookFn,
238
+ };
239
+
240
+ let eventId: FragnoId;
241
+
242
+ await internalFragment.inContext(async function () {
243
+ await this.uow(async ({ forSchema, executeMutate }) => {
244
+ const uow = forSchema(internalSchema);
245
+ eventId = uow.create("fragno_hooks", {
246
+ namespace,
247
+ hookName: "onFailure",
248
+ payload: { data: "test" },
249
+ status: "pending",
250
+ attempts: 0,
251
+ maxAttempts: 5,
252
+ lastAttemptAt: null,
253
+ nextRetryAt: null,
254
+ error: null,
255
+ nonce: "test-nonce",
256
+ });
257
+ await executeMutate();
258
+ });
259
+ });
260
+
261
+ await processHooks({
262
+ hooks,
263
+ namespace,
264
+ internalFragment,
265
+ defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 }),
266
+ });
267
+
268
+ expect(hookFn).toHaveBeenCalledOnce();
269
+
270
+ const result = await internalFragment.inContext(async function () {
271
+ return await this.uow(async ({ forSchema, executeRetrieve }) => {
272
+ const uow = forSchema(internalSchema);
273
+ const findUow = uow.find("fragno_hooks", (b) =>
274
+ b.whereIndex("primary", (eb) => eb("id", "=", eventId)),
275
+ );
276
+ await executeRetrieve();
277
+ const [events] = await findUow.retrievalPhase;
278
+ return events?.[0];
279
+ });
280
+ });
281
+
282
+ expect(result?.status).toBe("pending");
283
+ expect(result?.attempts).toBe(1);
284
+ expect(result?.error).toBe("Hook failed");
285
+ expect(result?.nextRetryAt).toBeInstanceOf(Date);
286
+ });
287
+
288
+ it("should mark failed hooks as permanently failed when max retries exceeded", async () => {
289
+ const namespace = "test-max-retries";
290
+ const hookFn = vi.fn().mockRejectedValue(new Error("Permanent failure"));
291
+ const hooks: HooksMap = {
292
+ onMaxRetries: hookFn,
293
+ };
294
+
295
+ let eventId: FragnoId;
296
+
297
+ await internalFragment.inContext(async function () {
298
+ await this.uow(async ({ forSchema, executeMutate }) => {
299
+ const uow = forSchema(internalSchema);
300
+ eventId = uow.create("fragno_hooks", {
301
+ namespace,
302
+ hookName: "onMaxRetries",
303
+ payload: { data: "test" },
304
+ status: "pending",
305
+ attempts: 0,
306
+ maxAttempts: 1,
307
+ lastAttemptAt: null,
308
+ nextRetryAt: null,
309
+ error: null,
310
+ nonce: "test-nonce",
311
+ });
312
+ await executeMutate();
313
+ });
314
+ });
315
+
316
+ await processHooks({
317
+ hooks,
318
+ namespace,
319
+ internalFragment,
320
+ defaultRetryPolicy: new NoRetryPolicy(),
321
+ });
322
+
323
+ const result = await internalFragment.inContext(async function () {
324
+ return await this.uow(async ({ forSchema, executeRetrieve }) => {
325
+ const uow = forSchema(internalSchema);
326
+ const findUow = uow.find("fragno_hooks", (b) =>
327
+ b.whereIndex("primary", (eb) => eb("id", "=", eventId)),
328
+ );
329
+ await executeRetrieve();
330
+ const [events] = await findUow.retrievalPhase;
331
+ return events?.[0];
332
+ });
333
+ });
334
+
335
+ expect(result?.status).toBe("failed");
336
+ expect(result?.attempts).toBe(1);
337
+ expect(result?.error).toBe("Permanent failure");
338
+ });
339
+
340
+ it("should handle missing hooks gracefully", async () => {
341
+ const namespace = "test-missing-hook";
342
+ const hooks: HooksMap = {
343
+ onExisting: vi.fn(),
344
+ };
345
+
346
+ let eventId: FragnoId;
347
+
348
+ await internalFragment.inContext(async function () {
349
+ await this.uow(async ({ forSchema, executeMutate }) => {
350
+ const uow = forSchema(internalSchema);
351
+ eventId = uow.create("fragno_hooks", {
352
+ namespace,
353
+ hookName: "onMissing",
354
+ payload: { data: "test" },
355
+ status: "pending",
356
+ attempts: 0,
357
+ maxAttempts: 1,
358
+ lastAttemptAt: null,
359
+ nextRetryAt: null,
360
+ error: null,
361
+ nonce: "test-nonce",
362
+ });
363
+ await executeMutate();
364
+ });
365
+ });
366
+
367
+ await processHooks({
368
+ hooks,
369
+ namespace,
370
+ internalFragment,
371
+ defaultRetryPolicy: new NoRetryPolicy(),
372
+ });
373
+
374
+ const result = await internalFragment.inContext(async function () {
375
+ return await this.uow(async ({ forSchema, executeRetrieve }) => {
376
+ const uow = forSchema(internalSchema);
377
+ const findUow = uow.find("fragno_hooks", (b) =>
378
+ b.whereIndex("primary", (eb) => eb("id", "=", eventId)),
379
+ );
380
+ await executeRetrieve();
381
+ const [events] = await findUow.retrievalPhase;
382
+ return events?.[0];
383
+ });
384
+ });
385
+
386
+ expect(result?.status).toBe("failed");
387
+ expect(result?.error).toBe("Hook 'onMissing' not found in hooks map");
388
+ });
389
+
390
+ it("should process multiple hooks in parallel", async () => {
391
+ const namespace = "test-parallel";
392
+ const hook1 = vi.fn();
393
+ const hook2 = vi.fn();
394
+ const hook3 = vi.fn();
395
+ const hooks: HooksMap = {
396
+ onHook1: hook1,
397
+ onHook2: hook2,
398
+ onHook3: hook3,
399
+ };
400
+
401
+ await internalFragment.inContext(async function () {
402
+ await this.uow(async ({ forSchema, executeMutate }) => {
403
+ const uow = forSchema(internalSchema);
404
+ uow.create("fragno_hooks", {
405
+ namespace,
406
+ hookName: "onHook1",
407
+ payload: { id: 1 },
408
+ status: "pending",
409
+ attempts: 0,
410
+ maxAttempts: 5,
411
+ lastAttemptAt: null,
412
+ nextRetryAt: null,
413
+ error: null,
414
+ nonce: "nonce-1",
415
+ });
416
+ uow.create("fragno_hooks", {
417
+ namespace,
418
+ hookName: "onHook2",
419
+ payload: { id: 2 },
420
+ status: "pending",
421
+ attempts: 0,
422
+ maxAttempts: 5,
423
+ lastAttemptAt: null,
424
+ nextRetryAt: null,
425
+ error: null,
426
+ nonce: "nonce-2",
427
+ });
428
+ uow.create("fragno_hooks", {
429
+ namespace,
430
+ hookName: "onHook3",
431
+ payload: { id: 3 },
432
+ status: "pending",
433
+ attempts: 0,
434
+ maxAttempts: 5,
435
+ lastAttemptAt: null,
436
+ nextRetryAt: null,
437
+ error: null,
438
+ nonce: "nonce-3",
439
+ });
440
+ await executeMutate();
441
+ });
442
+ });
443
+
444
+ await processHooks({
445
+ hooks,
446
+ namespace,
447
+ internalFragment,
448
+ defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 }),
449
+ });
450
+
451
+ expect(hook1).toHaveBeenCalledWith({ id: 1 });
452
+ expect(hook2).toHaveBeenCalledWith({ id: 2 });
453
+ expect(hook3).toHaveBeenCalledWith({ id: 3 });
454
+
455
+ // Verify all were marked as completed
456
+ const events = await internalFragment.inContext(async function () {
457
+ return await this.uow(async ({ forSchema, executeRetrieve }) => {
458
+ const uow = forSchema(internalSchema);
459
+ const findUow = uow.find("fragno_hooks", (b) =>
460
+ b.whereIndex("idx_namespace_status_retry", (eb) => eb("namespace", "=", namespace)),
461
+ );
462
+ await executeRetrieve();
463
+ const [results] = await findUow.retrievalPhase;
464
+ return results;
465
+ });
466
+ });
467
+
468
+ const completed = events.filter((e) => e.status === "completed");
469
+ expect(completed).toHaveLength(3);
470
+ });
471
+
472
+ it("should continue processing other hooks when one fails", async () => {
473
+ const namespace = "test-partial-failure";
474
+ const hook1 = vi.fn();
475
+ const hook2 = vi.fn().mockRejectedValue(new Error("Hook 2 failed"));
476
+ const hook3 = vi.fn();
477
+ const hooks: HooksMap = {
478
+ onHook1: hook1,
479
+ onHook2: hook2,
480
+ onHook3: hook3,
481
+ };
482
+
483
+ await internalFragment.inContext(async function () {
484
+ await this.uow(async ({ forSchema, executeMutate }) => {
485
+ const uow = forSchema(internalSchema);
486
+ uow.create("fragno_hooks", {
487
+ namespace,
488
+ hookName: "onHook1",
489
+ payload: { id: 1 },
490
+ status: "pending",
491
+ attempts: 0,
492
+ maxAttempts: 5,
493
+ lastAttemptAt: null,
494
+ nextRetryAt: null,
495
+ error: null,
496
+ nonce: "nonce-1",
497
+ });
498
+ uow.create("fragno_hooks", {
499
+ namespace,
500
+ hookName: "onHook2",
501
+ payload: { id: 2 },
502
+ status: "pending",
503
+ attempts: 0,
504
+ maxAttempts: 5,
505
+ lastAttemptAt: null,
506
+ nextRetryAt: null,
507
+ error: null,
508
+ nonce: "nonce-2",
509
+ });
510
+ uow.create("fragno_hooks", {
511
+ namespace,
512
+ hookName: "onHook3",
513
+ payload: { id: 3 },
514
+ status: "pending",
515
+ attempts: 0,
516
+ maxAttempts: 5,
517
+ lastAttemptAt: null,
518
+ nextRetryAt: null,
519
+ error: null,
520
+ nonce: "nonce-3",
521
+ });
522
+ await executeMutate();
523
+ });
524
+ });
525
+
526
+ await processHooks({
527
+ hooks,
528
+ namespace,
529
+ internalFragment,
530
+ defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 }),
531
+ });
532
+
533
+ expect(hook1).toHaveBeenCalledOnce();
534
+ expect(hook2).toHaveBeenCalledOnce();
535
+ expect(hook3).toHaveBeenCalledOnce();
536
+
537
+ // Verify hook1 and hook3 were completed, hook2 was marked for retry
538
+ const events = await internalFragment.inContext(async function () {
539
+ return await this.uow(async ({ forSchema, executeRetrieve }) => {
540
+ const uow = forSchema(internalSchema);
541
+ const findUow = uow.find("fragno_hooks", (b) =>
542
+ b.whereIndex("idx_namespace_status_retry", (eb) => eb("namespace", "=", namespace)),
543
+ );
544
+ await executeRetrieve();
545
+ const [results] = await findUow.retrievalPhase;
546
+ return results;
547
+ });
548
+ });
549
+
550
+ const completed = events.filter((e) => e.status === "completed");
551
+ const pending = events.filter((e) => e.status === "pending" && e.attempts === 1);
552
+
553
+ expect(completed).toHaveLength(2);
554
+ expect(pending).toHaveLength(1);
555
+ expect(pending[0]?.error).toBe("Hook 2 failed");
556
+ });
557
+
558
+ it("should do nothing when no pending events exist", async () => {
559
+ const namespace = "test-no-events";
560
+ const hookFn = vi.fn();
561
+ const hooks: HooksMap = {
562
+ onTest: hookFn,
563
+ };
564
+
565
+ await processHooks({
566
+ hooks,
567
+ namespace,
568
+ internalFragment,
569
+ defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 }),
570
+ });
571
+
572
+ expect(hookFn).not.toHaveBeenCalled();
573
+ });
574
+ });
575
+ });