@fragno-dev/db 0.2.2 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (587) hide show
  1. package/.turbo/turbo-build.log +404 -175
  2. package/CHANGELOG.md +109 -0
  3. package/README.md +54 -9
  4. package/dist/adapters/adapters.d.ts +23 -21
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/generic-sql/driver-config.d.ts +16 -1
  8. package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -1
  9. package/dist/adapters/generic-sql/driver-config.js +23 -1
  10. package/dist/adapters/generic-sql/driver-config.js.map +1 -1
  11. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +24 -9
  12. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
  13. package/dist/adapters/generic-sql/generic-sql-adapter.js +60 -22
  14. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
  15. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +169 -3
  16. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
  17. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -1
  18. package/dist/adapters/generic-sql/migration/dialect/mysql.js +25 -6
  19. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
  20. package/dist/adapters/generic-sql/migration/dialect/postgres.js +7 -6
  21. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
  22. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +193 -16
  23. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
  24. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -1
  25. package/dist/adapters/generic-sql/migration/executor.js +30 -3
  26. package/dist/adapters/generic-sql/migration/executor.js.map +1 -1
  27. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -1
  28. package/dist/adapters/generic-sql/migration/prepared-migrations.js +9 -9
  29. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
  30. package/dist/adapters/generic-sql/migration/sql-generator.js +75 -52
  31. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
  32. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +7 -6
  33. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
  34. package/dist/adapters/generic-sql/query/cursor-utils.js +42 -4
  35. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
  36. package/dist/adapters/generic-sql/query/db-now-sql.js +27 -0
  37. package/dist/adapters/generic-sql/query/db-now-sql.js.map +1 -0
  38. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +32 -21
  39. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
  40. package/dist/adapters/generic-sql/query/select-builder.js +5 -3
  41. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
  42. package/dist/adapters/generic-sql/query/sql-query-compiler.js +49 -18
  43. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
  44. package/dist/adapters/generic-sql/query/where-builder.js +43 -29
  45. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
  46. package/dist/adapters/generic-sql/sqlite-storage.d.ts +13 -0
  47. package/dist/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  48. package/dist/adapters/generic-sql/sqlite-storage.js +15 -0
  49. package/dist/adapters/generic-sql/sqlite-storage.js.map +1 -0
  50. package/dist/adapters/generic-sql/uow-decoder.js +6 -2
  51. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
  52. package/dist/adapters/generic-sql/uow-encoder.js +27 -8
  53. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
  54. package/dist/adapters/in-memory/condition-evaluator.js +135 -0
  55. package/dist/adapters/in-memory/condition-evaluator.js.map +1 -0
  56. package/dist/adapters/in-memory/errors.d.ts +13 -0
  57. package/dist/adapters/in-memory/errors.d.ts.map +1 -0
  58. package/dist/adapters/in-memory/errors.js +23 -0
  59. package/dist/adapters/in-memory/errors.js.map +1 -0
  60. package/dist/adapters/in-memory/in-memory-adapter.d.ts +27 -0
  61. package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -0
  62. package/dist/adapters/in-memory/in-memory-adapter.js +196 -0
  63. package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -0
  64. package/dist/adapters/in-memory/in-memory-uow.js +871 -0
  65. package/dist/adapters/in-memory/in-memory-uow.js.map +1 -0
  66. package/dist/adapters/in-memory/index.d.ts +4 -0
  67. package/dist/adapters/in-memory/index.js +4 -0
  68. package/dist/adapters/in-memory/options.d.ts +30 -0
  69. package/dist/adapters/in-memory/options.d.ts.map +1 -0
  70. package/dist/adapters/in-memory/options.js +62 -0
  71. package/dist/adapters/in-memory/options.js.map +1 -0
  72. package/dist/adapters/in-memory/reference-resolution.js +26 -0
  73. package/dist/adapters/in-memory/reference-resolution.js.map +1 -0
  74. package/dist/adapters/in-memory/sorted-array-index.js +129 -0
  75. package/dist/adapters/in-memory/sorted-array-index.js.map +1 -0
  76. package/dist/adapters/in-memory/store.js +71 -0
  77. package/dist/adapters/in-memory/store.js.map +1 -0
  78. package/dist/adapters/in-memory/value-comparison.js +28 -0
  79. package/dist/adapters/in-memory/value-comparison.js.map +1 -0
  80. package/dist/adapters/shared/from-unit-of-work-compiler.js +51 -24
  81. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
  82. package/dist/adapters/shared/uow-operation-compiler.js +11 -11
  83. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
  84. package/dist/adapters/sql/index.d.ts +5 -0
  85. package/dist/adapters/sql/index.js +4 -0
  86. package/dist/browser/adapters/adapters.d.ts +61 -0
  87. package/dist/browser/adapters/adapters.d.ts.map +1 -0
  88. package/dist/browser/adapters/generic-sql/migration/executor.d.ts +15 -0
  89. package/dist/browser/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  90. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  91. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  92. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts +11 -0
  93. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  94. package/dist/browser/adapters/in-memory/in-memory-adapter.d.ts +5 -0
  95. package/dist/browser/adapters/in-memory/index.d.ts +2 -0
  96. package/dist/browser/adapters/in-memory/options.d.ts +1 -0
  97. package/dist/browser/db-fragment-definition-builder.d.ts +237 -0
  98. package/dist/browser/db-fragment-definition-builder.d.ts.map +1 -0
  99. package/dist/browser/durable-hooks.d.ts +3 -0
  100. package/dist/browser/fragments/internal-fragment.d.ts +317 -0
  101. package/dist/browser/fragments/internal-fragment.d.ts.map +1 -0
  102. package/dist/browser/fragments/internal-fragment.schema.d.ts +1 -0
  103. package/dist/browser/hooks/durable-hooks-logger.d.ts +10 -0
  104. package/dist/browser/hooks/durable-hooks-logger.d.ts.map +1 -0
  105. package/dist/browser/hooks/hooks.d.ts +146 -0
  106. package/dist/browser/hooks/hooks.d.ts.map +1 -0
  107. package/dist/browser/id.js +1 -0
  108. package/dist/browser/internal/adapter-registry.d.ts +4 -0
  109. package/dist/browser/internal/outbox-state.d.ts +2 -0
  110. package/dist/browser/mod.d.ts +15 -0
  111. package/dist/browser/mod.d.ts.map +1 -0
  112. package/dist/browser/mod.js +17 -0
  113. package/dist/browser/mod.js.map +1 -0
  114. package/dist/browser/mod2.d.ts +48 -0
  115. package/dist/browser/mod2.d.ts.map +1 -0
  116. package/dist/browser/naming/sql-naming.d.ts +19 -0
  117. package/dist/browser/naming/sql-naming.d.ts.map +1 -0
  118. package/dist/browser/outbox/outbox.d.ts +21 -0
  119. package/dist/browser/outbox/outbox.d.ts.map +1 -0
  120. package/dist/browser/query/column-defaults.js +1 -0
  121. package/dist/browser/query/condition-builder.d.ts +44 -0
  122. package/dist/browser/query/condition-builder.d.ts.map +1 -0
  123. package/dist/browser/query/condition-builder.js +97 -0
  124. package/dist/browser/query/condition-builder.js.map +1 -0
  125. package/dist/browser/query/cursor.d.ts +105 -0
  126. package/dist/browser/query/cursor.d.ts.map +1 -0
  127. package/dist/browser/query/cursor.js +150 -0
  128. package/dist/browser/query/cursor.js.map +1 -0
  129. package/dist/browser/query/db-now.d.ts +22 -0
  130. package/dist/browser/query/db-now.d.ts.map +1 -0
  131. package/dist/browser/query/db-now.js +33 -0
  132. package/dist/browser/query/db-now.js.map +1 -0
  133. package/dist/browser/query/orm/orm.d.ts +18 -0
  134. package/dist/browser/query/orm/orm.d.ts.map +1 -0
  135. package/dist/browser/query/simple-query-interface.d.ts +108 -0
  136. package/dist/browser/query/simple-query-interface.d.ts.map +1 -0
  137. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts +423 -0
  138. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  139. package/dist/browser/query/unit-of-work/execute-unit-of-work.js +507 -0
  140. package/dist/browser/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  141. package/dist/browser/query/unit-of-work/retry-policy.d.ts +23 -0
  142. package/dist/browser/query/unit-of-work/retry-policy.d.ts.map +1 -0
  143. package/dist/browser/query/unit-of-work/retry-policy.js +40 -0
  144. package/dist/browser/query/unit-of-work/retry-policy.js.map +1 -0
  145. package/dist/browser/query/unit-of-work/unit-of-work.d.ts +703 -0
  146. package/dist/browser/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  147. package/dist/browser/query/unit-of-work/unit-of-work.js +1206 -0
  148. package/dist/browser/query/unit-of-work/unit-of-work.js.map +1 -0
  149. package/dist/browser/query/value-encoding.js +38 -0
  150. package/dist/browser/query/value-encoding.js.map +1 -0
  151. package/dist/browser/schema/create.d.ts +326 -0
  152. package/dist/browser/schema/create.d.ts.map +1 -0
  153. package/dist/browser/schema/create.js +89 -0
  154. package/dist/browser/schema/create.js.map +1 -0
  155. package/dist/browser/schema/generate-id.js +28 -0
  156. package/dist/browser/schema/generate-id.js.map +1 -0
  157. package/dist/browser/shared/providers.d.ts +6 -0
  158. package/dist/browser/shared/providers.d.ts.map +1 -0
  159. package/dist/browser/sql-driver/connection/connection-provider.d.ts +13 -0
  160. package/dist/browser/sql-driver/connection/connection-provider.d.ts.map +1 -0
  161. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  162. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  163. package/dist/browser/sql-driver/driver/runtime-driver.d.ts +23 -0
  164. package/dist/browser/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  165. package/dist/browser/sql-driver/query-executor/plugin.d.ts +17 -0
  166. package/dist/browser/sql-driver/query-executor/plugin.d.ts.map +1 -0
  167. package/dist/browser/sql-driver/query-executor/query-executor.d.ts +36 -0
  168. package/dist/browser/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  169. package/dist/browser/sql-driver/sql-driver-adapter.d.ts +29 -0
  170. package/dist/browser/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  171. package/dist/browser/sql-driver/sql-driver.d.ts +38 -0
  172. package/dist/browser/sql-driver/sql-driver.d.ts.map +1 -0
  173. package/dist/browser/sync/commands.d.ts +15 -0
  174. package/dist/browser/sync/commands.d.ts.map +1 -0
  175. package/dist/browser/sync/commands.js +27 -0
  176. package/dist/browser/sync/commands.js.map +1 -0
  177. package/dist/browser/sync/types.d.ts +63 -0
  178. package/dist/browser/sync/types.d.ts.map +1 -0
  179. package/dist/browser/util/types.d.ts +8 -0
  180. package/dist/browser/util/types.d.ts.map +1 -0
  181. package/dist/browser/with-database.d.ts +29 -0
  182. package/dist/browser/with-database.d.ts.map +1 -0
  183. package/dist/client.d.ts +4 -0
  184. package/dist/client.js +5 -0
  185. package/dist/db-fragment-definition-builder.d.ts +101 -33
  186. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  187. package/dist/db-fragment-definition-builder.js +450 -60
  188. package/dist/db-fragment-definition-builder.js.map +1 -1
  189. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts +20 -0
  190. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts.map +1 -0
  191. package/dist/dispatchers/cloudflare-do/dispatcher.js +147 -0
  192. package/dist/dispatchers/cloudflare-do/dispatcher.js.map +1 -0
  193. package/dist/dispatchers/cloudflare-do/index.d.ts +11 -0
  194. package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -0
  195. package/dist/dispatchers/cloudflare-do/index.js +31 -0
  196. package/dist/dispatchers/cloudflare-do/index.js.map +1 -0
  197. package/dist/dispatchers/node/dispatcher.d.ts +14 -0
  198. package/dist/dispatchers/node/dispatcher.d.ts.map +1 -0
  199. package/dist/dispatchers/node/dispatcher.js +80 -0
  200. package/dist/dispatchers/node/dispatcher.js.map +1 -0
  201. package/dist/dispatchers/node/index.d.ts +12 -0
  202. package/dist/dispatchers/node/index.d.ts.map +1 -0
  203. package/dist/dispatchers/node/index.js +27 -0
  204. package/dist/dispatchers/node/index.js.map +1 -0
  205. package/dist/durable-hooks.d.ts +31 -0
  206. package/dist/durable-hooks.d.ts.map +1 -0
  207. package/dist/durable-hooks.js +23 -0
  208. package/dist/durable-hooks.js.map +1 -0
  209. package/dist/fragments/internal-fragment.d.ts +186 -8
  210. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  211. package/dist/fragments/internal-fragment.js +203 -38
  212. package/dist/fragments/internal-fragment.js.map +1 -1
  213. package/dist/fragments/internal-fragment.routes.js +164 -0
  214. package/dist/fragments/internal-fragment.routes.js.map +1 -0
  215. package/dist/fragments/internal-fragment.schema.d.ts +15 -0
  216. package/dist/fragments/internal-fragment.schema.d.ts.map +1 -0
  217. package/dist/fragments/internal-fragment.schema.js +39 -0
  218. package/dist/fragments/internal-fragment.schema.js.map +1 -0
  219. package/dist/hooks/durable-hooks-logger.d.ts +10 -0
  220. package/dist/hooks/durable-hooks-logger.d.ts.map +1 -0
  221. package/dist/hooks/durable-hooks-logger.js +75 -0
  222. package/dist/hooks/durable-hooks-logger.js.map +1 -0
  223. package/dist/hooks/durable-hooks-processor.d.ts +1 -0
  224. package/dist/hooks/durable-hooks-processor.js +80 -0
  225. package/dist/hooks/durable-hooks-processor.js.map +1 -0
  226. package/dist/hooks/durable-hooks-runtime.js +44 -0
  227. package/dist/hooks/durable-hooks-runtime.js.map +1 -0
  228. package/dist/hooks/hooks.d.ts +100 -1
  229. package/dist/hooks/hooks.d.ts.map +1 -1
  230. package/dist/hooks/hooks.js +254 -27
  231. package/dist/hooks/hooks.js.map +1 -1
  232. package/dist/id.d.ts +2 -2
  233. package/dist/id.js +2 -2
  234. package/dist/internal/adapter-registry.d.ts +11 -0
  235. package/dist/internal/adapter-registry.d.ts.map +1 -0
  236. package/dist/internal/adapter-registry.js +135 -0
  237. package/dist/internal/adapter-registry.js.map +1 -0
  238. package/dist/internal/outbox-state.d.ts +2 -0
  239. package/dist/internal/outbox-state.js +26 -0
  240. package/dist/internal/outbox-state.js.map +1 -0
  241. package/dist/migration-engine/auto-from-schema.d.ts +33 -0
  242. package/dist/migration-engine/auto-from-schema.d.ts.map +1 -0
  243. package/dist/migration-engine/auto-from-schema.js +223 -37
  244. package/dist/migration-engine/auto-from-schema.js.map +1 -1
  245. package/dist/migration-engine/generation-engine.d.ts +16 -10
  246. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  247. package/dist/migration-engine/generation-engine.js +86 -35
  248. package/dist/migration-engine/generation-engine.js.map +1 -1
  249. package/dist/migration-engine/shared.d.ts +113 -0
  250. package/dist/migration-engine/shared.d.ts.map +1 -0
  251. package/dist/migration-engine/shared.js.map +1 -1
  252. package/dist/mod.d.ts +20 -12
  253. package/dist/mod.d.ts.map +1 -1
  254. package/dist/mod.js +18 -12
  255. package/dist/mod.js.map +1 -1
  256. package/dist/naming/sql-naming.d.ts +19 -0
  257. package/dist/naming/sql-naming.d.ts.map +1 -0
  258. package/dist/naming/sql-naming.js +116 -0
  259. package/dist/naming/sql-naming.js.map +1 -0
  260. package/dist/outbox/outbox-builder.js +156 -0
  261. package/dist/outbox/outbox-builder.js.map +1 -0
  262. package/dist/outbox/outbox.d.ts +54 -0
  263. package/dist/outbox/outbox.d.ts.map +1 -0
  264. package/dist/outbox/outbox.js +37 -0
  265. package/dist/outbox/outbox.js.map +1 -0
  266. package/dist/query/column-defaults.js +20 -4
  267. package/dist/query/column-defaults.js.map +1 -1
  268. package/dist/query/condition-builder.d.ts +7 -1
  269. package/dist/query/condition-builder.d.ts.map +1 -1
  270. package/dist/query/condition-builder.js +5 -1
  271. package/dist/query/condition-builder.js.map +1 -1
  272. package/dist/query/cursor-client.d.ts +105 -0
  273. package/dist/query/cursor-client.d.ts.map +1 -0
  274. package/dist/query/cursor-client.js +165 -0
  275. package/dist/query/cursor-client.js.map +1 -0
  276. package/dist/query/cursor.d.ts +3 -1
  277. package/dist/query/cursor.d.ts.map +1 -1
  278. package/dist/query/cursor.js +51 -14
  279. package/dist/query/cursor.js.map +1 -1
  280. package/dist/query/db-now.d.ts +22 -0
  281. package/dist/query/db-now.d.ts.map +1 -0
  282. package/dist/query/db-now.js +35 -0
  283. package/dist/query/db-now.js.map +1 -0
  284. package/dist/query/orm/orm.js.map +1 -1
  285. package/dist/query/serialize/create-sql-serializer.js +5 -4
  286. package/dist/query/serialize/create-sql-serializer.js.map +1 -1
  287. package/dist/query/serialize/dialect/mysql-serializer.js +12 -6
  288. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
  289. package/dist/query/serialize/dialect/postgres-serializer.js +25 -7
  290. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
  291. package/dist/query/serialize/dialect/sqlite-serializer.js +60 -12
  292. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
  293. package/dist/query/serialize/sql-serializer.js +2 -2
  294. package/dist/query/serialize/sql-serializer.js.map +1 -1
  295. package/dist/query/simple-query-interface.d.ts +13 -4
  296. package/dist/query/simple-query-interface.d.ts.map +1 -1
  297. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +37 -2
  298. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  299. package/dist/query/unit-of-work/execute-unit-of-work.js +50 -24
  300. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  301. package/dist/query/unit-of-work/unit-of-work.d.ts +92 -30
  302. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  303. package/dist/query/unit-of-work/unit-of-work.js +136 -11
  304. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  305. package/dist/query/value-decoding.js +16 -6
  306. package/dist/query/value-decoding.js.map +1 -1
  307. package/dist/query/value-encoding.js +29 -9
  308. package/dist/query/value-encoding.js.map +1 -1
  309. package/dist/schema/create.d.ts +103 -35
  310. package/dist/schema/create.d.ts.map +1 -1
  311. package/dist/schema/create.js +172 -58
  312. package/dist/schema/create.js.map +1 -1
  313. package/dist/schema/generate-id.js +2 -2
  314. package/dist/schema/generate-id.js.map +1 -1
  315. package/dist/schema/type-conversion/create-sql-type-mapper.js +4 -3
  316. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  317. package/dist/schema/type-conversion/dialect/sqlite.js +9 -0
  318. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  319. package/dist/schema/validator.d.ts +10 -0
  320. package/dist/schema/validator.d.ts.map +1 -0
  321. package/dist/schema/validator.js +123 -0
  322. package/dist/schema/validator.js.map +1 -0
  323. package/dist/schema-output/drizzle.d.ts +30 -0
  324. package/dist/schema-output/drizzle.d.ts.map +1 -0
  325. package/dist/{adapters/drizzle/generate.js → schema-output/drizzle.js} +88 -60
  326. package/dist/schema-output/drizzle.js.map +1 -0
  327. package/dist/schema-output/prisma.d.ts +17 -0
  328. package/dist/schema-output/prisma.d.ts.map +1 -0
  329. package/dist/schema-output/prisma.js +307 -0
  330. package/dist/schema-output/prisma.js.map +1 -0
  331. package/dist/sql-driver/dialects/durable-object-dialect.js +3 -9
  332. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -1
  333. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -1
  334. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -1
  335. package/dist/sql-driver/sql-driver-adapter.js.map +1 -1
  336. package/dist/sql-driver/sql.js.map +1 -1
  337. package/dist/sync/commands.d.ts +15 -0
  338. package/dist/sync/commands.d.ts.map +1 -0
  339. package/dist/sync/commands.js +27 -0
  340. package/dist/sync/commands.js.map +1 -0
  341. package/dist/sync/index.d.ts +4 -0
  342. package/dist/sync/index.js +4 -0
  343. package/dist/sync/read-tracking.d.ts +25 -0
  344. package/dist/sync/read-tracking.d.ts.map +1 -0
  345. package/dist/sync/read-tracking.js +148 -0
  346. package/dist/sync/read-tracking.js.map +1 -0
  347. package/dist/sync/submit.js +213 -0
  348. package/dist/sync/submit.js.map +1 -0
  349. package/dist/sync/types.d.ts +63 -0
  350. package/dist/sync/types.d.ts.map +1 -0
  351. package/dist/util/default-database-adapter.js +66 -0
  352. package/dist/util/default-database-adapter.js.map +1 -0
  353. package/dist/with-database.d.ts +3 -6
  354. package/dist/with-database.d.ts.map +1 -1
  355. package/dist/with-database.js +8 -7
  356. package/dist/with-database.js.map +1 -1
  357. package/package.json +62 -55
  358. package/src/adapters/adapters.ts +33 -26
  359. package/src/adapters/drizzle/migrate-drizzle.test.ts +99 -41
  360. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +601 -0
  361. package/src/adapters/drizzle/test-utils.ts +13 -8
  362. package/src/adapters/generic-sql/driver-config.ts +38 -0
  363. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +10 -8
  364. package/src/adapters/generic-sql/generic-sql-adapter.ts +117 -34
  365. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +55 -0
  366. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +297 -3
  367. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +120 -0
  368. package/src/adapters/generic-sql/migration/cold-kysely.ts +1 -0
  369. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +27 -8
  370. package/src/adapters/generic-sql/migration/dialect/mysql.ts +47 -8
  371. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +28 -9
  372. package/src/adapters/generic-sql/migration/dialect/postgres.ts +9 -4
  373. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +839 -8
  374. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +396 -53
  375. package/src/adapters/generic-sql/migration/executor.test.ts +52 -0
  376. package/src/adapters/generic-sql/migration/executor.ts +47 -4
  377. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +238 -46
  378. package/src/adapters/generic-sql/migration/prepared-migrations.ts +21 -13
  379. package/src/adapters/generic-sql/migration/sql-generator.ts +145 -66
  380. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +11 -8
  381. package/src/adapters/generic-sql/query/cursor-utils.test.ts +272 -0
  382. package/src/adapters/generic-sql/query/cursor-utils.ts +42 -7
  383. package/src/adapters/generic-sql/query/db-now-sql.ts +49 -0
  384. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +171 -35
  385. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +53 -40
  386. package/src/adapters/generic-sql/query/select-builder.test.ts +16 -11
  387. package/src/adapters/generic-sql/query/select-builder.ts +7 -3
  388. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +75 -6
  389. package/src/adapters/generic-sql/query/sql-query-compiler.ts +129 -24
  390. package/src/adapters/generic-sql/query/where-builder.test.ts +96 -20
  391. package/src/adapters/generic-sql/query/where-builder.ts +112 -41
  392. package/src/adapters/{kysely/kysely-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-migrations.test.ts} +11 -20
  393. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +851 -0
  394. package/src/adapters/{drizzle/drizzle-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-queries.test.ts} +18 -15
  395. package/src/adapters/generic-sql/{test/generic-drizzle-adapter-sqlite3.test.ts → sql-adapter-sqlite3-driver.test.ts} +282 -14
  396. package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +129 -12
  397. package/src/adapters/{kysely/kysely-adapter-sqlocal.test.ts → generic-sql/sql-adapter-sqlocal.test.ts} +9 -7
  398. package/src/adapters/generic-sql/sqlite-storage.ts +20 -0
  399. package/src/adapters/generic-sql/uow-decoder.test.ts +5 -4
  400. package/src/adapters/generic-sql/uow-decoder.ts +23 -5
  401. package/src/adapters/generic-sql/uow-encoder.test.ts +36 -3
  402. package/src/adapters/generic-sql/uow-encoder.ts +48 -13
  403. package/src/adapters/in-memory/condition-evaluator.test.ts +194 -0
  404. package/src/adapters/in-memory/condition-evaluator.ts +280 -0
  405. package/src/adapters/in-memory/errors.ts +20 -0
  406. package/src/adapters/in-memory/in-memory-adapter.ts +388 -0
  407. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +344 -0
  408. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +255 -0
  409. package/src/adapters/in-memory/in-memory-uow.ts +1724 -0
  410. package/src/adapters/in-memory/index.ts +3 -0
  411. package/src/adapters/in-memory/options.test.ts +42 -0
  412. package/src/adapters/in-memory/options.ts +91 -0
  413. package/src/adapters/in-memory/outbox.test.ts +361 -0
  414. package/src/adapters/in-memory/reference-resolution.test.ts +51 -0
  415. package/src/adapters/in-memory/reference-resolution.ts +67 -0
  416. package/src/adapters/in-memory/sorted-array-index.test.ts +124 -0
  417. package/src/adapters/in-memory/sorted-array-index.ts +228 -0
  418. package/src/adapters/in-memory/store.test.ts +69 -0
  419. package/src/adapters/in-memory/store.ts +145 -0
  420. package/src/adapters/in-memory/value-comparison.ts +53 -0
  421. package/src/adapters/in-memory/value-normalization.test.ts +58 -0
  422. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +1207 -0
  423. package/src/adapters/shared/from-unit-of-work-compiler.ts +159 -47
  424. package/src/adapters/shared/uow-operation-compiler.ts +28 -18
  425. package/src/adapters/sql/index.ts +12 -0
  426. package/src/browser/mod.ts +64 -0
  427. package/src/client.ts +19 -0
  428. package/src/db-fragment-definition-builder.test.ts +845 -53
  429. package/src/db-fragment-definition-builder.ts +911 -95
  430. package/src/db-fragment-instantiator.test.ts +210 -94
  431. package/src/db-fragment-integration.test.ts +17 -12
  432. package/src/dispatchers/cloudflare-do/dispatcher.ts +204 -0
  433. package/src/dispatchers/cloudflare-do/index.test.ts +206 -0
  434. package/src/dispatchers/cloudflare-do/index.ts +63 -0
  435. package/src/dispatchers/node/dispatcher.ts +112 -0
  436. package/src/dispatchers/node/index.test.ts +120 -0
  437. package/src/dispatchers/node/index.ts +50 -0
  438. package/src/durable-hooks.test.ts +80 -0
  439. package/src/durable-hooks.ts +67 -0
  440. package/src/fragments/internal-fragment.routes.test.ts +570 -0
  441. package/src/fragments/internal-fragment.routes.ts +334 -0
  442. package/src/fragments/internal-fragment.schema.ts +95 -0
  443. package/src/fragments/internal-fragment.test.ts +505 -83
  444. package/src/fragments/internal-fragment.ts +453 -70
  445. package/src/hooks/durable-hooks-logger.ts +126 -0
  446. package/src/hooks/durable-hooks-processor.pglite.test.ts +87 -0
  447. package/src/hooks/durable-hooks-processor.test.ts +282 -0
  448. package/src/hooks/durable-hooks-processor.ts +173 -0
  449. package/src/hooks/durable-hooks-runtime.test.ts +65 -0
  450. package/src/hooks/durable-hooks-runtime.ts +81 -0
  451. package/src/hooks/hooks.test.ts +455 -34
  452. package/src/hooks/hooks.ts +501 -34
  453. package/src/id.test.ts +34 -0
  454. package/src/id.ts +1 -3
  455. package/src/internal/adapter-registry.test.ts +93 -0
  456. package/src/internal/adapter-registry.ts +239 -0
  457. package/src/internal/outbox-state.ts +43 -0
  458. package/src/migration-engine/auto-from-schema.test.ts +107 -14
  459. package/src/migration-engine/auto-from-schema.ts +365 -44
  460. package/src/migration-engine/create.test.ts +4 -3
  461. package/src/migration-engine/create.ts +1 -1
  462. package/src/migration-engine/generation-engine.test.ts +292 -110
  463. package/src/migration-engine/generation-engine.ts +117 -66
  464. package/src/migration-engine/shared.ts +14 -0
  465. package/src/mod.ts +95 -39
  466. package/src/naming/sql-naming.ts +181 -0
  467. package/src/outbox/outbox-builder.ts +241 -0
  468. package/src/outbox/outbox.test.ts +424 -0
  469. package/src/outbox/outbox.ts +139 -0
  470. package/src/query/column-defaults.ts +42 -4
  471. package/src/query/condition-builder.test.ts +18 -3
  472. package/src/query/condition-builder.ts +7 -0
  473. package/src/query/cursor-client.test.ts +70 -0
  474. package/src/query/cursor-client.ts +263 -0
  475. package/src/query/cursor.test.ts +119 -20
  476. package/src/query/cursor.ts +88 -27
  477. package/src/query/db-now.ts +73 -0
  478. package/src/query/orm/orm.ts +2 -2
  479. package/src/query/query-type.test.ts +4 -3
  480. package/src/query/serialize/create-sql-serializer.ts +10 -5
  481. package/src/query/serialize/dialect/mysql-serializer.ts +13 -5
  482. package/src/query/serialize/dialect/postgres-serializer.ts +35 -5
  483. package/src/query/serialize/dialect/sqlite-serializer.test.ts +90 -3
  484. package/src/query/serialize/dialect/sqlite-serializer.ts +108 -12
  485. package/src/query/serialize/sql-serializer.ts +4 -4
  486. package/src/query/simple-query-interface.ts +15 -4
  487. package/src/query/unit-of-work/execute-unit-of-work.test.ts +372 -10
  488. package/src/query/unit-of-work/execute-unit-of-work.ts +87 -27
  489. package/src/query/unit-of-work/retry-policy.test.ts +1 -0
  490. package/src/query/unit-of-work/tx-builder.test.ts +73 -1
  491. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +17 -16
  492. package/src/query/unit-of-work/unit-of-work-types.test.ts +42 -12
  493. package/src/query/unit-of-work/unit-of-work.test.ts +196 -39
  494. package/src/query/unit-of-work/unit-of-work.ts +309 -38
  495. package/src/query/value-decoding.test.ts +63 -4
  496. package/src/query/value-decoding.ts +32 -6
  497. package/src/query/value-encoding.test.ts +86 -2
  498. package/src/query/value-encoding.ts +56 -6
  499. package/src/schema/create.test.ts +293 -47
  500. package/src/schema/create.ts +406 -70
  501. package/src/schema/generate-id.test.ts +3 -2
  502. package/src/schema/generate-id.ts +2 -2
  503. package/src/schema/serialize.test.ts +18 -5
  504. package/src/schema/type-conversion/create-sql-type-mapper.ts +8 -3
  505. package/src/schema/type-conversion/dialect/sqlite.ts +18 -0
  506. package/src/schema/type-conversion/type-mapping.test.ts +26 -1
  507. package/src/schema/validator.test.ts +199 -0
  508. package/src/schema/validator.ts +232 -0
  509. package/src/{adapters/drizzle/generate.test.ts → schema-output/drizzle.test.ts} +232 -129
  510. package/src/{adapters/drizzle/generate.ts → schema-output/drizzle.ts} +155 -99
  511. package/src/schema-output/prisma.test.ts +694 -0
  512. package/src/schema-output/prisma.ts +593 -0
  513. package/src/sql-driver/better-sqlite3.test.ts +5 -3
  514. package/src/sql-driver/dialects/durable-object-dialect.ts +3 -8
  515. package/src/sql-driver/query-executor/default-query-executor.ts +1 -1
  516. package/src/sql-driver/query-executor/query-executor-base.ts +1 -1
  517. package/src/sql-driver/query-executor/query-executor.ts +1 -1
  518. package/src/sql-driver/sql-driver-adapter.ts +2 -2
  519. package/src/sql-driver/sql.ts +2 -1
  520. package/src/sql-driver/sqlocal.test.ts +4 -2
  521. package/src/sync/commands.test.ts +39 -0
  522. package/src/sync/commands.ts +51 -0
  523. package/src/sync/conflict-checker.test.ts +450 -0
  524. package/src/sync/conflict-checker.ts +248 -0
  525. package/src/sync/index.ts +14 -0
  526. package/src/sync/plan.ts +9 -0
  527. package/src/sync/read-tracking.test.ts +177 -0
  528. package/src/sync/read-tracking.ts +287 -0
  529. package/src/sync/submit.test.ts +205 -0
  530. package/src/sync/submit.ts +328 -0
  531. package/src/sync/types.ts +80 -0
  532. package/src/util/default-database-adapter.ts +119 -0
  533. package/src/with-database.ts +20 -31
  534. package/tsconfig.json +1 -1
  535. package/tsdown.config.ts +38 -24
  536. package/vitest.config.ts +1 -0
  537. package/dist/adapters/drizzle/drizzle-adapter.d.ts +0 -20
  538. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +0 -1
  539. package/dist/adapters/drizzle/drizzle-adapter.js +0 -27
  540. package/dist/adapters/drizzle/drizzle-adapter.js.map +0 -1
  541. package/dist/adapters/drizzle/generate.d.ts +0 -30
  542. package/dist/adapters/drizzle/generate.d.ts.map +0 -1
  543. package/dist/adapters/drizzle/generate.js.map +0 -1
  544. package/dist/adapters/kysely/kysely-adapter.d.ts +0 -19
  545. package/dist/adapters/kysely/kysely-adapter.d.ts.map +0 -1
  546. package/dist/adapters/kysely/kysely-adapter.js +0 -17
  547. package/dist/adapters/kysely/kysely-adapter.js.map +0 -1
  548. package/dist/adapters/shared/table-name-mapper.d.ts +0 -12
  549. package/dist/adapters/shared/table-name-mapper.d.ts.map +0 -1
  550. package/dist/adapters/shared/table-name-mapper.js +0 -43
  551. package/dist/adapters/shared/table-name-mapper.js.map +0 -1
  552. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js +0 -165
  553. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +0 -1
  554. package/dist/packages/fragno/dist/api/bind-services.js +0 -20
  555. package/dist/packages/fragno/dist/api/bind-services.js.map +0 -1
  556. package/dist/packages/fragno/dist/api/error.js +0 -48
  557. package/dist/packages/fragno/dist/api/error.js.map +0 -1
  558. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +0 -320
  559. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +0 -1
  560. package/dist/packages/fragno/dist/api/fragment-instantiator.js +0 -525
  561. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +0 -1
  562. package/dist/packages/fragno/dist/api/fragno-response.js +0 -73
  563. package/dist/packages/fragno/dist/api/fragno-response.js.map +0 -1
  564. package/dist/packages/fragno/dist/api/internal/response-stream.js +0 -81
  565. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +0 -1
  566. package/dist/packages/fragno/dist/api/internal/route.js +0 -10
  567. package/dist/packages/fragno/dist/api/internal/route.js.map +0 -1
  568. package/dist/packages/fragno/dist/api/mutable-request-state.js +0 -97
  569. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +0 -1
  570. package/dist/packages/fragno/dist/api/request-context-storage.js +0 -43
  571. package/dist/packages/fragno/dist/api/request-context-storage.js.map +0 -1
  572. package/dist/packages/fragno/dist/api/request-input-context.js +0 -118
  573. package/dist/packages/fragno/dist/api/request-input-context.js.map +0 -1
  574. package/dist/packages/fragno/dist/api/request-middleware.js +0 -83
  575. package/dist/packages/fragno/dist/api/request-middleware.js.map +0 -1
  576. package/dist/packages/fragno/dist/api/request-output-context.js +0 -119
  577. package/dist/packages/fragno/dist/api/request-output-context.js.map +0 -1
  578. package/dist/packages/fragno/dist/api/route.js +0 -17
  579. package/dist/packages/fragno/dist/api/route.js.map +0 -1
  580. package/dist/packages/fragno/dist/internal/symbols.js +0 -10
  581. package/dist/packages/fragno/dist/internal/symbols.js.map +0 -1
  582. package/dist/schema-generator/schema-generator.d.ts +0 -15
  583. package/dist/schema-generator/schema-generator.d.ts.map +0 -1
  584. package/src/adapters/drizzle/drizzle-adapter.ts +0 -39
  585. package/src/adapters/kysely/kysely-adapter.ts +0 -27
  586. package/src/adapters/shared/table-name-mapper.ts +0 -50
  587. package/src/schema-generator/schema-generator.ts +0 -12
