bunsql-native-migrate 0.2.0 → 0.3.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.
@@ -10,6 +10,7 @@ export interface SqlLock {
10
10
  export interface SqlDialect {
11
11
  install(db: SQL): Promise<void>;
12
12
  record(db: SQL, migration: string, checksum: string): Promise<void>;
13
+ trackingTableExists?(db: SQL): Promise<boolean>;
13
14
  createLock?(db: SQL): SqlLock;
14
15
  }
15
16
 
@@ -54,14 +55,18 @@ export function createReservedLock(
54
55
  };
55
56
  }
56
57
 
57
- export function createSqlDriver(databaseUrl: string, dialect: SqlDialect): MigrationDriver {
58
+ export function createSqlDriver(
59
+ databaseUrl: string,
60
+ dialect: SqlDialect,
61
+ table: string,
62
+ ): MigrationDriver {
58
63
  const db = new SQL(databaseUrl);
59
64
  const lock = dialect.createLock?.(db);
60
65
 
61
66
  return {
62
67
  install: () => dialect.install(db),
63
68
  async listExecuted() {
64
- const rows = await db`SELECT migration, checksum FROM migrations ORDER BY id ASC`;
69
+ const rows = await db`SELECT migration, checksum FROM ${db.unsafe(table)} ORDER BY id ASC`;
65
70
  return rows.map(
66
71
  (r: { migration: string; checksum: string | null }): ExecutedMigration => ({
67
72
  name: r.migration,
@@ -71,12 +76,15 @@ export function createSqlDriver(databaseUrl: string, dialect: SqlDialect): Migra
71
76
  },
72
77
  record: (migration, checksum) => dialect.record(db, migration, checksum),
73
78
  async setChecksum(migration, checksum) {
74
- await db`UPDATE migrations SET checksum = ${checksum} WHERE migration = ${migration}`;
79
+ await db`UPDATE ${db.unsafe(table)} SET checksum = ${checksum} WHERE migration = ${migration}`;
75
80
  },
76
81
  async remove(migration) {
77
- await db`DELETE FROM migrations WHERE migration = ${migration}`;
82
+ await db`DELETE FROM ${db.unsafe(table)} WHERE migration = ${migration}`;
78
83
  },
79
84
  transaction: (run) => db.begin(run),
85
+ ...(dialect.trackingTableExists
86
+ ? { trackingTableExists: () => dialect.trackingTableExists!(db) }
87
+ : {}),
80
88
  ...(lock
81
89
  ? {
82
90
  tryLock: (timeoutSeconds: number) => lock.tryLock(timeoutSeconds),
@@ -1,36 +1,63 @@
1
- import type { MigrationDriver } from "../core/driver.js";
1
+ import type { DriverTableOptions, MigrationDriver } from "../core/driver.js";
2
+ import { doubleQuoted, validateIdentifier } from "../core/identifiers.js";
2
3
  import { createSqlDriver } from "./shared.js";
3
4
 
4
- export function create(databaseUrl: string): MigrationDriver {
5
- return createSqlDriver(databaseUrl, {
6
- async install(db) {
7
- await db`CREATE TABLE IF NOT EXISTS migrations (
8
- id INTEGER PRIMARY KEY AUTOINCREMENT,
9
- migration TEXT NOT NULL,
10
- checksum TEXT
11
- )`;
12
- const columns = (await db`PRAGMA table_info(migrations)`) as Array<{
13
- name: string;
14
- }>;
15
- const hasChecksum = columns.some((column) => column.name === "checksum");
16
- if (!hasChecksum) {
17
- await db`ALTER TABLE migrations ADD COLUMN checksum TEXT`;
18
- }
19
- await db`CREATE UNIQUE INDEX IF NOT EXISTS migrations_migration_unique ON migrations (migration)`;
20
- },
21
- async record(db, migration, checksum) {
22
- await db`INSERT OR IGNORE INTO migrations (migration, checksum)
23
- VALUES (${migration}, ${checksum})`;
24
- },
25
- createLock: (db) => ({
26
- async tryLock(timeoutSeconds: number) {
27
- await db.unsafe(`PRAGMA busy_timeout = ${timeoutSeconds * 1000}`);
28
- return true;
5
+ const TABLE_NAME_MAX_LENGTH = 128;
6
+ const UNIQUE_INDEX_SUFFIX = "_migration_unique";
7
+
8
+ function resolveTableRef(options: DriverTableOptions): {
9
+ table: string;
10
+ index: string;
11
+ name: string;
12
+ } {
13
+ const tableName = options.tableName ?? "migrations";
14
+ validateIdentifier("table", tableName, TABLE_NAME_MAX_LENGTH);
15
+ return {
16
+ table: doubleQuoted(tableName),
17
+ index: doubleQuoted(`${tableName}${UNIQUE_INDEX_SUFFIX}`),
18
+ name: tableName,
19
+ };
20
+ }
21
+
22
+ export function create(databaseUrl: string, options: DriverTableOptions = {}): MigrationDriver {
23
+ const { table, index, name } = resolveTableRef(options);
24
+ return createSqlDriver(
25
+ databaseUrl,
26
+ {
27
+ async install(db) {
28
+ await db`CREATE TABLE IF NOT EXISTS ${db.unsafe(table)} (
29
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
30
+ migration TEXT NOT NULL,
31
+ checksum TEXT
32
+ )`;
33
+ const columns = (await db.unsafe(`PRAGMA table_info(${table})`)) as Array<{
34
+ name: string;
35
+ }>;
36
+ const hasChecksum = columns.some((column) => column.name === "checksum");
37
+ if (!hasChecksum) {
38
+ await db`ALTER TABLE ${db.unsafe(table)} ADD COLUMN checksum TEXT`;
39
+ }
40
+ await db`CREATE UNIQUE INDEX IF NOT EXISTS ${db.unsafe(index)} ON ${db.unsafe(table)} (migration)`;
41
+ },
42
+ async trackingTableExists(db) {
43
+ const rows = await db`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ${name}`;
44
+ return rows.length > 0;
29
45
  },
30
- async releaseLock() {
31
- await db.unsafe("PRAGMA busy_timeout = 0");
46
+ async record(db, migration, checksum) {
47
+ await db`INSERT OR IGNORE INTO ${db.unsafe(table)} (migration, checksum)
48
+ VALUES (${migration}, ${checksum})`;
32
49
  },
33
- dispose() {},
34
- }),
35
- });
50
+ createLock: (db) => ({
51
+ async tryLock(timeoutSeconds: number) {
52
+ await db.unsafe(`PRAGMA busy_timeout = ${timeoutSeconds * 1000}`);
53
+ return true;
54
+ },
55
+ async releaseLock() {
56
+ await db.unsafe("PRAGMA busy_timeout = 0");
57
+ },
58
+ dispose() {},
59
+ }),
60
+ },
61
+ table,
62
+ );
36
63
  }
package/src/index.ts CHANGED
@@ -1,12 +1,21 @@
1
- import { createDriver, type ExecutedMigration, type MigrationDriver } from "./core/driver.js";
1
+ import {
2
+ createDriver,
3
+ type DriverTableOptions,
4
+ type ExecutedMigration,
5
+ type MigrationDriver,
6
+ } from "./core/driver.js";
7
+ import { InvalidIdentifierError } from "./core/identifiers.js";
2
8
  import { migrateUp } from "./api/up.js";
3
9
  import { migrateDown } from "./api/down.js";
4
10
  import { migrateStatus } from "./api/status.js";
5
11
  import { installMigrations } from "./api/install.js";
6
12
  import { createMigration } from "./api/create.js";
13
+ import { markMigrationsApplied } from "./api/mark.js";
7
14
  import {
8
15
  type MigrateDownOptions,
9
16
  type MigrateDownResult,
17
+ type MarkOptions,
18
+ type MarkResult,
10
19
  type MigrateOptions,
11
20
  type MigrateStatusResult,
12
21
  type MigrateUpOptions,
@@ -24,12 +33,15 @@ export {
24
33
  migrateStatus,
25
34
  installMigrations,
26
35
  createMigration,
36
+ markMigrationsApplied,
27
37
  ChecksumDriftError,
28
38
  GitStageError,
39
+ InvalidIdentifierError,
29
40
  MigrationLockError,
30
41
  MigrationNotFoundError,
31
42
  };
32
43
  export type {
44
+ DriverTableOptions,
33
45
  ExecutedMigration,
34
46
  MigrationDriver,
35
47
  MigrateOptions,
@@ -37,5 +49,7 @@ export type {
37
49
  MigrateUpResult,
38
50
  MigrateDownOptions,
39
51
  MigrateDownResult,
52
+ MarkOptions,
53
+ MarkResult,
40
54
  MigrateStatusResult,
41
55
  };