@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
@@ -1,29 +1,35 @@
1
- import { Kysely, SqliteDialect } from "kysely";
2
- import { describe, expect, it, beforeAll } from "vitest";
3
- import { execute } from "./execute";
4
- import type { MigrationOperation } from "../../../migration-engine/shared";
5
- import type { KyselyConfig } from "../kysely-adapter";
6
- import { SqliteMigrationExecutor } from "./execute-sqlite";
7
-
8
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
- type KyselyAny = Kysely<any>;
10
-
11
- function assertSingleResult<T>(result: T | T[]): asserts result is T {
12
- if (Array.isArray(result)) {
13
- throw new Error("Expected single result, got array");
1
+ import { describe, expect, it } from "vitest";
2
+ import type { MigrationOperation } from "../../../../migration-engine/shared";
3
+ import { createColdKysely } from "../cold-kysely";
4
+ import { SQLiteSQLGenerator } from "./sqlite";
5
+
6
+ describe("SQLiteSQLGenerator", () => {
7
+ const coldKysely = createColdKysely("sqlite");
8
+ const generator = new SQLiteSQLGenerator(coldKysely, "sqlite");
9
+
10
+ /**
11
+ * Helper to compile a single operation and extract the main SQL statement.
12
+ * SQLite preprocessing adds PRAGMA statement, so main statement is at index 1.
13
+ */
14
+ function compileOne(operation: MigrationOperation): string {
15
+ const statements = generator.compile([operation]);
16
+ // SQLite adds PRAGMA defer_foreign_keys at the beginning
17
+ expect(statements.length).toBeGreaterThanOrEqual(2);
18
+ expect(statements[0].sql).toBe("PRAGMA defer_foreign_keys = ON");
19
+ return statements[1].sql;
14
20
  }
15
- }
16
21
 
17
- describe("execute() - SQLite", () => {
18
- let db: KyselyAny;
19
- let config: KyselyConfig;
20
-
21
- beforeAll(async () => {
22
- // Create a Kysely instance with a SqliteDialect, but not actually connected to a database
23
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
- db = new Kysely({ dialect: new SqliteDialect({} as any) });
25
- config = { db, provider: "sqlite" };
26
- });
22
+ /**
23
+ * Helper to compile a single operation and extract all main SQL statements.
24
+ * For alter-table operations that generate multiple statements.
25
+ */
26
+ function compileMany(operation: MigrationOperation): string[] {
27
+ const statements = generator.compile([operation]);
28
+ expect(statements.length).toBeGreaterThanOrEqual(1);
29
+ expect(statements[0].sql).toBe("PRAGMA defer_foreign_keys = ON");
30
+ // Return everything except pragma statement
31
+ return statements.slice(1).map((s) => s.sql);
32
+ }
27
33
 
28
34
  describe("create-table", () => {
29
35
  it("should generate SQL for simple table with columns", () => {
@@ -52,14 +58,8 @@ describe("execute() - SQLite", () => {
52
58
  ],
53
59
  };
54
60
 
55
- const result = execute(operation, config, () => {
56
- throw new Error("No custom operations");
57
- });
58
-
59
- assertSingleResult(result);
60
-
61
- const compiled = result.compile();
62
- expect(compiled.sql).toMatchInlineSnapshot(
61
+ const sql = compileOne(operation);
62
+ expect(sql).toMatchInlineSnapshot(
63
63
  `"create table "users" ("id" integer not null unique, "name" text not null, "email" text not null)"`,
64
64
  );
65
65
  });
@@ -81,14 +81,8 @@ describe("execute() - SQLite", () => {
81
81
  ],
82
82
  };
83
83
 
84
- const result = execute(operation, config, () => {
85
- throw new Error("No custom operations");
86
- });
87
-
88
- assertSingleResult(result);
89
-
90
- const compiled = result.compile();
91
- expect(compiled.sql).toMatchInlineSnapshot(
84
+ const sql = compileOne(operation);
85
+ expect(sql).toMatchInlineSnapshot(
92
86
  `"create table "test_types" ("col_int" integer not null unique, "col_bigint" blob not null, "col_decimal" real not null, "col_bool" integer not null, "col_date" integer not null, "col_timestamp" integer not null, "col_json" text not null, "col_binary" blob not null, "col_varchar" text not null)"`,
93
87
  );
94
88
  });
@@ -104,14 +98,8 @@ describe("execute() - SQLite", () => {
104
98
  ],
105
99
  };
106
100
 
107
- const result = execute(operation, config, () => {
108
- throw new Error("No custom operations");
109
- });
110
-
111
- assertSingleResult(result);
112
-
113
- const compiled = result.compile();
114
- expect(compiled.sql).toMatchInlineSnapshot(
101
+ const sql = compileOne(operation);
102
+ expect(sql).toMatchInlineSnapshot(
115
103
  `"create table "nullable_test" ("id" integer not null unique, "optional_name" text, "optional_age" integer)"`,
116
104
  );
117
105
  });
@@ -146,14 +134,8 @@ describe("execute() - SQLite", () => {
146
134
  ],
147
135
  };
148
136
 
149
- const result = execute(operation, config, () => {
150
- throw new Error("No custom operations");
151
- });
152
-
153
- assertSingleResult(result);
154
-
155
- const compiled = result.compile();
156
- expect(compiled.sql).toMatchInlineSnapshot(
137
+ const sql = compileOne(operation);
138
+ expect(sql).toMatchInlineSnapshot(
157
139
  `"create table "defaults_test" ("id" integer not null unique, "status" text default 'pending' not null, "count" integer default 0 not null, "is_active" integer default true not null)"`,
158
140
  );
159
141
  });
@@ -174,14 +156,8 @@ describe("execute() - SQLite", () => {
174
156
  ],
175
157
  };
176
158
 
177
- const result = execute(operation, config, () => {
178
- throw new Error("No custom operations");
179
- });
180
-
181
- assertSingleResult(result);
182
-
183
- const compiled = result.compile();
184
- expect(compiled.sql).toMatchInlineSnapshot(
159
+ const sql = compileOne(operation);
160
+ expect(sql).toMatchInlineSnapshot(
185
161
  `"create table "timestamps_test" ("id" integer not null unique, "created_at" integer default CURRENT_TIMESTAMP not null)"`,
186
162
  );
187
163
  });
@@ -197,14 +173,8 @@ describe("execute() - SQLite", () => {
197
173
  ],
198
174
  };
199
175
 
200
- const result = execute(operation, config, () => {
201
- throw new Error("No custom operations");
202
- });
203
-
204
- assertSingleResult(result);
205
-
206
- const compiled = result.compile();
207
- expect(compiled.sql).toMatchInlineSnapshot(
176
+ const sql = compileOne(operation);
177
+ expect(sql).toMatchInlineSnapshot(
208
178
  `"create table "posts" ("id" integer not null unique, "user_id" integer not null, "title" text not null)"`,
209
179
  );
210
180
  });
@@ -220,14 +190,8 @@ describe("execute() - SQLite", () => {
220
190
  ],
221
191
  };
222
192
 
223
- const result = execute(operation, config, () => {
224
- throw new Error("No custom operations");
225
- });
226
-
227
- assertSingleResult(result);
228
-
229
- const compiled = result.compile();
230
- expect(compiled.sql).toMatchInlineSnapshot(
193
+ const sql = compileOne(operation);
194
+ expect(sql).toMatchInlineSnapshot(
231
195
  `"create table "items" ("id" integer not null unique, "_internalId" integer not null primary key autoincrement, "name" text not null)"`,
232
196
  );
233
197
  });
@@ -241,14 +205,8 @@ describe("execute() - SQLite", () => {
241
205
  to: "new_name",
242
206
  };
243
207
 
244
- const result = execute(operation, config, () => {
245
- throw new Error("No custom operations");
246
- });
247
-
248
- assertSingleResult(result);
249
-
250
- const compiled = result.compile();
251
- expect(compiled.sql).toMatchInlineSnapshot(`"alter table "old_name" rename to "new_name""`);
208
+ const sql = compileOne(operation);
209
+ expect(sql).toMatchInlineSnapshot(`"alter table "old_name" rename to "new_name""`);
252
210
  });
253
211
  });
