kysely 0.12.0 → 0.14.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 (172) hide show
  1. package/README.md +34 -10
  2. package/dist/cjs/{introspection → dialect}/database-introspector.d.ts +0 -0
  3. package/dist/cjs/{introspection → dialect}/database-introspector.js +0 -0
  4. package/dist/cjs/dialect/dialect-adapter-base.d.ts +36 -0
  5. package/dist/cjs/dialect/dialect.d.ts +1 -1
  6. package/dist/cjs/dialect/mysql/mysql-adapter.d.ts +38 -2
  7. package/dist/cjs/dialect/mysql/mysql-adapter.js +2 -1
  8. package/dist/cjs/dialect/mysql/mysql-dialect.d.ts +17 -1
  9. package/dist/cjs/dialect/mysql/mysql-driver.d.ts +29 -0
  10. package/dist/cjs/dialect/mysql/mysql-introspector.d.ts +4 -1
  11. package/dist/cjs/dialect/postgres/postgres-adapter.d.ts +38 -2
  12. package/dist/cjs/dialect/postgres/postgres-adapter.js +2 -1
  13. package/dist/cjs/dialect/postgres/postgres-dialect.d.ts +17 -1
  14. package/dist/cjs/dialect/postgres/postgres-driver.d.ts +29 -0
  15. package/dist/cjs/dialect/postgres/postgres-introspector.d.ts +4 -1
  16. package/dist/cjs/dialect/sqlite/sqlite-adapter.d.ts +38 -2
  17. package/dist/cjs/dialect/sqlite/sqlite-dialect.d.ts +17 -1
  18. package/dist/cjs/dialect/sqlite/sqlite-driver.d.ts +29 -0
  19. package/dist/cjs/dialect/sqlite/sqlite-introspector.d.ts +4 -1
  20. package/dist/cjs/driver/default-connection-provider.d.ts +4 -0
  21. package/dist/cjs/driver/runtime-driver.d.ts +29 -0
  22. package/dist/cjs/driver/single-connection-provider.d.ts +4 -0
  23. package/dist/cjs/index.d.ts +4 -3
  24. package/dist/cjs/index.js +3 -2
  25. package/dist/cjs/kysely.d.ts +152 -1
  26. package/dist/cjs/kysely.js +37 -0
  27. package/dist/cjs/migration/migration.d.ts +154 -11
  28. package/dist/cjs/migration/migration.js +256 -135
  29. package/dist/cjs/operation-node/check-constraint-node.d.ts +1 -1
  30. package/dist/cjs/operation-node/check-constraint-node.js +2 -3
  31. package/dist/cjs/operation-node/column-definition-node.d.ts +8 -7
  32. package/dist/cjs/operation-node/column-definition-node.js +0 -4
  33. package/dist/cjs/operation-node/common-table-expression-name-node.d.ts +15 -0
  34. package/dist/cjs/operation-node/common-table-expression-name-node.js +23 -0
  35. package/dist/cjs/operation-node/common-table-expression-node.d.ts +3 -3
  36. package/dist/cjs/operation-node/data-type-node.d.ts +1 -1
  37. package/dist/cjs/operation-node/generated-node.d.ts +20 -0
  38. package/dist/cjs/operation-node/generated-node.js +31 -0
  39. package/dist/cjs/operation-node/on-conflict-node.d.ts +13 -2
  40. package/dist/cjs/operation-node/on-conflict-node.js +39 -1
  41. package/dist/cjs/operation-node/operation-node-transformer.d.ts +4 -2
  42. package/dist/cjs/operation-node/operation-node-transformer.js +22 -6
  43. package/dist/cjs/operation-node/operation-node-visitor.d.ts +4 -2
  44. package/dist/cjs/operation-node/operation-node-visitor.js +2 -1
  45. package/dist/cjs/operation-node/operation-node.d.ts +1 -1
  46. package/dist/cjs/operation-node/with-node.d.ts +3 -1
  47. package/dist/cjs/operation-node/with-node.js +2 -1
  48. package/dist/cjs/package.json +1 -3
  49. package/dist/cjs/parser/parse-context.d.ts +14 -0
  50. package/dist/cjs/parser/with-parser.d.ts +32 -5
  51. package/dist/cjs/parser/with-parser.js +13 -2
  52. package/dist/cjs/plugin/camel-case/camel-case-plugin.d.ts +36 -2
  53. package/dist/cjs/plugin/immediate-value.ts/immediate-value-plugin.d.ts +34 -0
  54. package/dist/cjs/plugin/with-schema/with-schema-plugin.d.ts +34 -0
  55. package/dist/cjs/plugin/with-schema/with-schema-transformer.js +8 -0
  56. package/dist/cjs/query-builder/delete-query-builder.d.ts +545 -0
  57. package/dist/cjs/query-builder/insert-query-builder.d.ts +142 -76
  58. package/dist/cjs/query-builder/insert-query-builder.js +150 -15
  59. package/dist/cjs/query-builder/join-interface.d.ts +3 -6
  60. package/dist/cjs/query-builder/on-conflict-builder.d.ts +684 -0
  61. package/dist/cjs/query-builder/on-conflict-builder.js +323 -0
  62. package/dist/cjs/query-builder/returning-interface.d.ts +1 -1
  63. package/dist/cjs/query-builder/select-query-builder.d.ts +513 -2
  64. package/dist/cjs/query-builder/select-query-builder.js +2 -2
  65. package/dist/cjs/query-builder/update-query-builder.d.ts +547 -2
  66. package/dist/cjs/query-builder/update-query-builder.js +2 -2
  67. package/dist/cjs/query-builder/where-interface.d.ts +7 -10
  68. package/dist/cjs/query-compiler/default-query-compiler.d.ts +4 -2
  69. package/dist/cjs/query-compiler/default-query-compiler.js +48 -8
  70. package/dist/cjs/query-creator.d.ts +27 -3
  71. package/dist/cjs/query-creator.js +33 -1
  72. package/dist/cjs/query-executor/default-query-executor.d.ts +19 -0
  73. package/dist/cjs/query-executor/noop-query-executor.d.ts +19 -0
  74. package/dist/cjs/raw-builder/raw-builder.js +1 -1
  75. package/dist/cjs/schema/alter-table-builder.d.ts +253 -5
  76. package/dist/cjs/schema/alter-table-builder.js +45 -9
  77. package/dist/cjs/schema/column-definition-builder.d.ts +146 -6
  78. package/dist/cjs/schema/column-definition-builder.js +21 -8
  79. package/dist/cjs/schema/create-index-builder.d.ts +3 -2
  80. package/dist/cjs/schema/create-index-builder.js +2 -2
  81. package/dist/cjs/schema/create-table-builder.d.ts +3 -2
  82. package/dist/cjs/schema/create-table-builder.js +2 -2
  83. package/dist/esm/{introspection → dialect}/database-introspector.d.ts +0 -0
  84. package/dist/esm/{introspection → dialect}/database-introspector.js +0 -0
  85. package/dist/esm/dialect/dialect-adapter-base.d.ts +36 -0
  86. package/dist/esm/dialect/dialect.d.ts +1 -1
  87. package/dist/esm/dialect/mysql/mysql-adapter.d.ts +38 -2
  88. package/dist/esm/dialect/mysql/mysql-adapter.js +2 -1
  89. package/dist/esm/dialect/mysql/mysql-dialect.d.ts +17 -1
  90. package/dist/esm/dialect/mysql/mysql-driver.d.ts +29 -0
  91. package/dist/esm/dialect/mysql/mysql-introspector.d.ts +4 -1
  92. package/dist/esm/dialect/postgres/postgres-adapter.d.ts +38 -2
  93. package/dist/esm/dialect/postgres/postgres-adapter.js +2 -1
  94. package/dist/esm/dialect/postgres/postgres-dialect.d.ts +17 -1
  95. package/dist/esm/dialect/postgres/postgres-driver.d.ts +29 -0
  96. package/dist/esm/dialect/postgres/postgres-introspector.d.ts +4 -1
  97. package/dist/esm/dialect/sqlite/sqlite-adapter.d.ts +38 -2
  98. package/dist/esm/dialect/sqlite/sqlite-dialect.d.ts +17 -1
  99. package/dist/esm/dialect/sqlite/sqlite-driver.d.ts +29 -0
  100. package/dist/esm/dialect/sqlite/sqlite-introspector.d.ts +4 -1
  101. package/dist/esm/driver/default-connection-provider.d.ts +4 -0
  102. package/dist/esm/driver/runtime-driver.d.ts +29 -0
  103. package/dist/esm/driver/single-connection-provider.d.ts +4 -0
  104. package/dist/esm/index.d.ts +4 -3
  105. package/dist/esm/index.js +3 -2
  106. package/dist/esm/kysely.d.ts +152 -1
  107. package/dist/esm/kysely.js +37 -0
  108. package/dist/esm/migration/migration.d.ts +154 -11
  109. package/dist/esm/migration/migration.js +255 -134
  110. package/dist/esm/operation-node/check-constraint-node.d.ts +1 -1
  111. package/dist/esm/operation-node/check-constraint-node.js +2 -3
  112. package/dist/esm/operation-node/column-definition-node.d.ts +8 -7
  113. package/dist/esm/operation-node/column-definition-node.js +0 -4
  114. package/dist/esm/operation-node/common-table-expression-name-node.d.ts +15 -0
  115. package/dist/esm/operation-node/common-table-expression-name-node.js +20 -0
  116. package/dist/esm/operation-node/common-table-expression-node.d.ts +3 -3
  117. package/dist/esm/operation-node/data-type-node.d.ts +1 -1
  118. package/dist/esm/operation-node/generated-node.d.ts +20 -0
  119. package/dist/esm/operation-node/generated-node.js +28 -0
  120. package/dist/esm/operation-node/on-conflict-node.d.ts +13 -2
  121. package/dist/esm/operation-node/on-conflict-node.js +39 -1
  122. package/dist/esm/operation-node/operation-node-transformer.d.ts +4 -2
  123. package/dist/esm/operation-node/operation-node-transformer.js +22 -6
  124. package/dist/esm/operation-node/operation-node-visitor.d.ts +4 -2
  125. package/dist/esm/operation-node/operation-node-visitor.js +2 -1
  126. package/dist/esm/operation-node/operation-node.d.ts +1 -1
  127. package/dist/esm/operation-node/with-node.d.ts +3 -1
  128. package/dist/esm/operation-node/with-node.js +2 -1
  129. package/dist/esm/package.json +1 -3
  130. package/dist/esm/parser/parse-context.d.ts +14 -0
  131. package/dist/esm/parser/with-parser.d.ts +32 -5
  132. package/dist/esm/parser/with-parser.js +13 -2
  133. package/dist/esm/plugin/camel-case/camel-case-plugin.d.ts +36 -2
  134. package/dist/esm/plugin/immediate-value.ts/immediate-value-plugin.d.ts +34 -0
  135. package/dist/esm/plugin/with-schema/with-schema-plugin.d.ts +34 -0
  136. package/dist/esm/plugin/with-schema/with-schema-transformer.js +8 -0
  137. package/dist/esm/query-builder/delete-query-builder.d.ts +545 -0
  138. package/dist/esm/query-builder/insert-query-builder.d.ts +142 -76
  139. package/dist/esm/query-builder/insert-query-builder.js +150 -15
  140. package/dist/esm/query-builder/join-interface.d.ts +3 -6
  141. package/dist/esm/query-builder/on-conflict-builder.d.ts +684 -0
  142. package/dist/esm/query-builder/on-conflict-builder.js +317 -0
  143. package/dist/esm/query-builder/returning-interface.d.ts +1 -1
  144. package/dist/esm/query-builder/select-query-builder.d.ts +513 -2
  145. package/dist/esm/query-builder/select-query-builder.js +2 -2
  146. package/dist/esm/query-builder/update-query-builder.d.ts +547 -2
  147. package/dist/esm/query-builder/update-query-builder.js +2 -2
  148. package/dist/esm/query-builder/where-interface.d.ts +7 -10
  149. package/dist/esm/query-compiler/default-query-compiler.d.ts +4 -2
  150. package/dist/esm/query-compiler/default-query-compiler.js +48 -8
  151. package/dist/esm/query-creator.d.ts +27 -3
  152. package/dist/esm/query-creator.js +33 -1
  153. package/dist/esm/query-executor/default-query-executor.d.ts +19 -0
  154. package/dist/esm/query-executor/noop-query-executor.d.ts +19 -0
  155. package/dist/esm/raw-builder/raw-builder.js +1 -1
  156. package/dist/esm/schema/alter-table-builder.d.ts +253 -5
  157. package/dist/esm/schema/alter-table-builder.js +45 -9
  158. package/dist/esm/schema/column-definition-builder.d.ts +146 -6
  159. package/dist/esm/schema/column-definition-builder.js +21 -8
  160. package/dist/esm/schema/create-index-builder.d.ts +3 -2
  161. package/dist/esm/schema/create-index-builder.js +2 -2
  162. package/dist/esm/schema/create-table-builder.d.ts +3 -2
  163. package/dist/esm/schema/create-table-builder.js +2 -2
  164. package/package.json +8 -6
  165. package/dist/cjs/operation-node/generated-always-as-node.d.ts +0 -16
  166. package/dist/cjs/operation-node/generated-always-as-node.js +0 -25
  167. package/dist/cjs/parser/on-conflict-parser.d.ts +0 -10
  168. package/dist/cjs/parser/on-conflict-parser.js +0 -35
  169. package/dist/esm/operation-node/generated-always-as-node.d.ts +0 -16
  170. package/dist/esm/operation-node/generated-always-as-node.js +0 -22
  171. package/dist/esm/parser/on-conflict-parser.d.ts +0 -10
  172. package/dist/esm/parser/on-conflict-parser.js +0 -30
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MigrationModule = exports.MIGRATION_LOCK_ID = exports.MIGRATION_LOCK_TABLE = exports.MIGRATION_TABLE = void 0;
3
+ exports.MigrationModule = exports.NO_MIGRATIONS = exports.MIGRATION_LOCK_ID = exports.MIGRATION_LOCK_TABLE = exports.MIGRATION_TABLE = void 0;
4
4
  const path = require("path");
