@fragno-dev/db 0.1.2 → 0.1.5

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 (176) hide show
  1. package/.turbo/turbo-build.log +210 -146
  2. package/CHANGELOG.md +19 -0
  3. package/LICENSE.md +16 -0
  4. package/dist/adapters/adapters.js +1 -0
  5. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
  6. package/dist/adapters/drizzle/drizzle-adapter.js +4 -2
  7. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
  8. package/dist/adapters/drizzle/drizzle-query.js +2 -2
  9. package/dist/adapters/drizzle/drizzle-query.js.map +1 -1
  10. package/dist/adapters/drizzle/drizzle-uow-compiler.js +4 -4
  11. package/dist/adapters/drizzle/drizzle-uow-decoder.js +14 -4
  12. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +1 -1
  13. package/dist/adapters/drizzle/drizzle-uow-executor.js +78 -60
  14. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +1 -1
  15. package/dist/adapters/drizzle/generate.js +5 -4
  16. package/dist/adapters/drizzle/generate.js.map +1 -1
  17. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
  18. package/dist/adapters/kysely/kysely-adapter.js +33 -22
  19. package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
  20. package/dist/adapters/kysely/migration/execute-base.js +128 -0
  21. package/dist/adapters/kysely/migration/execute-base.js.map +1 -0
  22. package/dist/adapters/kysely/migration/execute-factory.js +27 -0
  23. package/dist/adapters/kysely/migration/execute-factory.js.map +1 -0
  24. package/dist/adapters/kysely/migration/execute-mssql.js +112 -0
  25. package/dist/adapters/kysely/migration/execute-mssql.js.map +1 -0
  26. package/dist/adapters/kysely/migration/execute-mysql.js +93 -0
  27. package/dist/adapters/kysely/migration/execute-mysql.js.map +1 -0
  28. package/dist/adapters/kysely/migration/execute-postgres.js +104 -0
  29. package/dist/adapters/kysely/migration/execute-postgres.js.map +1 -0
  30. package/dist/adapters/kysely/migration/execute-sqlite.js +123 -0
  31. package/dist/adapters/kysely/migration/execute-sqlite.js.map +1 -0
  32. package/dist/adapters/kysely/migration/execute.js +23 -168
  33. package/dist/adapters/kysely/migration/execute.js.map +1 -1
  34. package/dist/migration-engine/shared.d.ts +24 -5
  35. package/dist/migration-engine/shared.d.ts.map +1 -1
  36. package/dist/migration-engine/shared.js.map +1 -1
  37. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/alias.js +77 -0
  38. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/alias.js.map +1 -0
  39. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/casing.js +49 -0
  40. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/casing.js.map +1 -0
  41. package/dist/node_modules/{.bun/drizzle-orm@0.44.6_4fae081eecb963e2 → .pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8}/node_modules/drizzle-orm/column-builder.js +1 -1
  42. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/column-builder.js.map +1 -0
  43. package/dist/node_modules/{.bun/drizzle-orm@0.44.6_4fae081eecb963e2 → .pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8}/node_modules/drizzle-orm/column.js +1 -1
  44. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/column.js.map +1 -0
  45. package/dist/node_modules/{.bun/drizzle-orm@0.44.6_4fae081eecb963e2 → .pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8}/node_modules/drizzle-orm/entity.js +1 -1
  46. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/entity.js.map +1 -0
  47. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/errors.js +21 -0
  48. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/errors.js.map +1 -0
  49. package/dist/node_modules/{.bun/drizzle-orm@0.44.6_4fae081eecb963e2 → .pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8}/node_modules/drizzle-orm/pg-core/columns/common.js +1 -1
  50. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/pg-core/columns/common.js.map +1 -0
  51. package/dist/node_modules/{.bun/drizzle-orm@0.44.6_4fae081eecb963e2 → .pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8}/node_modules/drizzle-orm/pg-core/columns/enum.js +1 -1
  52. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/pg-core/columns/enum.js.map +1 -0
  53. package/dist/node_modules/{.bun/drizzle-orm@0.44.6_4fae081eecb963e2 → .pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8}/node_modules/drizzle-orm/pg-core/foreign-keys.js +1 -1
  54. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/pg-core/foreign-keys.js.map +1 -0
  55. package/dist/node_modules/{.bun/drizzle-orm@0.44.6_4fae081eecb963e2 → .pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8}/node_modules/drizzle-orm/pg-core/unique-constraint.js +1 -1
  56. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/pg-core/unique-constraint.js.map +1 -0
  57. package/dist/node_modules/{.bun/drizzle-orm@0.44.6_4fae081eecb963e2 → .pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8}/node_modules/drizzle-orm/pg-core/utils/array.js +1 -1
  58. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/pg-core/utils/array.js.map +1 -0
  59. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/query-builders/query-builder.js +14 -0
  60. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/query-builders/query-builder.js.map +1 -0
  61. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/query-promise.js +26 -0
  62. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/query-promise.js.map +1 -0
  63. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/relations.js +127 -0
  64. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/relations.js.map +1 -0
  65. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/selection-proxy.js +47 -0
  66. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/selection-proxy.js.map +1 -0
  67. package/dist/node_modules/{.bun/drizzle-orm@0.44.6_4fae081eecb963e2 → .pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8}/node_modules/drizzle-orm/sql/expressions/conditions.js +20 -2
  68. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sql/expressions/conditions.js.map +1 -0
  69. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sql/expressions/select.js +13 -0
  70. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sql/expressions/select.js.map +1 -0
  71. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sql/functions/aggregate.js +10 -0
  72. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sql/functions/aggregate.js.map +1 -0
  73. package/dist/node_modules/{.bun/drizzle-orm@0.44.6_4fae081eecb963e2 → .pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8}/node_modules/drizzle-orm/sql/sql.js +1 -1
  74. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sql/sql.js.map +1 -0
  75. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/columns/common.js +60 -0
  76. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/columns/common.js.map +1 -0
  77. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/db.js +269 -0
  78. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/db.js.map +1 -0
  79. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/dialect.js +457 -0
  80. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/dialect.js.map +1 -0
  81. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/foreign-keys.js +68 -0
  82. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/foreign-keys.js.map +1 -0
  83. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/count.js +41 -0
  84. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/count.js.map +1 -0
  85. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/delete.js +119 -0
  86. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/delete.js.map +1 -0
  87. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/insert.js +170 -0
  88. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/insert.js.map +1 -0
  89. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/query-builder.js +75 -0
  90. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/query-builder.js.map +1 -0
  91. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/query.js +107 -0
  92. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/query.js.map +1 -0
  93. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/raw.js +37 -0
  94. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/raw.js.map +1 -0
  95. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/select.js +621 -0
  96. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/select.js.map +1 -0
  97. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/update.js +170 -0
  98. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/query-builders/update.js.map +1 -0
  99. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/table.js +20 -0
  100. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/table.js.map +1 -0
  101. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/unique-constraint.js +48 -0
  102. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/unique-constraint.js.map +1 -0
  103. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/utils.js +17 -0
  104. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/utils.js.map +1 -0
  105. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/view-base.js +11 -0
  106. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/sqlite-core/view-base.js.map +1 -0
  107. package/dist/node_modules/{.bun/drizzle-orm@0.44.6_4fae081eecb963e2 → .pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8}/node_modules/drizzle-orm/subquery.js +2 -2
  108. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/subquery.js.map +1 -0
  109. package/dist/node_modules/{.bun/drizzle-orm@0.44.6_4fae081eecb963e2 → .pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8}/node_modules/drizzle-orm/table.js +8 -2
  110. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/table.js.map +1 -0
  111. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/table.utils.js +6 -0
  112. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/table.utils.js.map +1 -0
  113. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/tracing-utils.js +8 -0
  114. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/tracing-utils.js.map +1 -0
  115. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/tracing.js +8 -0
  116. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/tracing.js.map +1 -0
  117. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/utils.js +53 -0
  118. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/utils.js.map +1 -0
  119. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/view-common.js +6 -0
  120. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@electric-sql_pglite@0.3.11_@types_better-sqlite3@7.6.13_better-sqlite3@12.4.1_kysely@0.28.8/node_modules/drizzle-orm/view-common.js.map +1 -0
  121. package/dist/query/query.d.ts +4 -4
  122. package/dist/query/query.d.ts.map +1 -1
  123. package/dist/query/unit-of-work.d.ts +22 -22
  124. package/dist/query/unit-of-work.d.ts.map +1 -1
  125. package/dist/schema/create.d.ts +41 -41
  126. package/dist/schema/create.d.ts.map +1 -1
  127. package/dist/schema/serialize.js +3 -0
  128. package/dist/schema/serialize.js.map +1 -1
  129. package/package.json +20 -24
  130. package/src/adapters/drizzle/drizzle-adapter-sqlite.test.ts +585 -0
  131. package/src/adapters/drizzle/drizzle-adapter.test.ts +2 -2
  132. package/src/adapters/drizzle/drizzle-adapter.ts +11 -4
  133. package/src/adapters/drizzle/drizzle-query.ts +2 -2
  134. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +1 -1
  135. package/src/adapters/drizzle/drizzle-uow-decoder.ts +21 -4
  136. package/src/adapters/drizzle/drizzle-uow-executor.ts +155 -115
  137. package/src/adapters/drizzle/generate.test.ts +111 -14
  138. package/src/adapters/drizzle/generate.ts +12 -7
  139. package/src/adapters/kysely/kysely-adapter.ts +46 -27
  140. package/src/adapters/kysely/migration/execute-base.ts +256 -0
  141. package/src/adapters/kysely/migration/execute-factory.ts +30 -0
  142. package/src/adapters/kysely/migration/execute-mssql.ts +250 -0
  143. package/src/adapters/kysely/migration/execute-mysql.ts +211 -0
  144. package/src/adapters/kysely/migration/execute-postgres.ts +234 -0
  145. package/src/adapters/kysely/migration/execute-sqlite.test.ts +1363 -0
  146. package/src/adapters/kysely/migration/execute-sqlite.ts +247 -0
  147. package/src/adapters/kysely/migration/execute.ts +33 -396
  148. package/src/adapters/kysely/migration/kysely-migrator.test.ts +84 -2
  149. package/src/migration-engine/shared.ts +29 -11
  150. package/src/schema/serialize.test.ts +1 -0
  151. package/src/schema/serialize.ts +7 -0
  152. package/tsdown.config.ts +1 -0
  153. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column-builder.js.map +0 -1
  154. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column.js.map +0 -1
  155. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/entity.js.map +0 -1
  156. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/common.js.map +0 -1
  157. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/enum.js.map +0 -1
  158. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/foreign-keys.js.map +0 -1
  159. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/unique-constraint.js.map +0 -1
  160. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/utils/array.js.map +0 -1
  161. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/conditions.js.map +0 -1
  162. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/select.js +0 -13
  163. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/select.js.map +0 -1
  164. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/functions/aggregate.js +0 -10
  165. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/functions/aggregate.js.map +0 -1
  166. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/sql.js.map +0 -1
  167. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/subquery.js.map +0 -1
  168. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.js.map +0 -1
  169. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.utils.js +0 -6
  170. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.utils.js.map +0 -1
  171. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing-utils.js +0 -8
  172. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing-utils.js.map +0 -1
  173. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing.js +0 -8
  174. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing.js.map +0 -1
  175. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/view-common.js +0 -6
  176. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/view-common.js.map +0 -1
