@fragno-dev/db 0.3.0 → 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 (516) hide show
  1. package/.turbo/turbo-build.log +327 -160
  2. package/CHANGELOG.md +74 -0
  3. package/README.md +24 -0
  4. package/dist/adapters/adapters.d.ts +1 -1
  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/generic-sql-adapter.d.ts +0 -3
  8. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
  9. package/dist/adapters/generic-sql/generic-sql-adapter.js +11 -12
  10. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
  11. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +46 -6
  12. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
  13. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -1
  14. package/dist/adapters/generic-sql/migration/dialect/mysql.js +1 -1
  15. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
  16. package/dist/adapters/generic-sql/migration/dialect/postgres.js +1 -1
  17. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
  18. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +185 -19
  19. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
  20. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -1
  21. package/dist/adapters/generic-sql/migration/executor.js +30 -3
  22. package/dist/adapters/generic-sql/migration/executor.js.map +1 -1
  23. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -1
  24. package/dist/adapters/generic-sql/migration/prepared-migrations.js +3 -3
  25. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
  26. package/dist/adapters/generic-sql/migration/sql-generator.js +1 -1
  27. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
  28. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +1 -1
  29. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
  30. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
  31. package/dist/adapters/generic-sql/query/db-now-sql.js +27 -0
  32. package/dist/adapters/generic-sql/query/db-now-sql.js.map +1 -0
  33. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +9 -6
  34. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
  35. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
  36. package/dist/adapters/generic-sql/query/sql-query-compiler.js +37 -9
  37. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
  38. package/dist/adapters/generic-sql/query/where-builder.js +24 -20
  39. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
  40. package/dist/adapters/generic-sql/uow-decoder.js +1 -1
  41. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
  42. package/dist/adapters/generic-sql/uow-encoder.js +8 -9
  43. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
  44. package/dist/adapters/in-memory/condition-evaluator.js +10 -6
  45. package/dist/adapters/in-memory/condition-evaluator.js.map +1 -1
  46. package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -1
  47. package/dist/adapters/in-memory/in-memory-adapter.js +45 -25
  48. package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -1
  49. package/dist/adapters/in-memory/in-memory-uow.js +236 -13
  50. package/dist/adapters/in-memory/in-memory-uow.js.map +1 -1
  51. package/dist/adapters/in-memory/options.d.ts +2 -0
  52. package/dist/adapters/in-memory/options.d.ts.map +1 -1
  53. package/dist/adapters/in-memory/options.js +3 -2
  54. package/dist/adapters/in-memory/options.js.map +1 -1
  55. package/dist/adapters/in-memory/reference-resolution.js.map +1 -1
  56. package/dist/adapters/in-memory/store.js +1 -1
  57. package/dist/adapters/in-memory/store.js.map +1 -1
  58. package/dist/adapters/shared/from-unit-of-work-compiler.js +51 -24
  59. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
  60. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
  61. package/dist/browser/adapters/adapters.d.ts +61 -0
  62. package/dist/browser/adapters/adapters.d.ts.map +1 -0
  63. package/dist/browser/adapters/generic-sql/migration/executor.d.ts +15 -0
  64. package/dist/browser/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  65. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  66. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  67. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts +11 -0
  68. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  69. package/dist/browser/adapters/in-memory/in-memory-adapter.d.ts +5 -0
  70. package/dist/browser/adapters/in-memory/index.d.ts +2 -0
  71. package/dist/browser/adapters/in-memory/options.d.ts +1 -0
  72. package/dist/browser/db-fragment-definition-builder.d.ts +237 -0
  73. package/dist/browser/db-fragment-definition-builder.d.ts.map +1 -0
  74. package/dist/browser/durable-hooks.d.ts +3 -0
  75. package/dist/browser/fragments/internal-fragment.d.ts +317 -0
  76. package/dist/browser/fragments/internal-fragment.d.ts.map +1 -0
  77. package/dist/browser/fragments/internal-fragment.schema.d.ts +1 -0
  78. package/dist/browser/hooks/durable-hooks-logger.d.ts +10 -0
  79. package/dist/browser/hooks/durable-hooks-logger.d.ts.map +1 -0
  80. package/dist/browser/hooks/hooks.d.ts +146 -0
  81. package/dist/browser/hooks/hooks.d.ts.map +1 -0
  82. package/dist/browser/id.js +1 -0
  83. package/dist/browser/internal/adapter-registry.d.ts +4 -0
  84. package/dist/browser/internal/outbox-state.d.ts +2 -0
  85. package/dist/browser/mod.d.ts +15 -0
  86. package/dist/browser/mod.d.ts.map +1 -0
  87. package/dist/browser/mod.js +17 -0
  88. package/dist/browser/mod.js.map +1 -0
  89. package/dist/browser/mod2.d.ts +48 -0
  90. package/dist/browser/mod2.d.ts.map +1 -0
  91. package/dist/browser/naming/sql-naming.d.ts +19 -0
  92. package/dist/browser/naming/sql-naming.d.ts.map +1 -0
  93. package/dist/browser/outbox/outbox.d.ts +21 -0
  94. package/dist/browser/outbox/outbox.d.ts.map +1 -0
  95. package/dist/browser/query/column-defaults.js +1 -0
  96. package/dist/browser/query/condition-builder.d.ts +44 -0
  97. package/dist/browser/query/condition-builder.d.ts.map +1 -0
  98. package/dist/browser/query/condition-builder.js +97 -0
  99. package/dist/browser/query/condition-builder.js.map +1 -0
  100. package/dist/browser/query/cursor.d.ts +105 -0
  101. package/dist/browser/query/cursor.d.ts.map +1 -0
  102. package/dist/browser/query/cursor.js +150 -0
  103. package/dist/browser/query/cursor.js.map +1 -0
  104. package/dist/browser/query/db-now.d.ts +22 -0
  105. package/dist/browser/query/db-now.d.ts.map +1 -0
  106. package/dist/browser/query/db-now.js +33 -0
  107. package/dist/browser/query/db-now.js.map +1 -0
  108. package/dist/browser/query/orm/orm.d.ts +18 -0
  109. package/dist/browser/query/orm/orm.d.ts.map +1 -0
  110. package/dist/browser/query/simple-query-interface.d.ts +108 -0
  111. package/dist/browser/query/simple-query-interface.d.ts.map +1 -0
  112. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts +423 -0
  113. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  114. package/dist/browser/query/unit-of-work/execute-unit-of-work.js +507 -0
  115. package/dist/browser/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  116. package/dist/browser/query/unit-of-work/retry-policy.d.ts +23 -0
  117. package/dist/browser/query/unit-of-work/retry-policy.d.ts.map +1 -0
  118. package/dist/browser/query/unit-of-work/retry-policy.js +40 -0
  119. package/dist/browser/query/unit-of-work/retry-policy.js.map +1 -0
  120. package/dist/browser/query/unit-of-work/unit-of-work.d.ts +703 -0
  121. package/dist/browser/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  122. package/dist/browser/query/unit-of-work/unit-of-work.js +1206 -0
  123. package/dist/browser/query/unit-of-work/unit-of-work.js.map +1 -0
  124. package/dist/browser/query/value-encoding.js +38 -0
  125. package/dist/browser/query/value-encoding.js.map +1 -0
  126. package/dist/browser/schema/create.d.ts +326 -0
  127. package/dist/browser/schema/create.d.ts.map +1 -0
  128. package/dist/browser/schema/create.js +89 -0
  129. package/dist/browser/schema/create.js.map +1 -0
  130. package/dist/browser/schema/generate-id.js +28 -0
  131. package/dist/browser/schema/generate-id.js.map +1 -0
  132. package/dist/browser/shared/providers.d.ts +6 -0
  133. package/dist/browser/shared/providers.d.ts.map +1 -0
  134. package/dist/browser/sql-driver/connection/connection-provider.d.ts +13 -0
  135. package/dist/browser/sql-driver/connection/connection-provider.d.ts.map +1 -0
  136. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  137. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  138. package/dist/browser/sql-driver/driver/runtime-driver.d.ts +23 -0
  139. package/dist/browser/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  140. package/dist/browser/sql-driver/query-executor/plugin.d.ts +17 -0
  141. package/dist/browser/sql-driver/query-executor/plugin.d.ts.map +1 -0
  142. package/dist/browser/sql-driver/query-executor/query-executor.d.ts +36 -0
  143. package/dist/browser/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  144. package/dist/browser/sql-driver/sql-driver-adapter.d.ts +29 -0
  145. package/dist/browser/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  146. package/dist/browser/sql-driver/sql-driver.d.ts +38 -0
  147. package/dist/browser/sql-driver/sql-driver.d.ts.map +1 -0
  148. package/dist/browser/sync/commands.d.ts +15 -0
  149. package/dist/browser/sync/commands.d.ts.map +1 -0
  150. package/dist/browser/sync/commands.js +27 -0
  151. package/dist/browser/sync/commands.js.map +1 -0
  152. package/dist/browser/sync/types.d.ts +63 -0
  153. package/dist/browser/sync/types.d.ts.map +1 -0
  154. package/dist/browser/util/types.d.ts +8 -0
  155. package/dist/browser/util/types.d.ts.map +1 -0
  156. package/dist/browser/with-database.d.ts +29 -0
  157. package/dist/browser/with-database.d.ts.map +1 -0
  158. package/dist/client.d.ts +4 -0
  159. package/dist/client.js +5 -0
  160. package/dist/db-fragment-definition-builder.d.ts +85 -28
  161. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  162. package/dist/db-fragment-definition-builder.js +374 -46
  163. package/dist/db-fragment-definition-builder.js.map +1 -1
  164. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts +20 -0
  165. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts.map +1 -0
  166. package/dist/dispatchers/cloudflare-do/dispatcher.js +147 -0
  167. package/dist/dispatchers/cloudflare-do/dispatcher.js.map +1 -0
  168. package/dist/dispatchers/cloudflare-do/index.d.ts +5 -20
  169. package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -1
  170. package/dist/dispatchers/cloudflare-do/index.js +23 -55
  171. package/dist/dispatchers/cloudflare-do/index.js.map +1 -1
  172. package/dist/dispatchers/node/dispatcher.d.ts +14 -0
  173. package/dist/dispatchers/node/dispatcher.d.ts.map +1 -0
  174. package/dist/dispatchers/node/dispatcher.js +80 -0
  175. package/dist/dispatchers/node/dispatcher.js.map +1 -0
  176. package/dist/dispatchers/node/index.d.ts +5 -10
  177. package/dist/dispatchers/node/index.d.ts.map +1 -1
  178. package/dist/dispatchers/node/index.js +21 -53
  179. package/dist/dispatchers/node/index.js.map +1 -1
  180. package/dist/durable-hooks.d.ts +31 -0
  181. package/dist/durable-hooks.d.ts.map +1 -0
  182. package/dist/durable-hooks.js +23 -0
  183. package/dist/durable-hooks.js.map +1 -0
  184. package/dist/fragments/internal-fragment.d.ts +128 -27
  185. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  186. package/dist/fragments/internal-fragment.js +125 -78
  187. package/dist/fragments/internal-fragment.js.map +1 -1
  188. package/dist/fragments/internal-fragment.routes.js +138 -3
  189. package/dist/fragments/internal-fragment.routes.js.map +1 -1
  190. package/dist/fragments/internal-fragment.schema.d.ts +7 -1
  191. package/dist/fragments/internal-fragment.schema.d.ts.map +1 -1
  192. package/dist/fragments/internal-fragment.schema.js +18 -1
  193. package/dist/fragments/internal-fragment.schema.js.map +1 -1
  194. package/dist/hooks/durable-hooks-logger.d.ts +10 -0
  195. package/dist/hooks/durable-hooks-logger.d.ts.map +1 -0
  196. package/dist/hooks/durable-hooks-logger.js +75 -0
  197. package/dist/hooks/durable-hooks-logger.js.map +1 -0
  198. package/dist/hooks/durable-hooks-processor.d.ts +1 -14
  199. package/dist/hooks/durable-hooks-processor.js +58 -10
  200. package/dist/hooks/durable-hooks-processor.js.map +1 -1
  201. package/dist/hooks/durable-hooks-runtime.js +44 -0
  202. package/dist/hooks/durable-hooks-runtime.js.map +1 -0
  203. package/dist/hooks/hooks.d.ts +60 -2
  204. package/dist/hooks/hooks.d.ts.map +1 -1
  205. package/dist/hooks/hooks.js +214 -53
  206. package/dist/hooks/hooks.js.map +1 -1
  207. package/dist/id.d.ts +2 -2
  208. package/dist/id.js +2 -2
  209. package/dist/internal/adapter-registry.d.ts +11 -0
  210. package/dist/internal/adapter-registry.d.ts.map +1 -0
  211. package/dist/internal/adapter-registry.js +135 -0
  212. package/dist/internal/adapter-registry.js.map +1 -0
  213. package/dist/internal/outbox-state.d.ts +2 -0
  214. package/dist/internal/outbox-state.js +26 -0
  215. package/dist/internal/outbox-state.js.map +1 -0
  216. package/dist/migration-engine/auto-from-schema.d.ts +33 -0
  217. package/dist/migration-engine/auto-from-schema.d.ts.map +1 -0
  218. package/dist/migration-engine/auto-from-schema.js +210 -27
  219. package/dist/migration-engine/auto-from-schema.js.map +1 -1
  220. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  221. package/dist/migration-engine/generation-engine.js +17 -5
  222. package/dist/migration-engine/generation-engine.js.map +1 -1
  223. package/dist/migration-engine/shared.d.ts +113 -0
  224. package/dist/migration-engine/shared.d.ts.map +1 -0
  225. package/dist/migration-engine/shared.js.map +1 -1
  226. package/dist/mod.d.ts +12 -11
  227. package/dist/mod.d.ts.map +1 -1
  228. package/dist/mod.js +10 -10
  229. package/dist/mod.js.map +1 -1
  230. package/dist/naming/sql-naming.d.ts.map +1 -1
  231. package/dist/naming/sql-naming.js.map +1 -1
  232. package/dist/outbox/outbox-builder.js.map +1 -1
  233. package/dist/outbox/outbox.d.ts +3 -1
  234. package/dist/outbox/outbox.d.ts.map +1 -1
  235. package/dist/outbox/outbox.js.map +1 -1
  236. package/dist/query/column-defaults.js.map +1 -1
  237. package/dist/query/condition-builder.d.ts +7 -1
  238. package/dist/query/condition-builder.d.ts.map +1 -1
  239. package/dist/query/condition-builder.js +5 -1
  240. package/dist/query/condition-builder.js.map +1 -1
  241. package/dist/query/cursor-client.d.ts +105 -0
  242. package/dist/query/cursor-client.d.ts.map +1 -0
  243. package/dist/query/cursor-client.js +165 -0
  244. package/dist/query/cursor-client.js.map +1 -0
  245. package/dist/query/cursor.d.ts.map +1 -1
  246. package/dist/query/cursor.js +7 -1
  247. package/dist/query/cursor.js.map +1 -1
  248. package/dist/query/db-now.d.ts +15 -1
  249. package/dist/query/db-now.d.ts.map +1 -1
  250. package/dist/query/db-now.js +30 -2
  251. package/dist/query/db-now.js.map +1 -1
  252. package/dist/query/orm/orm.js.map +1 -1
  253. package/dist/query/serialize/create-sql-serializer.js +2 -2
  254. package/dist/query/serialize/create-sql-serializer.js.map +1 -1
  255. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
  256. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
  257. package/dist/query/serialize/dialect/sqlite-serializer.js +6 -2
  258. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
  259. package/dist/query/simple-query-interface.d.ts +7 -3
  260. package/dist/query/simple-query-interface.d.ts.map +1 -1
  261. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +37 -2
  262. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  263. package/dist/query/unit-of-work/execute-unit-of-work.js +39 -18
  264. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  265. package/dist/query/unit-of-work/unit-of-work.d.ts +42 -16
  266. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  267. package/dist/query/unit-of-work/unit-of-work.js +50 -6
  268. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  269. package/dist/query/value-decoding.js +8 -1
  270. package/dist/query/value-decoding.js.map +1 -1
  271. package/dist/query/value-encoding.js.map +1 -1
  272. package/dist/schema/create.d.ts +69 -25
  273. package/dist/schema/create.d.ts.map +1 -1
  274. package/dist/schema/create.js +91 -16
  275. package/dist/schema/create.js.map +1 -1
  276. package/dist/schema/type-conversion/create-sql-type-mapper.js +1 -1
  277. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  278. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  279. package/dist/schema/validator.d.ts.map +1 -1
  280. package/dist/schema/validator.js.map +1 -1
  281. package/dist/schema-output/drizzle.d.ts.map +1 -1
  282. package/dist/schema-output/drizzle.js +8 -6
  283. package/dist/schema-output/drizzle.js.map +1 -1
  284. package/dist/schema-output/prisma.d.ts.map +1 -1
  285. package/dist/schema-output/prisma.js +21 -10
  286. package/dist/schema-output/prisma.js.map +1 -1
  287. package/dist/sql-driver/dialects/durable-object-dialect.js +3 -9
  288. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -1
  289. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -1
  290. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -1
  291. package/dist/sql-driver/sql-driver-adapter.js.map +1 -1
  292. package/dist/sql-driver/sql.js.map +1 -1
  293. package/dist/sync/commands.d.ts +15 -0
  294. package/dist/sync/commands.d.ts.map +1 -0
  295. package/dist/sync/commands.js +27 -0
  296. package/dist/sync/commands.js.map +1 -0
  297. package/dist/sync/index.d.ts +4 -0
  298. package/dist/sync/index.js +4 -0
  299. package/dist/sync/read-tracking.d.ts +25 -0
  300. package/dist/sync/read-tracking.d.ts.map +1 -0
  301. package/dist/sync/read-tracking.js +148 -0
  302. package/dist/sync/read-tracking.js.map +1 -0
  303. package/dist/sync/submit.js +213 -0
  304. package/dist/sync/submit.js.map +1 -0
  305. package/dist/sync/types.d.ts +63 -0
  306. package/dist/sync/types.d.ts.map +1 -0
  307. package/dist/util/default-database-adapter.js +6 -1
  308. package/dist/util/default-database-adapter.js.map +1 -1
  309. package/dist/with-database.d.ts +3 -6
  310. package/dist/with-database.d.ts.map +1 -1
  311. package/dist/with-database.js +7 -15
  312. package/dist/with-database.js.map +1 -1
  313. package/package.json +33 -41
  314. package/src/adapters/adapters.ts +5 -4
  315. package/src/adapters/drizzle/migrate-drizzle.test.ts +46 -9
  316. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +5 -3
  317. package/src/adapters/drizzle/test-utils.ts +2 -1
  318. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +5 -3
  319. package/src/adapters/generic-sql/generic-sql-adapter.ts +21 -24
  320. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +1 -0
  321. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +81 -15
  322. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +4 -2
  323. package/src/adapters/generic-sql/migration/cold-kysely.ts +1 -0
  324. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +3 -2
  325. package/src/adapters/generic-sql/migration/dialect/mysql.ts +1 -0
  326. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +5 -4
  327. package/src/adapters/generic-sql/migration/dialect/postgres.ts +2 -1
  328. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +795 -3
  329. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +385 -57
  330. package/src/adapters/generic-sql/migration/executor.test.ts +52 -0
  331. package/src/adapters/generic-sql/migration/executor.ts +47 -4
  332. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +117 -14
  333. package/src/adapters/generic-sql/migration/prepared-migrations.ts +9 -8
  334. package/src/adapters/generic-sql/migration/sql-generator.ts +5 -3
  335. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +3 -3
  336. package/src/adapters/generic-sql/query/cursor-utils.test.ts +3 -2
  337. package/src/adapters/generic-sql/query/cursor-utils.ts +1 -1
  338. package/src/adapters/generic-sql/query/db-now-sql.ts +49 -0
  339. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +144 -8
  340. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +16 -17
  341. package/src/adapters/generic-sql/query/select-builder.test.ts +1 -0
  342. package/src/adapters/generic-sql/query/select-builder.ts +2 -2
  343. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +24 -5
  344. package/src/adapters/generic-sql/query/sql-query-compiler.ts +83 -13
  345. package/src/adapters/generic-sql/query/where-builder.test.ts +7 -5
  346. package/src/adapters/generic-sql/query/where-builder.ts +48 -29
  347. package/src/adapters/generic-sql/sql-adapter-pglite-migrations.test.ts +6 -15
  348. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +52 -7
  349. package/src/adapters/generic-sql/sql-adapter-pglite-queries.test.ts +9 -6
  350. package/src/adapters/generic-sql/sql-adapter-sqlite3-driver.test.ts +273 -5
  351. package/src/adapters/generic-sql/sql-adapter-sqlite3-uow.test.ts +123 -6
  352. package/src/adapters/generic-sql/sql-adapter-sqlocal.test.ts +4 -2
  353. package/src/adapters/generic-sql/uow-decoder.test.ts +4 -3
  354. package/src/adapters/generic-sql/uow-decoder.ts +3 -3
  355. package/src/adapters/generic-sql/uow-encoder.test.ts +4 -2
  356. package/src/adapters/generic-sql/uow-encoder.ts +14 -18
  357. package/src/adapters/in-memory/condition-evaluator.test.ts +2 -1
  358. package/src/adapters/in-memory/condition-evaluator.ts +9 -4
  359. package/src/adapters/in-memory/in-memory-adapter.ts +155 -44
  360. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +50 -2
  361. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +158 -3
  362. package/src/adapters/in-memory/in-memory-uow.ts +402 -26
  363. package/src/adapters/in-memory/options.test.ts +1 -0
  364. package/src/adapters/in-memory/options.ts +5 -1
  365. package/src/adapters/in-memory/outbox.test.ts +361 -0
  366. package/src/adapters/in-memory/reference-resolution.test.ts +3 -2
  367. package/src/adapters/in-memory/reference-resolution.ts +2 -2
  368. package/src/adapters/in-memory/sorted-array-index.test.ts +1 -0
  369. package/src/adapters/in-memory/store.test.ts +1 -0
  370. package/src/adapters/in-memory/store.ts +3 -3
  371. package/src/adapters/in-memory/value-normalization.test.ts +1 -0
  372. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +51 -7
  373. package/src/adapters/shared/from-unit-of-work-compiler.ts +156 -46
  374. package/src/adapters/shared/uow-operation-compiler.ts +3 -3
  375. package/src/browser/mod.ts +64 -0
  376. package/src/client.ts +19 -0
  377. package/src/db-fragment-definition-builder.test.ts +821 -47
  378. package/src/db-fragment-definition-builder.ts +857 -110
  379. package/src/db-fragment-instantiator.test.ts +114 -90
  380. package/src/db-fragment-integration.test.ts +9 -6
  381. package/src/dispatchers/cloudflare-do/dispatcher.ts +204 -0
  382. package/src/dispatchers/cloudflare-do/index.test.ts +145 -12
  383. package/src/dispatchers/cloudflare-do/index.ts +49 -90
  384. package/src/dispatchers/node/dispatcher.ts +112 -0
  385. package/src/dispatchers/node/index.test.ts +43 -14
  386. package/src/dispatchers/node/index.ts +38 -75
  387. package/src/durable-hooks.test.ts +80 -0
  388. package/src/durable-hooks.ts +67 -0
  389. package/src/fragments/internal-fragment.routes.test.ts +570 -0
  390. package/src/fragments/internal-fragment.routes.ts +297 -5
  391. package/src/fragments/internal-fragment.schema.ts +45 -1
  392. package/src/fragments/internal-fragment.test.ts +223 -251
  393. package/src/fragments/internal-fragment.ts +278 -154
  394. package/src/hooks/durable-hooks-logger.ts +126 -0
  395. package/src/hooks/durable-hooks-processor.pglite.test.ts +87 -0
  396. package/src/hooks/durable-hooks-processor.test.ts +179 -14
  397. package/src/hooks/durable-hooks-processor.ts +120 -14
  398. package/src/hooks/durable-hooks-runtime.test.ts +65 -0
  399. package/src/hooks/durable-hooks-runtime.ts +81 -0
  400. package/src/hooks/hooks.test.ts +314 -53
  401. package/src/hooks/hooks.ts +360 -81
  402. package/src/id.test.ts +34 -0
  403. package/src/id.ts +1 -3
  404. package/src/internal/adapter-registry.test.ts +93 -0
  405. package/src/internal/adapter-registry.ts +239 -0
  406. package/src/internal/outbox-state.ts +43 -0
  407. package/src/migration-engine/auto-from-schema.test.ts +93 -0
  408. package/src/migration-engine/auto-from-schema.ts +360 -42
  409. package/src/migration-engine/create.test.ts +2 -1
  410. package/src/migration-engine/create.ts +1 -1
  411. package/src/migration-engine/generation-engine.test.ts +66 -9
  412. package/src/migration-engine/generation-engine.ts +31 -10
  413. package/src/migration-engine/shared.ts +13 -0
  414. package/src/mod.ts +45 -27
  415. package/src/naming/sql-naming.ts +1 -0
  416. package/src/outbox/outbox-builder.ts +2 -2
  417. package/src/outbox/outbox.test.ts +216 -45
  418. package/src/outbox/outbox.ts +3 -1
  419. package/src/query/column-defaults.ts +1 -1
  420. package/src/query/condition-builder.test.ts +15 -0
  421. package/src/query/condition-builder.ts +7 -0
  422. package/src/query/cursor-client.test.ts +70 -0
  423. package/src/query/cursor-client.ts +263 -0
  424. package/src/query/cursor.test.ts +3 -2
  425. package/src/query/cursor.ts +15 -3
  426. package/src/query/db-now.ts +69 -2
  427. package/src/query/orm/orm.ts +2 -2
  428. package/src/query/query-type.test.ts +2 -1
  429. package/src/query/serialize/create-sql-serializer.ts +3 -3
  430. package/src/query/serialize/dialect/mysql-serializer.ts +1 -1
  431. package/src/query/serialize/dialect/postgres-serializer.ts +1 -1
  432. package/src/query/serialize/dialect/sqlite-serializer.test.ts +39 -2
  433. package/src/query/serialize/dialect/sqlite-serializer.ts +18 -5
  434. package/src/query/simple-query-interface.ts +10 -4
  435. package/src/query/unit-of-work/execute-unit-of-work.test.ts +347 -9
  436. package/src/query/unit-of-work/execute-unit-of-work.ts +63 -20
  437. package/src/query/unit-of-work/retry-policy.test.ts +1 -0
  438. package/src/query/unit-of-work/tx-builder.test.ts +73 -1
  439. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +5 -4
  440. package/src/query/unit-of-work/unit-of-work-types.test.ts +41 -11
  441. package/src/query/unit-of-work/unit-of-work.test.ts +28 -2
  442. package/src/query/unit-of-work/unit-of-work.ts +105 -19
  443. package/src/query/value-decoding.test.ts +50 -2
  444. package/src/query/value-decoding.ts +17 -4
  445. package/src/query/value-encoding.test.ts +1 -0
  446. package/src/query/value-encoding.ts +1 -1
  447. package/src/schema/create.test.ts +164 -5
  448. package/src/schema/create.ts +222 -24
  449. package/src/schema/generate-id.test.ts +1 -0
  450. package/src/schema/serialize.test.ts +4 -3
  451. package/src/schema/type-conversion/create-sql-type-mapper.ts +1 -1
  452. package/src/schema/type-conversion/dialect/sqlite.ts +2 -2
  453. package/src/schema/type-conversion/type-mapping.test.ts +2 -1
  454. package/src/schema/validator.test.ts +4 -2
  455. package/src/schema/validator.ts +1 -0
  456. package/src/schema-output/drizzle.test.ts +72 -19
  457. package/src/schema-output/drizzle.ts +24 -18
  458. package/src/schema-output/prisma.test.ts +172 -14
  459. package/src/schema-output/prisma.ts +34 -14
  460. package/src/sql-driver/better-sqlite3.test.ts +5 -3
  461. package/src/sql-driver/dialects/durable-object-dialect.ts +3 -8
  462. package/src/sql-driver/query-executor/default-query-executor.ts +1 -1
  463. package/src/sql-driver/query-executor/query-executor-base.ts +1 -1
  464. package/src/sql-driver/query-executor/query-executor.ts +1 -1
  465. package/src/sql-driver/sql-driver-adapter.ts +2 -2
  466. package/src/sql-driver/sql.ts +2 -1
  467. package/src/sql-driver/sqlocal.test.ts +4 -2
  468. package/src/sync/commands.test.ts +39 -0
  469. package/src/sync/commands.ts +51 -0
  470. package/src/sync/conflict-checker.test.ts +450 -0
  471. package/src/sync/conflict-checker.ts +248 -0
  472. package/src/sync/index.ts +14 -0
  473. package/src/sync/plan.ts +9 -0
  474. package/src/sync/read-tracking.test.ts +177 -0
  475. package/src/sync/read-tracking.ts +287 -0
  476. package/src/sync/submit.test.ts +205 -0
  477. package/src/sync/submit.ts +328 -0
  478. package/src/sync/types.ts +80 -0
  479. package/src/util/default-database-adapter.ts +15 -2
  480. package/src/with-database.ts +20 -50
  481. package/tsconfig.json +1 -1
  482. package/tsdown.config.ts +38 -26
  483. package/vitest.config.ts +1 -0
  484. package/dist/hooks/durable-hooks-processor.d.ts.map +0 -1
  485. package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js +0 -168
  486. package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js.map +0 -1
  487. package/dist/packages/fragno/dist/api/bind-services.js +0 -20
  488. package/dist/packages/fragno/dist/api/bind-services.js.map +0 -1
  489. package/dist/packages/fragno/dist/api/error.js +0 -48
  490. package/dist/packages/fragno/dist/api/error.js.map +0 -1
  491. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +0 -321
  492. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +0 -1
  493. package/dist/packages/fragno/dist/api/fragment-instantiator.js +0 -669
  494. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +0 -1
  495. package/dist/packages/fragno/dist/api/fragno-response.js +0 -73
  496. package/dist/packages/fragno/dist/api/fragno-response.js.map +0 -1
  497. package/dist/packages/fragno/dist/api/internal/response-stream.js +0 -81
  498. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +0 -1
  499. package/dist/packages/fragno/dist/api/internal/route.js +0 -10
  500. package/dist/packages/fragno/dist/api/internal/route.js.map +0 -1
  501. package/dist/packages/fragno/dist/api/mutable-request-state.js +0 -97
  502. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +0 -1
  503. package/dist/packages/fragno/dist/api/request-context-storage.js +0 -43
  504. package/dist/packages/fragno/dist/api/request-context-storage.js.map +0 -1
  505. package/dist/packages/fragno/dist/api/request-input-context.js +0 -185
  506. package/dist/packages/fragno/dist/api/request-input-context.js.map +0 -1
  507. package/dist/packages/fragno/dist/api/request-middleware.js +0 -83
  508. package/dist/packages/fragno/dist/api/request-middleware.js.map +0 -1
  509. package/dist/packages/fragno/dist/api/request-output-context.js +0 -119
  510. package/dist/packages/fragno/dist/api/request-output-context.js.map +0 -1
  511. package/dist/packages/fragno/dist/api/route.js +0 -30
  512. package/dist/packages/fragno/dist/api/route.js.map +0 -1
  513. package/dist/packages/fragno/dist/internal/symbols.js +0 -10
  514. package/dist/packages/fragno/dist/internal/symbols.js.map +0 -1
  515. package/dist/packages/fragno/dist/internal/trace-context.js +0 -12
  516. package/dist/packages/fragno/dist/internal/trace-context.js.map +0 -1