5
5
  const fs_1 = require("fs");
6
6
  const object_utils_js_1 = require("../util/object-utils.js");
7
7
  exports.MIGRATION_TABLE = 'kysely_migration';
8
8
  exports.MIGRATION_LOCK_TABLE = 'kysely_migration_lock';
9
9
  exports.MIGRATION_LOCK_ID = 'migration_lock';
10
+ exports.NO_MIGRATIONS = (0, object_utils_js_1.freeze)({ __noMigrations__: true });
10
11
  class MigrationModule {
11
12
  #db;
12
13
  #adapter;
@@ -15,171 +16,291 @@ class MigrationModule {
15
16
  this.#adapter = adapter;
16
17
  }
17
18
  async migrateToLatest(migrationsOrFolderPath) {
18
- await ensureMigrationTablesExists(this.#db);
19
- const allMigrations = await this.#getAllMigrations(migrationsOrFolderPath);
20
- await this.#migrateToLatest(allMigrations);
19
+ return this.#migrate(migrationsOrFolderPath, ({ migrations }) => migrations.length - 1);
21
20
  }
22
- async #getAllMigrations(migrationsOrFolderPath) {
23
- return (0, object_utils_js_1.isString)(migrationsOrFolderPath)
24
- ? await readMigrationsFromFolder(migrationsOrFolderPath)
25
- : migrationsOrFolderPath;
21
+ async migrateTo(migrationsOrFolderPath, targetMigrationName) {
22
+ return this.#migrate(migrationsOrFolderPath, ({ migrations }) => {
23
+ if (targetMigrationName === exports.NO_MIGRATIONS) {
24
+ return -1;
25
+ }
26
+ const index = migrations.findIndex((it) => it.name === targetMigrationName);
27
+ if (index === -1) {
28
+ throw new Error(`migration "${targetMigrationName}" doesn't exist`);
29
+ }
30
+ return index;
31
+ });
32
+ }
33
+ async migrateUp(migrationsOrFolderPath) {
34
+ return this.#migrate(migrationsOrFolderPath, ({ currentIndex, migrations }) => Math.min(currentIndex + 1, migrations.length - 1));
35
+ }
36
+ async migrateDown(migrationsOrFolderPath) {
37
+ return this.#migrate(migrationsOrFolderPath, ({ currentIndex }) => Math.max(currentIndex - 1, -1));
38
+ }
39
+ async #migrate(migrationsOrFolderPath, getTargetMigration) {
40
+ try {
41
+ await this.#ensureMigrationTablesExists();
42
+ return await this.#runMigrations(migrationsOrFolderPath, getTargetMigration);
43
+ }
44
+ catch (error) {
45
+ if (error instanceof MigrationResultSetError) {
46
+ return error.resultSet;
47
+ }
48
+ return { error };
49
+ }
50
+ }
51
+ async #ensureMigrationTablesExists() {
52
+ await this.#ensureMigrationTableExists();
53
+ await this.#ensureMigrationLockTableExists();
54
+ await this.#ensureLockRowExists();
26
55
  }
