@fragno-dev/db 0.1.14 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (445) hide show
  1. package/.turbo/turbo-build.log +242 -139
  2. package/CHANGELOG.md +47 -0
  3. package/README.md +123 -8
  4. package/dist/adapters/adapters.d.ts +19 -5
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/drizzle/drizzle-adapter.d.ts +6 -19
  8. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
  9. package/dist/adapters/drizzle/drizzle-adapter.js +7 -47
  10. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
  11. package/dist/adapters/drizzle/generate.d.ts +7 -1
  12. package/dist/adapters/drizzle/generate.d.ts.map +1 -1
  13. package/dist/adapters/drizzle/generate.js +46 -45
  14. package/dist/adapters/drizzle/generate.js.map +1 -1
  15. package/dist/adapters/generic-sql/driver-config.d.ts +74 -0
  16. package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -0
  17. package/dist/adapters/generic-sql/driver-config.js +94 -0
  18. package/dist/adapters/generic-sql/driver-config.js.map +1 -0
  19. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +43 -0
  20. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -0
  21. package/dist/adapters/generic-sql/generic-sql-adapter.js +87 -0
  22. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -0
  23. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +67 -0
  24. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -0
  25. package/dist/adapters/generic-sql/migration/cold-kysely.js +33 -0
  26. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -0
  27. package/dist/adapters/generic-sql/migration/dialect/mysql.js +60 -0
  28. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -0
  29. package/dist/adapters/generic-sql/migration/dialect/postgres.js +59 -0
  30. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -0
  31. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +96 -0
  32. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -0
  33. package/dist/adapters/generic-sql/migration/executor.d.ts +15 -0
  34. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  35. package/dist/adapters/generic-sql/migration/executor.js +18 -0
  36. package/dist/adapters/generic-sql/migration/executor.js.map +1 -0
  37. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  38. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  39. package/dist/adapters/generic-sql/migration/prepared-migrations.js +68 -0
  40. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -0
  41. package/dist/adapters/generic-sql/migration/sql-generator.js +212 -0
  42. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -0
  43. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +32 -0
  44. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -0
  45. package/dist/adapters/generic-sql/query/cursor-utils.js +37 -0
  46. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -0
  47. package/dist/adapters/generic-sql/query/dialect/mysql.js +33 -0
  48. package/dist/adapters/generic-sql/query/dialect/mysql.js.map +1 -0
  49. package/dist/adapters/generic-sql/query/dialect/postgres.js +32 -0
  50. package/dist/adapters/generic-sql/query/dialect/postgres.js.map +1 -0
  51. package/dist/adapters/generic-sql/query/dialect/sqlite.js +32 -0
  52. package/dist/adapters/generic-sql/query/dialect/sqlite.js.map +1 -0
  53. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +152 -0
  54. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -0
  55. package/dist/adapters/generic-sql/query/select-builder.js +69 -0
  56. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -0
  57. package/dist/adapters/generic-sql/query/sql-query-compiler.js +145 -0
  58. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -0
  59. package/dist/adapters/generic-sql/query/where-builder.js +129 -0
  60. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -0
  61. package/dist/adapters/generic-sql/result-interpreter.js +74 -0
  62. package/dist/adapters/generic-sql/result-interpreter.js.map +1 -0
  63. package/dist/adapters/generic-sql/uow-decoder.js +105 -0
  64. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -0
  65. package/dist/adapters/generic-sql/uow-encoder.js +93 -0
  66. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -0
  67. package/dist/adapters/kysely/kysely-adapter.d.ts +5 -16
  68. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
  69. package/dist/adapters/kysely/kysely-adapter.js +6 -159
  70. package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
  71. package/dist/adapters/{drizzle/drizzle-query.js → shared/from-unit-of-work-compiler.js} +48 -62
  72. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -0
  73. package/dist/adapters/{kysely/kysely-shared.d.ts → shared/table-name-mapper.d.ts} +3 -2
  74. package/dist/adapters/shared/table-name-mapper.d.ts.map +1 -0
  75. package/dist/adapters/shared/table-name-mapper.js +43 -0
  76. package/dist/adapters/shared/table-name-mapper.js.map +1 -0
  77. package/dist/adapters/shared/uow-operation-compiler.js +105 -0
  78. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -0
  79. package/dist/db-fragment-definition-builder.d.ts +186 -0
  80. package/dist/db-fragment-definition-builder.d.ts.map +1 -0
  81. package/dist/db-fragment-definition-builder.js +207 -0
  82. package/dist/db-fragment-definition-builder.js.map +1 -0
  83. package/dist/fragments/internal-fragment.d.ts +53 -0
  84. package/dist/fragments/internal-fragment.d.ts.map +1 -0
  85. package/dist/fragments/internal-fragment.js +111 -0
  86. package/dist/fragments/internal-fragment.js.map +1 -0
  87. package/dist/hooks/hooks.d.ts +51 -0
  88. package/dist/hooks/hooks.d.ts.map +1 -0
  89. package/dist/hooks/hooks.js +88 -0
  90. package/dist/hooks/hooks.js.map +1 -0
  91. package/dist/migration-engine/generation-engine.d.ts +0 -2
  92. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  93. package/dist/migration-engine/generation-engine.js +38 -56
  94. package/dist/migration-engine/generation-engine.js.map +1 -1
  95. package/dist/mod.d.ts +35 -23
  96. package/dist/mod.d.ts.map +1 -1
  97. package/dist/mod.js +48 -45
  98. package/dist/mod.js.map +1 -1
  99. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js +165 -0
  100. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +1 -0
  101. package/dist/packages/fragno/dist/api/bind-services.js +20 -0
  102. package/dist/packages/fragno/dist/api/bind-services.js.map +1 -0
  103. package/dist/packages/fragno/dist/api/error.js +48 -0
  104. package/dist/packages/fragno/dist/api/error.js.map +1 -0
  105. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +320 -0
  106. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -0
  107. package/dist/packages/fragno/dist/api/fragment-instantiator.js +525 -0
  108. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -0
  109. package/dist/packages/fragno/dist/api/fragno-response.js +73 -0
  110. package/dist/packages/fragno/dist/api/fragno-response.js.map +1 -0
  111. package/dist/packages/fragno/dist/api/internal/response-stream.js +81 -0
  112. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +1 -0
  113. package/dist/packages/fragno/dist/api/internal/route.js +10 -0
  114. package/dist/packages/fragno/dist/api/internal/route.js.map +1 -0
  115. package/dist/packages/fragno/dist/api/mutable-request-state.js +97 -0
  116. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +1 -0
  117. package/dist/packages/fragno/dist/api/request-context-storage.js +43 -0
  118. package/dist/packages/fragno/dist/api/request-context-storage.js.map +1 -0
  119. package/dist/packages/fragno/dist/api/request-input-context.js +118 -0
  120. package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -0
  121. package/dist/packages/fragno/dist/api/request-middleware.js +83 -0
  122. package/dist/packages/fragno/dist/api/request-middleware.js.map +1 -0
  123. package/dist/packages/fragno/dist/api/request-output-context.js +119 -0
  124. package/dist/packages/fragno/dist/api/request-output-context.js.map +1 -0
  125. package/dist/packages/fragno/dist/api/route.js +17 -0
  126. package/dist/packages/fragno/dist/api/route.js.map +1 -0
  127. package/dist/packages/fragno/dist/internal/symbols.js +10 -0
  128. package/dist/packages/fragno/dist/internal/symbols.js.map +1 -0
  129. package/dist/query/column-defaults.js +27 -0
  130. package/dist/query/column-defaults.js.map +1 -0
  131. package/dist/query/cursor.d.ts +14 -6
  132. package/dist/query/cursor.d.ts.map +1 -1
  133. package/dist/query/cursor.js +16 -7
  134. package/dist/query/cursor.js.map +1 -1
  135. package/dist/query/orm/orm.d.ts +1 -1
  136. package/dist/query/orm/orm.js.map +1 -1
  137. package/dist/query/serialize/create-sql-serializer.js +30 -0
  138. package/dist/query/serialize/create-sql-serializer.js.map +1 -0
  139. package/dist/query/serialize/dialect/mysql-serializer.js +87 -0
  140. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -0
  141. package/dist/query/serialize/dialect/postgres-serializer.js +80 -0
  142. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -0
  143. package/dist/query/serialize/dialect/sqlite-serializer.js +93 -0
  144. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -0
  145. package/dist/query/serialize/sql-serializer.js +67 -0
  146. package/dist/query/serialize/sql-serializer.js.map +1 -0
  147. package/dist/query/{query.d.ts → simple-query-interface.d.ts} +6 -6
  148. package/dist/query/simple-query-interface.d.ts.map +1 -0
  149. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +133 -0
  150. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  151. package/dist/query/unit-of-work/execute-unit-of-work.js +197 -0
  152. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  153. package/dist/query/unit-of-work/retry-policy.d.ts +88 -0
  154. package/dist/query/unit-of-work/retry-policy.d.ts.map +1 -0
  155. package/dist/query/unit-of-work/retry-policy.js +61 -0
  156. package/dist/query/unit-of-work/retry-policy.js.map +1 -0
  157. package/dist/query/{unit-of-work.d.ts → unit-of-work/unit-of-work.d.ts} +145 -58
  158. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  159. package/dist/query/{unit-of-work.js → unit-of-work/unit-of-work.js} +435 -198
  160. package/dist/query/unit-of-work/unit-of-work.js.map +1 -0
  161. package/dist/query/value-decoding.js +71 -0
  162. package/dist/query/value-decoding.js.map +1 -0
  163. package/dist/query/value-encoding.js +124 -0
  164. package/dist/query/value-encoding.js.map +1 -0
  165. package/dist/schema/create.d.ts +3 -0
  166. package/dist/schema/create.d.ts.map +1 -1
  167. package/dist/schema/create.js +4 -0
  168. package/dist/schema/create.js.map +1 -1
  169. package/dist/schema/type-conversion/create-sql-type-mapper.js +29 -0
  170. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -0
  171. package/dist/schema/type-conversion/dialect/mysql.js +57 -0
  172. package/dist/schema/type-conversion/dialect/mysql.js.map +1 -0
  173. package/dist/schema/type-conversion/dialect/postgres.js +56 -0
  174. package/dist/schema/type-conversion/dialect/postgres.js.map +1 -0
  175. package/dist/schema/type-conversion/dialect/sqlite.js +52 -0
  176. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -0
  177. package/dist/schema/type-conversion/type-mapping.js +63 -0
  178. package/dist/schema/type-conversion/type-mapping.js.map +1 -0
  179. package/dist/sql-driver/connection/connection-provider.d.ts +13 -0
  180. package/dist/sql-driver/connection/connection-provider.d.ts.map +1 -0
  181. package/dist/sql-driver/connection/connection-provider.js +19 -0
  182. package/dist/sql-driver/connection/connection-provider.js.map +1 -0
  183. package/dist/sql-driver/connection/single-connection-provider.js +23 -0
  184. package/dist/sql-driver/connection/single-connection-provider.js.map +1 -0
  185. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  186. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  187. package/dist/sql-driver/dialects/dialects.d.ts +2 -0
  188. package/dist/sql-driver/dialects/dialects.js +3 -0
  189. package/dist/sql-driver/dialects/durable-object-dialect.d.ts +72 -0
  190. package/dist/sql-driver/dialects/durable-object-dialect.d.ts.map +1 -0
  191. package/dist/sql-driver/dialects/durable-object-dialect.js +130 -0
  192. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -0
  193. package/dist/sql-driver/driver/runtime-driver.d.ts +23 -0
  194. package/dist/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  195. package/dist/sql-driver/driver/runtime-driver.js +56 -0
  196. package/dist/sql-driver/driver/runtime-driver.js.map +1 -0
  197. package/dist/sql-driver/query-executor/default-query-executor.js +26 -0
  198. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -0
  199. package/dist/sql-driver/query-executor/plugin.d.ts +17 -0
  200. package/dist/sql-driver/query-executor/plugin.d.ts.map +1 -0
  201. package/dist/sql-driver/query-executor/query-executor-base.js +25 -0
  202. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -0
  203. package/dist/sql-driver/query-executor/query-executor.d.ts +36 -0
  204. package/dist/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  205. package/dist/sql-driver/sql-driver-adapter.d.ts +29 -0
  206. package/dist/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  207. package/dist/sql-driver/sql-driver-adapter.js +68 -0
  208. package/dist/sql-driver/sql-driver-adapter.js.map +1 -0
  209. package/dist/sql-driver/sql-driver.d.ts +38 -0
  210. package/dist/sql-driver/sql-driver.d.ts.map +1 -0
  211. package/dist/sql-driver/sql-driver.js +1 -0
  212. package/dist/sql-driver/sql.js +50 -0
  213. package/dist/sql-driver/sql.js.map +1 -0
  214. package/dist/with-database.d.ts +32 -0
  215. package/dist/with-database.d.ts.map +1 -0
  216. package/dist/with-database.js +34 -0
  217. package/dist/with-database.js.map +1 -0
  218. package/package.json +43 -9
  219. package/src/adapters/adapters.ts +23 -4
  220. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +140 -185
  221. package/src/adapters/drizzle/{drizzle-adapter-sqlite.test.ts → drizzle-adapter-sqlite3.test.ts} +187 -55
  222. package/src/adapters/drizzle/drizzle-adapter.ts +14 -93
  223. package/src/adapters/drizzle/generate.test.ts +102 -269
  224. package/src/adapters/drizzle/generate.ts +89 -63
  225. package/src/adapters/drizzle/migrate-drizzle.test.ts +19 -0
  226. package/src/adapters/drizzle/shared.ts +0 -34
  227. package/src/adapters/drizzle/test-utils.ts +36 -5
  228. package/src/adapters/generic-sql/README.md +14 -0
  229. package/src/adapters/generic-sql/driver-config.ts +144 -0
  230. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +50 -0
  231. package/src/adapters/generic-sql/generic-sql-adapter.ts +146 -0
  232. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +130 -0
  233. package/src/adapters/generic-sql/migration/cold-kysely.ts +55 -0
  234. package/src/adapters/{kysely/migration/execute-mysql.test.ts → generic-sql/migration/dialect/mysql.test.ts} +342 -484
  235. package/src/adapters/generic-sql/migration/dialect/mysql.ts +104 -0
  236. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +1008 -0
  237. package/src/adapters/generic-sql/migration/dialect/postgres.ts +113 -0
  238. package/src/adapters/{kysely/migration/execute-sqlite.test.ts → generic-sql/migration/dialect/sqlite.test.ts} +307 -510
  239. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +189 -0
  240. package/src/adapters/generic-sql/migration/executor.ts +33 -0
  241. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +661 -0
  242. package/src/adapters/generic-sql/migration/prepared-migrations.ts +214 -0
  243. package/src/adapters/generic-sql/migration/sql-generator.ts +413 -0
  244. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +36 -0
  245. package/src/adapters/generic-sql/query/cursor-utils.ts +56 -0
  246. package/src/adapters/generic-sql/query/dialect/mysql.ts +34 -0
  247. package/src/adapters/generic-sql/query/dialect/postgres.ts +32 -0
  248. package/src/adapters/generic-sql/query/dialect/sqlite.ts +32 -0
  249. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +1568 -0
  250. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +314 -0
  251. package/src/adapters/generic-sql/query/select-builder.test.ts +256 -0
  252. package/src/adapters/generic-sql/query/select-builder.ts +137 -0
  253. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +195 -0
  254. package/src/adapters/generic-sql/query/sql-query-compiler.ts +367 -0
  255. package/src/adapters/generic-sql/query/where-builder.test.ts +744 -0
  256. package/src/adapters/generic-sql/query/where-builder.ts +211 -0
  257. package/src/adapters/generic-sql/result-interpreter.ts +102 -0
  258. package/src/adapters/generic-sql/test/generic-drizzle-adapter-sqlite3.test.ts +899 -0
  259. package/src/adapters/generic-sql/uow-decoder.test.ts +399 -0
  260. package/src/adapters/generic-sql/uow-decoder.ts +152 -0
  261. package/src/adapters/generic-sql/uow-encoder.test.ts +183 -0
  262. package/src/adapters/generic-sql/uow-encoder.ts +131 -0
  263. package/src/adapters/kysely/kysely-adapter-pglite.test.ts +90 -96
  264. package/src/adapters/kysely/kysely-adapter-sqlocal.test.ts +215 -0
  265. package/src/adapters/kysely/kysely-adapter.ts +10 -242
  266. package/src/adapters/{drizzle/drizzle-query.ts → shared/from-unit-of-work-compiler.ts} +111 -106
  267. package/src/adapters/shared/table-name-mapper.ts +50 -0
  268. package/src/adapters/shared/uow-operation-compiler.ts +211 -0
  269. package/src/db-fragment-definition-builder.test.ts +887 -0
  270. package/src/db-fragment-definition-builder.ts +737 -0
  271. package/src/db-fragment-instantiator.test.ts +543 -0
  272. package/src/db-fragment-integration.test.ts +406 -0
  273. package/src/fragments/internal-fragment.test.ts +549 -0
  274. package/src/fragments/internal-fragment.ts +249 -0
  275. package/src/hooks/hooks.test.ts +575 -0
  276. package/src/hooks/hooks.ts +179 -0
  277. package/src/migration-engine/generation-engine.test.ts +60 -27
  278. package/src/migration-engine/generation-engine.ts +99 -92
  279. package/src/mod.ts +139 -78
  280. package/src/query/column-defaults.ts +49 -0
  281. package/src/query/cursor.test.ts +147 -3
  282. package/src/query/cursor.ts +25 -8
  283. package/src/query/orm/orm.ts +1 -1
  284. package/src/query/query-type.test.ts +9 -9
  285. package/src/query/serialize/create-sql-serializer.ts +34 -0
  286. package/src/query/serialize/dialect/mysql-serializer.ts +142 -0
  287. package/src/query/serialize/dialect/postgres-serializer.ts +129 -0
  288. package/src/query/serialize/dialect/sqlite-serializer.test.ts +251 -0
  289. package/src/query/serialize/dialect/sqlite-serializer.ts +156 -0
  290. package/src/query/serialize/sql-serializer.ts +143 -0
  291. package/src/query/{query.ts → simple-query-interface.ts} +4 -4
  292. package/src/query/unit-of-work/execute-unit-of-work.test.ts +1310 -0
  293. package/src/query/unit-of-work/execute-unit-of-work.ts +504 -0
  294. package/src/query/unit-of-work/retry-policy.test.ts +217 -0
  295. package/src/query/unit-of-work/retry-policy.ts +141 -0
  296. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +831 -0
  297. package/src/query/{unit-of-work-types.test.ts → unit-of-work/unit-of-work-types.test.ts} +7 -5
  298. package/src/query/unit-of-work/unit-of-work.test.ts +1716 -0
  299. package/src/query/{unit-of-work.ts → unit-of-work/unit-of-work.ts} +716 -420
  300. package/src/query/{result-transform.test.ts → value-decoding.test.ts} +45 -298
  301. package/src/query/value-decoding.ts +113 -0
  302. package/src/query/value-encoding.test.ts +390 -0
  303. package/src/query/value-encoding.ts +168 -0
  304. package/src/schema/create.test.ts +5 -1
  305. package/src/schema/create.ts +5 -0
  306. package/src/schema/serialize.test.ts +165 -407
  307. package/src/schema/type-conversion/create-sql-type-mapper.ts +28 -0
  308. package/src/schema/type-conversion/dialect/mysql.ts +64 -0
  309. package/src/schema/type-conversion/dialect/postgres.ts +62 -0
  310. package/src/schema/type-conversion/dialect/sqlite.ts +63 -0
  311. package/src/schema/type-conversion/type-mapping.test.ts +137 -0
  312. package/src/schema/type-conversion/type-mapping.ts +153 -0
  313. package/src/shared/connection-pool.ts +5 -5
  314. package/src/sql-driver/better-sqlite3.test.ts +126 -0
  315. package/src/sql-driver/connection/connection-provider.ts +27 -0
  316. package/src/sql-driver/connection/single-connection-provider.ts +42 -0
  317. package/src/sql-driver/dialect-adapter/dialect-adapter.ts +9 -0
  318. package/src/sql-driver/dialect-adapter/sqlite-dialect-adapter.ts +7 -0
  319. package/src/sql-driver/dialects/dialects.ts +1 -0
  320. package/src/sql-driver/dialects/durable-object-dialect.ts +260 -0
  321. package/src/sql-driver/driver/runtime-driver.ts +91 -0
  322. package/src/sql-driver/query-executor/default-query-executor.ts +38 -0
  323. package/src/sql-driver/query-executor/plugin.ts +22 -0
  324. package/src/sql-driver/query-executor/query-executor-base.ts +53 -0
  325. package/src/sql-driver/query-executor/query-executor.ts +44 -0
  326. package/src/sql-driver/sql-driver-adapter.ts +96 -0
  327. package/src/sql-driver/sql-driver.ts +53 -0
  328. package/src/sql-driver/sql.ts +57 -0
  329. package/src/sql-driver/sqlocal.test.ts +117 -0
  330. package/src/with-database.ts +152 -0
  331. package/tsdown.config.ts +8 -2
  332. package/dist/adapters/drizzle/drizzle-connection-pool.js +0 -40
  333. package/dist/adapters/drizzle/drizzle-connection-pool.js.map +0 -1
  334. package/dist/adapters/drizzle/drizzle-query.d.ts +0 -23
  335. package/dist/adapters/drizzle/drizzle-query.d.ts.map +0 -1
  336. package/dist/adapters/drizzle/drizzle-query.js.map +0 -1
  337. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +0 -10
  338. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +0 -1
  339. package/dist/adapters/drizzle/drizzle-uow-compiler.js +0 -315
  340. package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +0 -1
  341. package/dist/adapters/drizzle/drizzle-uow-decoder.js +0 -116
  342. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +0 -1
  343. package/dist/adapters/drizzle/drizzle-uow-executor.js +0 -149
  344. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +0 -1
  345. package/dist/adapters/drizzle/join-column-utils.js +0 -28
  346. package/dist/adapters/drizzle/join-column-utils.js.map +0 -1
  347. package/dist/adapters/drizzle/shared.d.ts +0 -14
  348. package/dist/adapters/drizzle/shared.d.ts.map +0 -1
  349. package/dist/adapters/drizzle/shared.js +0 -35
  350. package/dist/adapters/drizzle/shared.js.map +0 -1
  351. package/dist/adapters/kysely/kysely-connection-pool.js +0 -41
  352. package/dist/adapters/kysely/kysely-connection-pool.js.map +0 -1
  353. package/dist/adapters/kysely/kysely-query-builder.js +0 -321
  354. package/dist/adapters/kysely/kysely-query-builder.js.map +0 -1
  355. package/dist/adapters/kysely/kysely-query-compiler.js +0 -66
  356. package/dist/adapters/kysely/kysely-query-compiler.js.map +0 -1
  357. package/dist/adapters/kysely/kysely-query.d.ts +0 -22
  358. package/dist/adapters/kysely/kysely-query.d.ts.map +0 -1
  359. package/dist/adapters/kysely/kysely-query.js +0 -223
  360. package/dist/adapters/kysely/kysely-query.js.map +0 -1
  361. package/dist/adapters/kysely/kysely-shared.d.ts.map +0 -1
  362. package/dist/adapters/kysely/kysely-shared.js +0 -18
  363. package/dist/adapters/kysely/kysely-shared.js.map +0 -1
  364. package/dist/adapters/kysely/kysely-uow-compiler.js +0 -170
  365. package/dist/adapters/kysely/kysely-uow-compiler.js.map +0 -1
  366. package/dist/adapters/kysely/kysely-uow-executor.js +0 -89
  367. package/dist/adapters/kysely/kysely-uow-executor.js.map +0 -1
  368. package/dist/adapters/kysely/migration/execute-base.js +0 -128
  369. package/dist/adapters/kysely/migration/execute-base.js.map +0 -1
  370. package/dist/adapters/kysely/migration/execute-factory.js +0 -34
  371. package/dist/adapters/kysely/migration/execute-factory.js.map +0 -1
  372. package/dist/adapters/kysely/migration/execute-mssql.js +0 -112
  373. package/dist/adapters/kysely/migration/execute-mssql.js.map +0 -1
  374. package/dist/adapters/kysely/migration/execute-mysql.js +0 -93
  375. package/dist/adapters/kysely/migration/execute-mysql.js.map +0 -1
  376. package/dist/adapters/kysely/migration/execute-postgres.js +0 -104
  377. package/dist/adapters/kysely/migration/execute-postgres.js.map +0 -1
  378. package/dist/adapters/kysely/migration/execute-sqlite.js +0 -123
  379. package/dist/adapters/kysely/migration/execute-sqlite.js.map +0 -1
  380. package/dist/adapters/kysely/migration/execute.js +0 -34
  381. package/dist/adapters/kysely/migration/execute.js.map +0 -1
  382. package/dist/bind-services.d.ts +0 -7
  383. package/dist/bind-services.d.ts.map +0 -1
  384. package/dist/bind-services.js +0 -14
  385. package/dist/bind-services.js.map +0 -1
  386. package/dist/fragment.d.ts +0 -173
  387. package/dist/fragment.d.ts.map +0 -1
  388. package/dist/fragment.js +0 -191
  389. package/dist/fragment.js.map +0 -1
  390. package/dist/migration-engine/create.d.ts +0 -37
  391. package/dist/migration-engine/create.d.ts.map +0 -1
  392. package/dist/migration-engine/create.js +0 -58
  393. package/dist/migration-engine/create.js.map +0 -1
  394. package/dist/migration-engine/shared.d.ts +0 -112
  395. package/dist/migration-engine/shared.d.ts.map +0 -1
  396. package/dist/query/query.d.ts.map +0 -1
  397. package/dist/query/result-transform.js +0 -168
  398. package/dist/query/result-transform.js.map +0 -1
  399. package/dist/query/unit-of-work.d.ts.map +0 -1
  400. package/dist/query/unit-of-work.js.map +0 -1
  401. package/dist/schema/serialize.js +0 -106
  402. package/dist/schema/serialize.js.map +0 -1
  403. package/dist/shared/settings-schema.js +0 -36
  404. package/dist/shared/settings-schema.js.map +0 -1
  405. package/src/adapters/drizzle/drizzle-adapter.test.ts +0 -170
  406. package/src/adapters/drizzle/drizzle-connection-pool.ts +0 -66
  407. package/src/adapters/drizzle/drizzle-query.test.ts +0 -499
  408. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +0 -1383
  409. package/src/adapters/drizzle/drizzle-uow-compiler.ts +0 -636
  410. package/src/adapters/drizzle/drizzle-uow-decoder.ts +0 -218
  411. package/src/adapters/drizzle/drizzle-uow-executor.ts +0 -276
  412. package/src/adapters/drizzle/join-column-utils.test.ts +0 -79
  413. package/src/adapters/drizzle/join-column-utils.ts +0 -39
  414. package/src/adapters/kysely/kysely-connection-pool.ts +0 -70
  415. package/src/adapters/kysely/kysely-query-builder.test.ts +0 -1344
  416. package/src/adapters/kysely/kysely-query-builder.ts +0 -666
  417. package/src/adapters/kysely/kysely-query-compiler.ts +0 -132
  418. package/src/adapters/kysely/kysely-query.test.ts +0 -498
  419. package/src/adapters/kysely/kysely-query.ts +0 -390
  420. package/src/adapters/kysely/kysely-shared.ts +0 -23
  421. package/src/adapters/kysely/kysely-uow-compiler.test.ts +0 -998
  422. package/src/adapters/kysely/kysely-uow-compiler.ts +0 -318
  423. package/src/adapters/kysely/kysely-uow-executor.ts +0 -145
  424. package/src/adapters/kysely/kysely-uow-joins.test.ts +0 -811
  425. package/src/adapters/kysely/migration/execute-base.ts +0 -256
  426. package/src/adapters/kysely/migration/execute-factory.ts +0 -53
  427. package/src/adapters/kysely/migration/execute-mssql.ts +0 -250
  428. package/src/adapters/kysely/migration/execute-mysql.ts +0 -211
  429. package/src/adapters/kysely/migration/execute-postgres.test.ts +0 -2657
  430. package/src/adapters/kysely/migration/execute-postgres.ts +0 -234
  431. package/src/adapters/kysely/migration/execute-sqlite.ts +0 -247
  432. package/src/adapters/kysely/migration/execute.ts +0 -50
  433. package/src/adapters/kysely/migration/kysely-migrator.test.ts +0 -261
  434. package/src/bind-services.test.ts +0 -214
  435. package/src/bind-services.ts +0 -37
  436. package/src/db-fragment.test.ts +0 -800
  437. package/src/fragment.ts +0 -727
  438. package/src/query/result-transform.ts +0 -271
  439. package/src/query/unit-of-work-multi-schema.test.ts +0 -64
  440. package/src/query/unit-of-work.test.ts +0 -943
  441. package/src/schema/serialize.ts +0 -396
  442. package/src/shared/settings-schema.ts +0 -61
  443. package/src/uow-context-integration.test.ts +0 -102
  444. package/src/uow-context.test.ts +0 -182
  445. /package/dist/query/{query.js → simple-query-interface.js} +0 -0