@@ -0,0 +1,1363 @@
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");
14
+ }
15
+ }
16
+
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
+ });
27
+
28
+ describe("create-table", () => {
29
+ it("should generate SQL for simple table with columns", () => {
30
+ const operation: MigrationOperation = {
31
+ type: "create-table",
32
+ name: "users",
33
+ columns: [
34
+ {
35
+ name: "id",
36
+ type: "integer",
37
+ isNullable: false,
38
+ role: "external-id",
39
+ },
40
+ {
41
+ name: "name",
42
+ type: "string",
43
+ isNullable: false,
44
+ role: "regular",
45
+ },
46
+ {
47
+ name: "email",
48
+ type: "string",
49
+ isNullable: false,
50
+ role: "regular",
51
+ },
52
+ ],
53
+ };
54
+
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(
63
+ `"create table "users" ("id" integer not null unique, "name" text not null, "email" text not null)"`,
64
+ );
65
+ });
66
+
67
+ it("should generate SQL for table with various column types", () => {
68
+ const operation: MigrationOperation = {
69
+ type: "create-table",
70
+ name: "test_types",
71
+ columns: [
72
+ { name: "col_int", type: "integer", isNullable: false, role: "external-id" },
73
+ { name: "col_bigint", type: "bigint", isNullable: false, role: "regular" },
74
+ { name: "col_decimal", type: "decimal", isNullable: false, role: "regular" },
75
+ { name: "col_bool", type: "bool", isNullable: false, role: "regular" },
76
+ { name: "col_date", type: "date", isNullable: false, role: "regular" },
77
+ { name: "col_timestamp", type: "timestamp", isNullable: false, role: "regular" },
78
+ { name: "col_json", type: "json", isNullable: false, role: "regular" },
79
+ { name: "col_binary", type: "binary", isNullable: false, role: "regular" },
80
+ { name: "col_varchar", type: "varchar(255)", isNullable: false, role: "regular" },
81
+ ],
82
+ };
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(
92
+ `"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
+ );
94
+ });
95
+
96
+ it("should generate SQL for table with nullable columns", () => {
97
+ const operation: MigrationOperation = {
98
+ type: "create-table",
99
+ name: "nullable_test",
100
+ columns: [
101
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
102
+ { name: "optional_name", type: "string", isNullable: true, role: "regular" },
103
+ { name: "optional_age", type: "integer", isNullable: true, role: "regular" },
104
+ ],
105
+ };
106
+
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(
115
+ `"create table "nullable_test" ("id" integer not null unique, "optional_name" text, "optional_age" integer)"`,
116
+ );
117
+ });
118
+
119
+ it("should generate SQL for table with default values", () => {
120
+ const operation: MigrationOperation = {
121
+ type: "create-table",
122
+ name: "defaults_test",
123
+ columns: [
124
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
125
+ {
126
+ name: "status",
127
+ type: "string",
128
+ isNullable: false,
129
+ role: "regular",
130
+ default: { value: "pending" },
131
+ },
132
+ {
133
+ name: "count",
134
+ type: "integer",
135
+ isNullable: false,
136
+ role: "regular",
137
+ default: { value: 0 },
138
+ },
139
+ {
140
+ name: "is_active",
141
+ type: "bool",
142
+ isNullable: false,
143
+ role: "regular",
144
+ default: { value: true },
145
+ },
146
+ ],
147
+ };
148
+
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(
157
+ `"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
+ );
159
+ });
160
+
161
+ it("should generate SQL for table with timestamp default to CURRENT_TIMESTAMP", () => {
162
+ const operation: MigrationOperation = {
163
+ type: "create-table",
164
+ name: "timestamps_test",
165
+ columns: [
166
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
167
+ {
168
+ name: "created_at",
169
+ type: "timestamp",
170
+ isNullable: false,
171
+ role: "regular",
172
+ default: { dbSpecial: "now" },
173
+ },
174
+ ],
175
+ };
176
+
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(
185
+ `"create table "timestamps_test" ("id" integer not null unique, "created_at" integer default CURRENT_TIMESTAMP not null)"`,
186
+ );
187
+ });
188
+
189
+ it("should generate SQL for table with reference column", () => {
190
+ const operation: MigrationOperation = {
191
+ type: "create-table",
192
+ name: "posts",
193
+ columns: [
194
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
195
+ { name: "user_id", type: "integer", isNullable: false, role: "reference" },
196
+ { name: "title", type: "string", isNullable: false, role: "regular" },
197
+ ],
198
+ };
199
+
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(
208
+ `"create table "posts" ("id" integer not null unique, "user_id" integer not null, "title" text not null)"`,
209
+ );
210
+ });
211
+
212
+ it("should generate SQL for table with auto-increment internal ID", () => {
213
+ const operation: MigrationOperation = {
214
+ type: "create-table",
215
+ name: "items",
216
+ columns: [
217
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
218
+ { name: "_internalId", type: "bigint", isNullable: false, role: "internal-id" },
219
+ { name: "name", type: "string", isNullable: false, role: "regular" },
220
+ ],
221
+ };
222
+
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(
231
+ `"create table "items" ("id" integer not null unique, "_internalId" integer not null primary key autoincrement, "name" text not null)"`,
232
+ );
233
+ });
234
+ });
235
+
236
+ describe("rename-table", () => {
237
+ it("should generate SQL for SQLite rename", () => {
238
+ const operation: MigrationOperation = {
239
+ type: "rename-table",
240
+ from: "old_name",
241
+ to: "new_name",
242
+ };
243
+
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""`);
252
+ });
253
+ });
254
+
255
+ describe("drop-table", () => {
256
+ it("should generate SQL to drop table", () => {
257
+ const operation: MigrationOperation = {
258
+ type: "drop-table",
259
+ name: "to_drop",
260
+ };
261
+
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""`);
270
+ });
271
+ });
272
+
273
+ describe("alter-table - create-column", () => {
274
+ it("should generate SQL to add a new column", () => {
275
+ const operation: MigrationOperation = {
276
+ type: "alter-table",
277
+ name: "test_table",
278
+ value: [
279
+ {
280
+ type: "create-column",
281
+ value: {
282
+ name: "new_column",
283
+ type: "string",
284
+ isNullable: true,
285
+ role: "regular",
286
+ },
287
+ },
288
+ ],
289
+ };
290
+
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(
302
+ `"alter table "test_table" add column "new_column" text"`,
303
+ );
304
+ });
305
+
306
+ it("should generate SQL for multiple columns", () => {
307
+ const operation: MigrationOperation = {
308
+ type: "alter-table",
309
+ name: "test_table",
310
+ value: [
311
+ {
312
+ type: "create-column",
313
+ value: {
314
+ name: "col1",
315
+ type: "string",
316
+ isNullable: true,
317
+ role: "regular",
318
+ },
319
+ },
320
+ {
321
+ type: "create-column",
322
+ value: {
323
+ name: "col2",
324
+ type: "integer",
325
+ isNullable: false,
326
+ role: "regular",
327
+ default: { value: 0 },
328
+ },
329
+ },
330
+ ],
331
+ };
332
+
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(
343
+ `"alter table "test_table" add column "col1" text"`,
344
+ );
345
+ expect(results[1].compile().sql).toMatchInlineSnapshot(
346
+ `"alter table "test_table" add column "col2" integer default 0 not null"`,
347
+ );
348
+ });
349
+ });
350
+
351
+ describe("alter-table - rename-column", () => {
352
+ it("should generate SQL to rename a column", () => {
353
+ const operation: MigrationOperation = {
354
+ type: "alter-table",
355
+ name: "test_table",
356
+ value: [
357
+ {
358
+ type: "rename-column",
359
+ from: "old_name",
360
+ to: "new_name",
361
+ },
362
+ ],
363
+ };
364
+
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(
376
+ `"alter table "test_table" rename column "old_name" to "new_name""`,
377
+ );
378
+ });
379
+ });
380
+
381
+ describe("alter-table - drop-column", () => {
382
+ it("should generate SQL to drop a column", () => {
383
+ const operation: MigrationOperation = {
384
+ type: "alter-table",
385
+ name: "test_table",
386
+ value: [
387
+ {
388
+ type: "drop-column",
389
+ name: "to_drop",
390
+ },
391
+ ],
392
+ };
393
+
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(
405
+ `"alter table "test_table" drop column "to_drop""`,
406
+ );
407
+ });
408
+ });
409
+
410
+ describe("alter-table - update-column", () => {
411
+ it("should throw error when trying to update column (SQLite limitation)", () => {
412
+ const operation: MigrationOperation = {
413
+ type: "alter-table",
414
+ name: "test_table",
415
+ value: [
416
+ {
417
+ type: "update-column",
418
+ name: "test_col",
419
+ value: {
420
+ name: "test_col",
421
+ type: "integer",
422
+ isNullable: true,
423
+ role: "regular",
424
+ },
425
+ updateDataType: true,
426
+ updateNullable: false,
427
+ updateDefault: false,
428
+ },
429
+ ],
430
+ };
431
+
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.");
437
+ });
438
+
439
+ it("should throw error when trying to update nullable constraint", () => {
440
+ const operation: MigrationOperation = {
441
+ type: "alter-table",
442
+ name: "test_table",
443
+ value: [
444
+ {
445
+ type: "update-column",
446
+ name: "test_col",
447
+ value: {
448
+ name: "test_col",
449
+ type: "string",
450
+ isNullable: false,
451
+ role: "regular",
452
+ },
453
+ updateDataType: false,
454
+ updateNullable: true,
455
+ updateDefault: false,
456
+ },
457
+ ],
458
+ };
459
+
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.");
465
+ });
466
+
467
+ it("should throw error when trying to update default value", () => {
468
+ const operation: MigrationOperation = {
469
+ type: "alter-table",
470
+ name: "test_table",
471
+ value: [
472
+ {
473
+ type: "update-column",
474
+ name: "test_col",
475
+ value: {
476
+ name: "test_col",
477
+ type: "string",
478
+ isNullable: false,
479
+ role: "regular",
480
+ default: { value: "default_value" },
481
+ },
482
+ updateDataType: false,
483
+ updateNullable: false,
484
+ updateDefault: true,
485
+ },
486
+ ],
487
+ };
488
+
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.");
494
+ });
495
+
496
+ it("should throw error when trying to update ID column", () => {
497
+ const operation: MigrationOperation = {
498
+ type: "alter-table",
499
+ name: "test_table",
500
+ value: [
501
+ {
502
+ type: "update-column",
503
+ name: "id",
504
+ value: {
505
+ name: "id",
506
+ type: "bigint",
507
+ isNullable: false,
508
+ role: "external-id",
509
+ },
510
+ updateDataType: true,
511
+ updateNullable: false,
512
+ updateDefault: false,
513
+ },
514
+ ],
515
+ };
516
+
517
+ expect(() => {
518
+ execute(operation, config, () => {
519
+ throw new Error("No custom operations");
520
+ });
521
+ }).toThrow(
522
+ "ID columns cannot be updated. Not every database supports updating primary keys and often requires workarounds.",
523
+ );
524
+ });
525
+
526
+ it("should throw error even for no-op update-column (SQLite limitation)", () => {
527
+ const operation: MigrationOperation = {
528
+ type: "alter-table",
529
+ name: "test_table",
530
+ value: [
531
+ {
532
+ type: "update-column",
533
+ name: "test_col",
534
+ value: {
535
+ name: "test_col",
536
+ type: "string",
537
+ isNullable: true,
538
+ role: "regular",
539
+ },
540
+ updateDataType: false,
541
+ updateNullable: false,
542
+ updateDefault: false,
543
+ },
544
+ ],
545
+ };
546
+
547
+ // 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.");
553
+ });
554
+ });
555
+
556
+ describe("add-foreign-key", () => {
557
+ it("should throw error when trying to add foreign key (SQLite limitation)", () => {
558
+ const operation: MigrationOperation = {
559
+ type: "add-foreign-key",
560
+ table: "posts",
561
+ value: {
562
+ name: "posts_user_id_fk",
563
+ columns: ["user_id"],
564
+ referencedTable: "users",
565
+ referencedColumns: ["id"],
566
+ },
567
+ };
568
+
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.",
575
+ );
576
+ });
577
+
578
+ it("should throw error for composite foreign key", () => {
579
+ const operation: MigrationOperation = {
580
+ type: "add-foreign-key",
581
+ table: "posts",
582
+ value: {
583
+ name: "posts_user_fk",
584
+ columns: ["org_id", "user_id"],
585
+ referencedTable: "users",
586
+ referencedColumns: ["org_id", "user_id"],
587
+ },
588
+ };
589
+
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.",
596
+ );
597
+ });
598
+ });
599
+
600
+ describe("drop-foreign-key", () => {
601
+ it("should throw error when trying to drop foreign key (SQLite limitation)", () => {
602
+ const operation: MigrationOperation = {
603
+ type: "drop-foreign-key",
604
+ table: "posts",
605
+ name: "posts_user_id_fk",
606
+ };
607
+
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.",
614
+ );
615
+ });
616
+ });
617
+
618
+ describe("add-index", () => {
619
+ it("should generate SQL for regular index", () => {
620
+ const operation: MigrationOperation = {
621
+ type: "add-index",
622
+ table: "test_table",
623
+ columns: ["email"],
624
+ name: "idx_email",
625
+ unique: false,
626
+ };
627
+
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
+ );
638
+ });
639
+
640
+ it("should generate SQL for unique index", () => {
641
+ const operation: MigrationOperation = {
642
+ type: "add-index",
643
+ table: "test_table",
644
+ columns: ["email"],
645
+ name: "idx_unique_email",
646
+ unique: true,
647
+ };
648
+
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(
657
+ `"create unique index "idx_unique_email" on "test_table" ("email")"`,
658
+ );
659
+ });
660
+
661
+ it("should generate SQL for composite index", () => {
662
+ const operation: MigrationOperation = {
663
+ type: "add-index",
664
+ table: "test_table",
665
+ columns: ["email", "name"],
666
+ name: "idx_email_name",
667
+ unique: false,
668
+ };
669
+
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(
678
+ `"create index "idx_email_name" on "test_table" ("email", "name")"`,
679
+ );
680
+ });
681
+
682
+ it("should generate SQL for unique composite index", () => {
683
+ const operation: MigrationOperation = {
684
+ type: "add-index",
685
+ table: "test_table",
686
+ columns: ["email", "name"],
687
+ name: "idx_unique_email_name",
688
+ unique: true,
689
+ };
690
+
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(
699
+ `"create unique index "idx_unique_email_name" on "test_table" ("email", "name")"`,
700
+ );
701
+ });
702
+ });
703
+
704
+ describe("drop-index", () => {
705
+ it("should generate SQL to drop index", () => {
706
+ const operation: MigrationOperation = {
707
+ type: "drop-index",
708
+ table: "test_table",
709
+ name: "idx_email",
710
+ };
711
+
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");
770
+ });
771
+ });
772
+
773
+ describe("complex migration scenarios", () => {
774
+ it("should generate correct SQL for full schema migration", () => {
775
+ // 1. Create users table
776
+ const createUsers = execute(
777
+ {
778
+ type: "create-table",
779
+ name: "users",
780
+ columns: [
781
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
782
+ { name: "email", type: "string", isNullable: false, role: "regular" },
783
+ { name: "name", type: "string", isNullable: false, role: "regular" },
784
+ ],
785
+ },
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
+ {
801
+ type: "add-index",
802
+ table: "users",
803
+ columns: ["email"],
804
+ name: "idx_unique_email",
805
+ unique: true,
806
+ },
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
+ {
822
+ type: "create-table",
823
+ name: "posts",
824
+ columns: [
825
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
826
+ { name: "user_id", type: "integer", isNullable: false, role: "reference" },
827
+ { name: "title", type: "string", isNullable: false, role: "regular" },
828
+ { name: "content", type: "string", isNullable: false, role: "regular" },
829
+ ],
830
+ },
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
+ {
849
+ type: "alter-table",
850
+ name: "posts",
851
+ value: [
852
+ {
853
+ type: "create-column",
854
+ value: {
855
+ name: "published",
856
+ type: "bool",
857
+ isNullable: false,
858
+ role: "regular",
859
+ default: { value: false },
860
+ },
861
+ },
862
+ ],
863
+ },
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
+ }
873
+
874
+ expect(alterResults[0].compile().sql).toMatchInlineSnapshot(
875
+ `"alter table "posts" add column "published" integer default false not null"`,
876
+ );
877
+ });
878
+
879
+ it("should handle multiple alter-table operations", () => {
880
+ const operation: MigrationOperation = {
881
+ type: "alter-table",
882
+ name: "users",
883
+ value: [
884
+ {
885
+ type: "create-column",
886
+ value: {
887
+ name: "age",
888
+ type: "integer",
889
+ isNullable: true,
890
+ role: "regular",
891
+ },
892
+ },
893
+ {
894
+ type: "rename-column",
895
+ from: "name",
896
+ to: "full_name",
897
+ },
898
+ {
899
+ type: "drop-column",
900
+ name: "old_field",
901
+ },
902
+ ],
903
+ };
904
+
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(
918
+ `"alter table "users" rename column "name" to "full_name""`,
919
+ );
920
+ expect(results[2].compile().sql).toMatchInlineSnapshot(
921
+ `"alter table "users" drop column "old_field""`,
922
+ );
923
+ });
924
+ });
925
+
926
+ describe("edge cases", () => {
927
+ it("should handle table names with special characters", () => {
928
+ const operation: MigrationOperation = {
929
+ type: "create-table",
930
+ name: "user-profiles",
931
+ columns: [{ name: "id", type: "integer", isNullable: false, role: "external-id" }],
932
+ };
933
+
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"');
942
+ });
943
+
944
+ it("should handle column names with special characters", () => {
945
+ const operation: MigrationOperation = {
946
+ type: "create-table",
947
+ name: "test",
948
+ columns: [
949
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
950
+ { name: "user-name", type: "string", isNullable: false, role: "regular" },
951
+ ],
952
+ };
953
+
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"');
962
+ });
963
+
964
+ it("should properly escape string default values", () => {
965
+ const operation: MigrationOperation = {
966
+ type: "create-table",
967
+ name: "test",
968
+ columns: [
969
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
970
+ {
971
+ name: "status",
972
+ type: "string",
973
+ isNullable: false,
974
+ role: "regular",
975
+ default: { value: "it's pending" },
976
+ },
977
+ ],
978
+ };
979
+
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(
988
+ `"create table "test" ("id" integer not null unique, "status" text default 'it''s pending' not null)"`,
989
+ );
990
+ });
991
+
992
+ it("should handle boolean values as integers (SQLite stores bools as 0/1)", () => {
993
+ const operation: MigrationOperation = {
994
+ type: "create-table",
995
+ name: "test",
996
+ columns: [
997
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
998
+ {
999
+ name: "is_active",
1000
+ type: "bool",
1001
+ isNullable: false,
1002
+ role: "regular",
1003
+ default: { value: true },
1004
+ },
1005
+ {
1006
+ name: "is_deleted",
1007
+ type: "bool",
1008
+ isNullable: false,
1009
+ role: "regular",
1010
+ default: { value: false },
1011
+ },
1012
+ ],
1013
+ };
1014
+
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(
1023
+ `"create table "test" ("id" integer not null unique, "is_active" integer default true not null, "is_deleted" integer default false not null)"`,
1024
+ );
1025
+ });
1026
+ });
1027
+
1028
+ describe("SQLite-specific behavior", () => {
1029
+ it("should handle bigint as integer (SQLite doesn't have true bigint)", () => {
1030
+ const operation: MigrationOperation = {
1031
+ type: "create-table",
1032
+ name: "test",
1033
+ columns: [
1034
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
1035
+ { name: "big_number", type: "bigint", isNullable: false, role: "regular" },
1036
+ ],
1037
+ };
1038
+
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");
1048
+ });
1049
+
1050
+ it("should handle date/timestamp as integer (SQLite stores dates as integers)", () => {
1051
+ const operation: MigrationOperation = {
1052
+ type: "create-table",
1053
+ name: "test",
1054
+ columns: [
1055
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
1056
+ { name: "birth_date", type: "date", isNullable: false, role: "regular" },
1057
+ { name: "created_at", type: "timestamp", isNullable: false, role: "regular" },
1058
+ ],
1059
+ };
1060
+
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(
1069
+ `"create table "test" ("id" integer not null unique, "birth_date" integer not null, "created_at" integer not null)"`,
1070
+ );
1071
+ });
1072
+
1073
+ it("should handle JSON as text (SQLite stores JSON as text)", () => {
1074
+ const operation: MigrationOperation = {
1075
+ type: "create-table",
1076
+ name: "test",
1077
+ columns: [
1078
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
1079
+ { name: "metadata", type: "json", isNullable: false, role: "regular" },
1080
+ ],
1081
+ };
1082
+
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(
1091
+ `"create table "test" ("id" integer not null unique, "metadata" text not null)"`,
1092
+ );
1093
+ });
1094
+
1095
+ it("should handle binary as blob", () => {
1096
+ const operation: MigrationOperation = {
1097
+ type: "create-table",
1098
+ name: "test",
1099
+ columns: [
1100
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
1101
+ { name: "file_data", type: "binary", isNullable: false, role: "regular" },
1102
+ ],
1103
+ };
1104
+
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(
1113
+ `"create table "test" ("id" integer not null unique, "file_data" blob not null)"`,
1114
+ );
1115
+ });
1116
+
1117
+ it("should handle decimal as real", () => {
1118
+ const operation: MigrationOperation = {
1119
+ type: "create-table",
1120
+ name: "test",
1121
+ columns: [
1122
+ { name: "id", type: "integer", isNullable: false, role: "external-id" },
1123
+ { name: "price", type: "decimal", isNullable: false, role: "regular" },
1124
+ ],
1125
+ };
1126
+
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(
1135
+ `"create table "test" ("id" integer not null unique, "price" real not null)"`,
1136
+ );
1137
+ });
1138
+ });
1139
+
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
+ describe("SQLite FK preprocessing", () => {
1174
+ it("should merge add-foreign-key into create-table when both are in same batch", () => {
1175
+ const operations: MigrationOperation[] = [
1176
+ {
1177
+ type: "create-table",
1178
+ name: "users",
1179
+ columns: [{ name: "id", type: "integer", isNullable: false, role: "internal-id" }],
1180
+ },
1181
+ {
1182
+ type: "create-table",
1183
+ name: "posts",
1184
+ columns: [
1185
+ { name: "id", type: "integer", isNullable: false, role: "internal-id" },
1186
+ { name: "author_id", type: "integer", isNullable: false, role: "reference" },
1187
+ ],
1188
+ },
1189
+ {
1190
+ type: "add-foreign-key",
1191
+ table: "posts",
1192
+ value: {
1193
+ name: "posts_users_author_fk",
1194
+ columns: ["author_id"],
1195
+ referencedTable: "users",
1196
+ referencedColumns: ["id"],
1197
+ },
1198
+ },
1199
+ ];
1200
+
1201
+ const executor = new SqliteMigrationExecutor(db, "sqlite");
1202
+ const preprocessed = executor.preprocessOperations(operations);
1203
+
1204
+ // Should have 2 operations (2 create-table, FK merged into posts table)
1205
+ expect(preprocessed).toHaveLength(2);
1206
+
1207
+ // First operation should be create users table
1208
+ expect(preprocessed[0]).toMatchObject({
1209
+ type: "create-table",
1210
+ name: "users",
1211
+ });
1212
+
1213
+ // Second operation should be create posts table with inline FK
1214
+ expect(preprocessed[1]).toMatchObject({
1215
+ type: "create-table",
1216
+ name: "posts",
1217
+ });
1218
+
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({
1223
+ name: "posts_users_author_fk",
1224
+ columns: ["author_id"],
1225
+ referencedTable: "users",
1226
+ referencedColumns: ["id"],
1227
+ });
1228
+ }
1229
+ });
1230
+
1231
+ 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
+ },
1248
+ ],
1249
+ },
1250
+ };
1251
+
1252
+ const result = execute(operation, config, () => {
1253
+ throw new Error("No custom operations");
1254
+ });
1255
+
1256
+ assertSingleResult(result);
1257
+
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");
1265
+ });
1266
+
1267
+ it("should keep add-foreign-key operations for existing tables (will throw error)", () => {
1268
+ const operations: MigrationOperation[] = [
1269
+ {
1270
+ type: "create-table",
1271
+ name: "users",
1272
+ columns: [{ name: "id", type: "integer", isNullable: false, role: "internal-id" }],
1273
+ },
1274
+ {
1275
+ type: "add-foreign-key",
1276
+ table: "posts", // posts table doesn't exist in this migration "batch"
1277
+ value: {
1278
+ name: "posts_users_author_fk",
1279
+ columns: ["author_id"],
1280
+ referencedTable: "users",
1281
+ referencedColumns: ["id"],
1282
+ },
1283
+ },
1284
+ ];
1285
+
1286
+ const executor = new SqliteMigrationExecutor(db, "sqlite");
1287
+ const preprocessed = executor.preprocessOperations(operations);
1288
+
1289
+ // Should have 2 operations (create-table + add-foreign-key)
1290
+ expect(preprocessed).toHaveLength(2);
1291
+
1292
+ // Second operation should still be add-foreign-key (not merged)
1293
+ expect(preprocessed[1]).toMatchObject({
1294
+ type: "add-foreign-key",
1295
+ table: "posts",
1296
+ });
1297
+ });
1298
+
1299
+ it("should handle multiple foreign keys on the same table", () => {
1300
+ const operations: MigrationOperation[] = [
1301
+ {
1302
+ type: "create-table",
1303
+ name: "users",
1304
+ columns: [{ name: "id", type: "integer", isNullable: false, role: "internal-id" }],
1305
+ },
1306
+ {
1307
+ type: "create-table",
1308
+ name: "categories",
1309
+ columns: [{ name: "id", type: "integer", isNullable: false, role: "internal-id" }],
1310
+ },
1311
+ {
1312
+ type: "create-table",
1313
+ name: "posts",
1314
+ columns: [
1315
+ { name: "id", type: "integer", isNullable: false, role: "internal-id" },
1316
+ { name: "author_id", type: "integer", isNullable: false, role: "reference" },
1317
+ { name: "category_id", type: "integer", isNullable: false, role: "reference" },
1318
+ ],
1319
+ },
1320
+ {
1321
+ type: "add-foreign-key",
1322
+ table: "posts",
1323
+ value: {
1324
+ name: "posts_users_author_fk",
1325
+ columns: ["author_id"],
1326
+ referencedTable: "users",
1327
+ referencedColumns: ["id"],
1328
+ },
1329
+ },
1330
+ {
1331
+ type: "add-foreign-key",
1332
+ table: "posts",
1333
+ value: {
1334
+ name: "posts_categories_category_fk",
1335
+ columns: ["category_id"],
1336
+ referencedTable: "categories",
1337
+ referencedColumns: ["id"],
1338
+ },
1339
+ },
1340
+ ];
1341
+
1342
+ const executor = new SqliteMigrationExecutor(db, "sqlite");
1343
+ const preprocessed = executor.preprocessOperations(operations);
1344
+
1345
+ // Should have 3 operations (3 create-table, both FKs merged into posts)
1346
+ expect(preprocessed).toHaveLength(3);
1347
+
1348
+ // Posts table should have both foreign keys merged
1349
+ const postsOp = preprocessed[2];
1350
+ expect(postsOp).toMatchObject({
1351
+ type: "create-table",
1352
+ name: "posts",
1353
+ });
1354
+
1355
+ 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");
1360
+ }
1361
+ });
1362
+ });
1363
+ });