@@ -1,7 +1,11 @@
1
- import { createHandlerTxBuilder, createServiceTxBuilder } from "./query/unit-of-work/execute-unit-of-work.js";
2
- import { createHookScheduler, prepareHookMutations } from "./hooks/hooks.js";
1
+ import { DurableHooksLogger } from "./hooks/durable-hooks-logger.js";
2
+ import { getDurableHooksRuntimeByConfig, getDurableHooksRuntimeByNamespace, registerDurableHooksRuntime } from "./hooks/durable-hooks-runtime.js";
3
+ import { createDurableHooksRunner, prepareHookMutations } from "./hooks/hooks.js";
3
4
  import { sanitizeNamespace } from "./naming/sql-naming.js";
5
+ import { HandlerTxBuilder, createHandlerTxBuilder, createServiceTxBuilder } from "./query/unit-of-work/execute-unit-of-work.js";
4
6
  import { resolveDatabaseAdapter } from "./util/default-database-adapter.js";
7
+ import { FragmentDefinitionBuilder } from "@fragno-dev/core";
8
+ import { FragnoApiError } from "@fragno-dev/core/api";
5
9
 
6
10
  //#region src/db-fragment-definition-builder.ts
7
11
  /**
@@ -19,6 +23,171 @@ function createDatabaseContext(options, schema) {
19
23
  function resolveDatabaseNamespace(options, schema) {
20
24
  return options.databaseNamespace !== void 0 ? options.databaseNamespace ?? null : sanitizeNamespace(schema.name);
21
25
  }
26
+ function resolveMountRoute(name, mountRoute) {
27
+ const resolved = mountRoute ?? `/api/${name}`;
28
+ return resolved.endsWith("/") ? resolved.slice(0, -1) : resolved;
29
+ }
30
+ const dbRoundtripGuardStateSymbol = Symbol("fragno-db-roundtrip-guard");
31
+ const requestSourceSymbol = Symbol.for("fragno-request-source");
32
+ const requestRouteSymbol = Symbol.for("fragno-request-route");
33
+ const requestWaitUntilSymbol = Symbol.for("fragno-request-wait-until");
34
+ const roundtripGuardDocsUrl = "https://fragno.dev/docs/fragno/for-library-authors/rules-of-fragno";
35
+ function wrapHandlerTxBuilderWithRoundtripGuard(builder, onExecute) {
36
+ const wrappedBuilders = /* @__PURE__ */ new WeakSet();
37
+ const applyExecuteGuard = (target) => {
38
+ if (wrappedBuilders.has(target)) return target;
39
+ wrappedBuilders.add(target);
40
+ const execute = target.execute.bind(target);
41
+ target.execute = () => {
42
+ onExecute();
43
+ return execute();
44
+ };
45
+ return target;
46
+ };
47
+ const wrap = (target) => {
48
+ const guarded = applyExecuteGuard(target);
49
+ return new Proxy(guarded, { get(obj, prop, receiver) {
50
+ const value = Reflect.get(obj, prop, receiver);
51
+ if (typeof value !== "function") return value;
52
+ if (prop === "execute") return value;
53
+ return (...args) => {
54
+ const result = value.apply(obj, args);
55
+ if (result instanceof HandlerTxBuilder) return wrap(result);
56
+ return result;
57
+ };
58
+ } });
59
+ };
60
+ return wrap(builder);
61
+ }
62
+ function buildDurableHooksLogContext(context) {
63
+ const logContext = {};
64
+ if (context?.route !== void 0) logContext["route"] = context.route;
65
+ if (context?.source !== void 0) logContext["source"] = context.source;
66
+ return logContext;
67
+ }
68
+ function notifyDurableHooks(notifier, namespace, notifyContext, logContextFields, options) {
69
+ const suffix = options?.crossNamespace ?? false ? " (cross-namespace)" : "";
70
+ const notifyStart = Date.now();
71
+ DurableHooksLogger.debug(`Durable hooks notify requested${suffix}`, {
72
+ namespace,
73
+ fields: logContextFields
74
+ });
75
+ const notifyPromise = Promise.resolve().then(() => notifier.notify(notifyContext)).then((processed) => {
76
+ DurableHooksLogger.debug(`Durable hooks notify completed${suffix}`, {
77
+ namespace,
78
+ fields: {
79
+ result: processed === void 0 ? null : processed,
80
+ ms: Date.now() - notifyStart,
81
+ ...logContextFields
82
+ }
83
+ });
84
+ }).catch((error) => {
85
+ DurableHooksLogger.error(`Durable hooks notify failed${suffix}`, {
86
+ namespace,
87
+ fields: {
88
+ error: DurableHooksLogger.toErrorMessage(error),
89
+ ...logContextFields
90
+ }
91
+ });
92
+ });
93
+ if (notifyContext.waitUntil) {
94
+ notifyContext.waitUntil(notifyPromise);
95
+ return;
96
+ }
97
+ }
98
+ function notifyDurableHooksAfterMutate({ uow, hooksConfig, internalFragment, autoSchedule, planMode, logContext }) {
99
+ if (planMode) return;
100
+ const notifyContext = {
101
+ source: logContext?.source ?? "request",
102
+ route: logContext?.route,
103
+ waitUntil: logContext?.waitUntil
104
+ };
105
+ const logContextFields = buildDurableHooksLogContext(logContext);
106
+ const triggeredHooks = uow.getTriggeredHooks();
107
+ const ownNamespaceTriggeredCount = hooksConfig ? triggeredHooks.filter((hook) => hook.namespace === hooksConfig.namespace).length : 0;
108
+ if (hooksConfig?.notifier && autoSchedule && ownNamespaceTriggeredCount > 0) notifyDurableHooks(hooksConfig.notifier, hooksConfig.namespace, notifyContext, logContextFields);
109
+ else if (hooksConfig && !autoSchedule && ownNamespaceTriggeredCount > 0) DurableHooksLogger.debug("Durable hooks notify skipped (autoSchedule=false)", {
110
+ namespace: hooksConfig.namespace,
111
+ fields: {
112
+ queued: ownNamespaceTriggeredCount,
113
+ ...logContextFields
114
+ }
115
+ });
116
+ else if (hooksConfig && !hooksConfig.notifier && ownNamespaceTriggeredCount > 0) DurableHooksLogger.debug("Durable hooks notify skipped (notifier missing)", {
117
+ namespace: hooksConfig.namespace,
118
+ fields: {
119
+ queued: ownNamespaceTriggeredCount,
120
+ ...logContextFields
121
+ }
122
+ });
123
+ if (triggeredHooks.length === 0) return;
124
+ const namespaces = /* @__PURE__ */ new Set();
125
+ const triggeredCountByNamespace = /* @__PURE__ */ new Map();
126
+ for (const hook of triggeredHooks) {
127
+ namespaces.add(hook.namespace);
128
+ triggeredCountByNamespace.set(hook.namespace, (triggeredCountByNamespace.get(hook.namespace) ?? 0) + 1);
129
+ }
130
+ if (hooksConfig) namespaces.delete(hooksConfig.namespace);
131
+ for (const namespace of namespaces) {
132
+ if (!internalFragment) {
133
+ DurableHooksLogger.debug("Durable hooks notifier missing scope for namespace", {
134
+ namespace,
135
+ fields: logContextFields
136
+ });
137
+ continue;
138
+ }
139
+ const runtime = getDurableHooksRuntimeByNamespace(namespace, internalFragment);
140
+ if (!runtime) {
141
+ DurableHooksLogger.debug("Durable hooks notifier missing for namespace", {
142
+ namespace,
143
+ fields: logContextFields
144
+ });
145
+ continue;
146
+ }
147
+ if (runtime.config.autoSchedule === false) {
148
+ DurableHooksLogger.debug("Durable hooks notify skipped (autoSchedule=false)", {
149
+ namespace,
150
+ fields: {
151
+ queued: triggeredCountByNamespace.get(namespace) ?? 0,
152
+ ...logContextFields
153
+ }
154
+ });
155
+ continue;
156
+ }
157
+ const notifier = runtime.config.notifier;
158
+ if (!notifier) {
159
+ DurableHooksLogger.debug("Durable hooks notifier missing for namespace", {
160
+ namespace,
161
+ fields: logContextFields
162
+ });
163
+ continue;
164
+ }
165
+ notifyDurableHooks(notifier, namespace, notifyContext, logContextFields, { crossNamespace: true });
166
+ }
167
+ }
168
+ function resolveDbRoundtripGuard(options) {
169
+ const guard = options.dbRoundtripGuard;
170
+ if (!guard) return null;
171
+ if (guard === true) return {
172
+ retrieveCount: 0,
173
+ mutateCount: 0,
174
+ maxRoundtrips: 1
175
+ };
176
+ return {
177
+ retrieveCount: 0,
178
+ mutateCount: 0,
179
+ maxRoundtrips: guard.maxRoundtrips ?? 1
180
+ };
181
+ }
182
+ function getDbRoundtripGuardState(storage, guard) {
183
+ const storageWithGuard = storage;
184
+ if (!storageWithGuard[dbRoundtripGuardStateSymbol]) storageWithGuard[dbRoundtripGuardStateSymbol] = { ...guard };
185
+ else storageWithGuard[dbRoundtripGuardStateSymbol].maxRoundtrips = guard.maxRoundtrips;
186
+ return storageWithGuard[dbRoundtripGuardStateSymbol];
187
+ }
188
+ function isRouteRequest(storage) {
189
+ return storage[requestSourceSymbol] === "route";
190
+ }
22
191
  /**
23
192
  * Builder for database fragments that wraps the core fragment builder
24
193
  * and provides database-specific functionality.
@@ -29,14 +198,18 @@ var DatabaseFragmentDefinitionBuilder = class DatabaseFragmentDefinitionBuilder
29
198
  #baseBuilder;
30
199
  #schema;
31
200
  #hooksFactory;
32
- constructor(baseBuilder, schema, hooksFactory) {
201
+ #syncRegistry;
202
+ #registryResolver;
203
+ constructor(baseBuilder, schema, hooksFactory, syncRegistry, registryResolver) {
33
204
  this.#baseBuilder = baseBuilder;
34
205
  this.#schema = schema;
35
206
  this.#hooksFactory = hooksFactory;
207
+ this.#syncRegistry = syncRegistry;
208
+ this.#registryResolver = registryResolver;
36
209
  }
37
210
  /**
38
211
  * Define dependencies for this database fragment.
39
- * The context includes database adapter and ORM instance.
212
+ * The context includes the database adapter.
40
213
  */