254
212
 
@@ -259,14 +217,8 @@ describe("execute() - SQLite", () => {
259
217
  name: "to_drop",
260
218
  };
261
219
 
262
- const result = execute(operation, config, () => {
263
- throw new Error("No custom operations");
264
- });
265
-
266
- assertSingleResult(result);
267
-
268
- const compiled = result.compile();
269
- expect(compiled.sql).toMatchInlineSnapshot(`"drop table "to_drop""`);
220
+ const sql = compileOne(operation);
221
+ expect(sql).toMatchInlineSnapshot(`"drop table "to_drop""`);
270
222
  });
271
223
  });
272
224
 
@@ -288,17 +240,9 @@ describe("execute() - SQLite", () => {
288
240
  ],
289
241
  };
290
242
 
291
- const results = execute(operation, config, () => {
292
- throw new Error("No custom operations");
293
- });
294
-
295
- if (!Array.isArray(results)) {
296
- throw new Error("Expected array of results");
297
- }
298
-
299
- expect(results).toHaveLength(1);
300
- const compiled = results[0].compile();
301
- expect(compiled.sql).toMatchInlineSnapshot(
243
+ const statements = compileMany(operation);
244
+ expect(statements).toHaveLength(1);
245
+ expect(statements[0]).toMatchInlineSnapshot(
302
246
  `"alter table "test_table" add column "new_column" text"`,
303
247
  );
304
248
  });
@@ -330,19 +274,12 @@ describe("execute() - SQLite", () => {
330
274
  ],
331
275
  };
332
276
 
333
- const results = execute(operation, config, () => {
334
- throw new Error("No custom operations");
335
- });
336
-
337
- if (!Array.isArray(results)) {
338
- throw new Error("Expected array of results");
339
- }
340
-
341
- expect(results).toHaveLength(2);
342
- expect(results[0].compile().sql).toMatchInlineSnapshot(
277
+ const statements = compileMany(operation);
278
+ expect(statements).toHaveLength(2);
279
+ expect(statements[0]).toMatchInlineSnapshot(
343
280
  `"alter table "test_table" add column "col1" text"`,
344
281
  );
345
- expect(results[1].compile().sql).toMatchInlineSnapshot(
282
+ expect(statements[1]).toMatchInlineSnapshot(
346
283
  `"alter table "test_table" add column "col2" integer default 0 not null"`,
347
284
  );
348
285
  });
@@ -362,17 +299,9 @@ describe("execute() - SQLite", () => {
362
299
  ],
363
300
  };
364
301
 
365
- const results = execute(operation, config, () => {
366
- throw new Error("No custom operations");
367
- });
368
-
369
- if (!Array.isArray(results)) {
370
- throw new Error("Expected array of results");
371
- }
372
-
373
- expect(results).toHaveLength(1);
374
- const compiled = results[0].compile();
375
- expect(compiled.sql).toMatchInlineSnapshot(
302
+ const statements = compileMany(operation);
303
+ expect(statements).toHaveLength(1);
304
+ expect(statements[0]).toMatchInlineSnapshot(
376
305
  `"alter table "test_table" rename column "old_name" to "new_name""`,
377
306
  );
378
307
  });
@@ -391,17 +320,9 @@ describe("execute() - SQLite", () => {
391
320
  ],
392
321
  };
393
322
 