27
- async #migrateToLatest(allMigrations) {
56
+ async #ensureMigrationTableExists() {
57
+ if (!(await this.#doesTableExists(exports.MIGRATION_TABLE))) {
58
+ try {
59
+ await this.#db.schema
60
+ .createTable(exports.MIGRATION_TABLE)
61
+ .ifNotExists()
62
+ .addColumn('name', 'varchar(255)', (col) => col.notNull().primaryKey())
63
+ // The migration run time as ISO string. This is not a real date type as we
64
+ // can't know which data type is supported by all future dialects.
65
+ .addColumn('timestamp', 'varchar(255)', (col) => col.notNull())
66
+ .execute();
67
+ }
68
+ catch (error) {
69
+ // At least on PostgreSQL, `if not exists` doesn't guarantee the `create table`
70
+ // query doesn't throw if the table already exits. That's why we check if
71
+ // the table exist here and ignore the error if it does.
72
+ if (!(await this.#doesTableExists(exports.MIGRATION_TABLE))) {
73
+ throw error;
74
+ }
75
+ }
76
+ }
77
+ }
78
+ async #ensureMigrationLockTableExists() {
79
+ if (!(await this.#doesTableExists(exports.MIGRATION_LOCK_TABLE))) {
80
+ try {
81
+ await this.#db.schema
82
+ .createTable(exports.MIGRATION_LOCK_TABLE)
83
+ .ifNotExists()
84
+ .addColumn('id', 'varchar(255)', (col) => col.notNull().primaryKey())
85
+ .addColumn('is_locked', 'integer', (col) => col.notNull().defaultTo(0))
86
+ .execute();
87
+ }
88
+ catch (error) {
89
+ // At least on PostgreSQL, `if not exists` doesn't guarantee the `create table`
90
+ // query doesn't throw if the table already exits. That's why we check if
91
+ // the table exist here and ignore the error if it does.
92
+ if (!(await this.#doesTableExists(exports.MIGRATION_LOCK_TABLE))) {
93
+ throw error;
94
+ }
95
+ }
96
+ }
97
+ }
98
+ async #ensureLockRowExists() {
99
+ if (!(await this.#doesLockRowExists())) {
100
+ try {
101
+ await this.#db
102
+ .insertInto(exports.MIGRATION_LOCK_TABLE)
103
+ .values({ id: exports.MIGRATION_LOCK_ID })
104
+ .execute();
105
+ }
106
+ catch (error) {
107
+ if (!(await this.#doesLockRowExists())) {
108
+ throw error;
109
+ }
110
+ }
111
+ }
112
+ }
113
+ async #doesTableExists(tableName) {
114
+ const metadata = await this.#db.introspection.getMetadata({
115
+ withInternalKyselyTables: true,
116
+ });
117
+ return !!metadata.tables.find((it) => it.name === tableName);
118
+ }
119
+ async #doesLockRowExists() {
120
+ const lockRow = await this.#db
121
+ .selectFrom(exports.MIGRATION_LOCK_TABLE)
122
+ .where('id', '=', exports.MIGRATION_LOCK_ID)
123
+ .select('id')
124
+ .executeTakeFirst();
125
+ return !!lockRow;
126
+ }
127
+ async #runMigrations(migrationsOrFolderPath, getTargetMigration) {
28
128
  const run = async (db) => {
29
129
  try {
30
130
  await this.#adapter.acquireMigrationLock(db);
31
- await runNewMigrations(db, allMigrations);
131
+ const state = await this.#getState(db, migrationsOrFolderPath);
132
+ if (state.migrations.length === 0) {
133
+ return { results: [] };
134
+ }
135
+ const targetIndex = getTargetMigration(state);
136
+ if (targetIndex === undefined) {
137
+ return { results: [] };
138
+ }
139
+ if (targetIndex < state.currentIndex) {
140
+ return await this.#migrateDown(db, state, targetIndex);
141
+ }
142
+ else if (targetIndex > state.currentIndex) {
143
+ return await this.#migrateUp(db, state, targetIndex);
144
+ }
145
+ return { results: [] };
32
146
  }
33
147
  finally {
34
148
  await this.#adapter.releaseMigrationLock(db);
35
149
  }
36
150
  };
