@kurdel/migrations 0.1.0-beta.2 → 0.1.0-beta.4

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
@@ -1,5 +1,15 @@
1
1
  # @kurdel/migrations
2
2
 
3
+ Schema blueprints use the connected database dialect. SQLite emits its native
4
+ integer primary keys and `DATETIME`, while PostgreSQL emits identity columns,
5
+ `TIMESTAMPTZ`, and native boolean defaults from the same migration source.
6
+
7
+ `MigrationManager` serializes `run`, `rollback`, and `refresh` through a
8
+ portable database lease. This prevents concurrent processes from applying the
9
+ same migration and releases the lease even when discovery or execution fails.
10
+ Use `manager.status()` to inspect applied batches and pending migration files
11
+ without acquiring the mutation lock.
12
+
3
13
  Database schema migration primitives for Kurdel. The package provides the
4
14
  `Migration`, `MigrationManager`, `Schema`, and `Blueprint` APIs used to define,
5
15
  apply, roll back, and refresh migrations.
@@ -1,3 +1,4 @@
1
+ import type { DatabaseDialect } from '@kurdel/db';
1
2
  import { Column } from './column.js';
2
3
  export interface IndexDefinition {
3
4
  columns: string[];
@@ -5,9 +6,11 @@ export interface IndexDefinition {
5
6
  unique: boolean;
6
7
  }
7
8
  export declare class Blueprint {
9
+ private readonly dialect;
8
10
  private readonly columns;
9
11
  private readonly constraints;
10
12
  private readonly indexes;
13
+ constructor(dialect?: DatabaseDialect);
11
14
  integer(name: string): Column;
12
15
  string(name: string, length?: number): Column;
13
16
  boolean(name: string): Column;
package/lib/blueprint.js CHANGED
@@ -1,8 +1,12 @@
1
1
  import { Column } from './column.js';
2
2
  export class Blueprint {
3
+ dialect;
3
4
  columns = [];
4
5
  constraints = [];
5
6
  indexes = [];
7
+ constructor(dialect = 'sqlite') {
8
+ this.dialect = dialect;
9
+ }
6
10
  integer(name) {
7
11
  return this.addColumn(name, 'INTEGER');
8
12
  }
@@ -13,7 +17,7 @@ export class Blueprint {
13
17
  return this.addColumn(name, 'BOOLEAN');
14
18
  }
15
19
  datetime(name) {
16
- return this.addColumn(name, 'DATETIME');
20
+ return this.addColumn(name, this.dialect === 'postgres' ? 'TIMESTAMPTZ' : 'DATETIME');
17
21
  }
18
22
  /** Supports both the legacy single-column form and composite keys. */
19
23
  primaryKey(columns) {
@@ -56,7 +60,7 @@ export class Blueprint {
56
60
  if (this.columns.some(column => column.name === name)) {
57
61
  throw new Error(`Column '${name}' is already defined`);
58
62
  }
59
- const column = new Column(name, type);
63
+ const column = new Column(name, type, this.dialect);
60
64
  this.columns.push(column);
61
65
  return column;
62
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"blueprint.js","sourceRoot":"","sources":["../src/blueprint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blueprint.js","sourceRoot":"","sources":["../src/blueprint.ts"],"names":[],"mappings":"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"}
package/lib/column.d.ts CHANGED
@@ -1,9 +1,11 @@
1
+ import type { DatabaseDialect } from '@kurdel/db';
1
2
  export type ColumnDefault = string | number | boolean | null;
2
3
  export declare class Column {
3
4
  readonly name: string;
4
5
  readonly type: string;
6
+ private readonly dialect;
5
7
  private readonly modifiers;
6
- constructor(name: string, type: string);
8
+ constructor(name: string, type: string, dialect?: DatabaseDialect);
7
9
  primaryKey(): this;
8
10
  notNull(): this;
9
11
  nullable(): this;
package/lib/column.js CHANGED
@@ -1,10 +1,12 @@
1
1
  export class Column {
2
2
  name;
3
3
  type;
4
+ dialect;
4
5
  modifiers = [];
5
- constructor(name, type) {
6
+ constructor(name, type, dialect = 'sqlite') {
6
7
  this.name = name;
7
8
  this.type = type;
9
+ this.dialect = dialect;
8
10
  }
9
11
  primaryKey() {
10
12
  return this.addModifier('PRIMARY KEY');
@@ -36,7 +38,11 @@ export class Column {
36
38
  return this.addModifier(constraint);
37
39
  }
38
40
  toString() {
39
- return `${this.name} ${this.type} ${this.modifiers.join(' ')}`.trim();
41
+ const identity = this.dialect === 'postgres' && this.type === 'INTEGER' &&
42
+ this.modifiers.includes('PRIMARY KEY')
43
+ ? ' GENERATED BY DEFAULT AS IDENTITY'
44
+ : '';
45
+ return `${this.name} ${this.type}${identity} ${this.modifiers.join(' ')}`.trim();
40
46
  }
41
47
  addModifier(modifier) {
42
48
  if (!this.modifiers.includes(modifier))
@@ -46,8 +52,11 @@ export class Column {
46
52
  serializeDefault(value) {
47
53
  if (value === null)
48
54
  return 'NULL';
49
- if (typeof value === 'boolean')
55
+ if (typeof value === 'boolean') {
56
+ if (this.dialect === 'postgres')
57
+ return value ? 'TRUE' : 'FALSE';
50
58
  return value ? '1' : '0';
59
+ }
51
60
  if (typeof value === 'number')
52
61
  return String(value);
53
62
  return `'${value.replaceAll("'", "''")}'`;
package/lib/column.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"column.js","sourceRoot":"","sources":["../src/column.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,MAAM;IAIC;IACA;IAJD,SAAS,GAAa,EAAE,CAAC;IAE1C,YACkB,IAAY,EACZ,IAAY;QADZ,SAAI,GAAJ,IAAI,CAAQ;QACZ,SAAI,GAAJ,IAAI,CAAQ;IAC3B,CAAC;IAEJ,UAAU;QACR,OAAO,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IACzC,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;IAED,QAAQ;QACN,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,KAAK,IAAI,CAAC;YAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,CAAC,KAAoB;QAC1B,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,UAAU,CAAC,UAAkB;QAC3B,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC9E,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,UAAU,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,UAAU,CAAC,KAAa,EAAE,MAAc,EAAE,QAAiB;QACzD,IAAI,UAAU,GAAG,cAAc,KAAK,KAAK,MAAM,GAAG,CAAC;QACnD,IAAI,QAAQ;YAAE,UAAU,IAAI,cAAc,QAAQ,EAAE,CAAC;QACrD,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;IAED,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;IACxE,CAAC;IAEO,WAAW,CAAC,QAAgB;QAClC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtE,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,gBAAgB,CAAC,KAAoB;QAC3C,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,MAAM,CAAC;QAClC,IAAI,OAAO,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACzD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACpD,OAAO,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;IAC5C,CAAC;CACF"}
1
+ {"version":3,"file":"column.js","sourceRoot":"","sources":["../src/column.ts"],"names":[],"mappings":"AAIA,MAAM,OAAO,MAAM;IAIC;IACA;IACC;IALF,SAAS,GAAa,EAAE,CAAC;IAE1C,YACkB,IAAY,EACZ,IAAY,EACX,UAA2B,QAAQ;QAFpC,SAAI,GAAJ,IAAI,CAAQ;QACZ,SAAI,GAAJ,IAAI,CAAQ;QACX,YAAO,GAAP,OAAO,CAA4B;IACnD,CAAC;IAEJ,UAAU;QACR,OAAO,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IACzC,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;IAED,QAAQ;QACN,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,KAAK,IAAI,CAAC;YAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,CAAC,KAAoB;QAC1B,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,UAAU,CAAC,UAAkB;QAC3B,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC9E,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,UAAU,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,UAAU,CAAC,KAAa,EAAE,MAAc,EAAE,QAAiB;QACzD,IAAI,UAAU,GAAG,cAAc,KAAK,KAAK,MAAM,GAAG,CAAC;QACnD,IAAI,QAAQ;YAAE,UAAU,IAAI,cAAc,QAAQ,EAAE,CAAC;QACrD,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;IAED,QAAQ;QACN,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YACrE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC;YACtC,CAAC,CAAC,mCAAmC;YACrC,CAAC,CAAC,EAAE,CAAC;QACP,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,GAAG,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;IACnF,CAAC;IAEO,WAAW,CAAC,QAAgB;QAClC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtE,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,gBAAgB,CAAC,KAAoB;QAC3C,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,MAAM,CAAC;QAClC,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,IAAI,CAAC,OAAO,KAAK,UAAU;gBAAE,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YACjE,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC3B,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACpD,OAAO,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;IAC5C,CAAC;CACF"}
package/lib/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './migration.js';
2
2
  export * from './migration-manager.js';
3
+ export * from './migration-lock.js';
3
4
  export * from './column.js';
4
5
  export * from './schema.js';
5
6
  export * from './blueprint.js';
package/lib/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './migration.js';
2
2
  export * from './migration-manager.js';
3
+ export * from './migration-lock.js';
3
4
  export * from './column.js';
4
5
  export * from './schema.js';
5
6
  export * from './blueprint.js';
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { Database } from '@kurdel/db';
2
+ export declare class MigrationLockedError extends Error {
3
+ constructor();
4
+ }
5
+ /** Portable lease preventing concurrent migration operations. */
6
+ export declare class MigrationLock {
7
+ private readonly connection;
8
+ private readonly leaseMs;
9
+ private readonly owner;
10
+ constructor(connection: Database, leaseMs?: number);
11
+ initialize(): Promise<void>;
12
+ acquire(now?: Date): Promise<void>;
13
+ release(): Promise<void>;
14
+ }
@@ -0,0 +1,47 @@
1
+ import crypto from 'node:crypto';
2
+ export class MigrationLockedError extends Error {
3
+ constructor() {
4
+ super('Another migration operation currently holds the database lock');
5
+ }
6
+ }
7
+ /** Portable lease preventing concurrent migration operations. */
8
+ export class MigrationLock {
9
+ connection;
10
+ leaseMs;
11
+ owner = crypto.randomUUID();
12
+ constructor(connection, leaseMs = 60 * 60 * 1000) {
13
+ this.connection = connection;
14
+ this.leaseMs = leaseMs;
15
+ }
16
+ async initialize() {
17
+ const datetime = this.connection.dialect === 'postgres' ? 'TIMESTAMPTZ' : 'DATETIME';
18
+ await this.connection.run({
19
+ sql: [
20
+ 'CREATE TABLE IF NOT EXISTS migration_locks',
21
+ `(id INTEGER PRIMARY KEY, owner VARCHAR(64) NOT NULL, expires_at ${datetime} NOT NULL);`,
22
+ ].join(' '),
23
+ params: [],
24
+ });
25
+ }
26
+ async acquire(now = new Date()) {
27
+ const expiresAt = new Date(now.getTime() + this.leaseMs);
28
+ const acquired = await this.connection.get({
29
+ sql: [
30
+ 'INSERT INTO migration_locks (id, owner, expires_at) VALUES (?, ?, ?)',
31
+ 'ON CONFLICT(id) DO UPDATE SET owner = excluded.owner, expires_at = excluded.expires_at',
32
+ 'WHERE migration_locks.expires_at <= ?',
33
+ 'RETURNING owner;',
34
+ ].join(' '),
35
+ params: [1, this.owner, expiresAt.toISOString(), now.toISOString()],
36
+ });
37
+ if (acquired?.owner !== this.owner)
38
+ throw new MigrationLockedError();
39
+ }
40
+ async release() {
41
+ await this.connection.run({
42
+ sql: 'DELETE FROM migration_locks WHERE id = ? AND owner = ?;',
43
+ params: [1, this.owner],
44
+ });
45
+ }
46
+ }
47
+ //# sourceMappingURL=migration-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-lock.js","sourceRoot":"","sources":["../src/migration-lock.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAIjC,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C;QACE,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACzE,CAAC;CACF;AAED,iEAAiE;AACjE,MAAM,OAAO,aAAa;IAIL;IACA;IAJF,KAAK,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAE7C,YACmB,UAAoB,EACpB,UAAU,EAAE,GAAG,EAAE,GAAG,IAAI;QADxB,eAAU,GAAV,UAAU,CAAU;QACpB,YAAO,GAAP,OAAO,CAAiB;IACxC,CAAC;IAEJ,KAAK,CAAC,UAAU;QACd,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC;QACrF,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YACxB,GAAG,EAAE;gBACH,4CAA4C;gBAC5C,mEAAmE,QAAQ,aAAa;aACzF,CAAC,IAAI,CAAC,GAAG,CAAC;YACX,MAAM,EAAE,EAAE;SACX,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE;QAC5B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YACzC,GAAG,EAAE;gBACH,sEAAsE;gBACtE,wFAAwF;gBACxF,uCAAuC;gBACvC,kBAAkB;aACnB,CAAC,IAAI,CAAC,GAAG,CAAC;YACX,MAAM,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC;SACpE,CAAkC,CAAC;QACpC,IAAI,QAAQ,EAAE,KAAK,KAAK,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,oBAAoB,EAAE,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YACxB,GAAG,EAAE,yDAAyD;YAC9D,MAAM,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC;SACxB,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -1,16 +1,26 @@
1
1
  import EventEmitter from 'events';
2
- import type { IDatabase } from '@kurdel/db';
2
+ import type { Database } from '@kurdel/db';
3
+ import { MigrationLoader } from './migration-loader.js';
4
+ import { MigrationLock } from './migration-lock.js';
3
5
  import { MigrationRegistry } from './migration-registry.js';
6
+ export type MigrationStatus = {
7
+ name: string;
8
+ state: 'applied' | 'pending' | 'missing';
9
+ batch?: number;
10
+ };
4
11
  export declare class MigrationManager extends EventEmitter {
5
12
  private connection;
6
13
  private loader;
7
14
  private registry;
8
- constructor(connection: IDatabase, registry: MigrationRegistry);
15
+ private lock;
16
+ constructor(connection: Database, registry: MigrationRegistry, loader?: MigrationLoader, lock?: MigrationLock);
9
17
  static create(): Promise<MigrationManager>;
10
- run(): Promise<void>;
11
- rollback(): Promise<void>;
12
- refresh(): Promise<void>;
18
+ run(): Promise<boolean>;
19
+ rollback(): Promise<boolean>;
20
+ refresh(): Promise<boolean>;
21
+ status(): Promise<MigrationStatus[]>;
13
22
  close(): Promise<void>;
23
+ private withLock;
14
24
  private runMigrations;
15
25
  private rollbackMigrations;
16
26
  private findMigrationsToRun;
@@ -1,53 +1,87 @@
1
1
  import EventEmitter from 'events';
2
2
  import { DBConnector } from '@kurdel/db';
3
3
  import { MigrationLoader } from './migration-loader.js';
4
+ import { MigrationLock } from './migration-lock.js';
4
5
  import { MigrationRegistry } from './migration-registry.js';
5
6
  export class MigrationManager extends EventEmitter {
6
7
  connection;
7
8
  loader;
8
9
  registry;
9
- constructor(connection, registry) {
10
+ lock;
11
+ constructor(connection, registry, loader = new MigrationLoader(), lock = new MigrationLock(connection)) {
10
12
  super();
11
13
  this.connection = connection;
12
14
  this.registry = registry;
13
- this.loader = new MigrationLoader();
15
+ this.loader = loader;
16
+ this.lock = lock;
14
17
  }
15
18
  static async create() {
16
19
  const connection = await new DBConnector().run();
17
- const registry = await MigrationRegistry.create(connection);
18
- return new MigrationManager(connection, registry);
20
+ try {
21
+ const registry = await MigrationRegistry.create(connection);
22
+ const lock = new MigrationLock(connection);
23
+ return new MigrationManager(connection, registry, new MigrationLoader(), lock);
24
+ }
25
+ catch (error) {
26
+ await connection.close();
27
+ throw error;
28
+ }
19
29
  }
20
30
  async run() {
21
- const migrations = await this.findMigrationsToRun();
22
- if (migrations.length === 0) {
23
- this.emit('up:nothing');
24
- }
25
- await this.runMigrations(migrations, await this.registry.next);
31
+ return this.withLock(async () => {
32
+ const migrations = await this.findMigrationsToRun();
33
+ if (migrations.length === 0)
34
+ this.emit('up:nothing');
35
+ return this.runMigrations(migrations, await this.registry.next);
36
+ });
26
37
  }
27
38
  async rollback() {
28
- const migrations = await this.findMigrationsToRollback(await this.registry.last);
29
- if (migrations.length === 0) {
30
- this.emit('down:nothing');
31
- }
32
- await this.rollbackMigrations(migrations);
39
+ return this.withLock(async () => {
40
+ const migrations = await this.findMigrationsToRollback(await this.registry.last);
41
+ if (migrations.length === 0)
42
+ this.emit('down:nothing');
43
+ return this.rollbackMigrations(migrations);
44
+ });
33
45
  }
34
46
  async refresh() {
35
- const migrationsToRollback = await this.findMigrationsToRollback();
36
- if (migrationsToRollback.length === 0) {
37
- this.emit('down:nothing');
38
- }
39
- const result = await this.rollbackMigrations(migrationsToRollback);
40
- if (!result) {
41
- return;
42
- }
43
- const migrationsToRun = await this.findMigrationsToRun();
44
- if (migrationsToRun.length === 0) {
45
- this.emit('up:nothing');
46
- }
47
- await this.runMigrations(migrationsToRun);
47
+ return this.withLock(async () => {
48
+ const migrationsToRollback = await this.findMigrationsToRollback();
49
+ if (migrationsToRollback.length === 0)
50
+ this.emit('down:nothing');
51
+ const result = await this.rollbackMigrations(migrationsToRollback);
52
+ if (!result)
53
+ return false;
54
+ const migrationsToRun = await this.findMigrationsToRun();
55
+ if (migrationsToRun.length === 0)
56
+ this.emit('up:nothing');
57
+ return this.runMigrations(migrationsToRun);
58
+ });
59
+ }
60
+ async status() {
61
+ const [history, imported] = await Promise.all([this.registry.history, this.loader.load()]);
62
+ const applied = new Map(history.map(record => [record.name, record.batch]));
63
+ const importedNames = imported.map(migration => migration.name);
64
+ return [
65
+ ...importedNames.map(name => applied.has(name)
66
+ ? { name, state: 'applied', batch: applied.get(name) }
67
+ : { name, state: 'pending' }),
68
+ ...history
69
+ .filter(record => !importedNames.includes(record.name))
70
+ .map(record => ({ name: record.name, state: 'missing', batch: record.batch })),
71
+ ];
48
72
  }
49
73
  async close() {
50
- this.connection.close();
74
+ await this.connection.close();
75
+ }
76
+ async withLock(work) {
77
+ await this.lock.initialize();
78
+ await this.lock.acquire();
79
+ try {
80
+ return await work();
81
+ }
82
+ finally {
83
+ await this.lock.release();
84
+ }
51
85
  }
52
86
  async runMigrations(migrations, batch = 1) {
53
87
  for (const migration of migrations) {
@@ -1 +1 @@
1
- {"version":3,"file":"migration-manager.js","sourceRoot":"","sources":["../src/migration-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"migration-manager.js","sourceRoot":"","sources":["../src/migration-manager.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,16 @@
1
- import type { IDatabase } from '@kurdel/db';
1
+ import type { Database } from '@kurdel/db';
2
+ export type MigrationRecord = {
3
+ id: number;
4
+ name: string;
5
+ batch: number;
6
+ };
2
7
  export declare class MigrationRegistry {
3
8
  private connection;
4
9
  private builder;
5
- constructor(connection: IDatabase);
6
- static create(connection: IDatabase): Promise<MigrationRegistry>;
10
+ constructor(connection: Database);
11
+ static create(connection: Database): Promise<MigrationRegistry>;
7
12
  get all(): Promise<string[]>;
13
+ get history(): Promise<MigrationRecord[]>;
8
14
  getBatch(batch: number): Promise<string[]>;
9
15
  get last(): Promise<number>;
10
16
  get next(): Promise<number>;
@@ -13,6 +19,5 @@ export declare class MigrationRegistry {
13
19
  private get;
14
20
  private getLastBatch;
15
21
  private getNextBatch;
16
- private existsMigrtionsTable;
17
22
  private createMigrationsTable;
18
23
  }
@@ -9,16 +9,17 @@ export class MigrationRegistry {
9
9
  }
10
10
  static async create(connection) {
11
11
  const registry = new MigrationRegistry(connection);
12
- const exists = await registry.existsMigrtionsTable();
13
- if (!exists) {
14
- await registry.createMigrationsTable();
15
- }
12
+ await registry.createMigrationsTable();
16
13
  return registry;
17
14
  }
18
15
  get all() {
19
16
  const query = this.builder.select('*').from('migrations').build();
20
17
  return this.get(query);
21
18
  }
19
+ get history() {
20
+ const query = this.builder.select('*').from('migrations').build();
21
+ return this.connection.all(query);
22
+ }
22
23
  getBatch(batch) {
23
24
  const query = this.builder.select('*').from('migrations').where('batch = ?', [batch]).build();
24
25
  return this.get(query);
@@ -52,22 +53,9 @@ export class MigrationRegistry {
52
53
  async getNextBatch() {
53
54
  return (await this.getLastBatch()) + 1;
54
55
  }
55
- async existsMigrtionsTable() {
56
- const selectCountQuery = this.builder
57
- .select('batch', { fn: 'COUNT' })
58
- .from('migrations')
59
- .build();
60
- try {
61
- await this.connection.get(selectCountQuery);
62
- return true;
63
- }
64
- catch {
65
- return false;
66
- }
67
- }
68
56
  async createMigrationsTable() {
69
57
  const schema = new Schema(this.connection);
70
- await schema.create('migrations', table => {
58
+ await schema.createIfNotExists('migrations', table => {
71
59
  table.integer('id');
72
60
  table.primaryKey('id');
73
61
  table.string('name');
@@ -1 +1 @@
1
- {"version":3,"file":"migration-registry.js","sourceRoot":"","sources":["../src/migration-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"migration-registry.js","sourceRoot":"","sources":["../src/migration-registry.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
- import type { IDatabase } from '@kurdel/db';
1
+ import type { Database } from '@kurdel/db';
2
2
  import { Schema } from './schema.js';
3
3
  export declare abstract class Migration {
4
4
  protected schema: Schema;
5
- constructor(connection: IDatabase);
5
+ constructor(connection: Database);
6
6
  abstract up(): Promise<any>;
7
7
  abstract down(): Promise<any>;
8
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"migration.js","sourceRoot":"","sources":["../src/migration.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,OAAgB,SAAS;IACnB,MAAM,CAAS;IAEzB,YAAY,UAAqB;QAC/B,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC;CAIF"}
1
+ {"version":3,"file":"migration.js","sourceRoot":"","sources":["../src/migration.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,OAAgB,SAAS;IACnB,MAAM,CAAS;IAEzB,YAAY,UAAoB;QAC9B,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC;CAIF"}
package/lib/schema.d.ts CHANGED
@@ -1,10 +1,12 @@
1
- import type { IDatabase } from '@kurdel/db';
1
+ import type { Database } from '@kurdel/db';
2
2
  import { Blueprint } from './blueprint.js';
3
3
  type Configure = (table: Blueprint) => void;
4
4
  export declare class Schema {
5
5
  private readonly connection;
6
- constructor(connection: IDatabase);
6
+ constructor(connection: Database);
7
7
  create(tableName: string, configure: Configure): Promise<void>;
8
+ createIfNotExists(tableName: string, configure: Configure): Promise<void>;
9
+ private createTable;
8
10
  drop(tableName: string): Promise<void>;
9
11
  dropIfExists(tableName: string): Promise<void>;
10
12
  private createIndex;
package/lib/schema.js CHANGED
@@ -5,17 +5,23 @@ export class Schema {
5
5
  this.connection = connection;
6
6
  }
7
7
  async create(tableName, configure) {
8
- const blueprint = new Blueprint();
8
+ await this.createTable(tableName, configure, false);
9
+ }
10
+ async createIfNotExists(tableName, configure) {
11
+ await this.createTable(tableName, configure, true);
12
+ }
13
+ async createTable(tableName, configure, ifNotExists) {
14
+ const blueprint = new Blueprint(this.connection.dialect);
9
15
  configure(blueprint);
10
16
  const definitions = blueprint.getColumnDefinitions();
11
17
  if (!definitions)
12
18
  throw new Error(`Table '${tableName}' must define at least one column`);
13
19
  await this.connection.run({
14
- sql: `CREATE TABLE ${tableName} (${definitions});`,
20
+ sql: `CREATE TABLE ${ifNotExists ? 'IF NOT EXISTS ' : ''}${tableName} (${definitions});`,
15
21
  params: [],
16
22
  });
17
23
  for (const index of blueprint.getIndexes()) {
18
- await this.createIndex(tableName, index);
24
+ await this.createIndex(tableName, index, ifNotExists);
19
25
  }
20
26
  }
21
27
  async drop(tableName) {
@@ -24,11 +30,14 @@ export class Schema {
24
30
  async dropIfExists(tableName) {
25
31
  await this.connection.run({ sql: `DROP TABLE IF EXISTS ${tableName};`, params: [] });
26
32
  }
27
- async createIndex(tableName, index) {
33
+ async createIndex(tableName, index, ifNotExists) {
28
34
  const name = index.name ?? `${tableName}_${index.columns.join('_')}_index`;
29
35
  const unique = index.unique ? 'UNIQUE ' : '';
30
36
  await this.connection.run({
31
- sql: `CREATE ${unique}INDEX ${name} ON ${tableName} (${index.columns.join(', ')});`,
37
+ sql: [
38
+ `CREATE ${unique}INDEX${ifNotExists ? ' IF NOT EXISTS' : ''} ${name}`,
39
+ `ON ${tableName} (${index.columns.join(', ')});`,
40
+ ].join(' '),
32
41
  params: [],
33
42
  });
34
43
  }
package/lib/schema.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAwB,MAAM,gBAAgB,CAAC;AAIjE,MAAM,OAAO,MAAM;IACY;IAA7B,YAA6B,UAAqB;QAArB,eAAU,GAAV,UAAU,CAAW;IAAG,CAAC;IAEtD,KAAK,CAAC,MAAM,CAAC,SAAiB,EAAE,SAAoB;QAClD,MAAM,SAAS,GAAG,IAAI,SAAS,EAAE,CAAC;QAClC,SAAS,CAAC,SAAS,CAAC,CAAC;QACrB,MAAM,WAAW,GAAG,SAAS,CAAC,oBAAoB,EAAE,CAAC;QACrD,IAAI,CAAC,WAAW;YAAE,MAAM,IAAI,KAAK,CAAC,UAAU,SAAS,mCAAmC,CAAC,CAAC;QAE1F,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YACxB,GAAG,EAAE,gBAAgB,SAAS,KAAK,WAAW,IAAI;YAClD,MAAM,EAAE,EAAE;SACX,CAAC,CAAC;QAEH,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC;YAC3C,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAiB;QAC1B,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,cAAc,SAAS,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,SAAiB;QAClC,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,wBAAwB,SAAS,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;IACvF,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,SAAiB,EAAE,KAAsB;QACjE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC3E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YACxB,GAAG,EAAE,UAAU,MAAM,SAAS,IAAI,OAAO,SAAS,KAAK,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YACnF,MAAM,EAAE,EAAE;SACX,CAAC,CAAC;IACL,CAAC;CACF"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAwB,MAAM,gBAAgB,CAAC;AAIjE,MAAM,OAAO,MAAM;IACY;IAA7B,YAA6B,UAAoB;QAApB,eAAU,GAAV,UAAU,CAAU;IAAG,CAAC;IAErD,KAAK,CAAC,MAAM,CAAC,SAAiB,EAAE,SAAoB;QAClD,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,SAAiB,EAAE,SAAoB;QAC7D,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IACrD,CAAC;IAEO,KAAK,CAAC,WAAW,CACvB,SAAiB,EACjB,SAAoB,EACpB,WAAoB;QAEpB,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACzD,SAAS,CAAC,SAAS,CAAC,CAAC;QACrB,MAAM,WAAW,GAAG,SAAS,CAAC,oBAAoB,EAAE,CAAC;QACrD,IAAI,CAAC,WAAW;YAAE,MAAM,IAAI,KAAK,CAAC,UAAU,SAAS,mCAAmC,CAAC,CAAC;QAE1F,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YACxB,GAAG,EAAE,gBAAgB,WAAW,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,KAAK,WAAW,IAAI;YACxF,MAAM,EAAE,EAAE;SACX,CAAC,CAAC;QAEH,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC;YAC3C,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAiB;QAC1B,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,cAAc,SAAS,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,SAAiB;QAClC,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,wBAAwB,SAAS,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;IACvF,CAAC;IAEO,KAAK,CAAC,WAAW,CACvB,SAAiB,EACjB,KAAsB,EACtB,WAAoB;QAEpB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC3E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YACxB,GAAG,EAAE;gBACH,UAAU,MAAM,QAAQ,WAAW,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE;gBACrE,MAAM,SAAS,KAAK,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;aACjD,CAAC,IAAI,CAAC,GAAG,CAAC;YACX,MAAM,EAAE,EAAE;SACX,CAAC,CAAC;IACL,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kurdel/migrations",
3
- "version": "0.1.0-beta.2",
3
+ "version": "0.1.0-beta.4",
4
4
  "description": "Database schema migration tools for Kurdel",
5
5
  "exports": {
6
6
  ".": "./lib/index.js"
@@ -47,6 +47,6 @@
47
47
  "@types/node": "^20.9.0"
48
48
  },
49
49
  "dependencies": {
50
- "@kurdel/db": "0.1.0-beta.2"
50
+ "@kurdel/db": "0.1.0-beta.4"
51
51
  }
52
52
  }