@@ -1,22 +1,47 @@
1
+ import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
2
+
1
3
  import SQLite from "better-sqlite3";
2
4
  import { SqliteDialect } from "kysely";
3
- import { beforeAll, describe, expect, it, vi } from "vitest";
5
+
4
6
  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";
7
+
9
8
  import { BetterSQLite3DriverConfig } from "../adapters/generic-sql/driver-config";
9
+ import { SqlAdapter } from "../adapters/generic-sql/generic-sql-adapter";
10
+ import type { FragnoPublicConfigWithDatabase } from "../db-fragment-definition-builder";
11
+ import { internalFragmentDef, internalSchema } from "../fragments/internal-fragment";
12
+ import { getRegistryForAdapterSync } from "../internal/adapter-registry";
13
+ import { ConcurrencyConflictError } from "../query/unit-of-work/execute-unit-of-work";
10
14
  import { ExponentialBackoffRetryPolicy, NoRetryPolicy } from "../query/unit-of-work/retry-policy";
11
- import type { FragnoId } from "../schema/create";
15
+ import { FragnoId } from "../schema/create";
16
+ import { DurableHooksLogger } from "./durable-hooks-logger";
17
+ import {
18
+ prepareHookMutations,
19
+ processHooks,
20
+ createDurableHooksRunner,
21
+ type HooksMap,
22
+ type HookContext,
23
+ type HookHandlerTx,
24
+ } from "./hooks";
25
+
26
+ const TEST_NS = "test";
27
+
28
+ type OptionsWithAdapter = FragnoPublicConfigWithDatabase & {
29
+ databaseAdapter: SqlAdapter;
30
+ };
12
31
 
