@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
@@ -1,3 +1,6 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
1
4
  import { describe, it, expect, vi, assert } from "vitest";
2
5
  import { instantiate, defineFragment } from "@fragno-dev/core";
3
6
  import { defineRoutes } from "@fragno-dev/core/route";
@@ -7,14 +10,22 @@ import type { DatabaseAdapter } from "./adapters/adapters";
7
10
  import type { SimpleQueryInterface } from "./query/simple-query-interface";
8
11
  import { RequestContextStorage } from "@fragno-dev/core/internal/request-context-storage";
9
12
  import { z } from "zod";
13
+ import { suffixNamingStrategy } from "./naming/sql-naming";
10
14
 
11
15
  // Create a test schema
12
- const testSchema = schema((s) => {
16
+ const testSchema = schema("test", (s) => {
13
17
  return s.addTable("users", (t) => {
14
18
  return t.addColumn("id", idColumn()).addColumn("name", column("string"));
15
19
  });
16
20
  });
17
21
 
22
+ // Schema with dashes in the name (used to test namespace sanitization)
23
+ const dashedSchema = schema("my-fragment", (s) => {
24
+ return s.addTable("items", (t) => {
25
+ return t.addColumn("id", idColumn()).addColumn("label", column("string"));
26
+ });
27
+ });
28
+
18
29
  type TestSchema = typeof testSchema;
19
30
 
20
31
  // Mock database adapter
@@ -29,11 +40,21 @@ function createMockAdapter(): DatabaseAdapter {
29
40
  findMany: vi.fn(),
30
41
  })),
31
42
  restrict: vi.fn(() => createMockRestrictedUow()),
43
+ signalReadyForRetrieval: vi.fn(),
44
+ signalReadyForMutation: vi.fn(),
45
+ retrievalPhase: Promise.resolve([]),
46
+ mutationPhase: Promise.resolve(),
32
47
  })),
33
48
  restrict: vi.fn(() => createMockRestrictedUow()),
49
+ getRetrievalOperations: vi.fn(() => []),
50
+ getMutationOperations: vi.fn(() => []),
34
51
  table: vi.fn(() => ({
35
52
  findMany: vi.fn(),
36
53
  })),
54
+ signalReadyForRetrieval: vi.fn(),
55
+ signalReadyForMutation: vi.fn(),
56
+ retrievalPhase: Promise.resolve([]),
57
+ mutationPhase: Promise.resolve(),
37
58
  });
38
59
 
39
60
  return {
@@ -43,16 +64,26 @@ function createMockAdapter(): DatabaseAdapter {
43
64
  findMany: vi.fn(),
44
65
  })),
45
66
  restrict: vi.fn(() => createMockRestrictedUow()),
67
+ signalReadyForRetrieval: vi.fn(),
68
+ signalReadyForMutation: vi.fn(),
69
+ retrievalPhase: Promise.resolve([]),
70
+ mutationPhase: Promise.resolve(),
46
71
  })),
47
72
  restrict: vi.fn(() => createMockRestrictedUow()),
48
- executeRetrieve: vi.fn(),
49
- executeMutations: vi.fn(),
73
+ executeRetrieve: vi.fn(async () => {}),
74
+ executeMutations: vi.fn(async () => ({ success: true })),
50
75
  commit: vi.fn(),
51
76
  rollback: vi.fn(),
77
+ registerSchema: vi.fn(),
52
78
  reset: vi.fn(),
79
+ getRetrievalOperations: vi.fn(() => []),
80
+ getMutationOperations: vi.fn(() => []),
81
+ getCreatedIds: vi.fn(() => []),
53
82
  table: vi.fn(() => ({
54
83
  findMany: vi.fn(),
55
84
  })),
85
+ idempotencyKey: "test-nonce",
86
+ state: "building-retrieval",
56
87
  };
57
88
  }),
58
89
  type: "mock",
@@ -60,16 +91,17 @@ function createMockAdapter(): DatabaseAdapter {
60
91
 
61
92
  return {
62
93
  createQueryEngine: vi.fn(() => mockdb),
63
- migrate: vi.fn(),
94
+ getSchemaVersion: vi.fn(async () => undefined),
64
95
  close: vi.fn(),
65
96
  type: "mock",
66
97
  contextStorage: new RequestContextStorage(),
98
+ namingStrategy: suffixNamingStrategy,
67
99
  } as unknown as DatabaseAdapter;
68
100
  }
69
101
 