41
214
  withDependencies(fn) {
42
215
  const wrappedFn = (context) => {
@@ -45,12 +218,11 @@ var DatabaseFragmentDefinitionBuilder = class DatabaseFragmentDefinitionBuilder
45
218
  const userDeps = fn({
46
219
  config: context.config,
47
220
  options: context.options,
48
- db: dbContext.db,
49
221
  databaseAdapter: dbContext.databaseAdapter
50
222
  });
51
223
  const createUow = () => dbContext.db.createUnitOfWork();
52
224
  const implicitDeps = {
53
- db: dbContext.db,
225
+ databaseAdapter: dbContext.databaseAdapter,
54
226
  schema: this.#schema,
55
227
  namespace,
56
228
  createUnitOfWork: createUow
@@ -60,13 +232,13 @@ var DatabaseFragmentDefinitionBuilder = class DatabaseFragmentDefinitionBuilder
60
232
  ...implicitDeps
61
233
  };
62
234
  };
63
- return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.withDependencies(wrappedFn), this.#schema, this.#hooksFactory);
235
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.withDependencies(wrappedFn), this.#schema, this.#hooksFactory, this.#syncRegistry, this.#registryResolver);
64
236
  }
65
237
  providesBaseService(fn) {
66
- return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.providesBaseService(fn), this.#schema, this.#hooksFactory);
238
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.providesBaseService(fn), this.#schema, this.#hooksFactory, this.#syncRegistry, this.#registryResolver);
67
239
  }
