@fragno-dev/db 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (362) hide show
  1. package/.turbo/turbo-build.log +206 -140
  2. package/CHANGELOG.md +67 -0
  3. package/README.md +30 -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 +27 -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 +55 -16
  14. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
  15. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +129 -3
  16. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
  17. package/dist/adapters/generic-sql/migration/dialect/mysql.js +24 -5
  18. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
  19. package/dist/adapters/generic-sql/migration/dialect/postgres.js +6 -5
  20. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
  21. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +21 -10
  22. package/dist/adapters/generic-sql/migration/dialect/sqlite.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 +8 -8
  25. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
  26. package/dist/adapters/generic-sql/migration/sql-generator.js +74 -51
  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 +6 -5
  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 +42 -4
  31. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
  32. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +25 -17
  33. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
  34. package/dist/adapters/generic-sql/query/select-builder.js +5 -3
  35. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
  36. package/dist/adapters/generic-sql/query/sql-query-compiler.js +15 -12
  37. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
  38. package/dist/adapters/generic-sql/query/where-builder.js +38 -28
  39. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
  40. package/dist/adapters/generic-sql/sqlite-storage.d.ts +13 -0
  41. package/dist/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  42. package/dist/adapters/generic-sql/sqlite-storage.js +15 -0
  43. package/dist/adapters/generic-sql/sqlite-storage.js.map +1 -0
  44. package/dist/adapters/generic-sql/uow-decoder.js +7 -3
  45. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
  46. package/dist/adapters/generic-sql/uow-encoder.js +28 -8
  47. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
  48. package/dist/adapters/in-memory/condition-evaluator.js +131 -0
  49. package/dist/adapters/in-memory/condition-evaluator.js.map +1 -0
  50. package/dist/adapters/in-memory/errors.d.ts +13 -0
  51. package/dist/adapters/in-memory/errors.d.ts.map +1 -0
  52. package/dist/adapters/in-memory/errors.js +23 -0
  53. package/dist/adapters/in-memory/errors.js.map +1 -0
  54. package/dist/adapters/in-memory/in-memory-adapter.d.ts +27 -0
  55. package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -0
  56. package/dist/adapters/in-memory/in-memory-adapter.js +176 -0
  57. package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -0
  58. package/dist/adapters/in-memory/in-memory-uow.js +648 -0
  59. package/dist/adapters/in-memory/in-memory-uow.js.map +1 -0
  60. package/dist/adapters/in-memory/index.d.ts +4 -0
  61. package/dist/adapters/in-memory/index.js +4 -0
  62. package/dist/adapters/in-memory/options.d.ts +28 -0
  63. package/dist/adapters/in-memory/options.d.ts.map +1 -0
  64. package/dist/adapters/in-memory/options.js +61 -0
  65. package/dist/adapters/in-memory/options.js.map +1 -0
  66. package/dist/adapters/in-memory/reference-resolution.js +26 -0
  67. package/dist/adapters/in-memory/reference-resolution.js.map +1 -0
  68. package/dist/adapters/in-memory/sorted-array-index.js +129 -0
  69. package/dist/adapters/in-memory/sorted-array-index.js.map +1 -0
  70. package/dist/adapters/in-memory/store.js +71 -0
  71. package/dist/adapters/in-memory/store.js.map +1 -0
  72. package/dist/adapters/in-memory/value-comparison.js +28 -0
  73. package/dist/adapters/in-memory/value-comparison.js.map +1 -0
  74. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
  75. package/dist/adapters/shared/uow-operation-compiler.js +11 -11
  76. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
  77. package/dist/adapters/sql/index.d.ts +5 -0
  78. package/dist/adapters/sql/index.js +4 -0
  79. package/dist/db-fragment-definition-builder.d.ts +45 -96
  80. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  81. package/dist/db-fragment-definition-builder.js +121 -99
  82. package/dist/db-fragment-definition-builder.js.map +1 -1
  83. package/dist/dispatchers/cloudflare-do/index.d.ts +26 -0
  84. package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -0
  85. package/dist/dispatchers/cloudflare-do/index.js +63 -0
  86. package/dist/dispatchers/cloudflare-do/index.js.map +1 -0
  87. package/dist/dispatchers/node/index.d.ts +17 -0
  88. package/dist/dispatchers/node/index.d.ts.map +1 -0
  89. package/dist/dispatchers/node/index.js +59 -0
  90. package/dist/dispatchers/node/index.js.map +1 -0
  91. package/dist/fragments/internal-fragment.d.ts +172 -9
  92. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  93. package/dist/fragments/internal-fragment.js +193 -74
  94. package/dist/fragments/internal-fragment.js.map +1 -1
  95. package/dist/fragments/internal-fragment.routes.js +29 -0
  96. package/dist/fragments/internal-fragment.routes.js.map +1 -0
  97. package/dist/fragments/internal-fragment.schema.d.ts +9 -0
  98. package/dist/fragments/internal-fragment.schema.d.ts.map +1 -0
  99. package/dist/fragments/internal-fragment.schema.js +22 -0
  100. package/dist/fragments/internal-fragment.schema.js.map +1 -0
  101. package/dist/hooks/durable-hooks-processor.d.ts +14 -0
  102. package/dist/hooks/durable-hooks-processor.d.ts.map +1 -0
  103. package/dist/hooks/durable-hooks-processor.js +32 -0
  104. package/dist/hooks/durable-hooks-processor.js.map +1 -0
  105. package/dist/hooks/hooks.d.ts +47 -4
  106. package/dist/hooks/hooks.d.ts.map +1 -1
  107. package/dist/hooks/hooks.js +106 -39
  108. package/dist/hooks/hooks.js.map +1 -1
  109. package/dist/migration-engine/auto-from-schema.js +14 -11
  110. package/dist/migration-engine/auto-from-schema.js.map +1 -1
  111. package/dist/migration-engine/generation-engine.d.ts +16 -10
  112. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  113. package/dist/migration-engine/generation-engine.js +72 -33
  114. package/dist/migration-engine/generation-engine.js.map +1 -1
  115. package/dist/migration-engine/shared.js.map +1 -1
  116. package/dist/mod.d.ts +17 -10
  117. package/dist/mod.d.ts.map +1 -1
  118. package/dist/mod.js +14 -8
  119. package/dist/mod.js.map +1 -1
  120. package/dist/naming/sql-naming.d.ts +19 -0
  121. package/dist/naming/sql-naming.d.ts.map +1 -0
  122. package/dist/naming/sql-naming.js +116 -0
  123. package/dist/naming/sql-naming.js.map +1 -0
  124. package/dist/node_modules/.pnpm/{rou3@0.7.10 → rou3@0.7.12}/node_modules/rou3/dist/index.js +8 -5
  125. package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js.map +1 -0
  126. package/dist/outbox/outbox-builder.js +156 -0
  127. package/dist/outbox/outbox-builder.js.map +1 -0
  128. package/dist/outbox/outbox.d.ts +52 -0
  129. package/dist/outbox/outbox.d.ts.map +1 -0
  130. package/dist/outbox/outbox.js +37 -0
  131. package/dist/outbox/outbox.js.map +1 -0
  132. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +3 -2
  133. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -1
  134. package/dist/packages/fragno/dist/api/fragment-instantiator.js +164 -20
  135. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -1
  136. package/dist/packages/fragno/dist/api/request-input-context.js +67 -0
  137. package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -1
  138. package/dist/packages/fragno/dist/api/route.js +14 -1
  139. package/dist/packages/fragno/dist/api/route.js.map +1 -1
  140. package/dist/packages/fragno/dist/internal/trace-context.js +12 -0
  141. package/dist/packages/fragno/dist/internal/trace-context.js.map +1 -0
  142. package/dist/query/column-defaults.js +20 -4
  143. package/dist/query/column-defaults.js.map +1 -1
  144. package/dist/query/cursor.d.ts +3 -1
  145. package/dist/query/cursor.d.ts.map +1 -1
  146. package/dist/query/cursor.js +45 -14
  147. package/dist/query/cursor.js.map +1 -1
  148. package/dist/query/db-now.d.ts +8 -0
  149. package/dist/query/db-now.d.ts.map +1 -0
  150. package/dist/query/db-now.js +7 -0
  151. package/dist/query/db-now.js.map +1 -0
  152. package/dist/query/serialize/create-sql-serializer.js +3 -2
  153. package/dist/query/serialize/create-sql-serializer.js.map +1 -1
  154. package/dist/query/serialize/dialect/mysql-serializer.js +12 -6
  155. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
  156. package/dist/query/serialize/dialect/postgres-serializer.js +25 -7
  157. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
  158. package/dist/query/serialize/dialect/sqlite-serializer.js +55 -11
  159. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
  160. package/dist/query/serialize/sql-serializer.js +2 -2
  161. package/dist/query/serialize/sql-serializer.js.map +1 -1
  162. package/dist/query/simple-query-interface.d.ts +6 -1
  163. package/dist/query/simple-query-interface.d.ts.map +1 -1
  164. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +351 -100
  165. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  166. package/dist/query/unit-of-work/execute-unit-of-work.js +440 -267
  167. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  168. package/dist/query/unit-of-work/unit-of-work.d.ts +67 -22
  169. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  170. package/dist/query/unit-of-work/unit-of-work.js +110 -13
  171. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  172. package/dist/query/value-decoding.js +8 -5
  173. package/dist/query/value-decoding.js.map +1 -1
  174. package/dist/query/value-encoding.js +29 -9
  175. package/dist/query/value-encoding.js.map +1 -1
  176. package/dist/schema/create.d.ts +40 -14
  177. package/dist/schema/create.d.ts.map +1 -1
  178. package/dist/schema/create.js +82 -42
  179. package/dist/schema/create.js.map +1 -1
  180. package/dist/schema/generate-id.d.ts +20 -0
  181. package/dist/schema/generate-id.d.ts.map +1 -0
  182. package/dist/schema/generate-id.js +28 -0
  183. package/dist/schema/generate-id.js.map +1 -0
  184. package/dist/schema/type-conversion/create-sql-type-mapper.js +3 -2
  185. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  186. package/dist/schema/type-conversion/dialect/sqlite.js +9 -0
  187. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  188. package/dist/schema/validator.d.ts +10 -0
  189. package/dist/schema/validator.d.ts.map +1 -0
  190. package/dist/schema/validator.js +123 -0
  191. package/dist/schema/validator.js.map +1 -0
  192. package/dist/schema-output/drizzle.d.ts +30 -0
  193. package/dist/schema-output/drizzle.d.ts.map +1 -0
  194. package/dist/{adapters/drizzle/generate.js → schema-output/drizzle.js} +82 -56
  195. package/dist/schema-output/drizzle.js.map +1 -0
  196. package/dist/schema-output/prisma.d.ts +17 -0
  197. package/dist/schema-output/prisma.d.ts.map +1 -0
  198. package/dist/schema-output/prisma.js +296 -0
  199. package/dist/schema-output/prisma.js.map +1 -0
  200. package/dist/util/default-database-adapter.js +61 -0
  201. package/dist/util/default-database-adapter.js.map +1 -0
  202. package/dist/with-database.d.ts +1 -1
  203. package/dist/with-database.d.ts.map +1 -1
  204. package/dist/with-database.js +12 -3
  205. package/dist/with-database.js.map +1 -1
  206. package/package.json +43 -28
  207. package/src/adapters/adapters.ts +30 -24
  208. package/src/adapters/drizzle/migrate-drizzle.test.ts +54 -33
  209. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +599 -0
  210. package/src/adapters/drizzle/test-utils.ts +12 -8
  211. package/src/adapters/generic-sql/driver-config.ts +38 -0
  212. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +5 -5
  213. package/src/adapters/generic-sql/generic-sql-adapter.ts +110 -24
  214. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +54 -0
  215. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +231 -3
  216. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +118 -0
  217. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +26 -8
  218. package/src/adapters/generic-sql/migration/dialect/mysql.ts +46 -8
  219. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +25 -7
  220. package/src/adapters/generic-sql/migration/dialect/postgres.ts +8 -4
  221. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +47 -8
  222. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +27 -12
  223. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +128 -39
  224. package/src/adapters/generic-sql/migration/prepared-migrations.ts +15 -8
  225. package/src/adapters/generic-sql/migration/sql-generator.ts +142 -65
  226. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +9 -6
  227. package/src/adapters/generic-sql/query/cursor-utils.test.ts +271 -0
  228. package/src/adapters/generic-sql/query/cursor-utils.ts +41 -6
  229. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +27 -27
  230. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +38 -24
  231. package/src/adapters/generic-sql/query/select-builder.test.ts +15 -11
  232. package/src/adapters/generic-sql/query/select-builder.ts +6 -2
  233. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +52 -2
  234. package/src/adapters/generic-sql/query/sql-query-compiler.ts +50 -15
  235. package/src/adapters/generic-sql/query/where-builder.test.ts +91 -17
  236. package/src/adapters/generic-sql/query/where-builder.ts +90 -38
  237. package/src/adapters/{kysely/kysely-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-migrations.test.ts} +6 -6
  238. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +806 -0
  239. package/src/adapters/{drizzle/drizzle-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-queries.test.ts} +11 -11
  240. package/src/adapters/generic-sql/{test/generic-drizzle-adapter-sqlite3.test.ts → sql-adapter-sqlite3-driver.test.ts} +49 -35
  241. package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +48 -32
  242. package/src/adapters/{kysely/kysely-adapter-sqlocal.test.ts → generic-sql/sql-adapter-sqlocal.test.ts} +6 -6
  243. package/src/adapters/generic-sql/sqlite-storage.ts +20 -0
  244. package/src/adapters/generic-sql/uow-decoder.test.ts +1 -1
  245. package/src/adapters/generic-sql/uow-decoder.ts +21 -3
  246. package/src/adapters/generic-sql/uow-encoder.test.ts +33 -2
  247. package/src/adapters/generic-sql/uow-encoder.ts +50 -11
  248. package/src/adapters/in-memory/condition-evaluator.test.ts +193 -0
  249. package/src/adapters/in-memory/condition-evaluator.ts +275 -0
  250. package/src/adapters/in-memory/errors.ts +20 -0
  251. package/src/adapters/in-memory/in-memory-adapter.ts +277 -0
  252. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +296 -0
  253. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +100 -0
  254. package/src/adapters/in-memory/in-memory-uow.ts +1348 -0
  255. package/src/adapters/in-memory/index.ts +3 -0
  256. package/src/adapters/in-memory/options.test.ts +41 -0
  257. package/src/adapters/in-memory/options.ts +87 -0
  258. package/src/adapters/in-memory/reference-resolution.test.ts +50 -0
  259. package/src/adapters/in-memory/reference-resolution.ts +67 -0
  260. package/src/adapters/in-memory/sorted-array-index.test.ts +123 -0
  261. package/src/adapters/in-memory/sorted-array-index.ts +228 -0
  262. package/src/adapters/in-memory/store.test.ts +68 -0
  263. package/src/adapters/in-memory/store.ts +145 -0
  264. package/src/adapters/in-memory/value-comparison.ts +53 -0
  265. package/src/adapters/in-memory/value-normalization.test.ts +57 -0
  266. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +1163 -0
  267. package/src/adapters/shared/from-unit-of-work-compiler.ts +3 -1
  268. package/src/adapters/shared/uow-operation-compiler.ts +26 -16
  269. package/src/adapters/sql/index.ts +12 -0
  270. package/src/db-fragment-definition-builder.test.ts +88 -54
  271. package/src/db-fragment-definition-builder.ts +201 -322
  272. package/src/db-fragment-instantiator.test.ts +169 -101
  273. package/src/db-fragment-integration.test.ts +301 -149
  274. package/src/dispatchers/cloudflare-do/index.test.ts +73 -0
  275. package/src/dispatchers/cloudflare-do/index.ts +104 -0
  276. package/src/dispatchers/node/index.test.ts +91 -0
  277. package/src/dispatchers/node/index.ts +87 -0
  278. package/src/fragments/internal-fragment.routes.ts +42 -0
  279. package/src/fragments/internal-fragment.schema.ts +51 -0
  280. package/src/fragments/internal-fragment.test.ts +730 -274
  281. package/src/fragments/internal-fragment.ts +447 -154
  282. package/src/hooks/durable-hooks-processor.test.ts +117 -0
  283. package/src/hooks/durable-hooks-processor.ts +67 -0
  284. package/src/hooks/hooks.test.ts +411 -259
  285. package/src/hooks/hooks.ts +265 -66
  286. package/src/migration-engine/auto-from-schema.test.ts +14 -14
  287. package/src/migration-engine/auto-from-schema.ts +5 -2
  288. package/src/migration-engine/create.test.ts +2 -2
  289. package/src/migration-engine/generation-engine.test.ts +229 -104
  290. package/src/migration-engine/generation-engine.ts +94 -64
  291. package/src/migration-engine/shared.ts +1 -0
  292. package/src/mod.ts +78 -30
  293. package/src/naming/sql-naming.ts +180 -0
  294. package/src/outbox/outbox-builder.ts +241 -0
  295. package/src/outbox/outbox.test.ts +253 -0
  296. package/src/outbox/outbox.ts +137 -0
  297. package/src/query/column-defaults.ts +41 -3
  298. package/src/query/condition-builder.test.ts +3 -3
  299. package/src/query/cursor.test.ts +116 -18
  300. package/src/query/cursor.ts +75 -26
  301. package/src/query/db-now.ts +6 -0
  302. package/src/query/query-type.test.ts +2 -2
  303. package/src/query/serialize/create-sql-serializer.ts +7 -2
  304. package/src/query/serialize/dialect/mysql-serializer.ts +12 -4
  305. package/src/query/serialize/dialect/postgres-serializer.ts +34 -4
  306. package/src/query/serialize/dialect/sqlite-serializer.test.ts +51 -1
  307. package/src/query/serialize/dialect/sqlite-serializer.ts +92 -9
  308. package/src/query/serialize/sql-serializer.ts +4 -4
  309. package/src/query/simple-query-interface.ts +5 -0
  310. package/src/query/unit-of-work/execute-unit-of-work.test.ts +1512 -1458
  311. package/src/query/unit-of-work/execute-unit-of-work.ts +1708 -596
  312. package/src/query/unit-of-work/tx-builder.test.ts +1041 -0
  313. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +32 -32
  314. package/src/query/unit-of-work/unit-of-work-types.test.ts +1 -1
  315. package/src/query/unit-of-work/unit-of-work.test.ts +231 -36
  316. package/src/query/unit-of-work/unit-of-work.ts +229 -31
  317. package/src/query/value-decoding.test.ts +13 -2
  318. package/src/query/value-decoding.ts +17 -4
  319. package/src/query/value-encoding.test.ts +85 -2
  320. package/src/query/value-encoding.ts +56 -6
  321. package/src/schema/create.test.ts +129 -42
  322. package/src/schema/create.ts +187 -47
  323. package/src/schema/generate-id.test.ts +57 -0
  324. package/src/schema/generate-id.ts +38 -0
  325. package/src/schema/serialize.test.ts +14 -2
  326. package/src/schema/type-conversion/create-sql-type-mapper.ts +7 -2
  327. package/src/schema/type-conversion/dialect/sqlite.ts +18 -0
  328. package/src/schema/type-conversion/type-mapping.test.ts +25 -1
  329. package/src/schema/validator.test.ts +197 -0
  330. package/src/schema/validator.ts +231 -0
  331. package/src/{adapters/drizzle/generate.test.ts → schema-output/drizzle.test.ts} +179 -129
  332. package/src/{adapters/drizzle/generate.ts → schema-output/drizzle.ts} +143 -93
  333. package/src/schema-output/prisma.test.ts +536 -0
  334. package/src/schema-output/prisma.ts +573 -0
  335. package/src/util/default-database-adapter.ts +106 -0
  336. package/src/with-database.ts +22 -3
  337. package/tsdown.config.ts +6 -4
  338. package/dist/adapters/drizzle/drizzle-adapter.d.ts +0 -20
  339. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +0 -1
  340. package/dist/adapters/drizzle/drizzle-adapter.js +0 -27
  341. package/dist/adapters/drizzle/drizzle-adapter.js.map +0 -1
  342. package/dist/adapters/drizzle/generate.d.ts +0 -30
  343. package/dist/adapters/drizzle/generate.d.ts.map +0 -1
  344. package/dist/adapters/drizzle/generate.js.map +0 -1
  345. package/dist/adapters/kysely/kysely-adapter.d.ts +0 -19
  346. package/dist/adapters/kysely/kysely-adapter.d.ts.map +0 -1
  347. package/dist/adapters/kysely/kysely-adapter.js +0 -17
  348. package/dist/adapters/kysely/kysely-adapter.js.map +0 -1
  349. package/dist/adapters/shared/table-name-mapper.d.ts +0 -12
  350. package/dist/adapters/shared/table-name-mapper.d.ts.map +0 -1
  351. package/dist/adapters/shared/table-name-mapper.js +0 -43
  352. package/dist/adapters/shared/table-name-mapper.js.map +0 -1
  353. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +0 -1
  354. package/dist/schema-generator/schema-generator.d.ts +0 -15
  355. package/dist/schema-generator/schema-generator.d.ts.map +0 -1
  356. package/src/adapters/drizzle/drizzle-adapter.ts +0 -39
  357. package/src/adapters/kysely/kysely-adapter.ts +0 -27
  358. package/src/adapters/shared/table-name-mapper.ts +0 -50
  359. package/src/schema-generator/schema-generator.ts +0 -12
  360. package/src/shared/config.ts +0 -10
  361. package/src/shared/connection-pool.ts +0 -24
  362. package/src/shared/prisma.ts +0 -45