13
32
  describe("Hook System", () => {
33
+ const handlerTx = (() => {
34
+ throw new Error("handlerTx not configured for hooks test");
35
+ }) as HookHandlerTx;
14
36
  let sqliteDatabase: SQLite.Database;
15
- let adapter: DrizzleAdapter;
37
+ let adapter: SqlAdapter;
16
38
  let internalFragment: ReturnType<typeof instantiateFragment>;
17
39
 
18
- function instantiateFragment(options: FragnoPublicConfigWithDatabase) {
19
- return instantiate(internalFragmentDef).withConfig({}).withOptions(options).build();
40
+ function instantiateFragment(options: OptionsWithAdapter) {
41
+ return instantiate(internalFragmentDef)
42
+ .withConfig({ registry: getRegistryForAdapterSync(options.databaseAdapter) })
43
+ .withOptions(options)
44
+ .build();
20
45
  }
21
46
 
22
47
  beforeAll(async () => {
@@ -26,18 +51,19 @@ describe("Hook System", () => {
26
51
  database: sqliteDatabase,
27
52
  });
28
53
 
29
- adapter = new DrizzleAdapter({
54
+ adapter = new SqlAdapter({
30
55
  dialect,
31
56
  driverConfig: new BetterSQLite3DriverConfig(),
32
57
  });
33
58
 
34
59
  {
35
- const migrations = adapter.prepareMigrations(internalSchema, "");
60
+ const migrations = adapter.prepareMigrations(internalSchema, TEST_NS);
36
61
  await migrations.executeWithDriver(adapter.driver, 0);
37
62
  }
38
63
 
39
- const options: FragnoPublicConfigWithDatabase = {
64
+ const options: OptionsWithAdapter = {
40
65
  databaseAdapter: adapter,
66
+ databaseNamespace: TEST_NS,
41
67
  };
42
68
 
43
69
  internalFragment = instantiateFragment(options);
@@ -48,8 +74,11 @@ describe("Hook System", () => {
48
74
  }, 12000);
49
75
 
50
76
  describe("prepareHookMutations", () => {
77
+ beforeEach(() => {
78
+ sqliteDatabase.exec("DELETE FROM fragno_hooks_test");
79
+ });
80
+
51
81
  it("should create hook records for triggered hooks", async () => {
52
- const namespace = "test-namespace";
53
82
  const hooks: HooksMap = {
54
83
  onTest: vi.fn(),
55
84
  };
@@ -68,12 +97,11 @@ describe("Hook System", () => {
68
97
  uow.triggerHook("onTest", { data: "test" });
69
98
 
70
99
  // Prepare hook mutations
71
- prepareHookMutations(uow, {
72
- hooks,
73
- namespace,
100
+ prepareHookMutations(
101
+ uow,
74
102
  internalFragment,
75
- defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 5 }),
76
- });
103
+ new ExponentialBackoffRetryPolicy({ maxRetries: 5 }),
104
+ );
77
105
  })
78
106
  .execute();
79
107
  });
@@ -86,7 +114,7 @@ describe("Hook System", () => {
86
114
  const events = await internalFragment.inContext(async function () {
87
115
  return await this.handlerTx()
88
116
  .withServiceCalls(
89
- () => [internalFragment.services.hookService.getPendingHookEvents(namespace)] as const,
117
+ () => [internalFragment.services.hookService.getHooksByNamespace(TEST_NS)] as const,
90
118
  )
91
119
  .transform(({ serviceResult: [result] }) => result)
92
120
  .execute();
@@ -101,8 +129,97 @@ describe("Hook System", () => {
101
129
  });
102
130
  });
103
131
 
132
+ it("should store a provided hook id", async () => {
133
+ const namespace = internalFragment.$internal.deps.namespace ?? internalSchema.name;
134
+ const hookId = "hook-id-1";
135
+ const hooks: HooksMap = {
136
+ onId: vi.fn(),
137
+ };
138
+
139
+ await internalFragment.inContext(async function () {
140
+ await this.handlerTx()
141
+ .mutate(({ forSchema }) => {
142
+ const uow = forSchema(internalSchema, hooks);
143
+
144
+ uow.triggerHook("onId", { data: "test" }, { id: hookId });
145
+
146
+ prepareHookMutations(
147
+ uow,
148
+ internalFragment,
149
+ new ExponentialBackoffRetryPolicy({ maxRetries: 5 }),
150
+ );
151
+ })
152
+ .execute();
153
+ });
154
+
155
+ const events = await internalFragment.inContext(async function () {
156
+ return await this.handlerTx()
157
+ .withServiceCalls(
158
+ () => [internalFragment.services.hookService.getHooksByNamespace(namespace)] as const,
159
+ )
160
+ .transform(({ serviceResult: [result] }) => result)
161
+ .execute();
162
+ });
163
+
164
+ expect(events).toHaveLength(1);
165
+ expect(events[0]?.id.externalId).toBe(hookId);
166
+ });
167
+
168
+ it("should fail when a hook id already exists", async () => {
169
+ const namespace = internalFragment.$internal.deps.namespace ?? internalSchema.name;
170
+ const hookId = "hook-id-conflict";
171
+ const hooks: HooksMap = {
172
+ onIdConflict: vi.fn(),
173
+ };
174
+
175
+ await internalFragment.inContext(async function () {
176
+ await this.handlerTx()
177
+ .mutate(({ forSchema }) => {
178
+ const uow = forSchema(internalSchema, hooks);
179
+
180
+ uow.triggerHook("onIdConflict", { data: "first" }, { id: hookId });
181
+
182
+ prepareHookMutations(
183
+ uow,
184
+ internalFragment,
185
+ new ExponentialBackoffRetryPolicy({ maxRetries: 5 }),
186
+ );
187
+ })
188
+ .execute();
189
+ });
190
+
191
+ await expect(
192
+ internalFragment.inContext(async function () {
193
+ await this.handlerTx()
194
+ .mutate(({ forSchema }) => {
195
+ const uow = forSchema(internalSchema, hooks);
196
+
197
+ uow.triggerHook("onIdConflict", { data: "second" }, { id: hookId });
198
+
199
+ prepareHookMutations(
200
+ uow,
201
+ internalFragment,
202
+ new ExponentialBackoffRetryPolicy({ maxRetries: 5 }),
203
+ );
204
+ })
205
+ .execute();
206
+ }),
207
+ ).rejects.toThrow();
208
+
209
+ const events = await internalFragment.inContext(async function () {
210
+ return await this.handlerTx()
211
+ .withServiceCalls(
212
+ () => [internalFragment.services.hookService.getHooksByNamespace(namespace)] as const,
213
+ )
214
+ .transform(({ serviceResult: [result] }) => result)
215
+ .execute();
216
+ });
217
+
218
+ expect(events).toHaveLength(1);
219
+ expect(events[0]?.id.externalId).toBe(hookId);
220
+ });
221
+
104
222
  it("should set maxAttempts to 1 when retry policy does not retry", async () => {
105
- const namespace = "test-no-retry";
106
223
  const hooks: HooksMap = {
107
224
  onNoRetry: vi.fn(),
108
225
  };
@@ -114,12 +231,7 @@ describe("Hook System", () => {
114
231
 
115
232
  uow.triggerHook("onNoRetry", { data: "test" });
116
233
 
117
- prepareHookMutations(uow, {
118
- hooks,
119
- namespace,
120
- internalFragment,
121
- defaultRetryPolicy: new NoRetryPolicy(),
122
- });
234
+ prepareHookMutations(uow, internalFragment, new NoRetryPolicy());
123
235
  })
124
236
  .execute();
125
237
  });
@@ -127,7 +239,7 @@ describe("Hook System", () => {
127
239
  const events = await internalFragment.inContext(async function () {
128
240
  return await this.handlerTx()
129
241
  .withServiceCalls(
130
- () => [internalFragment.services.hookService.getPendingHookEvents(namespace)] as const,
242
+ () => [internalFragment.services.hookService.getHooksByNamespace(TEST_NS)] as const,
131
243
  )
132
244
  .transform(({ serviceResult: [result] }) => result)
133
245
  .execute();
@@ -138,7 +250,6 @@ describe("Hook System", () => {
138
250
  });
139
251
 
140
252
  it("should use custom retry policy from trigger options", async () => {
141
- const namespace = "test-custom-retry";
142
253
  const hooks: HooksMap = {
143
254
  onCustomRetry: vi.fn(),
144
255
  };
@@ -156,12 +267,11 @@ describe("Hook System", () => {
156
267
  },
157
268
  );
158
269
 
159
- prepareHookMutations(uow, {
160
- hooks,
161
- namespace,
270
+ prepareHookMutations(
271
+ uow,
162
272
  internalFragment,
163
- defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 10 }),
164
- });
273
+ new ExponentialBackoffRetryPolicy({ maxRetries: 10 }),
274
+ );
165
275
  })
166
276
  .execute();
167
277
  });
@@ -169,7 +279,7 @@ describe("Hook System", () => {
169
279
  const events = await internalFragment.inContext(async function () {
170
280
  return await this.handlerTx()
171
281
  .withServiceCalls(
172
- () => [internalFragment.services.hookService.getPendingHookEvents(namespace)] as const,
282
+ () => [internalFragment.services.hookService.getHooksByNamespace(TEST_NS)] as const,
173
283
  )
174
284
  .transform(({ serviceResult: [result] }) => result)
175
285
  .execute();
@@ -177,6 +287,126 @@ describe("Hook System", () => {
177
287
 
178
288
  expect(events[0]?.maxAttempts).toBe(1);
179
289
  });
290
+
291
+ it("should set nextRetryAt when processAt is in the future", async () => {
292
+ const hooks: HooksMap = {
293
+ onScheduled: vi.fn(),
294
+ };
295
+ const futureTime = new Date(Date.now() + 60000);
296
+
297
+ await internalFragment.inContext(async function () {
298
+ await this.handlerTx()
299
+ .mutate(({ forSchema }) => {
300
+ const uow = forSchema(internalSchema, hooks);
301
+
302
+ uow.triggerHook("onScheduled", { data: "test" }, { processAt: futureTime });
303
+
304
+ prepareHookMutations(
305
+ uow,
306
+ internalFragment,
307
+ new ExponentialBackoffRetryPolicy({ maxRetries: 5 }),
308
+ );
309
+ })
310
+ .execute();
311
+ });
312
+
313
+ const events = await internalFragment.inContext(async function () {
314
+ return await this.handlerTx()
315
+ .withServiceCalls(
316
+ () => [internalFragment.services.hookService.getHooksByNamespace(TEST_NS)] as const,
317
+ )
318
+ .transform(({ serviceResult: [result] }) => result)
319
+ .execute();
320
+ });
321
+
322
+ expect(events).toHaveLength(1);
323
+ expect(events[0]?.nextRetryAt).toBeInstanceOf(Date);
324
+ expect(events[0]?.nextRetryAt?.getTime()).toBe(futureTime.getTime());
325
+ });
326
+
327
+ it("should keep processAt in the past while remaining immediately eligible", async () => {
328
+ const hooks: HooksMap = {
329
+ onImmediate: vi.fn(),
330
+ };
331
+ const pastTime = new Date(Date.now() - 60000);
332
+
333
+ await internalFragment.inContext(async function () {
334
+ await this.handlerTx()
335
+ .mutate(({ forSchema }) => {
336
+ const uow = forSchema(internalSchema, hooks);
337
+
338
+ uow.triggerHook("onImmediate", { data: "test" }, { processAt: pastTime });
339
+
340
+ prepareHookMutations(
341
+ uow,
342
+ internalFragment,
343
+ new ExponentialBackoffRetryPolicy({ maxRetries: 5 }),
344
+ );
345
+ })
346
+ .execute();
347
+ });
348
+
349
+ const events = await internalFragment.inContext(async function () {
350
+ return await this.handlerTx()
351
+ .withServiceCalls(
352
+ () => [internalFragment.services.hookService.getHooksByNamespace(TEST_NS)] as const,
353
+ )
354
+ .transform(({ serviceResult: [result] }) => result)
355
+ .execute();
356
+ });
357
+
358
+ expect(events).toHaveLength(1);
359
+ expect(events[0]?.nextRetryAt).toBeInstanceOf(Date);
360
+ expect(events[0]?.nextRetryAt?.getTime()).toBe(pastTime.getTime());
361
+ });
362
+
363
+ it("should preserve full hookName in queued hooks log summary when it contains colons", async () => {
364
+ const hookName = "on:segment:created";
365
+ const hooks: HooksMap = {
366
+ [hookName]: vi.fn(),
367
+ };
368
+ const debugSpy = vi.spyOn(DurableHooksLogger, "debug").mockImplementation(() => {});
369
+
370
+ try {
371
+ await internalFragment.inContext(async function () {
372
+ await this.handlerTx()
373
+ .mutate(({ forSchema }) => {
374
+ const uow = forSchema(internalSchema, hooks);
375
+ uow.triggerHook(hookName, { data: "test" });
376
+ prepareHookMutations(
377
+ uow,
378
+ internalFragment,
379
+ new ExponentialBackoffRetryPolicy({ maxRetries: 5 }),
380
+ );
381
+ })
382
+ .execute();
383
+ });
384
+
385
+ const queuedCall = debugSpy.mock.calls.find(
386
+ ([message]) => message === "Durable hooks queued",
387
+ );
388
+ expect(queuedCall).toBeDefined();
389
+
390
+ const fields = queuedCall?.[1]?.fields;
391
+ expect(typeof fields).toBe("function");
392
+
393
+ const summary = (
394
+ fields as () => {
395
+ hooks: Array<{ namespace: string; hookName: string; count: number }>;
396
+ total: number;
397
+ }
398
+ )();
399
+
400
+ expect(summary.hooks).toContainEqual({
401
+ namespace: TEST_NS,
402
+ hookName,
403
+ count: 1,
404
+ });
405
+ expect(summary.total).toBe(1);
406
+ } finally {
407
+ debugSpy.mockRestore();
408
+ }
409
+ });
180
410
  });
181
411
 
182
412
  describe("processHooks", () => {
@@ -216,6 +446,7 @@ describe("Hook System", () => {
216
446
  hooks,
217
447
  namespace,
218
448
  internalFragment,
449
+ handlerTx,
219
450
  defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 }),
220
451
  });
221
452
 
@@ -241,6 +472,79 @@ describe("Hook System", () => {
241
472
  expect(result?.lastAttemptAt).toBeInstanceOf(Date);
242
473
  });
243
474
 
475
+ it("should surface conflicts when a hook mutates its own record", async () => {
476
+ const namespace = "test-claim-conflict";
477
+ let eventId!: FragnoId;
478
+
479
+ const hookFn = vi.fn(async (payload: { externalId: string; version: number }) => {
480
+ const conflictId = new FragnoId({
481
+ externalId: payload.externalId,
482
+ version: payload.version,
483
+ });
484
+ await internalFragment.inContext(async function () {
485
+ await this.handlerTx()
486
+ .mutate(({ forSchema }) => {
487
+ const uow = forSchema(internalSchema);
488
+ uow.update("fragno_hooks", conflictId, (b) => b.set({ status: "processing" }));
489
+ })
490
+ .execute();
491
+ });
492
+ });
493
+
494
+ const hooks: HooksMap = {
495
+ onConflict: hookFn,
496
+ };
497
+
498
+ await internalFragment.inContext(async function () {
499
+ const createdId = await this.handlerTx()
500
+ .mutate(({ forSchema }) => {
501
+ const uow = forSchema(internalSchema);
502
+ return uow.create("fragno_hooks", {
503
+ id: "hook-conflict-id",
504
+ namespace,
505
+ hookName: "onConflict",
506
+ payload: { externalId: "hook-conflict-id", version: 0 },
507
+ status: "pending",
508
+ attempts: 0,
509
+ maxAttempts: 5,
510
+ lastAttemptAt: null,
511
+ nextRetryAt: null,
512
+ error: null,
513
+ nonce: "test-nonce-conflict",
514
+ });
515
+ })
516
+ .execute();
517
+ eventId = createdId;
518
+ });
519
+
520
+ await expect(
521
+ processHooks({
522
+ hooks,
523
+ namespace,
524
+ internalFragment,
525
+ handlerTx,
526
+ defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 }),
527
+ }),
528
+ ).rejects.toThrow(ConcurrencyConflictError);
529
+
530
+ expect(hookFn).toHaveBeenCalledOnce();
531
+ expect(hookFn).toHaveBeenCalledWith({
532
+ externalId: eventId.externalId,
533
+ version: eventId.version,
534
+ });
535
+
536
+ const event = await internalFragment.inContext(async function () {
537
+ return await this.handlerTx()
538
+ .withServiceCalls(
539
+ () => [internalFragment.services.hookService.getHookById(eventId)] as const,
540
+ )
541
+ .transform(({ serviceResult: [result] }) => result)
542
+ .execute();
543
+ });
544
+
545
+ expect(event?.status).toBe("processing");
546
+ });
547
+
244
548
  it("should mark failed hooks for retry", async () => {
245
549
  const namespace = "test-failure";
246
550
  const hookFn = vi.fn().mockRejectedValue(new Error("Hook failed"));
@@ -275,6 +579,7 @@ describe("Hook System", () => {
275
579
  hooks,
276
580
  namespace,
277
581
  internalFragment,
582
+ handlerTx,
278
583
  defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 }),
279
584
  });
280
585
 
@@ -329,6 +634,7 @@ describe("Hook System", () => {
329
634
  hooks,
330
635
  namespace,
331
636
  internalFragment,
637
+ handlerTx,
332
638
  defaultRetryPolicy: new NoRetryPolicy(),
333
639
  });
334
640
 
@@ -379,6 +685,7 @@ describe("Hook System", () => {
379
685
  hooks,
380
686
  namespace,
381
687
  internalFragment,
688
+ handlerTx,
382
689
  defaultRetryPolicy: new NoRetryPolicy(),
383
690
  });
384
691
 
@@ -395,6 +702,68 @@ describe("Hook System", () => {
395
702
  expect(result?.error).toBe("Hook 'onMissing' not found in hooks map");
396
703
  });
397
704
 
705
+ it("should re-queue stuck processing hooks and call the handler", async () => {
706
+ const namespace = "test-stuck-processing";
707
+ const hookFn = vi.fn();
708
+ const hooks: HooksMap = {
709
+ onStuck: hookFn,
710
+ };
711
+ const onStuckProcessingHooks = vi.fn();
712
+
713
+ let eventId: FragnoId;
714
+
715
+ await internalFragment.inContext(async function () {
716
+ const createdId = await this.handlerTx()
717
+ .mutate(({ forSchema }) => {
718
+ const uow = forSchema(internalSchema);
719
+ return uow.create("fragno_hooks", {
720
+ namespace,
721
+ hookName: "onStuck",
722
+ payload: { ok: true },
723
+ status: "processing",
724
+ attempts: 0,
725
+ maxAttempts: 5,
726
+ lastAttemptAt: new Date(Date.now() - 20 * 60_000),
727
+ nextRetryAt: null,
728
+ error: null,
729
+ nonce: "test-nonce",
730
+ });
731
+ })
732
+ .execute();
733
+ eventId = createdId;
734
+ });
735
+
736
+ await processHooks({
737
+ hooks,
738
+ namespace,
739
+ internalFragment,
740
+ handlerTx,
741
+ stuckProcessingTimeoutMinutes: 1,
742
+ onStuckProcessingHooks,
743
+ });
744
+
745
+ expect(hookFn).toHaveBeenCalledOnce();
746
+ expect(onStuckProcessingHooks).toHaveBeenCalledOnce();
747
+ expect(onStuckProcessingHooks).toHaveBeenCalledWith(
748
+ expect.objectContaining({
749
+ namespace,
750
+ timeoutMinutes: 1,
751
+ events: [expect.objectContaining({ hookName: "onStuck" })],
752
+ }),
753
+ );
754
+
755
+ const result = await internalFragment.inContext(async function () {
756
+ return await this.handlerTx()
757
+ .withServiceCalls(
758
+ () => [internalFragment.services.hookService.getHookById(eventId)] as const,
759
+ )
760
+ .transform(({ serviceResult: [event] }) => event)
761
+ .execute();
762
+ });
763
+
764
+ expect(result?.status).toBe("completed");
765
+ });
766
+
398
767
  it("should process multiple hooks in parallel", async () => {
399
768
  const namespace = "test-parallel";
400
769
  const hook1 = vi.fn();
@@ -454,6 +823,7 @@ describe("Hook System", () => {
454
823
  hooks,
455
824
  namespace,
456
825
  internalFragment,
826
+ handlerTx,
457
827
  defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 }),
458
828
  });
459
829
 
@@ -534,6 +904,7 @@ describe("Hook System", () => {
534
904
  hooks,
535
905
  namespace,
536
906
  internalFragment,
907
+ handlerTx,
537
908
  defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 }),
538
909
  });
539
910
 
@@ -570,10 +941,60 @@ describe("Hook System", () => {
570
941
  hooks,
571
942
  namespace,
572
943
  internalFragment,
944
+ handlerTx,
573
945
  defaultRetryPolicy: new ExponentialBackoffRetryPolicy({ maxRetries: 3 }),
574
946
  });
575
947
 
576
948
  expect(hookFn).not.toHaveBeenCalled();
577
949
  });
578
950
  });
951
+
952
+ describe("createDurableHooksRunner", () => {
953
+ it("should return the total processed count across queued reruns", async () => {
954
+ const namespace = "test-runner-queued";
955
+ let resolveHook!: () => void;
956
+ const hookDone = new Promise<void>((resolve) => {
957
+ resolveHook = resolve;
958
+ });
959
+ const hookFn = vi.fn(async () => {
960
+ await hookDone;
961
+ });
962
+
963
+ await internalFragment.inContext(async function () {
964
+ await this.handlerTx()
965
+ .mutate(({ forSchema }) => {
966
+ const uow = forSchema(internalSchema);
967
+ uow.create("fragno_hooks", {
968
+ namespace,
969
+ hookName: "onQueued",
970
+ payload: { ok: true },
971
+ status: "pending",
972
+ attempts: 0,
973
+ maxAttempts: 1,
974
+ lastAttemptAt: null,
975
+ nextRetryAt: null,
976
+ error: null,
977
+ nonce: "runner-queued-nonce",
978
+ });
979
+ })
980
+ .execute();
981
+ });
982
+
983
+ const runner = createDurableHooksRunner({
984
+ hooks: { onQueued: hookFn },
985
+ namespace,
986
+ internalFragment,
987
+ handlerTx,
988
+ defaultRetryPolicy: new NoRetryPolicy(),
989
+ });
990
+
991
+ const firstRun = runner.processDue();
992
+ const queuedRun = runner.processDue();
993
+ resolveHook();
994
+
995
+ await expect(firstRun).resolves.toBe(1);
996
+ await expect(queuedRun).resolves.toBe(1);
997
+ expect(hookFn).toHaveBeenCalledTimes(1);
998
+ });
999
+ });
579
1000
  });