394
- const results = execute(operation, config, () => {
395
- throw new Error("No custom operations");
396
- });
397
-
398
- if (!Array.isArray(results)) {
399
- throw new Error("Expected array of results");
400
- }
401
-
402
- expect(results).toHaveLength(1);
403
- const compiled = results[0].compile();
404
- expect(compiled.sql).toMatchInlineSnapshot(
323
+ const statements = compileMany(operation);
324
+ expect(statements).toHaveLength(1);
325
+ expect(statements[0]).toMatchInlineSnapshot(
405
326
  `"alter table "test_table" drop column "to_drop""`,
406
327
  );
407
328
  });
@@ -429,11 +350,9 @@ describe("execute() - SQLite", () => {
429
350
  ],
430
351
  };
431
352
 
432
- expect(() => {
433
- execute(operation, config, () => {
434
- throw new Error("No custom operations");
435
- });
436
- }).toThrow("SQLite doesn't support updating columns. Recreate the table instead.");
353
+ expect(() => generator.compile([operation])).toThrow(
354
+ "SQLite doesn't support updating columns. Recreate the table instead.",
355
+ );
437
356
  });
438
357
 
439
358
  it("should throw error when trying to update nullable constraint", () => {
@@ -457,11 +376,9 @@ describe("execute() - SQLite", () => {
457
376
  ],
458
377
  };
459
378
 
460
- expect(() => {
461
- execute(operation, config, () => {
462
- throw new Error("No custom operations");
463
- });
464
- }).toThrow("SQLite doesn't support updating columns. Recreate the table instead.");
379
+ expect(() => generator.compile([operation])).toThrow(
380
+ "SQLite doesn't support updating columns. Recreate the table instead.",
381
+ );
465
382
  });
466
383
 
467
384
  it("should throw error when trying to update default value", () => {
@@ -486,11 +403,9 @@ describe("execute() - SQLite", () => {
486
403
  ],
487
404
  };
488
405
 
489
- expect(() => {
490
- execute(operation, config, () => {
491
- throw new Error("No custom operations");
492
- });
493
- }).toThrow("SQLite doesn't support updating columns. Recreate the table instead.");
406
+ expect(() => generator.compile([operation])).toThrow(
407
+ "SQLite doesn't support updating columns. Recreate the table instead.",
408
+ );
494
409
  });
495
410
 
496
411
  it("should throw error when trying to update ID column", () => {
@@ -514,11 +429,7 @@ describe("execute() - SQLite", () => {
514
429
  ],
515
430
  };
516
431
 
517
- expect(() => {
518
- execute(operation, config, () => {
519
- throw new Error("No custom operations");
520
- });
521
- }).toThrow(
432
+ expect(() => generator.compile([operation])).toThrow(
522
433
  "ID columns cannot be updated. Not every database supports updating primary keys and often requires workarounds.",
523
434
  );
524
435
  });
@@ -545,11 +456,9 @@ describe("execute() - SQLite", () => {
545
456
  };
546
457
 
547
458
  // SQLite throws error before checking if it's a no-op
548
- expect(() => {
549
- execute(operation, config, () => {
550
- throw new Error("No custom operations");
551
- });
552
- }).toThrow("SQLite doesn't support updating columns. Recreate the table instead.");
459
+ expect(() => generator.compile([operation])).toThrow(
460
+ "SQLite doesn't support updating columns. Recreate the table instead.",
461
+ );
553
462
  });
554
463
  });
555
464
 
@@ -566,12 +475,8 @@ describe("execute() - SQLite", () => {
566
475
  },
567
476
  };
568
477
 
569
- expect(() => {
570
- execute(operation, config, () => {
571
- throw new Error("No custom operations");
572
- });
573
- }).toThrow(
574
- "SQLite doesn't support modifying foreign keys directly. Use `recreate-table` instead.",
478
+ expect(() => generator.compile([operation])).toThrow(
479
+ "SQLite doesn't support modifying foreign keys",
575
480
  );
576
481
  });
577
482
 
@@ -587,12 +492,8 @@ describe("execute() - SQLite", () => {
587
492
  },
588
493
  };
589
494
 
590
- expect(() => {
591
- execute(operation, config, () => {
592
- throw new Error("No custom operations");
593
- });
594
- }).toThrow(
595
- "SQLite doesn't support modifying foreign keys directly. Use `recreate-table` instead.",
495
+ expect(() => generator.compile([operation])).toThrow(
496
+ "SQLite doesn't support modifying foreign keys",
596
497
  );
597
498
  });
598
499
  });
@@ -605,12 +506,8 @@ describe("execute() - SQLite", () => {
605
506
  name: "posts_user_id_fk",
606
507
  };
607
508
 
608
- expect(() => {
609
- execute(operation, config, () => {
610
- throw new Error("No custom operations");
611
- });
612
- }).toThrow(
613
- "SQLite doesn't support modifying foreign keys directly. Use `recreate-table` instead.",
509
+ expect(() => generator.compile([operation])).toThrow(
510
+ "SQLite doesn't support modifying foreign keys",
614
511
  );
615
512
  });
616
513
  });
@@ -625,16 +522,8 @@ describe("execute() - SQLite", () => {
625
522
  unique: false,
626
523
  };
627
524
 
628
- const result = execute(operation, config, () => {
629
- throw new Error("No custom operations");
630
- });
631
-
632
- assertSingleResult(result);
633
-
634
- const compiled = result.compile();
635
- expect(compiled.sql).toMatchInlineSnapshot(
636
- `"create index "idx_email" on "test_table" ("email")"`,
637
- );
525
+ const sql = compileOne(operation);
526
+ expect(sql).toMatchInlineSnapshot(`"create index "idx_email" on "test_table" ("email")"`);
638
527
  });
639
528
 