@@ -0,0 +1,59 @@
1
+ //#region src/dispatchers/node/index.ts
2
+ function createDurableHooksDispatcher(options) {
3
+ const pollIntervalMs = options.pollIntervalMs ?? 5e3;
4
+ const onError = options.onError ?? ((error) => {
5
+ console.error("Durable hooks dispatcher error", error);
6
+ });
7
+ let timer;
8
+ let processing = false;
9
+ let queued = false;
10
+ let currentPromise;
11
+ const runProcess = () => {
12
+ if (processing) {
13
+ queued = true;
14
+ return currentPromise ?? Promise.resolve();
15
+ }
16
+ processing = true;
17
+ currentPromise = (async () => {
18
+ do {
19
+ queued = false;
20
+ try {
21
+ await options.processor.process();
22
+ } catch (error) {
23
+ onError(error);
24
+ }
25
+ } while (queued);
26
+ processing = false;
27
+ })();
28
+ return currentPromise;
29
+ };
30
+ const poll = async () => {
31
+ try {
32
+ const nextWakeAt = await options.processor.getNextWakeAt();
33
+ if (!nextWakeAt) return;
34
+ if (Date.now() >= nextWakeAt.getTime()) await runProcess();
35
+ } catch (error) {
36
+ onError(error);
37
+ }
38
+ };
39
+ return {
40
+ wake: async () => {
41
+ await runProcess();
42
+ },
43
+ startPolling: () => {
44
+ if (timer) return;
45
+ timer = setInterval(() => {
46
+ poll();
47
+ }, pollIntervalMs);
48
+ },
49
+ stopPolling: () => {
50
+ if (!timer) return;
51
+ clearInterval(timer);
52
+ timer = void 0;
53
+ }
54
+ };
55
+ }
56
+
57
+ //#endregion
58
+ export { createDurableHooksDispatcher };
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["timer: ReturnType<typeof setInterval> | undefined","currentPromise: Promise<void> | undefined"],"sources":["../../../src/dispatchers/node/index.ts"],"sourcesContent":["import type { DurableHooksProcessor } from \"../../hooks/durable-hooks-processor\";\n\nexport type DurableHooksDispatcher = {\n wake: () => Promise<void>;\n startPolling: () => void;\n stopPolling: () => void;\n};\n\nexport type DurableHooksDispatcherOptions = {\n processor: DurableHooksProcessor;\n pollIntervalMs?: number;\n onError?: (error: unknown) => void;\n};\n\nexport function createDurableHooksDispatcher(\n options: DurableHooksDispatcherOptions,\n): DurableHooksDispatcher {\n const pollIntervalMs = options.pollIntervalMs ?? 5000;\n const onError =\n options.onError ??\n ((error: unknown) => {\n console.error(\"Durable hooks dispatcher error\", error);\n });\n let timer: ReturnType<typeof setInterval> | undefined;\n let processing = false;\n let queued = false;\n let currentPromise: Promise<void> | undefined;\n\n const runProcess = () => {\n if (processing) {\n queued = true;\n return currentPromise ?? Promise.resolve();\n }\n\n processing = true;\n currentPromise = (async () => {\n do {\n queued = false;\n try {\n await options.processor.process();\n } catch (error) {\n onError(error);\n }\n } while (queued);\n processing = false;\n })();\n\n return currentPromise;\n };\n\n const poll = async () => {\n try {\n const nextWakeAt = await options.processor.getNextWakeAt();\n if (!nextWakeAt) {\n return;\n }\n if (Date.now() >= nextWakeAt.getTime()) {\n await runProcess();\n }\n } catch (error) {\n onError(error);\n }\n };\n\n return {\n wake: async () => {\n await runProcess();\n },\n startPolling: () => {\n if (timer) {\n return;\n }\n\n timer = setInterval(() => {\n void poll();\n }, pollIntervalMs);\n },\n stopPolling: () => {\n if (!timer) {\n return;\n }\n\n clearInterval(timer);\n timer = undefined;\n },\n };\n}\n"],"mappings":";AAcA,SAAgB,6BACd,SACwB;CACxB,MAAM,iBAAiB,QAAQ,kBAAkB;CACjD,MAAM,UACJ,QAAQ,aACN,UAAmB;AACnB,UAAQ,MAAM,kCAAkC,MAAM;;CAE1D,IAAIA;CACJ,IAAI,aAAa;CACjB,IAAI,SAAS;CACb,IAAIC;CAEJ,MAAM,mBAAmB;AACvB,MAAI,YAAY;AACd,YAAS;AACT,UAAO,kBAAkB,QAAQ,SAAS;;AAG5C,eAAa;AACb,oBAAkB,YAAY;AAC5B,MAAG;AACD,aAAS;AACT,QAAI;AACF,WAAM,QAAQ,UAAU,SAAS;aAC1B,OAAO;AACd,aAAQ,MAAM;;YAET;AACT,gBAAa;MACX;AAEJ,SAAO;;CAGT,MAAM,OAAO,YAAY;AACvB,MAAI;GACF,MAAM,aAAa,MAAM,QAAQ,UAAU,eAAe;AAC1D,OAAI,CAAC,WACH;AAEF,OAAI,KAAK,KAAK,IAAI,WAAW,SAAS,CACpC,OAAM,YAAY;WAEb,OAAO;AACd,WAAQ,MAAM;;;AAIlB,QAAO;EACL,MAAM,YAAY;AAChB,SAAM,YAAY;;EAEpB,oBAAoB;AAClB,OAAI,MACF;AAGF,WAAQ,kBAAkB;AACxB,IAAK,MAAM;MACV,eAAe;;EAEpB,mBAAmB;AACjB,OAAI,CAAC,MACH;AAGF,iBAAc,MAAM;AACpB,WAAQ;;EAEX"}
@@ -1,19 +1,42 @@
1
+ import { DbNow } from "../query/db-now.js";
1
2
  import { AnyColumn, AnyRelation, Column, FragnoId, IdColumn, Index, Schema, Table } from "../schema/create.js";