37
151
  if (this.#adapter.supportsTransactionalDdl) {
38
- await this.#db.transaction().execute(run);
152
+ return this.#db.transaction().execute(run);
39
153
  }
40
154
  else {
41
- await this.#db.connection().execute(run);
155
+ return this.#db.connection().execute(run);
42
156
  }
43
157
  }
44
- }
45
- exports.MigrationModule = MigrationModule;
46
- async function ensureMigrationTablesExists(db) {
47
- await ensureMigrationTableExists(db);
48
- await ensureMigrationLockTableExists(db);
49
- await ensureLockRowExists(db);
50
- }
51
- async function ensureMigrationTableExists(db) {
52
- if (!(await doesTableExists(db, exports.MIGRATION_TABLE))) {
53
- try {
54
- await db.schema
55
- .createTable(exports.MIGRATION_TABLE)
56
- .ifNotExists()
57
- .addColumn('name', 'varchar(255)', (col) => col.notNull().primaryKey())
58
- // The migration run time as ISO string. This is not a real date type as we
59
- // can't know which data type is supported by all future dialects.
60
- .addColumn('timestamp', 'varchar(255)', (col) => col.notNull())
61
- .execute();
62
- }
63
- catch (error) {
64
- // At least on PostgreSQL, `if not exists` doesn't guarantee the `create table`
65
- // query doesn't throw if the table already exits. That's why we check if
66
- // the table exist here and ignore the error if it does.
67
- if (!(await doesTableExists(db, exports.MIGRATION_TABLE))) {
68
- throw error;
158
+ async #getState(db, migrationsOrFolderPath) {
159
+ const migrations = await this.#resolveMigrations(migrationsOrFolderPath);
160
+ const executedMigrations = await this.#getExecutedMigrations(db);
161
+ this.#ensureMigrationsNotCorrupted(migrations, executedMigrations);
162
+ return (0, object_utils_js_1.freeze)({
163
+ migrations,
164
+ currentIndex: migrations.findIndex((it) => it.name === (0, object_utils_js_1.getLast)(executedMigrations)),
165
+ });
166
+ }
167
+ async #resolveMigrations(migrationsOrFolderPath) {
168
+ const allMigrations = (0, object_utils_js_1.isString)(migrationsOrFolderPath)
169
+ ? await this.#readMigrationsFromFolder(migrationsOrFolderPath)
170
+ : migrationsOrFolderPath;
171
+ return Object.keys(allMigrations)
172
+ .sort()
173
+ .map((name) => ({
174
+ ...allMigrations[name],
175
+ name,
176
+ }));
177
+ }
178
+ async #readMigrationsFromFolder(migrationsFolderPath) {
179
+ const files = await fs_1.promises.readdir(migrationsFolderPath);
180
+ const migrations = {};
181
+ for (const file of files) {
182
+ if ((file.endsWith('.js') || file.endsWith('.ts')) &&
183
+ !file.endsWith('.d.ts')) {
184
+ const migration = await Promise.resolve().then(() => require(path.join(migrationsFolderPath, file)));
185
+ if (isMigration(migration)) {
186
+ migrations[file.substring(0, file.length - 3)] = migration;
187
+ }
69
188
  }
70
189
  }
190
+ return migrations;
71
191
  }
72
- }
73
- async function ensureMigrationLockTableExists(db) {
74
- if (!(await doesTableExists(db, exports.MIGRATION_LOCK_TABLE))) {
75
- try {
76
- await db.schema
77
- .createTable(exports.MIGRATION_LOCK_TABLE)
78
- .ifNotExists()
79
- .addColumn('id', 'varchar(255)', (col) => col.notNull().primaryKey())
80
- .addColumn('is_locked', 'integer', (col) => col.notNull().defaultTo(0))
81
- .execute();
192
+ async #getExecutedMigrations(db) {
193
+ const executedMigrations = await db
194
+ .selectFrom(exports.MIGRATION_TABLE)
195
+ .select('name')
196
+ .orderBy('name')
197
+ .execute();
198
+ return executedMigrations.map((it) => it.name);
199
+ }
200
+ #ensureMigrationsNotCorrupted(migrations, executedMigrations) {
201
+ for (const executed of executedMigrations) {
202
+ if (!migrations.some((it) => it.name === executed)) {
203
+ throw new Error(`corrupted migrations: previously executed migration ${executed} is missing`);
204
+ }
82
205
  }
83
- catch (error) {
84
- // At least on PostgreSQL, `if not exists` doesn't guarantee the `create table`
85
- // query doesn't throw if the table already exits. That's why we check if
86
- // the table exist here and ignore the error if it does.
87
- if (!(await doesTableExists(db, exports.MIGRATION_LOCK_TABLE))) {
88
- throw error;
206
+ // Now we know all executed migrations exist in the `migrations` list.
207
+ // Next we need to make sure that the executed migrations are the first
208
+ // ones in the migration list.
209
+ for (let i = 0; i < executedMigrations.length; ++i) {
210
+ if (migrations[i].name !== executedMigrations[i]) {
211
+ throw new Error(`corrupted migrations: expected previously executed migration ${executedMigrations[i]} to be at index ${i} but ${migrations[i].name} was found in its place. New migrations must always have a name that comes alphabetically after the last executed migration.`);
89
212
  }
90
213
  }
91
214
  }
92
- }
93
- async function ensureLockRowExists(db) {
94
- if (!(await doesLockRowExists(db))) {
95
- try {
96
- await db
97
- .insertInto(exports.MIGRATION_LOCK_TABLE)
98
- .values({ id: exports.MIGRATION_LOCK_ID })
99
- .execute();
215
+ async #migrateDown(db, state, targetIndex) {
216
+ const results = [];
217
+ for (let i = state.currentIndex; i > targetIndex; --i) {
218
+ results.push({
219
+ migrationName: state.migrations[i].name,
220
+ direction: 'Down',
221
+ status: 'NotExecuted',
222
+ });
100
223
  }
101
- catch (error) {
102
- if (!(await doesLockRowExists(db))) {
103
- throw error;
224
+ for (let i = 0; i < results.length; ++i) {
225
+ const migration = state.migrations.find((it) => it.name === results[i].migrationName);
226
+ try {
227
+ if (migration.down) {
228
+ await migration.down(db);
229
+ await db
230
+ .deleteFrom(exports.MIGRATION_TABLE)
231
+ .where('name', '=', migration.name)
232
+ .execute();
233
+ results[i] = {
234
+ migrationName: migration.name,
235
+ direction: 'Down',
236
+ status: 'Success',
237
+ };
238
+ }
239
+ }
240
+ catch (error) {
241
+ results[i] = {
242
+ migrationName: migration.name,
243
+ direction: 'Down',
244
+ status: 'Error',
245
+ };
246
+ throw new MigrationResultSetError({
247
+ error,
248
+ results,
249
+ });
104
250
  }
105
251
  }
252
+ return { results };
106
253
  }
107
- }
108
- async function doesTableExists(db, tableName) {
109
- const metadata = await db.introspection.getMetadata({
110
- withInternalKyselyTables: true,
111
- });
112
- return !!metadata.tables.find((it) => it.name === tableName);
113
- }
114
- async function doesLockRowExists(db) {
115
- const lockRow = await db
116
- .selectFrom(exports.MIGRATION_LOCK_TABLE)
117
- .where('id', '=', exports.MIGRATION_LOCK_ID)
118
- .select('id')
119
- .executeTakeFirst();
120
- return !!lockRow;
121
- }
122
- async function readMigrationsFromFolder(migrationsFolderPath) {
123
- const files = await fs_1.promises.readdir(migrationsFolderPath);
124
- const migrations = {};
125
- for (const file of files) {
126
- if ((file.endsWith('.js') || file.endsWith('.ts')) &&
127
- !file.endsWith('.d.ts')) {
128
- const migration = await Promise.resolve().then(() => require(path.join(migrationsFolderPath, file)));
129
- if (isMigration(migration)) {
130
- migrations[file.substring(0, file.length - 3)] = migration;
254
+ async #migrateUp(db, state, targetIndex) {
255
+ const results = [];
256
+ for (let i = state.currentIndex + 1; i <= targetIndex; ++i) {
257
+ results.push({
258
+ migrationName: state.migrations[i].name,
259
+ direction: 'Up',
260
+ status: 'NotExecuted',
261
+ });
262
+ }
263
+ for (let i = 0; i < results.length; ++i) {
264
+ const migration = state.migrations.find((it) => it.name === results[i].migrationName);
265
+ try {
266
+ await migration.up(db);
267
+ await db
268
+ .insertInto(exports.MIGRATION_TABLE)
269
+ .values({
270
+ name: migration.name,
271
+ timestamp: new Date().toISOString(),
272
+ })
273
+ .execute();
274
+ results[i] = {
275
+ migrationName: migration.name,
276
+ direction: 'Up',
277
+ status: 'Success',
278
+ };
279
+ }
280
+ catch (error) {
281
+ results[i] = {
282
+ migrationName: migration.name,
283
+ direction: 'Up',
284
+ status: 'Error',
285
+ };
286
+ throw new MigrationResultSetError({
287
+ error,
288
+ results,
289
+ });
131
290
  }
132
291
  }
133
- }
134
- return migrations;
135
- }
136
- async function runNewMigrations(db, allMigrations) {
137
- const sortedMigrations = Object.keys(allMigrations)
138
- .sort()
139
- .map((name) => ({
140
- ...allMigrations[name],
141
- name,
142
- }));
143
- const executedMigrations = await db
144
- .selectFrom(exports.MIGRATION_TABLE)
145
- .select('name')
146
- .orderBy('name')
147
- .execute();
148
- const lastExecuted = (0, object_utils_js_1.getLast)(executedMigrations);
149
- const lastExecutedIndex = sortedMigrations.findIndex((it) => it.name === lastExecuted?.name);
150
- if (lastExecuted && lastExecutedIndex === -1) {
151
- throw new Error(`corrupted migrations: previously executed migration ${lastExecuted.name} is missing`);
152
- }
153
- const oldMigrations = lastExecuted
154
- ? sortedMigrations.slice(0, lastExecutedIndex + 1)
155
- : [];
156
- const newMigrations = lastExecuted
157
- ? sortedMigrations.slice(lastExecutedIndex + 1)
158
- : sortedMigrations;
159
- ensureMigrationsAreNotCorrupted(executedMigrations.map((it) => it.name), oldMigrations.map((it) => it.name));
160
- for (const migration of newMigrations) {
161
- await migration.up(db);
162
- await db
163
- .insertInto(exports.MIGRATION_TABLE)
164
- .values({
165
- name: migration.name,
166
- timestamp: new Date().toISOString(),
167
- })
168
- .execute();
292
+ return { results };
169
293
  }
170
294
  }
171
- function ensureMigrationsAreNotCorrupted(executedMigrationNames, oldMigrationNames) {
172
- const executedSet = new Set(executedMigrationNames);
173
- const oldMigrationSet = new Set(oldMigrationNames);
174
- for (const it of executedSet) {
175
- if (!oldMigrationSet.has(it)) {
176
- throw new Error(`corrupted migrations: previously executed migration ${it} is missing`);
177
- }
295
+ exports.MigrationModule = MigrationModule;
296
+ class MigrationResultSetError extends Error {
297
+ #resultSet;
298
+ constructor(result) {
299
+ super();
300
+ this.#resultSet = result;
178
301
  }
179
- for (const it of oldMigrationSet) {
180
- if (!executedSet.has(it)) {
181
- throw new Error(`corrupted migrations: new migration ${it} comes alphabetically before the last executed migration. New migrations must always have a name that comes alphabetically after the last executed migration.`);
182
- }
302
+ get resultSet() {
303
+ return this.#resultSet;
183
304
  }
184
305
  }
185
306
  function isMigration(obj) {
@@ -11,5 +11,5 @@ export interface CheckConstraintNode extends OperationNode {
11
11
  */
12
12
  export declare const CheckConstraintNode: Readonly<{
13
13
  is(node: OperationNode): node is CheckConstraintNode;
14
- create(expressionSql: string, constraintName?: string | undefined): CheckConstraintNode;
14
+ create(expression: RawNode, constraintName?: string | undefined): CheckConstraintNode;
15
15
  }>;
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CheckConstraintNode = void 0;
4
4
  const object_utils_js_1 = require("../util/object-utils.js");
5
- const raw_node_js_1 = require("./raw-node.js");
6
5
  const identifier_node_js_1 = require("./identifier-node.js");
7
6
  /**
8
7
  * @internal
@@ -11,10 +10,10 @@ exports.CheckConstraintNode = (0, object_utils_js_1.freeze)({
11
10
  is(node) {
12
11
  return node.kind === 'CheckConstraintNode';
13
12
  },
14
- create(expressionSql, constraintName) {
13
+ create(expression, constraintName) {
15
14
  return (0, object_utils_js_1.freeze)({
16
15
  kind: 'CheckConstraintNode',
17
- expression: raw_node_js_1.RawNode.createWithSql(expressionSql),
16
+ expression,
18
17
  name: constraintName ? identifier_node_js_1.IdentifierNode.create(constraintName) : undefined,
19
18
  });
20
19
  },
@@ -2,24 +2,25 @@ import { CheckConstraintNode } from './check-constraint-node.js';
2
2
  import { ColumnNode } from './column-node.js';
3
3
  import { DataTypeNode } from './data-type-node.js';
4
4
  import { DefaultValueNode } from './default-value-node.js';
5
- import { GeneratedAlwaysAsNode } from './generated-always-as-node.js';
5
+ import { GeneratedNode } from './generated-node.js';
6
6
  import { OperationNode } from './operation-node.js';
7
7
  import { RawNode } from './raw-node.js';
8
8
  import { ReferencesNode } from './references-node.js';
9
- export declare type ColumnDefinitionNodeProps = Omit<Partial<ColumnDefinitionNode>, 'kind'>;
9
+ export declare type ColumnDefinitionNodeProps = Omit<Partial<ColumnDefinitionNode>, 'kind' | 'dataType'>;
10
10
  export declare type ColumnDataTypeNode = DataTypeNode | RawNode;
11
11
  export interface ColumnDefinitionNode extends OperationNode {
12
12
  readonly kind: 'ColumnDefinitionNode';
13
13
  readonly column: ColumnNode;
14
14
  readonly dataType: ColumnDataTypeNode;
15
15
  readonly references?: ReferencesNode;
16
- readonly primaryKey: boolean;
17
- readonly autoIncrement: boolean;
18
- readonly unique: boolean;
19
- readonly nullable: boolean;
16
+ readonly primaryKey?: boolean;
17
+ readonly autoIncrement?: boolean;
18
+ readonly unique?: boolean;
19
+ readonly notNull?: boolean;
20
20
  readonly defaultTo?: DefaultValueNode;
21
21
  readonly check?: CheckConstraintNode;
22
- readonly generatedAlwaysAs?: GeneratedAlwaysAsNode;
22
+ readonly generated?: GeneratedNode;
23
+ readonly unsigned?: boolean;
23
24
  }
24
25
  /**
25
26
  * @internal
@@ -15,10 +15,6 @@ exports.ColumnDefinitionNode = (0, object_utils_js_1.freeze)({
15
15
  kind: 'ColumnDefinitionNode',
16
16
  column: column_node_js_1.ColumnNode.create(column),
17
17
  dataType,
18
- primaryKey: false,
19
- autoIncrement: false,
20
- unique: false,
21
- nullable: true,
22
18
  });
23
19
  },
24
20
  cloneWith(node, props) {
@@ -0,0 +1,15 @@
1
+ import { ColumnNode } from './column-node.js';
2
+ import { OperationNode } from './operation-node.js';
3
+ import { TableNode } from './table-node.js';
4
+ export interface CommonTableExpressionNameNode extends OperationNode {
5
+ readonly kind: 'CommonTableExpressionNameNode';
6
+ readonly table: TableNode;
7
+ readonly columns?: ReadonlyArray<ColumnNode>;
8
+ }
9
+ /**
10
+ * @internal
11
+ */
12
+ export declare const CommonTableExpressionNameNode: Readonly<{
13
+ is(node: OperationNode): node is CommonTableExpressionNameNode;
14
+ create(tableName: string, columnNames?: readonly string[] | undefined): CommonTableExpressionNameNode;
15
+ }>;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CommonTableExpressionNameNode = void 0;
4
+ const object_utils_js_1 = require("../util/object-utils.js");
5
+ const column_node_js_1 = require("./column-node.js");
6
+ const table_node_js_1 = require("./table-node.js");
7
+ /**
8
+ * @internal
9
+ */
10
+ exports.CommonTableExpressionNameNode = (0, object_utils_js_1.freeze)({
11
+ is(node) {
12
+ return node.kind === 'CommonTableExpressionNameNode';
13
+ },
14
+ create(tableName, columnNames) {
15
+ return (0, object_utils_js_1.freeze)({
16
+ kind: 'CommonTableExpressionNameNode',
17
+ table: table_node_js_1.TableNode.create(tableName),
18
+ columns: columnNames
19
+ ? (0, object_utils_js_1.freeze)(columnNames.map(column_node_js_1.ColumnNode.create))
20
+ : undefined,
21
+ });
22
+ },
23
+ });
@@ -1,10 +1,10 @@
1
- import { IdentifierNode } from './identifier-node.js';
1
+ import { CommonTableExpressionNameNode } from './common-table-expression-name-node.js';
2
2
  import { OperationNode } from './operation-node.js';
3
3
  import { QueryNode } from './query-node.js';
4
4
  import { RawNode } from './raw-node.js';
5
5
  export interface CommonTableExpressionNode extends OperationNode {
6
6
  readonly kind: 'CommonTableExpressionNode';
7
- readonly name: IdentifierNode;
7
+ readonly name: CommonTableExpressionNameNode;
8
8
  readonly expression: QueryNode | RawNode;
9
9
  }
10
10
  /**
@@ -12,5 +12,5 @@ export interface CommonTableExpressionNode extends OperationNode {
12
12
  */
13
13
  export declare const CommonTableExpressionNode: Readonly<{
14
14
  is(node: OperationNode): node is CommonTableExpressionNode;
15
- create(name: IdentifierNode, expression: QueryNode | RawNode): CommonTableExpressionNode;
15
+ create(name: CommonTableExpressionNameNode, expression: QueryNode | RawNode): CommonTableExpressionNode;
16
16
  }>;
@@ -1,5 +1,5 @@
1
1
  import { OperationNode } from './operation-node.js';
2
- export declare type ColumnDataType = 'varchar' | `varchar(${number})` | 'text' | 'integer' | 'int2' | 'int4' | 'int8' | 'bigint' | 'boolean' | 'real' | 'double precision' | 'float4' | 'float8' | 'decimal' | `decimal(${number}, ${number})` | 'numeric' | `numeric(${number}, ${number})` | 'binary' | 'date' | 'datetime' | 'time' | 'timetz' | 'timestamp' | 'timestamptz' | 'serial' | 'bigserial' | 'uuid' | 'json' | 'jsonb';
2
+ export declare type ColumnDataType = 'varchar' | `varchar(${number})` | 'text' | 'integer' | 'int2' | 'int4' | 'int8' | 'bigint' | 'boolean' | 'real' | 'double precision' | 'float4' | 'float8' | 'decimal' | `decimal(${number}, ${number})` | 'numeric' | `numeric(${number}, ${number})` | 'binary' | 'date' | 'datetime' | 'time' | 'timetz' | 'timestamp' | 'timestamptz' | 'serial' | 'bigserial' | 'uuid' | 'json' | 'jsonb' | 'blob';
3
3
  export declare type DataTypeParams = Omit<DataTypeNode, 'kind' | 'dataType'>;
4
4
  export interface DataTypeNode extends OperationNode {
5
5
  readonly kind: 'DataTypeNode';
@@ -0,0 +1,20 @@
1
+ import { OperationNode } from './operation-node.js';
2
+ import { RawNode } from './raw-node.js';
3
+ export declare type GeneratedNodeParams = Omit<GeneratedNode, 'kind' | 'expression'>;
4
+ export interface GeneratedNode extends OperationNode {
5
+ readonly kind: 'GeneratedNode';
6
+ readonly byDefault?: boolean;
7
+ readonly always?: boolean;
8
+ readonly identity?: boolean;
9
+ readonly stored?: boolean;
10
+ readonly expression?: RawNode;
11
+ }
12
+ /**
13
+ * @internal
14
+ */
15
+ export declare const GeneratedNode: Readonly<{
16
+ is(node: OperationNode): node is GeneratedNode;
17
+ create(params: GeneratedNodeParams): GeneratedNode;
18
+ createWithExpression(expression: RawNode): GeneratedNode;
19
+ cloneWith(node: GeneratedNode, params: GeneratedNodeParams): GeneratedNode;
20
+ }>;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GeneratedNode = void 0;
4
+ const object_utils_js_1 = require("../util/object-utils.js");
5
+ /**
6
+ * @internal
7
+ */
8
+ exports.GeneratedNode = (0, object_utils_js_1.freeze)({
9
+ is(node) {
10
+ return node.kind === 'GeneratedNode';
11
+ },
12
+ create(params) {
13
+ return (0, object_utils_js_1.freeze)({
14
+ kind: 'GeneratedNode',
15
+ ...params,
16
+ });
17
+ },
18
+ createWithExpression(expression) {
19
+ return (0, object_utils_js_1.freeze)({
20
+ kind: 'GeneratedNode',
21
+ always: true,
22
+ expression,
23
+ });
24
+ },
25
+ cloneWith(node, params) {
26
+ return (0, object_utils_js_1.freeze)({
27
+ ...node,
28
+ ...params,
29
+ });
30
+ },
31
+ });