640
529
  it("should generate SQL for unique index", () => {
@@ -646,14 +535,8 @@ describe("execute() - SQLite", () => {
646
535
  unique: true,
647
536
  };
648
537
 
649
- const result = execute(operation, config, () => {
650
- throw new Error("No custom operations");
651
- });
652
-
653
- assertSingleResult(result);
654
-
655
- const compiled = result.compile();
656
- expect(compiled.sql).toMatchInlineSnapshot(
538
+ const sql = compileOne(operation);
539
+ expect(sql).toMatchInlineSnapshot(
657
540
  `"create unique index "idx_unique_email" on "test_table" ("email")"`,
658
541
  );
659
542
  });
@@ -667,14 +550,8 @@ describe("execute() - SQLite", () => {
667
550
  unique: false,
668
551
  };
669
552
 
670
- const result = execute(operation, config, () => {
671
- throw new Error("No custom operations");
672
- });
673
-
674
- assertSingleResult(result);
675
-
676
- const compiled = result.compile();
677
- expect(compiled.sql).toMatchInlineSnapshot(
553
+ const sql = compileOne(operation);
554
+ expect(sql).toMatchInlineSnapshot(
678
555
  `"create index "idx_email_name" on "test_table" ("email", "name")"`,
679
556
  );
680
557
  });
@@ -688,14 +565,8 @@ describe("execute() - SQLite", () => {
688
565
  unique: true,
689
566
  };
690
567
 
691
- const result = execute(operation, config, () => {
692
- throw new Error("No custom operations");
693
- });
694
-
695
- assertSingleResult(result);
696
-
697
- const compiled = result.compile();
698
- expect(compiled.sql).toMatchInlineSnapshot(
568
+ const sql = compileOne(operation);
569
+ expect(sql).toMatchInlineSnapshot(
699
570
  `"create unique index "idx_unique_email_name" on "test_table" ("email", "name")"`,
700
571
  );
701
572
  });
@@ -709,71 +580,14 @@ describe("execute() - SQLite", () => {
709
580
  name: "idx_email",
710
581
  };
711
582
 
712
- const result = execute(operation, config, () => {
713
- throw new Error("No custom operations");
714
- });
715
-
716
- assertSingleResult(result);
717
-
718
- const compiled = result.compile();
719
- expect(compiled.sql).toMatchInlineSnapshot(`"drop index if exists "idx_email""`);
720
- });
721
- });
722
-
723
- describe("custom operations", () => {
724
- it("should handle custom operations via callback", () => {
725
- const operation: MigrationOperation = {
726
- type: "custom",
727
- customType: "test-operation",
728
- data: "test-data",
729
- };
730
-
731
- let customCallbackCalled = false;
732
-
733
- const result = execute(operation, config, (op) => {
734
- customCallbackCalled = true;
735
- expect(op).toEqual(operation);
736
-
737
- // Return a kysely query
738
- return db.schema.createTable("custom_table").addColumn("id", "integer");
739
- });
740
-
741
- expect(customCallbackCalled).toBe(true);
742
-
743
- assertSingleResult(result);
744
-
745
- const compiled = result.compile();
746
- expect(compiled.sql).toContain("create table");
747
- expect(compiled.sql).toContain("custom_table");
748
- });
749
-
750
- it("should support custom operations returning array of nodes", () => {
751
- const operation: MigrationOperation = {
752
- type: "custom",
753
- customType: "multi-operation",
754
- };
755
-
756
- const results = execute(operation, config, () => {
757
- return [
758
- db.schema.createTable("table1").addColumn("id", "integer"),
759
- db.schema.createTable("table2").addColumn("id", "integer"),
760
- ];
761
- });
762
-
763
- if (!Array.isArray(results)) {
764
- throw new Error("Expected array of results");
765
- }
766
-
767
- expect(results).toHaveLength(2);
768
- expect(results[0].compile().sql).toContain("table1");
769
- expect(results[1].compile().sql).toContain("table2");
583
+ const sql = compileOne(operation);
584
+ expect(sql).toMatchInlineSnapshot(`"drop index if exists "idx_email" on "test_table""`);
770
585
  });
771
586
  });
772
587
 