2
3
  import { RetryPolicy } from "../query/unit-of-work/retry-policy.js";
4
+ import { TxResult } from "../query/unit-of-work/execute-unit-of-work.js";
3
5
  import { DatabaseHandlerContext, DatabaseRequestStorage, DatabaseServiceContext, FragnoPublicConfigWithDatabase, ImplicitDatabaseDependencies } from "../db-fragment-definition-builder.js";
6
+ import "../mod.js";
7
+ import { internalSchema } from "./internal-fragment.schema.js";
4
8
  import * as _fragno_dev_core0 from "@fragno-dev/core";
5
9
  import { InstantiatedFragmentFromDefinition } from "@fragno-dev/core";
6
10
 
7
11
  //#region src/fragments/internal-fragment.d.ts
8
- declare const internalFragmentDef: _fragno_dev_core0.FragmentDefinition<{}, FragnoPublicConfigWithDatabase, ImplicitDatabaseDependencies<Schema<Record<"fragno_db_settings", Table<Record<string, AnyColumn> & Record<"id", IdColumn<"varchar(30)", string | FragnoId | null, FragnoId>> & Record<"key", Column<"string", string, string>> & Record<"value", Column<"string", string, string>>, Record<string, AnyRelation>, Record<string, Index<AnyColumn[], readonly string[]>> & Record<"unique_key", Index<readonly [Column<"string", string, string>] & AnyColumn[], readonly ["key"]>>>> & Record<"fragno_hooks", Table<Record<string, AnyColumn> & Record<"id", IdColumn<"varchar(30)", string | FragnoId | null, FragnoId>> & Record<"namespace", Column<"string", string, string>> & Record<"hookName", Column<"string", string, string>> & Record<"payload", Column<"json", unknown, unknown>> & Record<"status", Column<"string", string, string>> & Record<"attempts", Column<"integer", number | null, number>> & Record<"maxAttempts", Column<"integer", number | null, number>> & Record<"lastAttemptAt", Column<"timestamp", Date | null, Date | null>> & Record<"nextRetryAt", Column<"timestamp", Date | null, Date | null>> & Record<"error", Column<"string", string | null, string | null>> & Record<"createdAt", Column<"timestamp", Date | null, Date>> & Record<"nonce", Column<"string", string, string>>, Record<string, AnyRelation>, Record<string, Index<AnyColumn[], readonly string[]>> & Record<"idx_namespace_status_retry", Index<readonly [Column<"string", string, string>, Column<"string", string, string>, Column<"timestamp", Date | null, Date | null>] & AnyColumn[], readonly ["namespace", "status", "nextRetryAt"]>> & Record<"idx_nonce", Index<readonly [Column<"string", string, string>] & AnyColumn[], readonly ["nonce"]>>>>>>, {}, {
12
+ declare const internalFragmentDef: _fragno_dev_core0.FragmentDefinition<{}, FragnoPublicConfigWithDatabase, ImplicitDatabaseDependencies<Schema<Record<"fragno_db_settings", Table<Record<string, AnyColumn> & Record<"id", IdColumn<"varchar(30)", string | FragnoId | null, FragnoId>> & Record<"key", Column<"string", string, string>> & Record<"value", Column<"string", string, string>>, Record<string, AnyRelation>, Record<string, Index<AnyColumn[], readonly string[]>> & Record<"unique_key", Index<readonly [Column<"string", string, string>] & AnyColumn[], readonly ["key"]>>>> & Record<"fragno_hooks", Table<Record<string, AnyColumn> & Record<"id", IdColumn<"varchar(30)", string | FragnoId | null, FragnoId>> & Record<"namespace", Column<"string", string, string>> & Record<"hookName", Column<"string", string, string>> & Record<"payload", Column<"json", unknown, unknown>> & Record<"status", Column<"string", string, string>> & Record<"attempts", Column<"integer", number | null, number>> & Record<"maxAttempts", Column<"integer", number | null, number>> & Record<"lastAttemptAt", Column<"timestamp", (DbNow | Date) | null, Date | null>> & Record<"nextRetryAt", Column<"timestamp", (DbNow | Date) | null, Date | null>> & Record<"error", Column<"string", string | null, string | null>> & Record<"createdAt", Column<"timestamp", (DbNow | Date) | null, Date>> & Record<"nonce", Column<"string", string, string>>, Record<string, AnyRelation>, Record<string, Index<AnyColumn[], readonly string[]>> & Record<"idx_namespace_status_retry", Index<readonly [Column<"string", string, string>, Column<"string", string, string>, Column<"timestamp", (DbNow | Date) | null, Date | null>] & AnyColumn[], readonly ["namespace", "status", "nextRetryAt"]>> & Record<"idx_nonce", Index<readonly [Column<"string", string, string>] & AnyColumn[], readonly ["nonce"]>>>> & Record<"fragno_db_outbox", Table<Record<string, AnyColumn> & Record<"id", IdColumn<"varchar(30)", string | FragnoId | null, FragnoId>> & Record<"versionstamp", Column<"string", string, string>> & Record<"uowId", Column<"string", string, string>> & Record<"payload", Column<"json", unknown, unknown>> & Record<"refMap", Column<"json", unknown, unknown>> & Record<"createdAt", Column<"timestamp", (DbNow | Date) | null, Date>>, Record<string, AnyRelation>, Record<string, Index<AnyColumn[], readonly string[]>> & Record<"idx_outbox_versionstamp", Index<readonly [Column<"string", string, string>] & AnyColumn[], readonly ["versionstamp"]>> & Record<"idx_outbox_uow", Index<readonly [Column<"string", string, string>] & AnyColumn[], readonly ["uowId"]>>>>>>, {
13
+ getDbNow: () => Promise<Date>;
14
+ }, {
9
15
  settingsService: {
10
- get(namespace: string, key: string): Promise<{
16
+ /**
17
+ * Get a setting by namespace and key.
18
+ */
19
+ get(namespace: string, key: string): TxResult<{
20
+ id: FragnoId;
21
+ key: string;
22
+ value: string;
23
+ } | undefined, {
11
24
  id: FragnoId;
12
25
  key: string;
13
26
  value: string;
14
27
  } | undefined>;
15
- set(namespace: string, key: string, value: string): Promise<void>;
16
- delete(id: FragnoId): Promise<void>;
28
+ /**
29
+ * Set a setting value by namespace and key.
30
+ */
31
+ set(namespace: string, key: string, value: string): TxResult<void, {
32
+ id: FragnoId;
33
+ key: string;
34
+ value: string;
35
+ } | null>;
36
+ /**
37
+ * Delete a setting by ID.
38
+ */
39
+ delete(id: FragnoId): TxResult<void, void>;
17
40
  };
18
41
  } & {
19
42
  hookService: {
@@ -21,26 +44,166 @@ declare const internalFragmentDef: _fragno_dev_core0.FragmentDefinition<{}, Frag
21
44
  * Get pending hook events for processing.
22
45
  * Returns all pending events for the given namespace that are ready to be processed.
23
46
  */
24
- getPendingHookEvents(namespace: string): Promise<{
47
+ getPendingHookEvents(namespace: string): TxResult<{
25
48
  id: FragnoId;
26
49
  hookName: string;
27
50
  payload: unknown;
28
51
  attempts: number;
29
52
  maxAttempts: number;
30
- nonce: string;
53
+ idempotencyKey: string;
54
+ }[], {
55
+ id: FragnoId;
56
+ hookName: string;
57
+ payload: unknown;
58
+ attempts: number;
59
+ maxAttempts: number;
60
+ idempotencyKey: string;
31
61
  }[]>;
62
+ /**
63
+ * Claim pending hook events for processing.
64
+ * Returns ready events and marks them as processing in the same transaction.
65
+ */
66
+ claimPendingHookEvents(namespace: string): TxResult<{
67
+ id: FragnoId;
68
+ hookName: string;
69
+ payload: unknown;
70
+ attempts: number;
71
+ maxAttempts: number;
72
+ idempotencyKey: string;
73
+ }[], {
74
+ id: FragnoId;
75
+ hookName: string;
76
+ payload: unknown;
77
+ attempts: number;
78
+ maxAttempts: number;
79
+ idempotencyKey: string;
80
+ }[]>;
81
+ /**
82
+ * Re-queue hook events that have been stuck in processing for too long.
83
+ */
84
+ requeueStuckProcessingHooks(namespace: string, staleBefore: Date): TxResult<{
85
+ id: FragnoId;
86
+ hookName: string;
87
+ attempts: number;
88
+ maxAttempts: number;
89
+ lastAttemptAt: Date | null;
90
+ nextRetryAt: Date | null;
91
+ }[], {
92
+ id: FragnoId;
93
+ hookName: string;
94
+ attempts: number;
95
+ maxAttempts: number;
96
+ lastAttemptAt: Date | null;
97
+ nextRetryAt: Date | null;
98
+ }[]>;
99
+ /**
100
+ * Get the next time a processing hook becomes stale.
101
+ */
102
+ getNextProcessingStaleAt(namespace: string, timeoutMinutes: number, now?: Date): TxResult<Date | null, Date | null>;
103
+ /**
104
+ * Get the earliest pending hook wake time for a namespace.
105
+ * Optionally considers processing hooks becoming stale when timeoutMinutes is provided.
106
+ */
107
+ getNextHookWakeAt(namespace: string, timeoutMinutes?: number | false, now?: Date): TxResult<Date | null, Date | null>;
32
108
  /**
33
109
  * Mark a hook event as completed.
34
110
  */
35
- markHookCompleted(eventId: FragnoId): void;
111
+ markHookCompleted(eventId: FragnoId): TxResult<void, void>;
36
112
  /**
37
113
  * Mark a hook event as failed and schedule next retry.
38
114
  */
39
- markHookFailed(eventId: FragnoId, error: string, attempts: number, retryPolicy: RetryPolicy): void;
115
+ markHookFailed(eventId: FragnoId, error: string, attempts: number, retryPolicy: RetryPolicy, now?: Date): TxResult<void, void>;
40
116
  /**
41
117
  * Mark a hook event as processing (to prevent concurrent execution).
42
118
  */
43
- markHookProcessing(eventId: FragnoId): void;
119
+ markHookProcessing(eventId: FragnoId): TxResult<void, void>;
120
+ /**
121
+ * Get a hook event by ID (for testing/verification purposes).
122
+ */
123
+ getHookById(eventId: FragnoId): TxResult<{
124
+ id: FragnoId;
125
+ namespace: string;
126
+ hookName: string;
127
+ payload: unknown;
128
+ status: string;
129
+ attempts: number;
130
+ maxAttempts: number;
131
+ lastAttemptAt: Date | null;
132
+ nextRetryAt: Date | null;
133
+ error: string | null;
134
+ createdAt: Date;
135
+ nonce: string;
136
+ } | undefined, {
137
+ id: FragnoId;
138
+ namespace: string;
139
+ hookName: string;
140
+ payload: unknown;
141
+ status: string;
142
+ attempts: number;
143
+ maxAttempts: number;
144
+ lastAttemptAt: Date | null;
145
+ nextRetryAt: Date | null;
146
+ error: string | null;
147
+ createdAt: Date;
148
+ nonce: string;
149
+ } | undefined>;
150
+ /**
151
+ * Get all hook events for a namespace (for testing/verification purposes).
152
+ */
153
+ getHooksByNamespace(namespace: string): TxResult<{
154
+ id: FragnoId;
155
+ namespace: string;
156
+ hookName: string;
157
+ payload: unknown;
158
+ status: string;
159
+ attempts: number;
160
+ maxAttempts: number;
161
+ lastAttemptAt: Date | null;
162
+ nextRetryAt: Date | null;
163
+ error: string | null;
164
+ createdAt: Date;
165
+ nonce: string;
166
+ }[], {
167
+ id: FragnoId;
168
+ namespace: string;
169
+ hookName: string;
170
+ payload: unknown;
171
+ status: string;
172
+ attempts: number;
173
+ maxAttempts: number;
174
+ lastAttemptAt: Date | null;
175
+ nextRetryAt: Date | null;
176
+ error: string | null;
177
+ createdAt: Date;
178
+ nonce: string;
179
+ }[]>;
180
+ };
181
+ } & {
182
+ outboxService: {
183
+ /**
184
+ * List outbox entries ordered by versionstamp (ascending).
185
+ */
186
+ list({
187
+ afterVersionstamp,
188
+ limit
189
+ }?: {
190
+ afterVersionstamp?: string;
191
+ limit?: number;
192
+ }): TxResult<{
193
+ id: FragnoId;
194
+ versionstamp: string;
195
+ uowId: string;
196
+ payload: unknown;
197
+ refMap: {} | undefined;
198
+ createdAt: Date;
199
+ }[], {
200
+ id: FragnoId;
201
+ versionstamp: string;
202
+ uowId: string;
203
+ payload: unknown;
204
+ refMap: {} | undefined;
205
+ createdAt: Date;
206
+ }[]>;
44
207
  };
45
208
  }, {}, {}, DatabaseServiceContext<{}>, DatabaseHandlerContext<{}>, DatabaseRequestStorage, {}>;
46
209
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"internal-fragment.d.ts","names":[],"sources":["../../src/fragments/internal-fragment.ts"],"sourcesContent":[],"mappings":";;;;;;;AAoDa,cAAA,mBAuKH,oBAvKsB,kBAuKtB,CAAA,CAAA,CAAA,EAvKsB,8BAuKtB,EAvKsB,4BAuKtB,CAvKsB,MAuKtB,CAvKsB,MAuKtB,CAAA,oBAAA,EAvKsB,KAuKtB,CAvKsB,MAuKtB,CAAA,MAAA,EAvKsB,SAAA,CAuKtB,GAvKsB,MAuKtB,CAAA,IAAA,EAvKsB,QAuKtB,CAAA,aAAA,EAAA,MAAA,GAvKsB,QAuKtB,GAAA,IAAA,EAvKsB,QAuKtB,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,KAAA,EAvKsB,MAuKtB,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,OAAA,EAvKsB,MAuKtB,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,CAAA,EAvKsB,MAuKtB,CAAA,MAAA,EAvKsB,WAAA,CAuKtB,EAvKsB,MAuKtB,CAAA,MAAA,EAvKsB,KAuKtB,CAvKsB,SAAA,EAuKtB,EAAA,SAAA,MAAA,EAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,YAAA,EAvKsB,KAuKtB,CAAA,SAAA,CAvKsB,MAuKtB,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,CAAA,GAvKsB,SAAA,EAuKtB,EAAA,SAAA,CAAA,KAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,cAAA,EAvKsB,KAuKtB,CAvKsB,MAuKtB,CAAA,MAAA,EAvKsB,SAAA,CAuKtB,GAvKsB,MAuKtB,CAAA,IAAA,EAvKsB,QAuKtB,CAAA,aAAA,EAAA,MAAA,GAvKsB,QAuKtB,GAAA,IAAA,EAvKsB,QAuKtB,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,WAAA,EAvKsB,MAuKtB,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,UAAA,EAvKsB,MAuKtB,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,SAAA,EAvKsB,MAuKtB,CAAA,MAAA,EAAA,OAAA,EAAA,OAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,QAAA,EAvKsB,MAuKtB,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,UAAA,EAvKsB,MAuKtB,CAAA,SAAA,EAAA,MAAA,GAAA,IAAA,EAAA,MAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,aAAA,EAvKsB,MAuKtB,CAAA,SAAA,EAAA,MAAA,GAAA,IAAA,EAAA,MAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,eAAA,EAvKsB,MAuKtB,CAAA,WAAA,EAvKsB,IAuKtB,GAAA,IAAA,EAvKsB,IAuKtB,GAAA,IAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,aAAA,EAvKsB,MAuKtB,CAAA,WAAA,EAvKsB,IAuKtB,GAAA,IAAA,EAvKsB,IAuKtB,GAAA,IAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,OAAA,EAvKsB,MAuKtB,CAAA,QAAA,EAAA,MAAA,GAAA,IAAA,EAAA,MAAA,GAAA,IAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,WAAA,EAvKsB,MAuKtB,CAAA,WAAA,EAvKsB,IAuKtB,GAAA,IAAA,EAvKsB,IAuKtB,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,OAAA,EAvKsB,MAuKtB,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,CAAA,EAvKsB,MAuKtB,CAAA,MAAA,EAvKsB,WAAA,CAuKtB,EAvKsB,MAuKtB,CAAA,MAAA,EAvKsB,KAuKtB,CAvKsB,SAAA,EAuKtB,EAAA,SAAA,MAAA,EAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,4BAAA,EAvKsB,KAuKtB,CAAA,SAAA,CAvKsB,MAuKtB,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAvKsB,MAuKtB,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAvKsB,MAuKtB,CAAA,WAAA,EAvKsB,IAuKtB,GAAA,IAAA,EAvKsB,IAuKtB,GAAA,IAAA,CAAA,CAAA,GAvKsB,SAAA,EAuKtB,EAAA,SAAA,CAAA,WAAA,EAAA,QAAA,EAAA,aAAA,CAAA,CAAA,CAAA,GAvKsB,MAuKtB,CAAA,WAAA,EAvKsB,KAuKtB,CAAA,SAAA,CAvKsB,MAuKtB,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,CAAA,GAvKsB,SAAA,EAuKtB,EAAA,SAAA,CAAA,OAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAA,CAAA,CAAA,EAAA;EAvKsB,eAAA,EAAA;IAAA,GAAA,CAAA,SAAA,EAAA,MAAA,EAAA,GAAA,EAAA,MAAA,CAAA,EAqBvB,OArBuB,CAAA;MAAA,EAAA,EAqBT,QArBS;MAAA,GAAA,EAAA,MAAA;MAAA,KAAA,EAAA,MAAA;IAAA,CAAA,GAAA,SAAA,CAAA;IAAA,GAAA,CAAA,SAAA,EAAA,MAAA,EAAA,GAAA,EAAA,MAAA,EAAA,KAAA,EAAA,MAAA,CAAA,EA8B6B,OA9B7B,CAAA,IAAA,CAAA;IAAA,MAAA,CAAA,EAAA,EAqDT,QArDS,CAAA,EAqDD,OArDC,CAAA,IAAA,CAAA;EAAA,CAAA;CAAA,GAAA;EAAA,WAAA,EAAA;IAAA;;;;IAAA,oBAAA,CAAA,SAAA,EAAA,MAAA,CAAA,EAkEqB,OAlErB,CAAA;MAAA,EAAA,EAoElB,QApEkB;MAAA,QAAA,EAAA,MAAA;MAAA,OAAA,EAAA,OAAA;MAAA,QAAA,EAAA,MAAA;MAAA,WAAA,EAAA,MAAA;MAAA,KAAA,EAAA,MAAA;IAAA,CAAA,EAAA,CAAA;IAAA;;;IAAA,iBAAA,CAAA,OAAA,EA2GC,QA3GD,CAAA,EAAA,IAAA;IAAA;;;IAAA,cAAA,CAAA,OAAA,EAsHf,QAtHe,EAAA,KAAA,EAAA,MAAA,EAAA,QAAA,EAAA,MAAA,EAAA,WAAA,EAyHX,WAzHW,CAAA,EAAA,IAAA;IAAA;;;IAAA,kBAAA,CAAA,OAAA,EA+JE,QA/JF,CAAA,EAAA,IAAA;EAAA,CAAA;CAAA,EAAA,CAAA,CAAA,EAAA,CAAA,CAAA,wBAAA,CAAA,CAAA,CAAA,CAAA,wBAAA,CAAA,CAAA,CAAA,CAAA,wBAAA,EAAA,CAAA,CAAA,CAAA;;;;;AAAA,KA6KpB,wBAAA,GAA2B,kCA7KP,CAAA,OA8KvB,mBA9KuB,CAAA"}
1
+ {"version":3,"file":"internal-fragment.d.ts","names":[],"sources":["../../src/fragments/internal-fragment.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1,111 +1,230 @@
1
- import { column, idColumn, schema } from "../schema/create.js";
2
1
  import { FragmentDefinitionBuilder } from "../packages/fragno/dist/api/fragment-definition-builder.js";
2
+ import { FragnoId } from "../schema/create.js";
3
+ import { SETTINGS_NAMESPACE, SETTINGS_TABLE_NAME, internalSchema } from "./internal-fragment.schema.js";
4
+ import { dbNow } from "../query/db-now.js";
3
5
  import { DatabaseFragmentDefinitionBuilder } from "../db-fragment-definition-builder.js";
4
6
 
5
7
  //#region src/fragments/internal-fragment.ts
6
- const SETTINGS_TABLE_NAME = "fragno_db_settings";
7
- const SETTINGS_NAMESPACE = "fragno-db-settings";
8
- const internalSchema = schema((s) => {
9
- return s.addTable(SETTINGS_TABLE_NAME, (t) => {
10
- return t.addColumn("id", idColumn()).addColumn("key", column("string")).addColumn("value", column("string")).createIndex("unique_key", ["key"], { unique: true });
11
- }).addTable("fragno_hooks", (t) => {
12
- return t.addColumn("id", idColumn()).addColumn("namespace", column("string")).addColumn("hookName", column("string")).addColumn("payload", column("json")).addColumn("status", column("string")).addColumn("attempts", column("integer").defaultTo(0)).addColumn("maxAttempts", column("integer").defaultTo(5)).addColumn("lastAttemptAt", column("timestamp").nullable()).addColumn("nextRetryAt", column("timestamp").nullable()).addColumn("error", column("string").nullable()).addColumn("createdAt", column("timestamp").defaultTo((b) => b.now())).addColumn("nonce", column("string")).createIndex("idx_namespace_status_retry", [
13
- "namespace",
14
- "status",
15
- "nextRetryAt"
16
- ]).createIndex("idx_nonce", ["nonce"]);
17
- });
18
- });
19
- const internalFragmentDef = new DatabaseFragmentDefinitionBuilder(new FragmentDefinitionBuilder("$fragno-internal-fragment"), internalSchema, "").providesService("settingsService", ({ defineService }) => {
8
+ const internalFragmentDef = new DatabaseFragmentDefinitionBuilder(new FragmentDefinitionBuilder("$fragno-internal-fragment"), internalSchema).providesBaseService(({ deps }) => ({ getDbNow: async () => {
9
+ if (deps.db.now) return deps.db.now();
10
+ return /* @__PURE__ */ new Date();
11
+ } })).providesService("settingsService", ({ defineService }) => {
20
12
  return defineService({
21
- async get(namespace, key) {
13
+ get(namespace, key) {
22
14
  const fullKey = `${namespace}.${key}`;
23
- const [results] = await this.uow(internalSchema).find(SETTINGS_TABLE_NAME, (b) => b.whereIndex("unique_key", (eb) => eb("key", "=", fullKey))).retrievalPhase;
24
- return results?.[0];
15
+ return this.serviceTx(internalSchema).retrieve((uow) => uow.findFirst(SETTINGS_TABLE_NAME, (b) => b.whereIndex("unique_key", (eb) => eb("key", "=", fullKey)))).transformRetrieve(([result]) => result ?? void 0).build();
25
16
  },
26
- async set(namespace, key, value) {
17
+ set(namespace, key, value) {
27
18
  const fullKey = `${namespace}.${key}`;
28
- const uow = this.uow(internalSchema);
29
- const [existing] = await uow.find(SETTINGS_TABLE_NAME, (b) => b.whereIndex("unique_key", (eb) => eb("key", "=", fullKey))).retrievalPhase;
30
- if (existing?.[0]) uow.update(SETTINGS_TABLE_NAME, existing[0].id, (b) => b.set({ value }).check());
31
- else uow.create(SETTINGS_TABLE_NAME, {
32
- key: fullKey,
33
- value
34
- });
35
- await uow.mutationPhase;
19
+ return this.serviceTx(internalSchema).retrieve((uow) => uow.findFirst(SETTINGS_TABLE_NAME, (b) => b.whereIndex("unique_key", (eb) => eb("key", "=", fullKey)))).transformRetrieve(([result]) => result).mutate(({ uow, retrieveResult }) => {
20
+ if (retrieveResult) uow.update(SETTINGS_TABLE_NAME, retrieveResult.id, (b) => b.set({ value }).check());
21
+ else uow.create(SETTINGS_TABLE_NAME, {
22
+ key: fullKey,
23
+ value
24
+ });
25
+ }).build();
36
26
  },
37
- async delete(id) {
38
- const uow = this.uow(internalSchema);
39
- uow.delete(SETTINGS_TABLE_NAME, id);
40
- await uow.mutationPhase;
27
+ delete(id) {
28
+ return this.serviceTx(internalSchema).mutate(({ uow }) => uow.delete(SETTINGS_TABLE_NAME, id)).build();
41
29
  }
42
30
  });
43
31
  }).providesService("hookService", ({ defineService }) => {
44
32
  return defineService({
45
- async getPendingHookEvents(namespace) {
46
- const [events] = await this.uow(internalSchema).find("fragno_hooks", (b) => b.whereIndex("idx_namespace_status_retry", (eb) => eb.and(eb("namespace", "=", namespace), eb("status", "=", "pending")))).retrievalPhase;
47
- const now = /* @__PURE__ */ new Date();
48
- return events.filter((event) => {
49
- if (!event.nextRetryAt) return true;
50
- return event.nextRetryAt <= now;
51
- }).map((event) => ({
52
- id: event.id,
53
- hookName: event.hookName,
54
- payload: event.payload,
55
- attempts: event.attempts,
56
- maxAttempts: event.maxAttempts,
57
- nonce: event.nonce
58
- }));
33
+ getPendingHookEvents(namespace) {
34
+ const now = dbNow();
35
+ return this.serviceTx(internalSchema).retrieve((uow) => uow.find("fragno_hooks", (b) => b.whereIndex("idx_namespace_status_retry", (eb) => eb.and(eb("namespace", "=", namespace), eb("status", "=", "pending"), eb.or(eb.isNull("nextRetryAt"), eb("nextRetryAt", "<=", now)))))).transformRetrieve(([events]) => {
36
+ return events.map((event) => ({
37
+ id: event.id,
38
+ hookName: event.hookName,
39
+ payload: event.payload,
40
+ attempts: event.attempts,
41
+ maxAttempts: event.maxAttempts,
42
+ idempotencyKey: event.nonce
43
+ }));
44
+ }).build();
45
+ },
46
+ claimPendingHookEvents(namespace) {
47
+ const now = dbNow();
48
+ return this.serviceTx(internalSchema).retrieve((uow) => uow.find("fragno_hooks", (b) => b.whereIndex("idx_namespace_status_retry", (eb) => eb.and(eb("namespace", "=", namespace), eb("status", "=", "pending"), eb.or(eb.isNull("nextRetryAt"), eb("nextRetryAt", "<=", now)))))).transformRetrieve(([events]) => {
49
+ return events.map((event) => ({
50
+ id: event.id,
51
+ hookName: event.hookName,
52
+ payload: event.payload,
53
+ attempts: event.attempts,
54
+ maxAttempts: event.maxAttempts,
55
+ idempotencyKey: event.nonce
56
+ }));
57
+ }).mutate(({ uow, retrieveResult }) => {
58
+ if (retrieveResult.length === 0) return;
59
+ for (const event of retrieveResult) uow.update("fragno_hooks", event.id, (b) => b.set({
60
+ status: "processing",
61
+ lastAttemptAt: now
62
+ }).check());
63
+ }).transform(({ retrieveResult }) => retrieveResult.map((event) => ({
64
+ ...event,
65
+ id: new FragnoId({
66
+ externalId: event.id.externalId,
67
+ internalId: event.id.internalId,
68
+ version: event.id.version + 1
69
+ })
70
+ }))).build();
71
+ },
72
+ requeueStuckProcessingHooks(namespace, staleBefore) {
73
+ return this.serviceTx(internalSchema).retrieve((uow) => uow.find("fragno_hooks", (b) => b.whereIndex("idx_namespace_status_retry", (eb) => eb.and(eb("namespace", "=", namespace), eb("status", "=", "processing"))))).transformRetrieve(([events]) => {
74
+ return events.filter((event) => {
75
+ if (!event.lastAttemptAt) return true;
76
+ return event.lastAttemptAt <= staleBefore;
77
+ }).map((event) => ({
78
+ id: event.id,
79
+ hookName: event.hookName,
80
+ attempts: event.attempts,
81
+ maxAttempts: event.maxAttempts,
82
+ lastAttemptAt: event.lastAttemptAt,
83
+ nextRetryAt: event.nextRetryAt
84
+ }));
85
+ }).mutate(({ uow, retrieveResult }) => {
86
+ for (const event of retrieveResult) uow.update("fragno_hooks", event.id, (b) => b.set({
87
+ status: "pending",
88
+ nextRetryAt: null
89
+ }).check());
90
+ }).transform(({ retrieveResult }) => retrieveResult).build();
91
+ },
92
+ getNextProcessingStaleAt(namespace, timeoutMinutes, now) {
93
+ return this.serviceTx(internalSchema).retrieve((uow) => uow.find("fragno_hooks", (b) => b.whereIndex("idx_namespace_status_retry", (eb) => eb.and(eb("namespace", "=", namespace), eb("status", "=", "processing"))))).transformRetrieve(([events]) => {
94
+ if (events.length === 0) return null;
95
+ const baseNow = now ?? /* @__PURE__ */ new Date();
96
+ const nowMs = baseNow.getTime();
97
+ const timeoutMs = timeoutMinutes * 6e4;
98
+ let earliestStaleAt = null;
99
+ for (const event of events) {
100
+ if (!event.lastAttemptAt) return baseNow;
101
+ const staleAtMs = event.lastAttemptAt.getTime() + timeoutMs;
102
+ if (staleAtMs <= nowMs) return baseNow;
103
+ const staleAt = new Date(staleAtMs);
104
+ if (!earliestStaleAt || staleAt < earliestStaleAt) earliestStaleAt = staleAt;
105
+ }
106
+ return earliestStaleAt;
107
+ }).build();
108
+ },
109
+ getNextHookWakeAt(namespace, timeoutMinutes, now) {
110
+ const baseNow = now ?? /* @__PURE__ */ new Date();
111
+ const includeProcessing = typeof timeoutMinutes === "number" && timeoutMinutes > 0;
112
+ const timeoutMs = includeProcessing ? timeoutMinutes * 6e4 : 0;
113
+ return this.serviceTx(internalSchema).retrieve((uow) => uow.find("fragno_hooks", (b) => b.whereIndex("idx_namespace_status_retry", (eb) => {
114
+ if (includeProcessing) return eb.and(eb("namespace", "=", namespace), eb.or(eb("status", "=", "pending"), eb("status", "=", "processing")));
115
+ return eb.and(eb("namespace", "=", namespace), eb("status", "=", "pending"));
116
+ }).select([
117
+ "status",
118
+ "nextRetryAt",
119
+ "lastAttemptAt"
120
+ ]))).transformRetrieve(([events]) => {
121
+ if (events.length === 0) return null;
122
+ const nowMs = baseNow.getTime();
123
+ let earliestPendingAt = null;
124
+ let earliestStaleAt = null;
125
+ for (const event of events) {
126
+ if (event.status === "pending") {
127
+ const nextRetryAt = event.nextRetryAt;
128
+ if (!nextRetryAt || nextRetryAt.getTime() <= nowMs) return baseNow;
129
+ if (!earliestPendingAt || nextRetryAt < earliestPendingAt) earliestPendingAt = nextRetryAt;
130
+ continue;
131
+ }
132
+ if (!includeProcessing || event.status !== "processing") continue;
133
+ const lastAttemptAt = event.lastAttemptAt;
134
+ if (!lastAttemptAt) return baseNow;
135
+ const staleAtMs = lastAttemptAt.getTime() + timeoutMs;
136
+ if (staleAtMs <= nowMs) return baseNow;
137
+ const staleAt = new Date(staleAtMs);
138
+ if (!earliestStaleAt || staleAt < earliestStaleAt) earliestStaleAt = staleAt;
139
+ }
140
+ if (!earliestPendingAt) return earliestStaleAt ?? null;
141
+ if (!earliestStaleAt) return earliestPendingAt;
142
+ return earliestPendingAt <= earliestStaleAt ? earliestPendingAt : earliestStaleAt;
143
+ }).build();
59
144
  },
60
145
  markHookCompleted(eventId) {
61
- this.uow(internalSchema).update("fragno_hooks", eventId, (b) => b.set({
146
+ return this.serviceTx(internalSchema).mutate(({ uow }) => uow.update("fragno_hooks", eventId, (b) => b.set({
62
147
  status: "completed",
63
- lastAttemptAt: /* @__PURE__ */ new Date()
64
- }).check());
148
+ lastAttemptAt: dbNow()
149
+ }).check())).build();
65
150
  },
66
- markHookFailed(eventId, error, attempts, retryPolicy) {
67
- const uow = this.uow(internalSchema);
151
+ markHookFailed(eventId, error, attempts, retryPolicy, now) {
68
152
  const newAttempts = attempts + 1;
69
- if (retryPolicy.shouldRetry(newAttempts - 1)) {
70
- const delayMs = retryPolicy.getDelayMs(newAttempts - 1);
71
- const nextRetryAt = new Date(Date.now() + delayMs);
72
- uow.update("fragno_hooks", eventId, (b) => b.set({
73
- status: "pending",
153
+ const shouldRetry = retryPolicy.shouldRetry(newAttempts - 1);
154
+ return this.serviceTx(internalSchema).mutate(({ uow }) => {
155
+ if (shouldRetry) {
156
+ const delayMs = retryPolicy.getDelayMs(newAttempts - 1);
157
+ const baseNow = now ?? /* @__PURE__ */ new Date();
158
+ const nextRetryAt = new Date(baseNow.getTime() + delayMs);
159
+ uow.update("fragno_hooks", eventId, (b) => b.set({
160
+ status: "pending",
161
+ attempts: newAttempts,
162
+ lastAttemptAt: dbNow(),
163
+ nextRetryAt,
164
+ error
165
+ }).check());
166
+ } else uow.update("fragno_hooks", eventId, (b) => b.set({
167
+ status: "failed",
74
168
  attempts: newAttempts,
75
- lastAttemptAt: /* @__PURE__ */ new Date(),
76
- nextRetryAt,
169
+ lastAttemptAt: dbNow(),
77
170
  error
78
171
  }).check());
79
- } else uow.update("fragno_hooks", eventId, (b) => b.set({
80
- status: "failed",
81
- attempts: newAttempts,
82
- lastAttemptAt: /* @__PURE__ */ new Date(),
83
- error
84
- }).check());
172
+ }).build();
85
173
  },
86
174
  markHookProcessing(eventId) {
87
- this.uow(internalSchema).update("fragno_hooks", eventId, (b) => b.set({
175
+ return this.serviceTx(internalSchema).mutate(({ uow }) => uow.update("fragno_hooks", eventId, (b) => b.set({
88
176
  status: "processing",
89
- lastAttemptAt: /* @__PURE__ */ new Date()
90
- }).check());
177
+ lastAttemptAt: dbNow()
178
+ }).check())).build();
179
+ },
180
+ getHookById(eventId) {
181
+ return this.serviceTx(internalSchema).retrieve((uow) => uow.findFirst("fragno_hooks", (b) => b.whereIndex("primary", (eb) => eb("id", "=", eventId)))).transformRetrieve(([result]) => result ?? void 0).build();
182
+ },
183
+ getHooksByNamespace(namespace) {
184
+ return this.serviceTx(internalSchema).retrieve((uow) => uow.find("fragno_hooks", (b) => b.whereIndex("idx_namespace_status_retry", (eb) => eb("namespace", "=", namespace)))).transformRetrieve(([events]) => events).build();
91
185
  }
92
186
  });
187
+ }).providesService("outboxService", ({ defineService }) => {
188
+ return defineService({ list({ afterVersionstamp, limit } = {}) {
189
+ const afterValue = afterVersionstamp?.toLowerCase();
190
+ return this.serviceTx(internalSchema).retrieve((uow) => uow.find("fragno_db_outbox", (b) => {
191
+ let builder = afterValue ? b.whereIndex("idx_outbox_versionstamp", (eb) => eb("versionstamp", ">", afterValue)) : b.whereIndex("idx_outbox_versionstamp");
192
+ builder = builder.orderByIndex("idx_outbox_versionstamp", "asc");
193
+ if (limit !== void 0) builder = builder.pageSize(limit);
194
+ return builder;
195
+ })).transformRetrieve(([entries]) => entries.map((entry) => ({
196
+ id: entry.id,
197
+ versionstamp: entry.versionstamp,
198
+ uowId: entry.uowId,
199
+ payload: entry.payload,
200
+ refMap: entry.refMap ?? void 0,
201
+ createdAt: entry.createdAt
202
+ }))).build();
203
+ } });
93
204
  }).build();
94
205
  async function getSchemaVersionFromDatabase(fragment, namespace) {
95
206
  try {
96
- return await fragment.inContext(async function() {
97
- const version = await this.uow(async ({ executeRetrieve }) => {
98
- const version$1 = fragment.services.settingsService.get(namespace, "schema_version");
99
- await executeRetrieve();
100
- return version$1;
207
+ const readSchemaVersion = async (targetNamespace) => {
208
+ const setting = await fragment.inContext(async function() {
209
+ return await this.handlerTx().withServiceCalls(() => [fragment.services.settingsService.get(targetNamespace, "schema_version")]).transform(({ serviceResult: [result] }) => result).execute();
101
210
  });
102
- return version ? parseInt(version.value, 10) : 0;
103
- });
211
+ if (!setting) return;
212
+ const parsed = parseInt(setting.value, 10);
213
+ return Number.isNaN(parsed) ? void 0 : parsed;
214
+ };
215
+ const primary = await readSchemaVersion(namespace);
216
+ if (primary !== void 0) return primary;
217
+ const legacyNamespace = namespace === "" ? internalSchema.name : namespace === internalSchema.name ? "" : null;
218
+ if (legacyNamespace !== null) {
219
+ const legacy = await readSchemaVersion(legacyNamespace);
220
+ if (legacy !== void 0) return legacy;
221
+ }
222
+ return 0;
104
223
  } catch {
105
224
  return 0;
106
225
  }
107
226
  }
108
227
 
109
228
  //#endregion
110
- export { SETTINGS_NAMESPACE, SETTINGS_TABLE_NAME, getSchemaVersionFromDatabase, internalFragmentDef, internalSchema };
229
+ export { getSchemaVersionFromDatabase, internalFragmentDef };
111
230
  //# sourceMappingURL=internal-fragment.js.map