kysely 0.16.8 → 0.16.9
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.
package/README.md
CHANGED
|
@@ -204,14 +204,24 @@ export async function down(db: Kysely<any>): Promise<void> {
|
|
|
204
204
|
```
|
|
205
205
|
|
|
206
206
|
The `up` function is called when you update your database schema to next version and `down`
|
|
207
|
-
when you go back to previous version. The only argument
|
|
208
|
-
`Kysely<any>`. It
|
|
209
|
-
should never depend on the current code of your app because they need to work even
|
|
210
|
-
changes
|
|
207
|
+
when you go back to previous version. The only argument for the functions is an instance of
|
|
208
|
+
`Kysely<any>`. It's important to use `Kysely<any>` and not `Kysely<YourDatabase>`. Migrations
|
|
209
|
+
should never depend on the current code of your app because they need to work even when the app
|
|
210
|
+
changes. Migrations need to be "frozen in time".
|
|
211
211
|
|
|
212
212
|
The migrations can use the [Kysely.schema](https://koskimas.github.io/kysely/classes/SchemaModule.html)
|
|
213
213
|
module to modify the schema. Migrations can also run normal queries to modify data.
|
|
214
214
|
|
|
215
|
+
Execution order of the migrations is the alpabetical order of their names. An excellent way to name your
|
|
216
|
+
migrations is to prefix them with an ISO 8601 date string. A date prefix works well in large teams
|
|
217
|
+
where multiple team members may add migrations at the same time in parallel commits without knowing
|
|
218
|
+
about the other migrations.
|
|
219
|
+
|
|
220
|
+
You don't need to store your migrations as separate files if you don't want to. You can easily
|
|
221
|
+
implement your own [MigrationProvider](https://koskimas.github.io/kysely/interfaces/MigrationProvider.html)
|
|
222
|
+
and give it to the [Migrator](https://koskimas.github.io/kysely/classes/Migrator.html) class
|
|
223
|
+
when you instantiate one.
|
|
224
|
+
|
|
215
225
|
### PostgreSQL migration example
|
|
216
226
|
|
|
217
227
|
```ts
|
|
@@ -295,9 +305,9 @@ const migrator = new Migrator(migratorConfig);
|
|
|
295
305
|
await migrator.migrateToLatest(pathToMigrationsFolder)
|
|
296
306
|
```
|
|
297
307
|
|
|
298
|
-
to run all migrations that have not yet been run.
|
|
299
|
-
|
|
300
|
-
documentation for more info.
|
|
308
|
+
to run all migrations that have not yet been run. See the
|
|
309
|
+
[Migrator](https://koskimas.github.io/kysely/classes/Migrator.html)
|
|
310
|
+
class's documentation for more info.
|
|
301
311
|
|
|
302
312
|
Kysely doesn't have a CLI for running migrations and probably never will. This is because Kysely's
|
|
303
313
|
migrations are also written in typescript. To run the migrations, you need to first build the
|
|
@@ -352,9 +362,11 @@ async function migrateToLatest() {
|
|
|
352
362
|
migrateToLatest()
|
|
353
363
|
```
|
|
354
364
|
|
|
355
|
-
The migration methods use a lock on the database level
|
|
365
|
+
The migration methods use a lock on the database level and parallel calls are executed serially.
|
|
356
366
|
This means that you can safely call `migrateToLatest` and other migration methods from multiple
|
|
357
|
-
server instances simultaneously and the migrations are guaranteed to only be executed once.
|
|
367
|
+
server instances simultaneously and the migrations are guaranteed to only be executed once. The
|
|
368
|
+
locks are also automatically released if the migration process crashes or the connection to the
|
|
369
|
+
database fails.
|
|
358
370
|
|
|
359
371
|
# Deno
|
|
360
372
|
|
|
@@ -36,6 +36,12 @@ export interface Migration {
|
|
|
36
36
|
export declare class Migrator {
|
|
37
37
|
#private;
|
|
38
38
|
constructor(props: MigratorProps);
|
|
39
|
+
/**
|
|
40
|
+
* Returns a {@link MigrationInfo} object for each migration.
|
|
41
|
+
*
|
|
42
|
+
* The returned array is sorted by migration name.
|
|
43
|
+
*/
|
|
44
|
+
getMigrations(): Promise<ReadonlyArray<MigrationInfo>>;
|
|
39
45
|
/**
|
|
40
46
|
* Runs all migrations that have not yet been run.
|
|
41
47
|
*
|
|
@@ -219,3 +225,19 @@ export interface MigrationProvider {
|
|
|
219
225
|
export interface NoMigrations {
|
|
220
226
|
readonly __noMigrations__: true;
|
|
221
227
|
}
|
|
228
|
+
export interface MigrationInfo {
|
|
229
|
+
/**
|
|
230
|
+
* Name of the migration.
|
|
231
|
+
*/
|
|
232
|
+
name: string;
|
|
233
|
+
/**
|
|
234
|
+
* The actual migration.
|
|
235
|
+
*/
|
|
236
|
+
migration: Migration;
|
|
237
|
+
/**
|
|
238
|
+
* When was the migration executed.
|
|
239
|
+
*
|
|
240
|
+
* If this is undefined, the migration hasn't been executed yet.
|
|
241
|
+
*/
|
|
242
|
+
executedAt?: Date;
|
|
243
|
+
}
|
|
@@ -32,6 +32,28 @@ class Migrator {
|
|
|
32
32
|
constructor(props) {
|
|
33
33
|
this.#props = (0, object_utils_js_1.freeze)(props);
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Returns a {@link MigrationInfo} object for each migration.
|
|
37
|
+
*
|
|
38
|
+
* The returned array is sorted by migration name.
|
|
39
|
+
*/
|
|
40
|
+
async getMigrations() {
|
|
41
|
+
const executedMigrations = (await this.#doesTableExists(exports.MIGRATION_TABLE))
|
|
42
|
+
? await this.#props.db
|
|
43
|
+
.selectFrom(exports.MIGRATION_TABLE)
|
|
44
|
+
.select(['name', 'timestamp'])
|
|
45
|
+
.execute()
|
|
46
|
+
: [];
|
|
47
|
+
const migrations = await this.#resolveMigrations();
|
|
48
|
+
return migrations.map(({ name, ...migration }) => {
|
|
49
|
+
const executed = executedMigrations.find((it) => it.name === name);
|
|
50
|
+
return {
|
|
51
|
+
name,
|
|
52
|
+
migration,
|
|
53
|
+
executedAt: executed ? new Date(executed.timestamp) : undefined,
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
}
|
|
35
57
|
/**
|
|
36
58
|
* Runs all migrations that have not yet been run.
|
|
37
59
|
*
|
|
@@ -215,7 +237,7 @@ class Migrator {
|
|
|
215
237
|
try {
|
|
216
238
|
await this.#props.db
|
|
217
239
|
.insertInto(exports.MIGRATION_LOCK_TABLE)
|
|
218
|
-
.values({ id: exports.MIGRATION_LOCK_ID })
|
|
240
|
+
.values({ id: exports.MIGRATION_LOCK_ID, is_locked: 0 })
|
|
219
241
|
.execute();
|
|
220
242
|
}
|
|
221
243
|
catch (error) {
|
|
@@ -36,6 +36,12 @@ export interface Migration {
|
|
|
36
36
|
export declare class Migrator {
|
|
37
37
|
#private;
|
|
38
38
|
constructor(props: MigratorProps);
|
|
39
|
+
/**
|
|
40
|
+
* Returns a {@link MigrationInfo} object for each migration.
|
|
41
|
+
*
|
|
42
|
+
* The returned array is sorted by migration name.
|
|
43
|
+
*/
|
|
44
|
+
getMigrations(): Promise<ReadonlyArray<MigrationInfo>>;
|
|
39
45
|
/**
|
|
40
46
|
* Runs all migrations that have not yet been run.
|
|
41
47
|
*
|
|
@@ -219,3 +225,19 @@ export interface MigrationProvider {
|
|
|
219
225
|
export interface NoMigrations {
|
|
220
226
|
readonly __noMigrations__: true;
|
|
221
227
|
}
|
|
228
|
+
export interface MigrationInfo {
|
|
229
|
+
/**
|
|
230
|
+
* Name of the migration.
|
|
231
|
+
*/
|
|
232
|
+
name: string;
|
|
233
|
+
/**
|
|
234
|
+
* The actual migration.
|
|
235
|
+
*/
|
|
236
|
+
migration: Migration;
|
|
237
|
+
/**
|
|
238
|
+
* When was the migration executed.
|
|
239
|
+
*
|
|
240
|
+
* If this is undefined, the migration hasn't been executed yet.
|
|
241
|
+
*/
|
|
242
|
+
executedAt?: Date;
|
|
243
|
+
}
|
|
@@ -30,6 +30,28 @@ export class Migrator {
|
|
|
30
30
|
constructor(props) {
|
|
31
31
|
this.#props = freeze(props);
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Returns a {@link MigrationInfo} object for each migration.
|
|
35
|
+
*
|
|
36
|
+
* The returned array is sorted by migration name.
|
|
37
|
+
*/
|
|
38
|
+
async getMigrations() {
|
|
39
|
+
const executedMigrations = (await this.#doesTableExists(MIGRATION_TABLE))
|
|
40
|
+
? await this.#props.db
|
|
41
|
+
.selectFrom(MIGRATION_TABLE)
|
|
42
|
+
.select(['name', 'timestamp'])
|
|
43
|
+
.execute()
|
|
44
|
+
: [];
|
|
45
|
+
const migrations = await this.#resolveMigrations();
|
|
46
|
+
return migrations.map(({ name, ...migration }) => {
|
|
47
|
+
const executed = executedMigrations.find((it) => it.name === name);
|
|
48
|
+
return {
|
|
49
|
+
name,
|
|
50
|
+
migration,
|
|
51
|
+
executedAt: executed ? new Date(executed.timestamp) : undefined,
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
}
|
|
33
55
|
/**
|
|
34
56
|
* Runs all migrations that have not yet been run.
|
|
35
57
|
*
|
|
@@ -213,7 +235,7 @@ export class Migrator {
|
|
|
213
235
|
try {
|
|
214
236
|
await this.#props.db
|
|
215
237
|
.insertInto(MIGRATION_LOCK_TABLE)
|
|
216
|
-
.values({ id: MIGRATION_LOCK_ID })
|
|
238
|
+
.values({ id: MIGRATION_LOCK_ID, is_locked: 0 })
|
|
217
239
|
.execute();
|
|
218
240
|
}
|
|
219
241
|
catch (error) {
|