68
240
  providesService(serviceName, fn) {
69
- return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.providesService(serviceName, fn), this.#schema, this.#hooksFactory);
241
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.providesService(serviceName, fn), this.#schema, this.#hooksFactory, this.#syncRegistry, this.#registryResolver);
70
242
  }
71
243
  /**
72
244
  * Provide a private service that is only accessible to the fragment author.
@@ -76,7 +248,7 @@ var DatabaseFragmentDefinitionBuilder = class DatabaseFragmentDefinitionBuilder
76
248
  * to later ones.
77
249
  */
78
250
  providesPrivateService(serviceName, fn) {
79
- return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.providesPrivateService(serviceName, fn), this.#schema, this.#hooksFactory);
251
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.providesPrivateService(serviceName, fn), this.#schema, this.#hooksFactory, this.#syncRegistry, this.#registryResolver);
80
252
  }
81
253
  /**
82
254
  * Define durable hooks for this fragment.
@@ -103,26 +275,36 @@ var DatabaseFragmentDefinitionBuilder = class DatabaseFragmentDefinitionBuilder
103
275
  return fn({
104
276
  config: context.config,
105
277
  options: context.options,
278
+ deps: context.deps,
279
+ services: context.services,
280
+ serviceDeps: context.serviceDeps,
106
281
  defineHook
107
282
  });
108
283
  };
109
- const newBuilder = new DatabaseFragmentDefinitionBuilder(this.#baseBuilder, this.#schema);
284
+ const newBuilder = new DatabaseFragmentDefinitionBuilder(this.#baseBuilder, this.#schema, this.#hooksFactory, this.#syncRegistry, this.#registryResolver);
110
285
  newBuilder.#hooksFactory = hooksFactory;
111
286
  return newBuilder;
112
287
  }
113
288
  /**
289
+ * Register sync command definitions for this fragment.
290
+ */
291
+ withSyncCommands(registry) {
292
+ if (registry.schemaName !== this.#schema.name) throw new Error(`Sync command registry schema name "${registry.schemaName}" does not match fragment schema "${this.#schema.name}".`);
293
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder, this.#schema, this.#hooksFactory, registry, this.#registryResolver);
294
+ }
295
+ /**
114
296
  * Declare that this fragment uses a required service provided by the runtime.
115
297
  * Delegates to the base builder.
116
298
  */
117
299
  usesService(serviceName) {
118
- return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.usesService(serviceName), this.#schema, this.#hooksFactory);
300
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.usesService(serviceName), this.#schema, this.#hooksFactory, this.#syncRegistry, this.#registryResolver);
119
301
  }
120
302
  /**
121
303
  * Declare that this fragment uses an optional service provided by the runtime.
122
304
  * Delegates to the base builder.
123
305
  */
124
306
  usesOptionalService(serviceName) {
125
- return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.usesOptionalService(serviceName), this.#schema, this.#hooksFactory);
307
+ return new DatabaseFragmentDefinitionBuilder(this.#baseBuilder.usesOptionalService(serviceName), this.#schema, this.#hooksFactory, this.#syncRegistry, this.#registryResolver);
126
308
  }
127
309
  /**
128
310
  * Build the final database fragment definition.
@@ -141,10 +323,32 @@ var DatabaseFragmentDefinitionBuilder = class DatabaseFragmentDefinitionBuilder
141
323
  userDeps = {};
142
324
  } else throw error;
143
325
  }
144
- const { db } = createDatabaseContext(context.options, this.#schema);
326
+ const dbContext = createDatabaseContext(context.options, this.#schema);
327
+ const { db } = dbContext;
145
328
  const namespace = resolveDatabaseNamespace(context.options, this.#schema);
329
+ const dryRun = process.env["FRAGNO_INIT_DRY_RUN"] === "true";
330
+ const isInternalFragment$1 = baseDef.name === "$fragno-internal-fragment";
331
+ if (!dryRun && !isInternalFragment$1 && this.#registryResolver) {
332
+ const registry = this.#registryResolver.getRegistryForAdapterSync(dbContext.databaseAdapter);
333
+ const outboxEnabled = context.options.outbox?.enabled ?? false;
334
+ registry.registerSchema({
335
+ name: this.#schema.name,
336
+ namespace,
337
+ version: this.#schema.version,
338
+ tables: Object.keys(this.#schema.tables).sort()
339
+ }, {
340
+ name: baseDef.name,
341
+ mountRoute: resolveMountRoute(baseDef.name, context.options.mountRoute)
342
+ }, { outboxEnabled });
343
+ if (this.#syncRegistry) registry.registerSyncCommands({
344
+ fragmentName: baseDef.name,
345
+ schemaName: this.#syncRegistry.schemaName,
346
+ namespace,
347
+ commands: this.#syncRegistry.commands
348
+ });
349
+ }
146
350
  const implicitDeps = {
147
- db,
351
+ databaseAdapter: dbContext.databaseAdapter,
148
352
  schema: this.#schema,
149
353
  namespace,
150
354
  createUnitOfWork: () => db.createUnitOfWork()
@@ -157,70 +361,109 @@ var DatabaseFragmentDefinitionBuilder = class DatabaseFragmentDefinitionBuilder
157
361
  const builderWithStorage = this.#baseBuilder.withExternalRequestStorage(({ options }) => {
158
362
  return createDatabaseContext(options, this.#schema).databaseAdapter.contextStorage;
159
363
  }).withRequestStorage(({ options }) => {
160
- return { uow: createDatabaseContext(options, this.#schema).db.createUnitOfWork() };
364
+ return { uow: createDatabaseContext(options, this.#schema).db.createBaseUnitOfWork() };
161
365
  });
162
- const internalFragmentFactory = baseDef.linkedFragments?.["_fragno_internal"];
163
366
  const hooksConfigCache = /* @__PURE__ */ new WeakMap();
164
367
  const createHooksConfig = (context) => {
165
368
  if (!this.#hooksFactory) return;
166
369
  const depsKey = typeof context.deps === "object" && context.deps !== null ? context.deps : void 0;
167
- const cachedHooksConfig = depsKey ? hooksConfigCache.get(depsKey) : void 0;
168
- if (cachedHooksConfig) return cachedHooksConfig;
169
370
  const namespaceKey = resolveDatabaseNamespace(context.options, this.#schema) ?? this.#schema.name;
170
371
  const durableHooksOptions = context.options.durableHooks;
372
+ DurableHooksLogger.configure(durableHooksOptions?.logging, namespaceKey);
373
+ const cachedHooksConfig = depsKey ? hooksConfigCache.get(depsKey) : void 0;
374
+ if (cachedHooksConfig) {
375
+ if (!cachedHooksConfig.hooks && context.services) cachedHooksConfig.hooks = this.#hooksFactory({
376
+ config: context.config,
377
+ options: context.options,
378
+ deps: context.deps,
379
+ services: context.services,
380
+ serviceDeps: context.serviceDeps ?? {}
381
+ });
382
+ return cachedHooksConfig;
383
+ }
384
+ const autoSchedule = durableHooksOptions?.autoSchedule !== false;
171
385
  const baseAdapter = resolveDatabaseAdapter(context.options, this.#schema);
172
386
  const hookAdapter = baseAdapter.getHookProcessingAdapter?.() ?? baseAdapter;
173
387
  const hookOptions = hookAdapter === baseAdapter ? context.options : {
174
388
  ...context.options,
175
389
  databaseAdapter: hookAdapter
176
390
  };
391
+ const registryResolver = this.#registryResolver;
392
+ if (!registryResolver) throw new Error("Adapter registry resolver is missing for durable hooks.");
177
393
  const dbContextForHooks = createDatabaseContext(hookOptions, this.#schema);
394
+ const hookContextStorage = dbContextForHooks.databaseAdapter.contextStorage;
178
395
  const hooksConfig = {
179
- hooks: this.#hooksFactory(context),
180
- namespace: namespaceKey,
181
- internalFragment: internalFragmentFactory({
396
+ hooks: context.services ? this.#hooksFactory({
182
397
  config: context.config,
183
- options: hookOptions
184
- }),
398
+ options: context.options,
399
+ deps: context.deps,
400
+ services: context.services,
401
+ serviceDeps: context.serviceDeps ?? {}
402
+ }) : void 0,
403
+ namespace: namespaceKey,
404
+ internalFragment: registryResolver.getInternalFragment(hookAdapter),
405
+ autoSchedule,
185
406
  handlerTx: (execOptions) => {
186
407
  const userOnBeforeMutate = execOptions?.onBeforeMutate;
187
408
  const userOnAfterMutate = execOptions?.onAfterMutate;
409
+ const planMode = execOptions?.planMode ?? false;
410
+ let storageRef = null;
411
+ const getHookWaitUntil = () => {
412
+ if (!hookContextStorage.hasStore()) return;
413
+ return hookContextStorage.getStore()[requestWaitUntilSymbol];
414
+ };
188
415
  return createHandlerTxBuilder({
189
416
  ...execOptions,
190
417
  createUnitOfWork: () => {
191
- const uow = dbContextForHooks.db.createUnitOfWork();
192
- uow.registerSchema(hooksConfig.internalFragment.$internal.deps.schema, hooksConfig.internalFragment.$internal.deps.namespace);
193
- return uow;
418
+ const baseUow = dbContextForHooks.db.createBaseUnitOfWork();
419
+ baseUow.registerSchema(hooksConfig.internalFragment.$internal.deps.schema, hooksConfig.internalFragment.$internal.deps.namespace);
420
+ if (storageRef) storageRef.uow = baseUow;
421
+ return baseUow;
194
422
  },
195
423
  onBeforeMutate: (uow) => {
196
- prepareHookMutations(uow, hooksConfig);
424
+ if (!planMode) prepareHookMutations(uow, hooksConfig.internalFragment, hooksConfig.defaultRetryPolicy);
197
425
  if (userOnBeforeMutate) userOnBeforeMutate(uow);
198
426
  },
199
427
  onAfterMutate: async (uow) => {
200
- hooksConfig.scheduler?.schedule().catch((error) => {
201
- console.error("Durable hooks processing failed", error);
428
+ notifyDurableHooksAfterMutate({
429
+ uow,
430
+ hooksConfig,
431
+ internalFragment: hooksConfig.internalFragment,
432
+ autoSchedule,
433
+ planMode,
434
+ logContext: {
435
+ source: "hook",
436
+ waitUntil: getHookWaitUntil()
437
+ }
202
438
  });
203
439
  if (userOnAfterMutate) await userOnAfterMutate(uow);
204
440
  }
205
- });
441
+ }, void 0, (run) => hookContextStorage.runWithInitializer(() => {
442
+ const inheritedWaitUntil = getHookWaitUntil();
443
+ storageRef = { uow: null };
444
+ if (inheritedWaitUntil) storageRef[requestWaitUntilSymbol] = inheritedWaitUntil;
445
+ return storageRef;
446
+ }, run));
206
447
  },
207
448
  stuckProcessingTimeoutMinutes: durableHooksOptions?.stuckProcessingTimeoutMinutes,
208
449
  onStuckProcessingHooks: durableHooksOptions?.onStuckProcessingHooks
209
450
  };
210
- hooksConfig.scheduler = createHookScheduler(hooksConfig);
451
+ hooksConfig.runner = createDurableHooksRunner(hooksConfig);
452
+ registerDurableHooksRuntime(hooksConfig);
211
453
  if (depsKey) hooksConfigCache.set(depsKey, hooksConfig);
212
454
  return hooksConfig;
213
455
  };
456
+ const isInternalFragment = baseDef.name === "$fragno-internal-fragment";
214
457
  const finalDef = builderWithStorage.withThisContext(({ storage, config, options, deps }) => {
215
458
  const hooksConfig = createHooksConfig({
216
459
  config,
217
460
  options,
218
461
  deps
219
462
  });
220
- const internalFragment = hooksConfig?.internalFragment ?? (internalFragmentFactory ? internalFragmentFactory({
221
- config,
222
- options
223
- }) : void 0);
463
+ const autoSchedule = options.durableHooks?.autoSchedule !== false;
464
+ const registryResolver = this.#registryResolver;
465
+ const databaseAdapter = deps.databaseAdapter ?? resolveDatabaseAdapter(options, this.#schema);
466
+ const internalFragment = isInternalFragment ? void 0 : hooksConfig?.internalFragment ?? registryResolver?.getInternalFragment(databaseAdapter);
224
467
  function serviceTx(schema) {
225
468
  const uow = storage.getStore()?.uow;
226
469
  if (!uow) throw new Error("No UnitOfWork in context. Service must be called within a route handler OR using `withUnitOfWork`.");
@@ -232,7 +475,36 @@ var DatabaseFragmentDefinitionBuilder = class DatabaseFragmentDefinitionBuilder
232
475
  if (!currentStorage) throw new Error("No storage in context. Handler must be called within a request context.");
233
476
  const userOnBeforeMutate = execOptions?.onBeforeMutate;
234
477
  const userOnAfterMutate = execOptions?.onAfterMutate;
235
- return createHandlerTxBuilder({
478
+ const userOnAfterRetrieve = execOptions?.onAfterRetrieve;
479
+ const planMode = execOptions?.planMode ?? false;
480
+ const roundtripGuard = isRouteRequest(currentStorage) ? resolveDbRoundtripGuard(options) : null;
481
+ const roundtripState = roundtripGuard ? getDbRoundtripGuardState(currentStorage, roundtripGuard) : null;
482
+ const routeInfo = currentStorage[requestRouteSymbol];
483
+ const routeWaitUntil = currentStorage[requestWaitUntilSymbol];
484
+ const routeLabel = routeInfo && routeInfo.method && routeInfo.path ? `${routeInfo.method} ${routeInfo.path}` : null;
485
+ const routeSuffix = routeLabel ? ` (route: ${routeLabel})` : "";
486
+ const buildRoundtripError = (kind) => new FragnoApiError({
487
+ message: `[fragno-db] Fragment "${baseDef.name}" executed more than ${roundtripState?.maxRoundtrips ?? 1} ${kind} database roundtrip(s) in a single request${routeSuffix}. Combine reads/writes into one handlerTx() or increase dbRoundtripGuard. See ${roundtripGuardDocsUrl}`,
488
+ code: "DB_ROUNDTRIP_LIMIT_EXCEEDED"
489
+ }, 500);
490
+ const roundtripExecutionState = roundtripState ? {
491
+ countedRetrieve: false,
492
+ countedMutate: false
493
+ } : null;
494
+ const resetRoundtripExecutionState = () => {
495
+ if (!roundtripExecutionState) return;
496
+ roundtripExecutionState.countedRetrieve = false;
497
+ roundtripExecutionState.countedMutate = false;
498
+ };
499
+ const guardOnAfterRetrieve = roundtripState ? async (uow, results) => {
500
+ if (roundtripExecutionState && !roundtripExecutionState.countedRetrieve && uow.getRetrievalOperations().length > 0) {
501
+ roundtripExecutionState.countedRetrieve = true;
502
+ roundtripState.retrieveCount += 1;
503
+ if (roundtripState.retrieveCount > roundtripState.maxRoundtrips) throw buildRoundtripError("retrieve");
504
+ }
505
+ if (userOnAfterRetrieve) await userOnAfterRetrieve(uow, results);
506
+ } : userOnAfterRetrieve;
507
+ const builder = createHandlerTxBuilder({
236
508
  ...execOptions,
237
509
  createUnitOfWork: () => {
238
510
  currentStorage.uow.reset();
@@ -240,27 +512,83 @@ var DatabaseFragmentDefinitionBuilder = class DatabaseFragmentDefinitionBuilder
240
512
  return currentStorage.uow;
241
513
  },
242
514
  onBeforeMutate: (uow) => {
243
- if (hooksConfig) prepareHookMutations(uow, hooksConfig);
515
+ if (internalFragment && !planMode) prepareHookMutations(uow, internalFragment, hooksConfig?.defaultRetryPolicy);
244
516
  if (userOnBeforeMutate) userOnBeforeMutate(uow);
517
+ if (roundtripState && roundtripExecutionState && !roundtripExecutionState.countedMutate && uow.getMutationOperations().length > 0) {
518
+ roundtripExecutionState.countedMutate = true;
519
+ roundtripState.mutateCount += 1;
520
+ if (roundtripState.mutateCount > roundtripState.maxRoundtrips) throw buildRoundtripError("mutate");
521
+ }
245
522
  },
523
+ onAfterRetrieve: guardOnAfterRetrieve,
246
524
  onAfterMutate: async (uow) => {
247
- if (hooksConfig?.scheduler) hooksConfig.scheduler.schedule().catch((error) => {
248
- console.error("Durable hooks processing failed", error);
525
+ notifyDurableHooksAfterMutate({
526
+ uow,
527
+ hooksConfig,
528
+ internalFragment,
529
+ autoSchedule,
530
+ planMode,
531
+ logContext: {
532
+ route: routeLabel,
533
+ source: "request",
534
+ waitUntil: routeWaitUntil
535
+ }
249
536
  });
537
+ if (hooksConfig && !planMode) {
538
+ const runtimeState = getDurableHooksRuntimeByConfig(hooksConfig);
539
+ if (runtimeState && !runtimeState.dispatcherRegistered && !runtimeState.dispatcherWarningEmitted) {
540
+ if (uow.getTriggeredHooks().some((hook) => hook.namespace === hooksConfig.namespace)) {
541
+ runtimeState.dispatcherWarningEmitted = true;
542
+ DurableHooksLogger.warn("Durable hooks dispatcher not configured for fragment", {
543
+ namespace: hooksConfig.namespace,
544
+ fields: { guidance: "Hooks will only run during requests; scheduled/retry hooks may stall. Create a dispatcher with createDurableHooksProcessor([...]) from `@fragno-dev/db/dispatchers/node` or `@fragno-dev/db/dispatchers/cloudflare-do`." }
545
+ });
546
+ }
547
+ }
548
+ }
250
549
  if (userOnAfterMutate) await userOnAfterMutate(uow);
251
550
  }
252
551
  });
552
+ if (roundtripState) return wrapHandlerTxBuilderWithRoundtripGuard(builder, resetRoundtripExecutionState);
553
+ return builder;
554
+ }
555
+ function callServices(serviceCalls) {
556
+ let callWasArray = false;
557
+ return handlerTx().withServiceCalls(() => {
558
+ const calls = serviceCalls();
559
+ callWasArray = Array.isArray(calls);
560
+ return callWasArray ? calls : [calls];
561
+ }).execute().then((result) => callWasArray ? result : result[0]);
253
562
  }
254
563
  return {
255
564
  serviceContext,
256
- handlerContext: { handlerTx }
565
+ handlerContext: {
566
+ handlerTx,
567
+ callServices
568
+ }
257
569
  };
258
570
  }).build();
259
- if (this.#hooksFactory) finalDef.internalDataFactory = ({ config, options, deps }) => ({ durableHooks: createHooksConfig({
260
- config,
261
- options,
262
- deps
263
- }) });
571
+ if (this.#hooksFactory) finalDef.internalDataFactory = ({ config, options, deps, services, serviceDeps }) => {
572
+ const hooksConfig = createHooksConfig({
573
+ config,
574
+ options,
575
+ deps,
576
+ services,
577
+ serviceDeps
578
+ });
579
+ if (!hooksConfig) return {};
580
+ return { durableHooksToken: registerDurableHooksRuntime(hooksConfig) };
581
+ };
582
+ if (this.#registryResolver) {
583
+ const registryInternalRoutes = ({ deps }) => {
584
+ const databaseAdapter = deps.databaseAdapter;
585
+ if (!databaseAdapter) throw new Error("Database adapter is missing for internal routes.");
586
+ const internalFragment = this.#registryResolver.getInternalFragment(databaseAdapter);
587
+ if (!internalFragment) return [];
588
+ return internalFragment.routes ?? [];
589
+ };
590
+ finalDef.internalRoutes = [...finalDef.internalRoutes ?? [], registryInternalRoutes];
591
+ }
264
592
  return {
265
593
  ...finalDef,
266
594
  dependencies