773
588
  describe("complex migration scenarios", () => {
774
589
  it("should generate correct SQL for full schema migration", () => {
775
- // 1. Create users table
776
- const createUsers = execute(
590
+ const operations: MigrationOperation[] = [
777
591
  {
778
592
  type: "create-table",
779
593
  name: "users",
@@ -783,20 +597,6 @@ describe("execute() - SQLite", () => {
783
597
  { name: "name", type: "string", isNullable: false, role: "regular" },
784
598
  ],
785
599
  },
786
- config,
787
- () => {
788
- throw new Error("No custom operations");
789
- },
790
- );
791
-
792
- assertSingleResult(createUsers);
793
-
794
- expect(createUsers.compile().sql).toMatchInlineSnapshot(
795
- `"create table "users" ("id" integer not null unique, "email" text not null, "name" text not null)"`,
796
- );
797
-
798
- // 2. Add unique index on email
799
- const addIndex = execute(
800
600
  {
801
601
  type: "add-index",
802
602
  table: "users",
@@ -804,20 +604,6 @@ describe("execute() - SQLite", () => {
804
604
  name: "idx_unique_email",
805
605
  unique: true,
806
606
  },
807
- config,
808
- () => {
809
- throw new Error("No custom operations");
810
- },
811
- );
812
-
813
- assertSingleResult(addIndex);
814
-
815
- expect(addIndex.compile().sql).toMatchInlineSnapshot(
816
- `"create unique index "idx_unique_email" on "users" ("email")"`,
817
- );
818
-
819
- // 3. Create posts table
820
- const createPosts = execute(
821
607
  {
822
608
  type: "create-table",
823
609
  name: "posts",
@@ -828,23 +614,6 @@ describe("execute() - SQLite", () => {
828
614
  { name: "content", type: "string", isNullable: false, role: "regular" },
829
615
  ],
830
616
  },
831
- config,
832
- () => {
833
- throw new Error("No custom operations");
834
- },
835
- );
836
-
837
- assertSingleResult(createPosts);
838
-
839
- expect(createPosts.compile().sql).toMatchInlineSnapshot(
840
- `"create table "posts" ("id" integer not null unique, "user_id" integer not null, "title" text not null, "content" text not null)"`,
841
- );
842
-
843
- // 4. Note: Cannot add foreign key after table creation in SQLite
844
- // Foreign keys must be defined in the CREATE TABLE statement
845
-
846
- // 5. Alter posts table to add a new column
847
- const alterResults = execute(
848
617
  {
849
618
  type: "alter-table",
850
619
  name: "posts",
@@ -861,17 +630,22 @@ describe("execute() - SQLite", () => {
861
630
  },
862
631
  ],
863
632
  },
864
- config,
865
- () => {
866
- throw new Error("No custom operations");
867
- },
868
- );
869
-
870
- if (!Array.isArray(alterResults)) {
871
- throw new Error("Expected array of results");
872
- }
633
+ ];
873
634
 
874
- expect(alterResults[0].compile().sql).toMatchInlineSnapshot(
635
+ const statements = generator.compile(operations);
636
+ // PRAGMA + 4 operations
637
+ expect(statements).toHaveLength(5);
638
+ expect(statements[0].sql).toBe("PRAGMA defer_foreign_keys = ON");
639
+ expect(statements[1].sql).toMatchInlineSnapshot(
640
+ `"create table "users" ("id" integer not null unique, "email" text not null, "name" text not null)"`,
641
+ );
642
+ expect(statements[2].sql).toMatchInlineSnapshot(
643
+ `"create unique index "idx_unique_email" on "users" ("email")"`,
644
+ );
645
+ expect(statements[3].sql).toMatchInlineSnapshot(
646
+ `"create table "posts" ("id" integer not null unique, "user_id" integer not null, "title" text not null, "content" text not null)"`,
647
+ );
648
+ expect(statements[4].sql).toMatchInlineSnapshot(
875
649
  `"alter table "posts" add column "published" integer default false not null"`,
876
650
  );
877
651
  });
@@ -902,24 +676,13 @@ describe("execute() - SQLite", () => {
902
676
  ],
903
677
  };
904
678
 
905
- const results = execute(operation, config, () => {
906
- throw new Error("No custom operations");
907
- });
908
-
909
- if (!Array.isArray(results)) {
910
- throw new Error("Expected array of results");
911
- }
912
-
913
- expect(results).toHaveLength(3);
914
- expect(results[0].compile().sql).toMatchInlineSnapshot(
915
- `"alter table "users" add column "age" integer"`,
916
- );
917
- expect(results[1].compile().sql).toMatchInlineSnapshot(
679
+ const statements = compileMany(operation);
680
+ expect(statements).toHaveLength(3);
681
+ expect(statements[0]).toMatchInlineSnapshot(`"alter table "users" add column "age" integer"`);
682
+ expect(statements[1]).toMatchInlineSnapshot(
918
683
  `"alter table "users" rename column "name" to "full_name""`,
919
684
  );
920
- expect(results[2].compile().sql).toMatchInlineSnapshot(
921
- `"alter table "users" drop column "old_field""`,
922
- );
685
+ expect(statements[2]).toMatchInlineSnapshot(`"alter table "users" drop column "old_field""`);
923
686
  });
924
687
  });
925
688
 
@@ -931,14 +694,8 @@ describe("execute() - SQLite", () => {
931
694
  columns: [{ name: "id", type: "integer", isNullable: false, role: "external-id" }],
932
695
  };
933
696
 
934
- const result = execute(operation, config, () => {
935
- throw new Error("No custom operations");
936
- });
937
-
938
- assertSingleResult(result);
939
-
940
- const compiled = result.compile();
941
- expect(compiled.sql).toContain('"user-profiles"');
697
+ const sql = compileOne(operation);
698
+ expect(sql).toContain('"user-profiles"');
942
699
  });
943
700
 
944
701
  it("should handle column names with special characters", () => {
@@ -951,14 +708,8 @@ describe("execute() - SQLite", () => {
951
708
  ],
952
709
  };
953
710
 
954
- const result = execute(operation, config, () => {
955
- throw new Error("No custom operations");
956
- });
957
-
958
- assertSingleResult(result);
959
-
960
- const compiled = result.compile();
961
- expect(compiled.sql).toContain('"user-name"');
711
+ const sql = compileOne(operation);
712
+ expect(sql).toContain('"user-name"');
962
713
  });
963
714
 
964
715
  it("should properly escape string default values", () => {
@@ -977,14 +728,8 @@ describe("execute() - SQLite", () => {
977
728
  ],
978
729
  };
979
730
 
980
- const result = execute(operation, config, () => {
981
- throw new Error("No custom operations");
982
- });
983
-
984
- assertSingleResult(result);
985
-
986
- const compiled = result.compile();
987
- expect(compiled.sql).toMatchInlineSnapshot(
731
+ const sql = compileOne(operation);
732
+ expect(sql).toMatchInlineSnapshot(
988
733
  `"create table "test" ("id" integer not null unique, "status" text default 'it''s pending' not null)"`,
989
734
  );
990
735
  });
@@ -1012,21 +757,15 @@ describe("execute() - SQLite", () => {
1012
757
  ],
1013
758
  };
1014
759
 
1015
- const result = execute(operation, config, () => {
1016
- throw new Error("No custom operations");
1017
- });
1018
-
1019
- assertSingleResult(result);
1020
-
1021
- const compiled = result.compile();
1022
- expect(compiled.sql).toMatchInlineSnapshot(
760
+ const sql = compileOne(operation);
761
+ expect(sql).toMatchInlineSnapshot(
1023
762
  `"create table "test" ("id" integer not null unique, "is_active" integer default true not null, "is_deleted" integer default false not null)"`,
1024
763
  );
1025
764
  });
1026
765
  });
1027
766
 
1028
767
  describe("SQLite-specific behavior", () => {
1029
- it("should handle bigint as integer (SQLite doesn't have true bigint)", () => {
768
+ it("should handle bigint as blob (SQLite stores bigint as blob)", () => {
1030
769
  const operation: MigrationOperation = {
1031
770
  type: "create-table",
1032
771
  name: "test",
@@ -1036,15 +775,8 @@ describe("execute() - SQLite", () => {
1036
775
  ],
1037
776
  };
1038
777
 
1039
- const result = execute(operation, config, () => {
1040
- throw new Error("No custom operations");
1041
- });
1042
-
1043
- assertSingleResult(result);
1044
-
1045
- const compiled = result.compile();
1046
- expect(compiled.sql).toContain("integer");
1047
- expect(compiled.sql).not.toContain("bigint");
778
+ const sql = compileOne(operation);
779
+ expect(sql).toContain("blob");
1048
780
  });
1049
781
 
1050
782
  it("should handle date/timestamp as integer (SQLite stores dates as integers)", () => {
@@ -1058,14 +790,8 @@ describe("execute() - SQLite", () => {
1058
790
  ],
1059
791
  };
1060
792
 
1061
- const result = execute(operation, config, () => {
1062
- throw new Error("No custom operations");
1063
- });
1064
-
1065
- assertSingleResult(result);
1066
-
1067
- const compiled = result.compile();
1068
- expect(compiled.sql).toMatchInlineSnapshot(
793
+ const sql = compileOne(operation);
794
+ expect(sql).toMatchInlineSnapshot(
1069
795
  `"create table "test" ("id" integer not null unique, "birth_date" integer not null, "created_at" integer not null)"`,
1070
796
  );
1071
797
  });
@@ -1080,14 +806,8 @@ describe("execute() - SQLite", () => {
1080
806
  ],
1081
807
  };
1082
808
 
1083
- const result = execute(operation, config, () => {
1084
- throw new Error("No custom operations");
1085
- });
1086
-
1087
- assertSingleResult(result);
1088
-
1089
- const compiled = result.compile();
1090
- expect(compiled.sql).toMatchInlineSnapshot(
809
+ const sql = compileOne(operation);
810
+ expect(sql).toMatchInlineSnapshot(
1091
811
  `"create table "test" ("id" integer not null unique, "metadata" text not null)"`,
1092
812
  );
1093
813
  });
@@ -1102,14 +822,8 @@ describe("execute() - SQLite", () => {
1102
822
  ],
1103
823
  };
1104
824
 
1105
- const result = execute(operation, config, () => {
1106
- throw new Error("No custom operations");
1107
- });
1108
-
1109
- assertSingleResult(result);
1110
-
1111
- const compiled = result.compile();
1112
- expect(compiled.sql).toMatchInlineSnapshot(
825
+ const sql = compileOne(operation);
826
+ expect(sql).toMatchInlineSnapshot(
1113
827
  `"create table "test" ("id" integer not null unique, "file_data" blob not null)"`,
1114
828
  );
1115
829
  });
@@ -1124,52 +838,13 @@ describe("execute() - SQLite", () => {
1124
838
  ],
1125
839
  };
1126
840
 
1127
- const result = execute(operation, config, () => {
1128
- throw new Error("No custom operations");
1129
- });
1130
-
1131
- assertSingleResult(result);
1132
-
1133
- const compiled = result.compile();
1134
- expect(compiled.sql).toMatchInlineSnapshot(
841
+ const sql = compileOne(operation);
842
+ expect(sql).toMatchInlineSnapshot(
1135
843
  `"create table "test" ("id" integer not null unique, "price" real not null)"`,
1136
844
  );
1137
845
  });
1138
846
  });
1139
847
 
1140
- describe("foreign key limitations", () => {
1141
- it("should document that foreign keys must be in CREATE TABLE for SQLite", () => {
1142
- // This test documents SQLite's limitation:
1143
- // Foreign keys MUST be defined in the CREATE TABLE statement
1144
- // They cannot be added with ALTER TABLE ADD FOREIGN KEY
1145
-
1146
- const createTableWithFKOperation: MigrationOperation = {
1147
- type: "custom",
1148
- customType: "create-table-with-fk",
1149
- };
1150
-
1151
- const result = execute(createTableWithFKOperation, config, () => {
1152
- // In practice, you would use Kysely's schema builder to create
1153
- // a table with foreign key constraints inline
1154
- return db.schema
1155
- .createTable("posts")
1156
- .addColumn("id", "integer", (col) => col.notNull().unique())
1157
- .addColumn("user_id", "integer", (col) =>
1158
- col.notNull().references("users.id").onDelete("cascade"),
1159
- )
1160
- .addColumn("title", "text", (col) => col.notNull());
1161
- });
1162
-
1163
- assertSingleResult(result);
1164
-
1165
- const compiled = result.compile();
1166
- expect(compiled.sql).toContain("create table");
1167
- expect(compiled.sql).toContain("posts");
1168
- expect(compiled.sql).toContain("user_id");
1169
- expect(compiled.sql).toContain("references");
1170
- });
1171
- });
1172
-
1173
848
  describe("SQLite FK preprocessing", () => {
1174
849
  it("should merge add-foreign-key into create-table when both are in same batch", () => {
1175
850
  const operations: MigrationOperation[] = [
@@ -1198,28 +873,38 @@ describe("execute() - SQLite", () => {
1198
873
  },
1199
874
  ];
1200
875
 
1201
- const executor = new SqliteMigrationExecutor(db, "sqlite");
1202
- const preprocessed = executor.preprocessOperations(operations);
876
+ const preprocessed = generator.preprocess(operations);
877
+
878
+ // PRAGMA + 2 create-table operations (FK merged into posts table)
879
+ expect(preprocessed).toHaveLength(3);
1203
880
 
1204
- // Should have 2 operations (2 create-table, FK merged into posts table)
1205
- expect(preprocessed).toHaveLength(2);
881
+ // First should be pragma
882
+ expect(preprocessed[0]).toEqual({ type: "custom", sql: "PRAGMA defer_foreign_keys = ON" });
1206
883
 
1207
- // First operation should be create users table
1208
- expect(preprocessed[0]).toMatchObject({
884
+ // Second operation should be create users table
885
+ expect(preprocessed[1]).toMatchObject({
1209
886
  type: "create-table",
1210
887
  name: "users",
1211
888
  });
1212
889
 
1213
- // Second operation should be create posts table with inline FK
1214
- expect(preprocessed[1]).toMatchObject({
890
+ // Third operation should be create posts table with inline FK
891
+ expect(preprocessed[2]).toMatchObject({
1215
892
  type: "create-table",
1216
893
  name: "posts",
1217
894
  });
1218
895
 
1219
- if (preprocessed[1].type === "create-table") {
1220
- expect(preprocessed[1].metadata?.inlineForeignKeys).toBeDefined();
1221
- expect(preprocessed[1].metadata?.inlineForeignKeys).toHaveLength(1);
1222
- expect(preprocessed[1].metadata?.inlineForeignKeys?.[0]).toMatchObject({
896
+ if (preprocessed[2].type === "create-table") {
897
+ const metadata = preprocessed[2].metadata as {
898
+ inlineForeignKeys?: {
899
+ name: string;
900
+ columns: string[];
901
+ referencedTable: string;
902
+ referencedColumns: string[];
903
+ }[];
904
+ };
905
+ expect(metadata?.inlineForeignKeys).toBeDefined();
906
+ expect(metadata?.inlineForeignKeys).toHaveLength(1);
907
+ expect(metadata?.inlineForeignKeys?.[0]).toMatchObject({
1223
908
  name: "posts_users_author_fk",
1224
909
  columns: ["author_id"],
1225
910
  referencedTable: "users",
@@ -1229,39 +914,46 @@ describe("execute() - SQLite", () => {
1229
914
  });
1230
915
 
1231
916
  it("should generate SQL with inline foreign key constraints", () => {
1232
- const operation: MigrationOperation = {
1233
- type: "create-table",
1234
- name: "posts",
1235
- columns: [
1236
- { name: "id", type: "integer", isNullable: false, role: "internal-id" },
1237
- { name: "author_id", type: "integer", isNullable: false, role: "reference" },
1238
- { name: "title", type: "string", isNullable: false, role: "regular" },
1239
- ],
1240
- metadata: {
1241
- inlineForeignKeys: [
1242
- {
1243
- name: "posts_users_author_fk",
1244
- columns: ["author_id"],
1245
- referencedTable: "users",
1246
- referencedColumns: ["id"],
1247
- },
917
+ const operations: MigrationOperation[] = [
918
+ {
919
+ type: "create-table",
920
+ name: "users",
921
+ columns: [{ name: "id", type: "integer", isNullable: false, role: "internal-id" }],
922
+ },
923
+ {
924
+ type: "create-table",
925
+ name: "posts",
926
+ columns: [
927
+ { name: "id", type: "integer", isNullable: false, role: "internal-id" },
928
+ { name: "author_id", type: "integer", isNullable: false, role: "reference" },
929
+ { name: "title", type: "string", isNullable: false, role: "regular" },
1248
930
  ],
1249
931
  },
1250
- };
932
+ {
933
+ type: "add-foreign-key",
934
+ table: "posts",
935
+ value: {
936
+ name: "posts_users_author_fk",
937
+ columns: ["author_id"],
938
+ referencedTable: "users",
939
+ referencedColumns: ["id"],
940
+ },
941
+ },
942
+ ];
1251
943
 
1252
- const result = execute(operation, config, () => {
1253
- throw new Error("No custom operations");
1254
- });
944
+ const statements = generator.compile(operations);
1255
945
 
1256
- assertSingleResult(result);
946
+ // PRAGMA + 2 create-table operations
947
+ expect(statements).toHaveLength(3);
948
+ expect(statements[0].sql).toBe("PRAGMA defer_foreign_keys = ON");
1257
949
 
1258
- const compiled = result.compile();
1259
- // Should contain the foreign key constraint
1260
- expect(compiled.sql).toContain("posts_users_author_fk");
1261
- expect(compiled.sql).toContain("foreign key");
1262
- expect(compiled.sql).toContain("author_id");
1263
- expect(compiled.sql).toContain("references");
1264
- expect(compiled.sql).toContain("users");
950
+ // Posts table should contain inline FK constraint
951
+ const postsSql = statements[2].sql;
952
+ expect(postsSql).toContain("posts_users_author_fk");
953
+ expect(postsSql).toContain("foreign key");
954
+ expect(postsSql).toContain("author_id");
955
+ expect(postsSql).toContain("references");
956
+ expect(postsSql).toContain("users");
1265
957
  });
1266
958
 
1267
959
  it("should keep add-foreign-key operations for existing tables (will throw error)", () => {
@@ -1283,14 +975,13 @@ describe("execute() - SQLite", () => {
1283
975
  },
1284
976
  ];
1285
977
 
1286
- const executor = new SqliteMigrationExecutor(db, "sqlite");
1287
- const preprocessed = executor.preprocessOperations(operations);
978
+ const preprocessed = generator.preprocess(operations);
1288
979
 
1289
- // Should have 2 operations (create-table + add-foreign-key)
1290
- expect(preprocessed).toHaveLength(2);
980
+ // PRAGMA + create-table + add-foreign-key
981
+ expect(preprocessed).toHaveLength(3);
1291
982
 
1292
- // Second operation should still be add-foreign-key (not merged)
1293
- expect(preprocessed[1]).toMatchObject({
983
+ // Third operation should still be add-foreign-key (not merged)
984
+ expect(preprocessed[2]).toMatchObject({
1294
985
  type: "add-foreign-key",
1295
986
  table: "posts",
1296
987
  });
@@ -1339,25 +1030,131 @@ describe("execute() - SQLite", () => {
1339
1030
  },
1340
1031
  ];
1341
1032
 
1342
- const executor = new SqliteMigrationExecutor(db, "sqlite");
1343
- const preprocessed = executor.preprocessOperations(operations);
1033
+ const preprocessed = generator.preprocess(operations);
1344
1034
 
1345
- // Should have 3 operations (3 create-table, both FKs merged into posts)
1346
- expect(preprocessed).toHaveLength(3);
1035
+ // PRAGMA + 3 create-table operations (both FKs merged into posts)
1036
+ expect(preprocessed).toHaveLength(4);
1347
1037
 
1348
1038
  // Posts table should have both foreign keys merged
1349
- const postsOp = preprocessed[2];
1039
+ const postsOp = preprocessed[3];
1350
1040
  expect(postsOp).toMatchObject({
1351
1041
  type: "create-table",
1352
1042
  name: "posts",
1353
1043
  });
1354
1044
 
1355
1045
  if (postsOp.type === "create-table") {
1356
- expect(postsOp.metadata?.inlineForeignKeys).toBeDefined();
1357
- expect(postsOp.metadata?.inlineForeignKeys).toHaveLength(2);
1358
- expect(postsOp.metadata?.inlineForeignKeys?.[0].name).toBe("posts_users_author_fk");
1359
- expect(postsOp.metadata?.inlineForeignKeys?.[1].name).toBe("posts_categories_category_fk");
1046
+ const metadata = postsOp.metadata as { inlineForeignKeys?: { name: string }[] };
1047
+ expect(metadata?.inlineForeignKeys).toBeDefined();
1048
+ expect(metadata?.inlineForeignKeys).toHaveLength(2);
1049
+ expect(metadata?.inlineForeignKeys?.[0].name).toBe("posts_users_author_fk");
1050
+ expect(metadata?.inlineForeignKeys?.[1].name).toBe("posts_categories_category_fk");
1360
1051
  }
1361
1052
  });
1362
1053
  });
1054
+
1055
+ describe("table name mapping", () => {
1056
+ const mapper = {
1057
+ toPhysical: (name: string) => `prefix_${name}`,
1058
+ toLogical: (name: string) => name.replace("prefix_", ""),
1059
+ };
1060
+
1061
+ it("should apply table name mapping to create-table", () => {
1062
+ const operation: MigrationOperation = {
1063
+ type: "create-table",
1064
+ name: "users",
1065
+ columns: [{ name: "id", type: "integer", isNullable: false, role: "external-id" }],
1066
+ };
1067
+
1068
+ const statements = generator.compile([operation], mapper);
1069
+ expect(statements[1].sql).toMatchInlineSnapshot(
1070
+ `"create table "prefix_users" ("id" integer not null unique)"`,
1071
+ );
1072
+ });
1073
+
1074
+ it("should apply table name mapping to indexes", () => {
1075
+ const operation: MigrationOperation = {
1076
+ type: "add-index",
1077
+ table: "users",
1078
+ columns: ["email"],
1079
+ name: "idx_email",
1080
+ unique: true,
1081
+ };
1082
+
1083
+ const statements = generator.compile([operation], mapper);
1084
+ expect(statements[1].sql).toMatchInlineSnapshot(
1085
+ `"create unique index "idx_email_prefix_users" on "prefix_users" ("email")"`,
1086
+ );
1087
+ });
1088
+ });
1089
+
1090
+ describe("preprocessing", () => {
1091
+ it("should add PRAGMA and handle FK merging", () => {
1092
+ const operations: MigrationOperation[] = [
1093
+ {
1094
+ type: "create-table",
1095
+ name: "users",
1096
+ columns: [{ name: "id", type: "string", isNullable: false, role: "external-id" }],
1097
+ },
1098
+ ];
1099
+
1100
+ const preprocessed = generator.preprocess(operations);
1101
+ expect(preprocessed.length).toBe(2);
1102
+ expect(preprocessed[0]).toEqual({ type: "custom", sql: "PRAGMA defer_foreign_keys = ON" });
1103
+ expect(preprocessed[1]).toEqual(operations[0]);
1104
+ });
1105
+
1106
+ it("should return empty array for empty operations", () => {
1107
+ const preprocessed = generator.preprocess([]);
1108
+ expect(preprocessed).toHaveLength(0);
1109
+ });
1110
+ });
1111
+
1112
+ describe("getDefaultValue", () => {
1113
+ it("should return literal value for all column types", () => {
1114
+ const defaultValue = generator.getDefaultValue({
1115
+ name: "status",
1116
+ type: "string",
1117
+ isNullable: false,
1118
+ role: "regular",
1119
+ default: { value: "active" },
1120
+ });
1121
+
1122
+ expect(defaultValue).toBeDefined();
1123
+ });
1124
+
1125
+ it("should return CURRENT_TIMESTAMP for dbSpecial: now", () => {
1126
+ const defaultValue = generator.getDefaultValue({
1127
+ name: "created_at",
1128
+ type: "timestamp",
1129
+ isNullable: false,
1130
+ role: "regular",
1131
+ default: { dbSpecial: "now" },
1132
+ });
1133
+
1134
+ expect(defaultValue).toBeDefined();
1135
+ });
1136
+
1137
+ it("should return undefined for runtime defaults", () => {
1138
+ const defaultValue = generator.getDefaultValue({
1139
+ name: "id",
1140
+ type: "string",
1141
+ isNullable: false,
1142
+ role: "regular",
1143
+ default: { runtime: "cuid" },
1144
+ });
1145
+
1146
+ expect(defaultValue).toBeUndefined();
1147
+ });
1148
+
1149
+ it("should return undefined when no default is set", () => {
1150
+ const defaultValue = generator.getDefaultValue({
1151
+ name: "name",
1152
+ type: "string",
1153
+ isNullable: false,
1154
+ role: "regular",
1155
+ });
1156
+
1157
+ expect(defaultValue).toBeUndefined();
1158
+ });
1159
+ });
1363
1160
  });