@@ -8,9 +8,13 @@ import {
8
8
  InternalIdColumn,
9
9
  } from "../../schema/create";
10
10
  import type { SQLProvider } from "../../shared/providers";
11
- import { schemaToDBType, type DBTypeLiteral } from "../../schema/serialize";
12
- import { createTableNameMapper, sanitizeNamespace } from "./shared";
13
- import { settingsSchema, SETTINGS_TABLE_NAME } from "../../shared/settings-schema";
11
+ import {
12
+ createTableNameMapper,
13
+ sanitizeNamespace,
14
+ type TableNameMapper,
15
+ } from "../shared/table-name-mapper";
16
+ import { type DatabaseTypeLiteral } from "../../schema/type-conversion/type-mapping";
17
+ import { createSQLTypeMapper } from "../../schema/type-conversion/create-sql-type-mapper";
14
18
 
15
19
  // ============================================================================
16
20
  // PROVIDER CONFIGURATION
@@ -99,10 +103,11 @@ function generateCustomType(
99
103
 
100
104
  function generateBinaryCustomType(ctx: GeneratorContext, customTypes: string[]): string {
101
105
  const name = "customBinary";
106
+ const typeMapper = createSQLTypeMapper(ctx.provider);
102
107
  const code = generateCustomType(ctx, name, {
103
108
  dataType: "Uint8Array",
104
109
  driverDataType: "Buffer",
105
- databaseDataType: schemaToDBType({ type: "binary" }, ctx.provider),
110
+ databaseDataType: typeMapper.getDatabaseType({ type: "binary" }),
106
111
  fromDriverCode: "return new Uint8Array(value.buffer, value.byteOffset, value.byteLength)",
107
112
  toDriverCode: `return value instanceof Buffer? value : Buffer.from(value)`,
108
113
  });
@@ -125,15 +130,16 @@ interface ColumnTypeFunction {
125
130
 
126
131
  /**
127
132
  * Maps SQL database types to Drizzle function names and parameters.
128
- * Uses schemaToDBType as the source of truth for type conversion.
133
+ * Uses SQLTypeMapper as the source of truth for type conversion.
129
134
  */
130
135
  function getColumnTypeFunction(
131
136
  ctx: GeneratorContext,
132
137
  column: AnyColumn,
133
138
  customTypes: string[],
134
139
  ): ColumnTypeFunction {
135
- // Get the canonical database type from schemaToDBType
136
- const dbType = schemaToDBType(column, ctx.provider);
140
+ // Get the canonical database type from type mapper
141
+ const typeMapper = createSQLTypeMapper(ctx.provider);
142
+ const dbType = typeMapper.getDatabaseType(column);
137
143
 
138
144
  // Map database types to Drizzle function names
139
145
  return mapDBTypeToDrizzleFunction(ctx, dbType, column, customTypes);
@@ -144,7 +150,7 @@ function getColumnTypeFunction(
144
150
  */
145
151
  function mapDBTypeToDrizzleFunction(
146
152
  ctx: GeneratorContext,
147
- dbType: DBTypeLiteral,
153
+ dbType: DatabaseTypeLiteral,
148
154
  column: AnyColumn,
149
155
  customTypes: string[],
150
156
  ): ColumnTypeFunction {
@@ -184,7 +190,11 @@ function mapDBTypeToDrizzleFunction(
184
190
  case "longblob":
185
191
  return { name: generateBinaryCustomType(ctx, customTypes), isCustomType: true };
186
192
  case "bigint":
187
- return { name: "bigint" };
193
+ // MySQL bigint requires mode parameter
194
+ return { name: "bigint", params: [`{ mode: "number" }`] };
195
+ case "integer":
196
+ // MySQL uses "int" not "integer" in Drizzle ORM
197
+ return { name: "int" };
188
198
  default:
189
199
  if (dbType.startsWith("varchar(")) {
190
200
  const length = parseVarchar(dbType);
@@ -228,6 +238,24 @@ function mapDBTypeToDrizzleFunction(
228
238
  return { name: dbType };
229
239
  }
230
240
 
241
+ // ============================================================================
242
+ // TABLE NAME HELPERS
243
+ // ============================================================================
244
+
245
+ /**
246
+ * Get the physical table name (with namespace suffix) using the mapper if available
247
+ */
248
+ function getPhysicalTableName(
249
+ logicalName: string,
250
+ namespace: string | undefined,
251
+ mapper: TableNameMapper | undefined,
252
+ ): string {
253
+ if (!namespace) {
254
+ return logicalName;
255
+ }
256
+ return mapper ? mapper.toPhysical(logicalName) : `${logicalName}_${sanitizeNamespace(namespace)}`;
257
+ }
258
+
231
259
  // ============================================================================
232
260
  // COLUMN GENERATION
233
261
  // ============================================================================
@@ -315,8 +343,12 @@ function generateAllColumns(
315
343
  // CONSTRAINT GENERATION
316
344
  // ============================================================================
317
345
 
318
- function generateForeignKeys(ctx: GeneratorContext, table: AnyTable, namespace?: string): string[] {
319
- const mapper = namespace ? createTableNameMapper(namespace) : undefined;
346
+ function generateForeignKeys(
347
+ ctx: GeneratorContext,
348
+ table: AnyTable,
349
+ namespace?: string,
350
+ mapper?: TableNameMapper,
351
+ ): string[] {
320
352
  const keys: string[] = [];
321
353
 
322
354
  for (const relation of Object.values(table.relations)) {
@@ -338,7 +370,7 @@ function generateForeignKeys(ctx: GeneratorContext, table: AnyTable, namespace?:
338
370
  if (isSelfReference) {
339
371
  foreignColumns.push(`table.${actualRefCol}`);
340
372
  } else {
341
- // Suffix the foreign table reference with namespace if provided
373
+ // Use sanitized TypeScript export name for identifier reference
342
374
  const foreignTableRef = namespace
343
375
  ? `${relation.table.ormName}_${sanitizeNamespace(namespace)}`
344
376
  : relation.table.ormName;
@@ -388,8 +420,12 @@ function generateTableConstraints(
388
420
  ctx: GeneratorContext,
389
421
  table: AnyTable,
390
422
  namespace?: string,
423
+ mapper?: TableNameMapper,
391
424
  ): string[] {
392
- return [...generateForeignKeys(ctx, table, namespace), ...generateIndexes(ctx, table, namespace)];
425
+ return [
426
+ ...generateForeignKeys(ctx, table, namespace, mapper),
427
+ ...generateIndexes(ctx, table, namespace),
428
+ ];
393
429
  }
394
430
 
395
431
  // ============================================================================
@@ -401,20 +437,18 @@ function generateTable(
401
437
  table: AnyTable,
402
438
  customTypes: string[],
403
439
  namespace?: string,
440
+ mapper?: TableNameMapper,
404
441
  ): string {
405
442
  const tableFn = PROVIDER_TABLE_FUNCTIONS[ctx.provider];
406
443
  ctx.imports.addImport(tableFn, ctx.importSource);
407
444
 
408
445
  const columns = generateAllColumns(ctx, table, customTypes);
409
- const constraints = generateTableConstraints(ctx, table, namespace);
446
+ const constraints = generateTableConstraints(ctx, table, namespace, mapper);
410
447
 
411
- // Suffix table name with namespace if provided, and sanitize for use as database table name
412
- // Database table names must also be valid identifiers to work with Drizzle's relational query system
413
- const physicalTableName = namespace
414
- ? `${table.ormName}_${sanitizeNamespace(namespace)}`
415
- : table.ormName;
416
- // Same sanitized name for TypeScript export
417
- const exportName = physicalTableName;
448
+ // Physical table name in the database (respects mapper configuration)
449
+ const physicalTableName = getPhysicalTableName(table.ormName, namespace, mapper);
450
+ // TypeScript export name must always be sanitized to be a valid JavaScript identifier
451
+ const exportName = namespace ? `${table.ormName}_${sanitizeNamespace(namespace)}` : table.ormName;
418
452
 
419
453
  const args: string[] = [`"${physicalTableName}"`, `{\n${columns.join(",\n")}\n}`];
420
454
 
@@ -434,6 +468,7 @@ function generateRelation(
434
468
  table: AnyTable,
435
469
  namespace?: string,
436
470
  inverseRelations?: Array<{ fromTable: AnyTable; relation: Relation }>,
471
+ _mapper?: TableNameMapper,
437
472
  ): string | undefined {
438
473
  const relations: string[] = [];
439
474
  let hasOne = false;
@@ -455,7 +490,7 @@ function generateRelation(
455
490
  const fields: string[] = [];
456
491
  const references: string[] = [];
457
492
 
458
- // Use sanitized namespace for identifier references
493
+ // Use sanitized TypeScript export names for identifier references
459
494
  const tableRef = namespace
460
495
  ? `${table.ormName}_${sanitizeNamespace(namespace)}`
461
496
  : table.ormName;
@@ -493,6 +528,7 @@ function generateRelation(
493
528
  if (relation.type === "one") {
494
529
  hasMany = true;
495
530
 
531
+ // Use sanitized TypeScript export name for identifier reference
496
532
  const fromTableRef = namespace
497
533
  ? `${fromTable.ormName}_${sanitizeNamespace(namespace)}`
498
534
  : fromTable.ormName;
@@ -523,13 +559,14 @@ function generateRelation(
523
559
  }
524
560
  const relationParams = params.length > 0 ? `{ ${params.join(", ")} }` : "{}";
525
561
 
526
- const tableRef = namespace ? `${table.ormName}_${sanitizeNamespace(namespace)}` : table.ormName;
527
- const relationsName = namespace
528
- ? `${table.ormName}_${sanitizeNamespace(namespace)}Relations`
529
- : `${table.ormName}Relations`;
562
+ // Use sanitized names for TypeScript export identifiers
563
+ const exportTableRef = namespace
564
+ ? `${table.ormName}_${sanitizeNamespace(namespace)}`
565
+ : table.ormName;
566
+ const relationsName = namespace ? `${exportTableRef}Relations` : `${table.ormName}Relations`;
530
567
 
531
568
  ctx.imports.addImport("relations", "drizzle-orm");
532
- return `export const ${relationsName} = relations(${tableRef}, (${relationParams}) => ({
569
+ return `export const ${relationsName} = relations(${exportTableRef}, (${relationParams}) => ({
533
570
  ${relations.join(",\n")}
534
571
  }));`;
535
572
  }
@@ -546,22 +583,22 @@ function generateFragmentSchemaExport(
546
583
  schema: AnySchema,
547
584
  namespace: string,
548
585
  tablesWithRelations?: Set<string>,
586
+ _mapper?: TableNameMapper,
549
587
  ): string {
550
588
  const drizzleEntries: string[] = [];
551
589
 
552
590
  for (const table of Object.values(schema.tables)) {
553
- const physicalExportName = namespace
591
+ // TypeScript export name (always sanitized for valid JS identifiers)
592
+ const exportName = namespace
554
593
  ? `${table.ormName}_${sanitizeNamespace(namespace)}`
555
594
  : table.ormName;
556
595
 
557
596
  // Add physical table name to drizzle schema
558
- drizzleEntries.push(` ${physicalExportName}: ${physicalExportName}`);
597
+ drizzleEntries.push(` ${exportName}: ${exportName}`);
559
598
 
560
599
  // Include relations for this table if they exist (either explicit or inverse)
561
600
  if (tablesWithRelations?.has(table.name)) {
562
- const relationsName = namespace
563
- ? `${table.ormName}_${sanitizeNamespace(namespace)}Relations`
564
- : `${table.ormName}Relations`;
601
+ const relationsName = namespace ? `${exportName}Relations` : `${table.ormName}Relations`;
565
602
 
566
603
  drizzleEntries.push(` ${relationsName}: ${relationsName}`);
567
604
  }
@@ -570,11 +607,11 @@ function generateFragmentSchemaExport(
570
607
  // The key insight: Drizzle needs BOTH the table alias AND its relations alias
571
608
  // in the same schema object for relational queries to work
572
609
  if (namespace) {
573
- drizzleEntries.push(` ${table.ormName}: ${physicalExportName}`);
610
+ drizzleEntries.push(` ${table.ormName}: ${exportName}`);
574
611
 
575
612
  // Also add the relations under the aliased name if they exist
576
613
  if (tablesWithRelations?.has(table.name)) {
577
- const physicalRelationsName = `${table.ormName}_${sanitizeNamespace(namespace)}Relations`;
614
+ const physicalRelationsName = `${exportName}Relations`;
578
615
  const aliasRelationsName = `${table.ormName}Relations`;
579
616
  drizzleEntries.push(` ${aliasRelationsName}: ${physicalRelationsName}`);
580
617
  }
@@ -584,6 +621,7 @@ function generateFragmentSchemaExport(
584
621
  // Add schema version as a number
585
622
  drizzleEntries.push(` schemaVersion: ${schema.version}`);
586
623
 
624
+ // Use logical name (not physical) for the schema export variable name, sanitized for valid JS identifier
587
625
  const exportName = namespace ? `${sanitizeNamespace(namespace)}_schema` : "_schema";
588
626
 
589
627
  return `export const ${exportName} = {\n${drizzleEntries.join(",\n")}\n}`;
@@ -601,25 +639,15 @@ export interface GenerateSchemaOptions {
601
639
  /** Module to import from */
602
640
  from: string;
603
641
  };
642
+ /** Optional mapper factory for creating table name mappers with custom sanitization */
643
+ mapperFactory?: (namespace: string | undefined) => TableNameMapper | undefined;
604
644
  }
605
645
 
606
646
  /**
607
647
  * Generate a settings table for storing fragment versions
608
648
  */
609
- function generateSettingsTable(ctx: GeneratorContext): string {
610
- // Use centralized settings schema
611
-
612
- // Extract the table from the schema
613
- const settingsTable =
614
- settingsSchema.tables[SETTINGS_TABLE_NAME as keyof typeof settingsSchema.tables];
615
-
616
- // Generate the table using the existing generateTable function
617
- const customTypes: string[] = [];
618
- return generateTable(ctx, settingsTable, customTypes);
619
- }
620
-
621
649
  /**
622
- * Generate a schema file from one or more fragments with a shared settings table
650
+ * Generate a schema file from one or more fragments with automatic de-duplication
623
651
  */
624
652
  export function generateSchema(
625
653
  fragments: { namespace: string; schema: AnySchema }[],
@@ -629,20 +657,13 @@ export function generateSchema(
629
657
  const ctx = createContext(provider, options?.idGeneratorImport);
630
658
  const customTypes: string[] = [];
631
659
  const sections: string[] = [];
660
+ const getMapper =
661
+ options?.mapperFactory ||
662
+ ((ns: string | undefined) => (ns ? createTableNameMapper(ns, true) : undefined));
632
663
 
633
- // Generate settings table first
634
- sections.push("");
635
- sections.push("// ============================================================================");
636
- sections.push("// Settings Table (shared across all fragments)");
637
- sections.push("// ============================================================================");
638
- sections.push("");
639
- sections.push(generateSettingsTable(ctx));
640
- sections.push("");
641
- sections.push(`export const fragnoDbSettingSchemaVersion = ${settingsSchema.version};`);
642
-
643
- // Generate each fragment's tables
644
- for (const { namespace, schema } of fragments) {
664
+ for (const { schema, namespace } of fragments) {
645
665
  const fragmentTables: string[] = [];
666
+ const mapper = getMapper(namespace);
646
667
 
647
668
  // Add section header
648
669
  fragmentTables.push("");
@@ -656,7 +677,7 @@ export function generateSchema(
656
677
 
657
678
  // Generate tables for this fragment
658
679
  for (const table of Object.values(schema.tables)) {
659
- const tableCode = generateTable(ctx, table, customTypes, namespace);
680
+ const tableCode = generateTable(ctx, table, customTypes, namespace, mapper);
660
681
  fragmentTables.push("");
661
682
  fragmentTables.push(tableCode);
662
683
  }
@@ -683,6 +704,7 @@ export function generateSchema(
683
704
  table,
684
705
  namespace,
685
706
  inverseRelations.get(table.name),
707
+ mapper,
686
708
  );
687
709
  if (relationCode) {
688
710
  fragmentTables.push("");
@@ -691,9 +713,13 @@ export function generateSchema(
691
713
  }
692
714
  }
693
715
 
694
- // Generate schema export object
695
- fragmentTables.push("");
696
- fragmentTables.push(generateFragmentSchemaExport(schema, namespace, tablesWithRelations));
716
+ // Generate schema export object (skip for empty namespace to avoid duplicate _schema exports)
717
+ if (namespace !== "") {
718
+ fragmentTables.push("");
719
+ fragmentTables.push(
720
+ generateFragmentSchemaExport(schema, namespace, tablesWithRelations, mapper),
721
+ );
722
+ }
697
723
 
698
724
  sections.push(...fragmentTables);
699
725
  }
@@ -158,6 +158,23 @@ describe("generateSchema and migrate", () => {
158
158
  "_version" integer DEFAULT 0 NOT NULL
159
159
  );
160
160
 
161
+ CREATE TABLE "fragno_hooks" (
162
+ "id" varchar(30) NOT NULL,
163
+ "namespace" text NOT NULL,
164
+ "hookName" text NOT NULL,
165
+ "payload" json NOT NULL,
166
+ "status" text NOT NULL,
167
+ "attempts" integer DEFAULT 0 NOT NULL,
168
+ "maxAttempts" integer DEFAULT 5 NOT NULL,
169
+ "lastAttemptAt" timestamp,
170
+ "nextRetryAt" timestamp,
171
+ "error" text,
172
+ "createdAt" timestamp DEFAULT now() NOT NULL,
173
+ "nonce" text NOT NULL,
174
+ "_internalId" bigserial PRIMARY KEY NOT NULL,
175
+ "_version" integer DEFAULT 0 NOT NULL
176
+ );
177
+
161
178
  CREATE TABLE "users" (
162
179
  "id" varchar(30) NOT NULL,
163
180
  "name" text NOT NULL,
@@ -231,6 +248,8 @@ describe("generateSchema and migrate", () => {
231
248
  ALTER TABLE "postTags" ADD CONSTRAINT "postTags_posts_post_fk" FOREIGN KEY ("postId") REFERENCES "public"."posts"("_internalId") ON DELETE no action ON UPDATE no action;
232
249
  ALTER TABLE "postTags" ADD CONSTRAINT "postTags_tags_tag_fk" FOREIGN KEY ("tagId") REFERENCES "public"."tags"("_internalId") ON DELETE no action ON UPDATE no action;
233
250
  CREATE UNIQUE INDEX "unique_key" ON "fragno_db_settings" USING btree ("key");
251
+ CREATE INDEX "idx_namespace_status_retry" ON "fragno_hooks" USING btree ("namespace","status","nextRetryAt");
252
+ CREATE INDEX "idx_nonce" ON "fragno_hooks" USING btree ("nonce");
234
253
  CREATE UNIQUE INDEX "idx_users_email" ON "users" USING btree ("email");
235
254
  CREATE INDEX "idx_users_name" ON "users" USING btree ("name");
236
255
  CREATE INDEX "idx_users_active" ON "users" USING btree ("isActive");
@@ -22,40 +22,6 @@ export function parseDrizzle(drizzle: unknown) {
22
22
  return [db, drizzleTables] as const;
23
23
  }
24
24
 
25
- /**
26
- * Maps logical table names (used by fragment authors) to physical table names (with namespace suffix)
27
- */
28
- export interface TableNameMapper {
29
- toPhysical(logicalName: string): string;
30
- toLogical(physicalName: string): string;
31
- }
32
-
33
- /**
34
- * Sanitize a namespace to be a valid JavaScript identifier
35
- * Replaces hyphens and other invalid characters with underscores
36
- */
37
- export function sanitizeNamespace(namespace: string): string {
38
- return namespace.replace(/[^a-zA-Z0-9_]/g, "_");
39
- }
40
-
41
- /**
42
- * Creates a table name mapper for a given namespace.
43
- * Physical names have format: {logicalName}_{sanitizedNamespace}
44
- * The namespace is sanitized to match TypeScript export names used in the schema
45
- */
46
- export function createTableNameMapper(namespace: string): TableNameMapper {
47
- const sanitized = sanitizeNamespace(namespace);
48
- return {
49
- toPhysical: (logicalName: string) => `${logicalName}_${sanitized}`,
50
- toLogical: (physicalName: string) => {
51
- if (physicalName.endsWith(`_${sanitized}`)) {
52
- return physicalName.slice(0, -(sanitized.length + 1));
53
- }
54
- return physicalName;
55
- },
56
- };
57
- }
58
-
59
25
  export interface DrizzleResult {
60
26
  rows: Record<string, unknown>[];
61
27
  affectedRows: number;
@@ -1,7 +1,8 @@
1
- import { mkdir, writeFile, rm } from "node:fs/promises";
1
+ import { mkdir, writeFile, rm, access } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { generateSchema, type SupportedProvider } from "./generate";
4
4
  import type { Schema } from "../../schema/create";
5
+ import { internalSchema } from "../../fragments/internal-fragment";
5
6
 
6
7
  /**
7
8
  * Writes a Fragno schema to a temporary TypeScript file and dynamically imports it.
@@ -34,20 +35,50 @@ export async function writeAndLoadSchema(
34
35
  // Generate unique schema file path
35
36
  const schemaFilePath = join(
36
37
  testDir,
37
- `test-schema-${Date.now()}-${Math.random().toString(36).slice(2, 9)}.ts`,
38
+ `test-schema-${testFileName}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}.ts`,
38
39
  );
39
40
 
40
41
  // Generate and write the Drizzle schema to file
41
- // Use empty namespace for tests to avoid table name prefixing
42
- const drizzleSchemaTs = generateSchema([{ namespace: namespace ?? "", schema }], dialect);
42
+ // Always include settings schema first (as done in generation-engine.ts), then the test schema
43
+ // De-duplicate: if the test schema IS the settings schema, don't add it twice
44
+ const fragments: Array<{ namespace: string; schema: Schema }> = [
45
+ { namespace: "", schema: internalSchema },
46
+ ];
47
+
48
+ if (schema !== internalSchema) {
49
+ fragments.push({ namespace: namespace ?? "", schema });
50
+ }
51
+
52
+ const drizzleSchemaTs = generateSchema(fragments, dialect);
43
53
  await writeFile(schemaFilePath, drizzleSchemaTs, "utf-8");
44
54
 
55
+ // Ensure the file is accessible before importing (handle race conditions)
56
+ let retries = 0;
57
+ const maxRetries = 10;
58
+ while (retries < maxRetries) {
59
+ try {
60
+ await access(schemaFilePath);
61
+ break;
62
+ } catch {
63
+ if (retries === maxRetries - 1) {
64
+ throw new Error(`Schema file was not accessible after writing: ${schemaFilePath}`);
65
+ }
66
+ // Wait a bit before retrying
67
+ await new Promise((resolve) => setTimeout(resolve, 10));
68
+ retries++;
69
+ }
70
+ }
71
+
45
72
  // Dynamically import the generated schema (with cache busting)
46
73
  const schemaModule = await import(`${schemaFilePath}?t=${Date.now()}`);
47
74
 
48
75
  // Cleanup function to remove the test-specific directory
49
76
  const cleanup = async () => {
50
- await rm(testDir, { recursive: true, force: true });
77
+ try {
78
+ await rm(testDir, { recursive: true, force: true });
79
+ } catch {
80
+ // Ignore error if directory doesn't exist
81
+ }
51
82
  };
52
83
 
53
84
  return {
@@ -0,0 +1,14 @@
1
+ # Generic SQL Adapter
2
+
3
+ ## Goals:
4
+
5
+ - Follow roughly the Kysely interfaces so that we can use Kysely adapters.
6
+ - Use this to replace ALL query execution logic.
7
+ - "Own" the result transformation step.
8
+ - Optionally able to create SQL migrations internally.
9
+ - Be able to map names (tables, columns, constraints, etc)
10
+ - Be able to run migrations directly from the Fragment
11
+
12
+ ## Non-goal:
13
+
14
+ - Generate schemas in ORM-specific DSLs, this is left to the ORM adapters.
@@ -0,0 +1,144 @@
1
+ export const supportedDatabases = ["sqlite", "postgresql", "mysql"] as const;
2
+ export type SupportedDatabase = (typeof supportedDatabases)[number];
3
+
4
+ export const supportedDriverTypes = [
5
+ "sqlocal",
6
+ "cloudflare_durable_objects",
7
+ "better-sqlite3",
8
+ "pg",
9
+ "pglite",
10
+ "mysql2",
11
+ ] as const;
12
+
13
+ export type SupportedDriverType = (typeof supportedDriverTypes)[number];
14
+
15
+ export abstract class DriverConfig<T extends SupportedDriverType = SupportedDriverType> {
16
+ abstract readonly driverType: T;
17
+ abstract readonly databaseType: SupportedDatabase;
18
+
19
+ abstract readonly supportsReturning: boolean;
20
+ abstract readonly supportsJson: boolean;
21
+
22
+ /**
23
+ * Column name for internal ID in RETURNING results.
24
+ * Only defined if supportsReturning is true.
25
+ */
26
+ abstract readonly internalIdColumn: string | undefined;
27
+
28
+ get supportsRowsAffected(): boolean {
29
+ return !!this.extractAffectedRows;
30
+ }
31
+
32
+ /**
33
+ * Extract the number of affected rows from a query result.
34
+ * Only implemented for drivers that support affected rows reporting.
35
+ *
36
+ * @param result - The query result from the SQL driver
37
+ * @returns The number of affected rows as bigint
38
+ * @throws Error if affected rows information is not found in the result
39
+ */
40
+ extractAffectedRows?(result: Record<string, unknown>): bigint;
41
+ }
42
+
43
+ export class SQLocalDriverConfig extends DriverConfig<"sqlocal"> {
44
+ override readonly driverType = "sqlocal";
45
+ override readonly databaseType = "sqlite";
46
+ override readonly supportsReturning = true;
47
+ override readonly supportsJson = false;
48
+ override readonly internalIdColumn = "_internalId";
49
+ }
50
+
51
+ export class CloudflareDurableObjectsDriverConfig extends DriverConfig<"cloudflare_durable_objects"> {
52
+ override readonly driverType = "cloudflare_durable_objects";
53
+ override readonly databaseType = "sqlite";
54
+ override readonly supportsReturning = true;
55
+ override readonly supportsJson = false;
56
+ override readonly internalIdColumn = "_internalId";
57
+ }
58
+
59
+ export class BetterSQLite3DriverConfig extends DriverConfig<"better-sqlite3"> {
60
+ override readonly driverType = "better-sqlite3";
61
+ override readonly databaseType = "sqlite";
62
+ override readonly supportsReturning = true;
63
+ override readonly supportsJson = false;
64
+ override readonly internalIdColumn = "_internalId";
65
+
66
+ override extractAffectedRows(result: Record<string, unknown>): bigint {
67
+ if ("numAffectedRows" in result) {
68
+ const value = result["numAffectedRows"];
69
+ if (typeof value === "bigint") {
70
+ return value;
71
+ }
72
+ if (typeof value === "number") {
73
+ return BigInt(value);
74
+ }
75
+ }
76
+
77
+ throw new Error(
78
+ `No affected rows found in result: ${JSON.stringify(result)}. Driver ${this.driverType} is expected to support affected rows.`,
79
+ );
80
+ }
81
+ }
82
+
83
+ export class NodePostgresDriverConfig extends DriverConfig<"pg"> {
84
+ override readonly driverType = "pg";
85
+ override readonly databaseType = "postgresql";
86
+ override readonly supportsReturning = true;
87
+ override readonly supportsJson = true;
88
+ override readonly internalIdColumn = "_internalId";
89
+
90
+ override extractAffectedRows(result: Record<string, unknown>): bigint {
91
+ if ("numAffectedRows" in result) {
92
+ const value = result["numAffectedRows"];
93
+ if (typeof value === "bigint") {
94
+ return value;
95
+ }
96
+ if (typeof value === "number") {
97
+ return BigInt(value);
98
+ }
99
+ }
100
+ if ("numChangedRows" in result) {
101
+ const value = result["numChangedRows"];
102
+ if (typeof value === "bigint") {
103
+ return value;
104
+ }
105
+ if (typeof value === "number") {
106
+ return BigInt(value);
107
+ }
108
+ }
109
+ throw new Error(
110
+ `No affected rows found in result: ${JSON.stringify(result)}. Driver ${this.driverType} is expected to support affected rows.`,
111
+ );
112
+ }
113
+ }
114
+
115
+ export class PGLiteDriverConfig extends DriverConfig<"pglite"> {
116
+ override readonly driverType = "pglite";
117
+ override readonly databaseType = "postgresql";
118
+ override readonly supportsReturning = true;
119
+ override readonly supportsJson = true;
120
+ override readonly internalIdColumn = "_internalId";
121
+
122
+ override extractAffectedRows(result: Record<string, unknown>): bigint {
123
+ if ("affectedRows" in result) {
124
+ const value = result["affectedRows"];
125
+ if (typeof value === "bigint") {
126
+ return value;
127
+ }
128
+ if (typeof value === "number") {
129
+ return BigInt(value);
130
+ }
131
+ }
132
+ throw new Error(
133
+ `No affected rows found in result: ${JSON.stringify(result)}. Driver ${this.driverType} is expected to support affected rows.`,
134
+ );
135
+ }
136
+ }
137
+
138
+ export class MySQL2DriverConfig extends DriverConfig<"mysql2"> {
139
+ override readonly driverType = "mysql2";
140
+ override readonly databaseType = "mysql";
141
+ override readonly supportsReturning = false;
142
+ override readonly supportsJson = true;
143
+ override readonly internalIdColumn = undefined;
144
+ }