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 to the functions is an instance of
208
- `Kysely<any>`. It is 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 if the app
210
- changes completely. Migrations need to be "frozen in time".
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. The migrations are executed in alphabetical
299
- order by their name. See the [Migrator](https://koskimas.github.io/kysely/classes/Migrator.html)
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, and parallel calls are executed serially.
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kysely",
3
- "version": "0.16.8",
3
+ "version": "0.16.9",
4
4
  "description": "Type safe SQL query builder",
5
5
  "repository": {
6
6
  "type": "git",