70
102
  describe("db-fragment-instantiator", () => {
71
103
  describe("Unit of Work in request context", () => {
72
- it("should provide executeRestrictedUnitOfWork on this context in route handlers", async () => {
104
+ it("should provide handlerTx on this context in route handlers", async () => {
73
105
  const definition = defineFragment("test-db-fragment")
74
106
  .extend(withDatabase(testSchema))
75
107
  .build();
@@ -79,10 +111,10 @@ describe("db-fragment-instantiator", () => {
79
111
  method: "GET",
80
112
  path: "/test",
81
113
  handler: async function (_input, { json }) {
82
- // Access executeRestrictedUnitOfWork from this context
83
- expect(this.uow).toBeDefined();
114
+ // Access handlerTx from this context
115
+ expect(this.handlerTx).toBeDefined();
84
116
 
85
- return json({ hasExecuteMethod: !!this.uow });
117
+ return json({ hasHandlerTxBuilder: !!this.handlerTx });
86
118
  },
87
119
  }),
88
120
  ]);
@@ -96,10 +128,10 @@ describe("db-fragment-instantiator", () => {
96
128
  const response = await fragment.handler(new Request("http://localhost/api/test"));
97
129
  const data = await response.json();
98
130
 
99
- expect(data).toEqual({ hasExecuteMethod: true });
131
+ expect(data).toEqual({ hasHandlerTxBuilder: true });
100
132
  });
101
133
 
102
- it("should provide schema-typed UOW via executeRestrictedUnitOfWork", async () => {
134
+ it("should provide schema-typed UOW via handlerTx", async () => {
103
135
  const definition = defineFragment("test-db-fragment")
104
136
  .extend(withDatabase(testSchema))
105
137
  .build();
@@ -109,10 +141,12 @@ describe("db-fragment-instantiator", () => {
109
141
  method: "GET",
110
142
  path: "/test",
111
143
  handler: async function (_input, { json }) {
112
- const result = await this.uow(async ({ forSchema }) => {
113
- const uow = forSchema(testSchema);
114
- return { hasSchemaUow: !!uow };
115
- });
144
+ const result = await this.handlerTx()
145
+ .mutate(({ forSchema }) => {
146
+ const uow = forSchema(testSchema);
147
+ return { hasSchemaUow: !!uow };
148
+ })
149
+ .execute();
116
150
 
117
151
  return json(result);
118
152
  },
@@ -189,8 +223,8 @@ describe("db-fragment-instantiator", () => {
189
223
  });
190
224
 
191
225
  describe("database operations with UOW", () => {
192
- it("should allow accessing schema-typed UOW in handlers via executeRestrictedUnitOfWork", async () => {
193
- const testSchemaWithCounter = schema((s) => {
226
+ it("should allow accessing schema-typed UOW in handlers via handlerTx", async () => {
227
+ const testSchemaWithCounter = schema("testschemawithcounter", (s) => {
194
228
  return s.addTable("counters", (t) => {
195
229
  return t.addColumn("id", idColumn()).addColumn("value", column("integer"));
196
230
  });
@@ -205,11 +239,13 @@ describe("db-fragment-instantiator", () => {
205
239
  method: "GET",
206
240
  path: "/counters",
207
241
  handler: async function (_input, { json }) {
208
- const result = await this.uow(async ({ forSchema }) => {
209
- const uow = forSchema(testSchemaWithCounter);
210
- // Verify that we can access the UOW
211
- return { hasCountersTable: !!uow };
212
- });
242
+ const result = await this.handlerTx()
243
+ .mutate(({ forSchema }) => {
244
+ const uow = forSchema(testSchemaWithCounter);
245
+ // Verify that we can access the UOW
246
+ return { hasCountersTable: !!uow };
247
+ })
248
+ .execute();
213
249
 
214
250
  return json(result);
215
251
  },
@@ -230,14 +266,15 @@ describe("db-fragment-instantiator", () => {
230
266
  });
231
267
 
232
268
  describe("service integration with UOW", () => {
233
- it("should allow services to access UOW via forSchema", async () => {
269
+ it("should allow services to access UOW via serviceTx", async () => {
234
270
  const definition = defineFragment("test-db-fragment")
235
271
  .extend(withDatabase(testSchema))
236
272
  .providesBaseService(({ defineService }) =>
237
273
  defineService({
238
274
  checkTypedUowExists: function () {
239
- const uow = this.uow(testSchema);
240
- return !!uow;
275
+ return this.serviceTx(testSchema)
276
+ .mutate(({ uow }) => !!uow)
277
+ .build();
241
278
  },
242
279
  }),
243
280
  )
@@ -249,7 +286,10 @@ describe("db-fragment-instantiator", () => {
249
286
  path: "/check",
250
287
  outputSchema: z.object({ hasTypedUow: z.boolean() }),
251
288
  handler: async function (_input, { json }) {
252
- const hasTypedUow = services.checkTypedUowExists();
289
+ const hasTypedUow = await this.handlerTx()
290
+ .withServiceCalls(() => [services.checkTypedUowExists()] as const)
291
+ .transform(({ serviceResult: [result] }) => result)
292
+ .execute();
253
293
  return json({ hasTypedUow });
254
294
  },
255
295
  }),
@@ -266,73 +306,18 @@ describe("db-fragment-instantiator", () => {
266
306
  assert(response.type === "json");
267
307
  expect(response.data).toEqual({ hasTypedUow: true });
268
308
  });
269
-
270
- it.skip("should share same UOW across multiple service calls from handler", async () => {
271
- const definition = defineFragment("test-db-fragment")
272
- .extend(withDatabase(testSchema))
273
- .providesService("helpers", ({ defineService }) =>
274
- defineService({
275
- logUow: function () {
276
- return this.uow(testSchema);
277
- },
278
- }),
279
- )
280
- .providesService("main", ({ defineService }) =>
281
- defineService({
282
- markUow: function () {
283
- return this.uow(testSchema);
284
- },
285
- }),
286
- )
287
- .build();
288
-
289
- const routes = defineRoutes(definition).create(({ services, defineRoute }) => [
290
- defineRoute({
291
- method: "GET",
292
- path: "/nested",
293
- handler: async function (_input, { json }) {
294
- // Mark the UOW with an ID
295
- const uow1 = services.main.markUow();
296
- const uow2 = services.helpers.logUow();
297
- const uow3 = services.main.markUow();
298
-
299
- console.log({
300
- x: uow1 === uow2,
301
- y: uow2 === uow3,
302
- z: uow1 === uow3,
303
- });
304
-
305
- return json({
306
- same: uow1 === uow2 && uow2 === uow3,
307
- });
308
- },
309
- }),
310
- ]);
311
-
312
- const mockAdapter = createMockAdapter();
313
- const fragment = instantiate(definition)
314
- .withRoutes([routes])
315
- .withOptions({ mountRoute: "/api", databaseAdapter: mockAdapter })
316
- .build();
317
-
318
- const response = await fragment.handler(new Request("http://localhost/api/nested"));
319
- const data = await response.json();
320
-
321
- expect(data).toEqual({
322
- same: true,
323
- });
324
- });
325
309
  });
326
310
 
327
311
  describe("inContext with database fragments", () => {
328
- it("should allow calling services with UOW via inContext", () => {
312
+ it("should allow calling services with UOW via inContext", async () => {
329
313
  const definition = defineFragment("test-db-fragment")
330
314
  .extend(withDatabase(testSchema))
331
315
  .providesBaseService(({ defineService }) =>
332
316
  defineService({
333
317
  getUowExists: function () {
334
- const uow = this.uow(testSchema);
335
- return !!uow;
318
+ return this.serviceTx(testSchema)
319
+ .mutate(({ uow }) => !!uow)
320
+ .build();
336
321
  },
337
322
  }),
338
323
  )
@@ -343,7 +328,12 @@ describe("db-fragment-instantiator", () => {
343
328
  .withOptions({ databaseAdapter: mockAdapter })
344
329
  .build();
345
330
 
346
- const result = fragment.inContext(() => fragment.services.getUowExists());
331
+ const result = await fragment.inContext(async function () {
332
+ return await this.handlerTx()
333
+ .withServiceCalls(() => [fragment.services.getUowExists()] as const)
334
+ .transform(({ serviceResult: [exists] }) => exists)
335
+ .execute();
336
+ });
347
337
  expect(result).toBe(true);
348
338
  });
349
339
  });
@@ -370,10 +360,12 @@ describe("db-fragment-instantiator", () => {
370
360
  method: "GET",
371
361
  path: "/test",
372
362
  handler: async function (_input, { json }) {
373
- const result = await this.uow(async ({ forSchema }) => {
374
- const uow = forSchema(testSchema);
375
- return { hasUow: !!uow };
376
- });
363
+ const result = await this.handlerTx()
364
+ .mutate(({ forSchema }) => {
365
+ const uow = forSchema(testSchema);
366
+ return { hasUow: !!uow };
367
+ })
368
+ .execute();
377
369
  return json(result);
378
370
  },
379
371
  }),
@@ -473,7 +465,73 @@ describe("db-fragment-instantiator", () => {
473
465
  .build();
474
466
 
475
467
  expect(fragment.$internal.deps.schema).toBe(testSchema);
476
- expect(fragment.$internal.deps.namespace).toBe("test-db-fragment");
468
+ expect(fragment.$internal.deps.namespace).toBe("test");
469
+ });
470
+
471
+ it("should use databaseNamespace override when provided", () => {
472
+ const definition = defineFragment("test-db-fragment")
473
+ .extend(withDatabase(testSchema))
474
+ .build();
475
+
476
+ const mockAdapter = createMockAdapter();
477
+ const fragment = instantiate(definition)
478
+ .withOptions({
479
+ mountRoute: "/api",
480
+ databaseAdapter: mockAdapter,
481
+ databaseNamespace: "custom-namespace",
482
+ })
483
+ .build();
484
+
485
+ expect(fragment.$internal.deps.namespace).toBe("custom-namespace");
486
+ });
487
+
488
+ it("should allow explicit null namespace override", () => {
489
+ const definition = defineFragment("test-db-fragment")
490
+ .extend(withDatabase(testSchema))
491
+ .build();
492
+
493
+ const mockAdapter = createMockAdapter();
494
+ const fragment = instantiate(definition)
495
+ .withOptions({
496
+ mountRoute: "/api",
497
+ databaseAdapter: mockAdapter,
498
+ databaseNamespace: null,
499
+ })
500
+ .build();
501
+
502
+ expect(fragment.$internal.deps.namespace).toBeNull();
503
+ });
504
+
505
+ it("should sanitize dashes in schema.name when used as default namespace", () => {
506
+ const definition = defineFragment("test-dashed-fragment")
507
+ .extend(withDatabase(dashedSchema))
508
+ .build();
509
+
510
+ const mockAdapter = createMockAdapter();
511
+ const fragment = instantiate(definition)
512
+ .withOptions({ mountRoute: "/api", databaseAdapter: mockAdapter })
513
+ .build();
514
+
515
+ // schema.name is "my-fragment", but default namespace should be sanitized to "my_fragment"
516
+ expect(fragment.$internal.deps.namespace).toBe("my_fragment");
517
+ });
518
+
519
+ it("should NOT sanitize explicit databaseNamespace even when it contains dashes", () => {
520
+ const definition = defineFragment("test-dashed-fragment")
521
+ .extend(withDatabase(dashedSchema))
522
+ .build();
523
+
524
+ const mockAdapter = createMockAdapter();
525
+ const fragment = instantiate(definition)
526
+ .withOptions({
527
+ mountRoute: "/api",
528
+ databaseAdapter: mockAdapter,
529
+ databaseNamespace: "my-fragment",
530
+ })
531
+ .build();
532
+
533
+ // Explicit override should be used as-is, dashes preserved
534
+ expect(fragment.$internal.deps.namespace).toBe("my-fragment");
477
535
  });
478
536
 
479
537
  it("should populate $internal when using providesBaseService without withDependencies", () => {
@@ -504,27 +562,37 @@ describe("db-fragment-instantiator", () => {
504
562
  });
505
563
  });
506
564
 
507
- describe("error handling", () => {
508
- it("should throw when databaseAdapter is not provided", () => {
565
+ describe("default adapter", () => {
566
+ it("should default to sqlite adapter when databaseAdapter is not provided", () => {
509
567
  const definition = defineFragment("test-db-fragment")
510
568
  .extend(withDatabase(testSchema))
511
569
  .build();
512
-
513
- expect(() => {
514
- instantiate(definition)
515
- // @ts-expect-error - Test case
516
- .withOptions({})
517
- .build();
518
- }).toThrow("Database fragment requires a database adapter");
570
+ const previous = process.env["FRAGNO_DATA_DIR"];
571
+ const dataDir = fs.mkdtempSync(path.join(os.tmpdir(), "fragno-db-default-"));
572
+ process.env["FRAGNO_DATA_DIR"] = dataDir;
573
+
574
+ try {
575
+ const fragment = instantiate(definition).withOptions({}).build();
576
+ expect(fragment.$internal.options.databaseAdapter).toBeDefined();
577
+ expect(fragment.$internal.deps.db).toBeDefined();
578
+ } finally {
579
+ if (previous === undefined) {
580
+ delete process.env["FRAGNO_DATA_DIR"];
581
+ } else {
582
+ process.env["FRAGNO_DATA_DIR"] = previous;
583
+ }
584
+ }
519
585
  });
520
586
 
521
- it("should throw when forSchema called outside request context", () => {
587
+ it("should throw when serviceTx called outside request context", () => {
522
588
  const definition = defineFragment("test-db-fragment")
523
589
  .extend(withDatabase(testSchema))
524
590
  .providesBaseService(({ defineService }) =>
525
591
  defineService({
526
592
  tryGetUow: function () {
527
- return this.uow(testSchema);
593
+ return this.serviceTx(testSchema)
594
+ .mutate(({ uow }) => uow)
595
+ .build();
528
596
  },
529
597
  }),
530
598
  )