bunsql-native-migrate 0.1.2 → 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.
@@ -12,10 +12,21 @@ export interface MigrationDriver {
12
12
  setChecksum(migration: string, checksum: string): Promise<void>;
13
13
  remove(migration: string): Promise<void>;
14
14
  transaction<T>(run: (tx: SQL) => Promise<T>): Promise<T>;
15
+ trackingTableExists?(): Promise<boolean>;
16
+ tryLock?(timeoutSeconds: number): Promise<boolean>;
17
+ releaseLock?(): Promise<void>;
15
18
  close(): Promise<void>;
16
19
  }
17
20
 
18
- export async function createDriver(databaseUrl: string): Promise<MigrationDriver> {
21
+ export interface DriverTableOptions {
22
+ tableName?: string;
23
+ schema?: string;
24
+ }
25
+
26
+ export async function createDriver(
27
+ databaseUrl: string,
28
+ options: DriverTableOptions = {},
29
+ ): Promise<MigrationDriver> {
19
30
  let protocol: string;
20
31
  try {
21
32
  protocol = new URL(databaseUrl).protocol.replace(":", "");
@@ -26,20 +37,25 @@ export async function createDriver(databaseUrl: string): Promise<MigrationDriver
26
37
  throw new Error(`Cannot parse database URL: ${databaseUrl}`);
27
38
  }
28
39
  }
40
+ if (options.schema !== undefined && protocol !== "postgres" && protocol !== "postgresql") {
41
+ throw new Error(
42
+ "The schema option is only supported for postgres URLs — MySQL/MariaDB selects the database in the URL, SQLite has no schemas",
43
+ );
44
+ }
29
45
  switch (protocol) {
30
46
  case "postgres":
31
47
  case "postgresql": {
32
48
  const mod = await import("./../drivers/postgres.js");
33
- return mod.create(databaseUrl);
49
+ return mod.create(databaseUrl, options);
34
50
  }
35
51
  case "sqlite": {
36
52
  const mod = await import("./../drivers/sqlite.js");
37
- return mod.create(databaseUrl);
53
+ return mod.create(databaseUrl, options);
38
54
  }
39
55
  case "mariadb":
40
56
  case "mysql": {
41
57
  const mod = await import("./../drivers/mariadb.js");
42
- return mod.create(databaseUrl);
58
+ return mod.create(databaseUrl, options);
43
59
  }
44
60
  default:
45
61
  throw new Error(
@@ -0,0 +1,7 @@
1
+ export function formatDuration(durationMs: number): string {
2
+ const roundedMs = Math.round(durationMs);
3
+ if (roundedMs < 1000) {
4
+ return `${roundedMs}ms`;
5
+ }
6
+ return `${(durationMs / 1000).toFixed(1)}s`;
7
+ }
package/src/core/fs.ts CHANGED
@@ -3,11 +3,13 @@ import path from "node:path";
3
3
 
4
4
  export const DEFAULT_MIGRATIONS_DIR = "migrations";
5
5
 
6
- export async function listFiles(dir: string, ext: string): Promise<string[]> {
6
+ export const MIGRATION_EXTENSIONS = ["js", "ts", "up.sql"] as const;
7
+
8
+ export async function listFiles(dir: string, extensions: readonly string[]): Promise<string[]> {
7
9
  const matchedFiles: string[] = [];
8
10
  const entries = await readdir(dir, { withFileTypes: true });
9
11
  for (const entry of entries) {
10
- if (entry.isFile() && entry.name.endsWith(`.${ext}`)) {
12
+ if (entry.isFile() && extensions.some((ext) => entry.name.endsWith(`.${ext}`))) {
11
13
  matchedFiles.push(entry.name);
12
14
  }
13
15
  }
@@ -0,0 +1,32 @@
1
+ export type IdentifierKind = "table" | "schema";
2
+
3
+ const IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_$]*$/;
4
+
5
+ export class InvalidIdentifierError extends Error {
6
+ readonly kind: IdentifierKind;
7
+ readonly value: string;
8
+
9
+ constructor(kind: IdentifierKind, value: string, maxLength: number) {
10
+ super(
11
+ `Invalid ${kind} name: "${value}" — expected an identifier of letters, digits, underscores and dollar signs ` +
12
+ `starting with a letter or underscore, at most ${maxLength} characters`,
13
+ );
14
+ this.name = "InvalidIdentifierError";
15
+ this.kind = kind;
16
+ this.value = value;
17
+ }
18
+ }
19
+
20
+ export function validateIdentifier(kind: IdentifierKind, value: string, maxLength: number): void {
21
+ if (!IDENTIFIER_PATTERN.test(value) || value.length > maxLength) {
22
+ throw new InvalidIdentifierError(kind, value, maxLength);
23
+ }
24
+ }
25
+
26
+ export function doubleQuoted(name: string): string {
27
+ return `"${name}"`;
28
+ }
29
+
30
+ export function backtickQuoted(name: string): string {
31
+ return `\`${name}\``;
32
+ }
@@ -1,42 +1,88 @@
1
1
  import { type SQL } from "bun";
2
- import type { MigrationDriver } from "../core/driver.js";
3
- import { createSqlDriver } from "./shared.js";
2
+ import type { DriverTableOptions, MigrationDriver } from "../core/driver.js";
3
+ import { backtickQuoted, validateIdentifier } from "../core/identifiers.js";
4
+ import { createReservedLock, createSqlDriver } from "./shared.js";
4
5
 
5
- async function checksumColumnExists(db: SQL): Promise<boolean> {
6
+ const LOCK_NAME_PREFIX = "bunsql-native-migrate:";
7
+
8
+ const TABLE_NAME_MAX_LENGTH = 47;
9
+ const UNIQUE_INDEX_SUFFIX = "_migration_unique";
10
+
11
+ function resolveTableRef(options: DriverTableOptions): {
12
+ table: string;
13
+ index: string;
14
+ name: string;
15
+ } {
16
+ const tableName = options.tableName ?? "migrations";
17
+ validateIdentifier("table", tableName, TABLE_NAME_MAX_LENGTH);
18
+ return {
19
+ table: backtickQuoted(tableName),
20
+ index: backtickQuoted(`${tableName}${UNIQUE_INDEX_SUFFIX}`),
21
+ name: tableName,
22
+ };
23
+ }
24
+
25
+ async function checksumColumnExists(db: SQL, tableName: string): Promise<boolean> {
6
26
  const rows = await db`SELECT column_name FROM information_schema.columns
7
27
  WHERE table_schema = DATABASE()
8
- AND table_name = 'migrations'
28
+ AND table_name = ${tableName}
9
29
  AND column_name = 'checksum'`;
10
30
  return rows.length > 0;
11
31
  }
12
32
 
13
- async function uniqueIndexExists(db: SQL): Promise<boolean> {
33
+ async function uniqueIndexExists(db: SQL, tableName: string): Promise<boolean> {
14
34
  const rows = await db`SELECT index_name FROM information_schema.statistics
15
35
  WHERE table_schema = DATABASE()
16
- AND table_name = 'migrations'
17
- AND index_name = 'migrations_migration_unique'`;
36
+ AND table_name = ${tableName}
37
+ AND index_name = ${`${tableName}${UNIQUE_INDEX_SUFFIX}`}`;
18
38
  return rows.length > 0;
19
39
  }
20
40
 
21
- export function create(databaseUrl: string): MigrationDriver {
22
- return createSqlDriver(databaseUrl, {
23
- async install(db) {
24
- await db`CREATE TABLE IF NOT EXISTS migrations (
25
- id INTEGER PRIMARY KEY AUTO_INCREMENT,
26
- migration VARCHAR(255) NOT NULL,
27
- checksum VARCHAR(64),
28
- CONSTRAINT migrations_migration_unique UNIQUE (migration)
29
- )`;
30
- if (!(await checksumColumnExists(db))) {
31
- await db`ALTER TABLE migrations ADD COLUMN checksum VARCHAR(64)`;
32
- }
33
- if (!(await uniqueIndexExists(db))) {
34
- await db`CREATE UNIQUE INDEX migrations_migration_unique ON migrations (migration)`;
35
- }
36
- },
37
- async record(db, migration, checksum) {
38
- await db`INSERT IGNORE INTO migrations (migration, checksum)
39
- VALUES (${migration}, ${checksum})`;
41
+ export function create(databaseUrl: string, options: DriverTableOptions = {}): MigrationDriver {
42
+ const { table, index, name } = resolveTableRef(options);
43
+ return createSqlDriver(
44
+ databaseUrl,
45
+ {
46
+ async install(db) {
47
+ await db`CREATE TABLE IF NOT EXISTS ${db.unsafe(table)} (
48
+ id INTEGER PRIMARY KEY AUTO_INCREMENT,
49
+ migration VARCHAR(255) NOT NULL,
50
+ checksum VARCHAR(64),
51
+ CONSTRAINT ${db.unsafe(index)} UNIQUE (migration)
52
+ )`;
53
+ if (!(await checksumColumnExists(db, name))) {
54
+ await db`ALTER TABLE ${db.unsafe(table)} ADD COLUMN checksum VARCHAR(64)`;
55
+ }
56
+ if (!(await uniqueIndexExists(db, name))) {
57
+ await db`CREATE UNIQUE INDEX ${db.unsafe(index)} ON ${db.unsafe(table)} (migration)`;
58
+ }
59
+ },
60
+ async trackingTableExists(db) {
61
+ const rows = await db`SELECT 1 FROM information_schema.tables
62
+ WHERE table_schema = DATABASE()
63
+ AND table_name = ${name}`;
64
+ return rows.length > 0;
65
+ },
66
+ async record(db, migration, checksum) {
67
+ await db`INSERT IGNORE INTO ${db.unsafe(table)} (migration, checksum)
68
+ VALUES (${migration}, ${checksum})`;
69
+ },
70
+ createLock: (db) =>
71
+ createReservedLock(
72
+ db,
73
+ async (lock) => {
74
+ const rows =
75
+ (await lock`SELECT GET_LOCK(CONCAT(${LOCK_NAME_PREFIX}, MD5(DATABASE())), 0) AS locked`) as Array<{
76
+ locked: number | string | null;
77
+ }>;
78
+ const locked = rows[0]?.locked;
79
+ return locked === 1 || locked === "1";
80
+ },
81
+ async (lock) => {
82
+ await lock`SELECT RELEASE_LOCK(CONCAT(${LOCK_NAME_PREFIX}, MD5(DATABASE())))`;
83
+ },
84
+ ),
40
85
  },
41
- });
86
+ table,
87
+ );
42
88
  }
@@ -1,21 +1,86 @@
1
- import type { MigrationDriver } from "../core/driver.js";
2
- import { createSqlDriver } from "./shared.js";
1
+ import { type SQL } from "bun";
2
+ import type { DriverTableOptions, MigrationDriver } from "../core/driver.js";
3
+ import { doubleQuoted, validateIdentifier } from "../core/identifiers.js";
4
+ import { createReservedLock, createSqlDriver } from "./shared.js";
3
5
 
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 SERIAL PRIMARY KEY,
9
- migration VARCHAR(255) NOT NULL,
10
- checksum VARCHAR(64)
11
- )`;
12
- await db`ALTER TABLE migrations ADD COLUMN IF NOT EXISTS checksum VARCHAR(64)`;
13
- await db`CREATE UNIQUE INDEX IF NOT EXISTS migrations_migration_unique ON migrations (migration)`;
14
- },
15
- async record(db, migration, checksum) {
16
- await db`INSERT INTO migrations (migration, checksum)
17
- VALUES (${migration}, ${checksum})
18
- ON CONFLICT (migration) DO NOTHING`;
6
+ const LOCK_SCOPE = "bunsql-native-migrate:up";
7
+
8
+ const IDENTIFIER_MAX_LENGTH = 63;
9
+ const UNIQUE_INDEX_SUFFIX = "_migration_unique";
10
+
11
+ interface TableRef {
12
+ table: string;
13
+ index: string;
14
+ name: string;
15
+ schemaName?: string;
16
+ }
17
+
18
+ function resolveTableRef(options: DriverTableOptions): TableRef {
19
+ const tableName = options.tableName ?? "migrations";
20
+ validateIdentifier("table", tableName, IDENTIFIER_MAX_LENGTH);
21
+ const index = doubleQuoted(`${tableName}${UNIQUE_INDEX_SUFFIX}`);
22
+ if (options.schema === undefined) {
23
+ return { table: doubleQuoted(tableName), index, name: tableName };
24
+ }
25
+ validateIdentifier("schema", options.schema, IDENTIFIER_MAX_LENGTH);
26
+ return {
27
+ table: `${doubleQuoted(options.schema)}.${doubleQuoted(tableName)}`,
28
+ index,
29
+ name: tableName,
30
+ schemaName: options.schema,
31
+ };
32
+ }
33
+
34
+ async function advisoryKeyComponents(lock: SQL): Promise<[number, number]> {
35
+ const rows = (await lock`SELECT current_database() AS name`) as Array<{ name: string }>;
36
+ const hash = Bun.hash.wyhash(`${LOCK_SCOPE}:${rows[0]?.name ?? ""}`);
37
+ return [Number((hash >> 32n) & 0x7fffffffn), Number(hash & 0x7fffffffn)];
38
+ }
39
+
40
+ export function create(databaseUrl: string, options: DriverTableOptions = {}): MigrationDriver {
41
+ const { table, index, name, schemaName } = resolveTableRef(options);
42
+ return createSqlDriver(
43
+ databaseUrl,
44
+ {
45
+ async install(db) {
46
+ await db`CREATE TABLE IF NOT EXISTS ${db.unsafe(table)} (
47
+ id SERIAL PRIMARY KEY,
48
+ migration VARCHAR(255) NOT NULL,
49
+ checksum VARCHAR(64)
50
+ )`;
51
+ await db`ALTER TABLE ${db.unsafe(table)} ADD COLUMN IF NOT EXISTS checksum VARCHAR(64)`;
52
+ await db`CREATE UNIQUE INDEX IF NOT EXISTS ${db.unsafe(index)} ON ${db.unsafe(table)} (migration)`;
53
+ },
54
+ async trackingTableExists(db) {
55
+ const rows = schemaName
56
+ ? await db`SELECT 1 FROM information_schema.tables
57
+ WHERE table_schema = ${schemaName} AND table_name = ${name}`
58
+ : await db`SELECT 1 FROM information_schema.tables
59
+ WHERE table_schema = current_schema() AND table_name = ${name}`;
60
+ return rows.length > 0;
61
+ },
62
+ async record(db, migration, checksum) {
63
+ await db`INSERT INTO ${db.unsafe(table)} (migration, checksum)
64
+ VALUES (${migration}, ${checksum})
65
+ ON CONFLICT (migration) DO NOTHING`;
66
+ },
67
+ createLock: (db) =>
68
+ createReservedLock(
69
+ db,
70
+ async (lock) => {
71
+ const [first, second] = await advisoryKeyComponents(lock);
72
+ const rows =
73
+ (await lock`SELECT pg_try_advisory_lock(${first}, ${second}) AS locked`) as Array<{
74
+ locked: boolean;
75
+ }>;
76
+ return rows[0]?.locked === true;
77
+ },
78
+ async (lock) => {
79
+ const [first, second] = await advisoryKeyComponents(lock);
80
+ await lock`SELECT pg_advisory_unlock(${first}, ${second})`;
81
+ },
82
+ ),
19
83
  },
20
- });
84
+ table,
85
+ );
21
86
  }
@@ -1,18 +1,72 @@
1
- import { SQL } from "bun";
1
+ import { SQL, type ReservedSQL } from "bun";
2
2
  import type { ExecutedMigration, MigrationDriver } from "../core/driver.js";
3
3
 
4
+ export interface SqlLock {
5
+ tryLock(timeoutSeconds: number): Promise<boolean>;
6
+ releaseLock(): Promise<void>;
7
+ dispose(): void;
8
+ }
9
+
4
10
  export interface SqlDialect {
5
11
  install(db: SQL): Promise<void>;
6
12
  record(db: SQL, migration: string, checksum: string): Promise<void>;
13
+ trackingTableExists?(db: SQL): Promise<boolean>;
14
+ createLock?(db: SQL): SqlLock;
15
+ }
16
+
17
+ export function createReservedLock(
18
+ db: SQL,
19
+ acquire: (lock: SQL) => Promise<boolean>,
20
+ release: (lock: SQL) => Promise<void>,
21
+ ): SqlLock {
22
+ let lockConnection: ReservedSQL | null = null;
23
+
24
+ return {
25
+ async tryLock() {
26
+ const connection = await db.reserve();
27
+ lockConnection = connection;
28
+ try {
29
+ const acquired = await acquire(connection);
30
+ if (!acquired) {
31
+ connection.release();
32
+ lockConnection = null;
33
+ }
34
+ return acquired;
35
+ } catch (error) {
36
+ connection.release();
37
+ lockConnection = null;
38
+ throw error;
39
+ }
40
+ },
41
+ async releaseLock() {
42
+ const connection = lockConnection;
43
+ if (!connection) return;
44
+ lockConnection = null;
45
+ try {
46
+ await release(connection);
47
+ } finally {
48
+ connection.release();
49
+ }
50
+ },
51
+ dispose() {
52
+ lockConnection?.release();
53
+ lockConnection = null;
54
+ },
55
+ };
7
56
  }
8
57
 
9
- export function createSqlDriver(databaseUrl: string, dialect: SqlDialect): MigrationDriver {
58
+ export function createSqlDriver(
59
+ databaseUrl: string,
60
+ dialect: SqlDialect,
61
+ table: string,
62
+ ): MigrationDriver {
10
63
  const db = new SQL(databaseUrl);
64
+ const lock = dialect.createLock?.(db);
11
65
 
12
66
  return {
13
67
  install: () => dialect.install(db),
14
68
  async listExecuted() {
15
- 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`;
16
70
  return rows.map(
17
71
  (r: { migration: string; checksum: string | null }): ExecutedMigration => ({
18
72
  name: r.migration,
@@ -22,13 +76,23 @@ export function createSqlDriver(databaseUrl: string, dialect: SqlDialect): Migra
22
76
  },
23
77
  record: (migration, checksum) => dialect.record(db, migration, checksum),
24
78
  async setChecksum(migration, checksum) {
25
- await db`UPDATE migrations SET checksum = ${checksum} WHERE migration = ${migration}`;
79
+ await db`UPDATE ${db.unsafe(table)} SET checksum = ${checksum} WHERE migration = ${migration}`;
26
80
  },
27
81
  async remove(migration) {
28
- await db`DELETE FROM migrations WHERE migration = ${migration}`;
82
+ await db`DELETE FROM ${db.unsafe(table)} WHERE migration = ${migration}`;
29
83
  },
30
84
  transaction: (run) => db.begin(run),
85
+ ...(dialect.trackingTableExists
86
+ ? { trackingTableExists: () => dialect.trackingTableExists!(db) }
87
+ : {}),
88
+ ...(lock
89
+ ? {
90
+ tryLock: (timeoutSeconds: number) => lock.tryLock(timeoutSeconds),
91
+ releaseLock: () => lock.releaseLock(),
92
+ }
93
+ : {}),
31
94
  async close() {
95
+ lock?.dispose();
32
96
  db.close({ timeout: 0 });
33
97
  },
34
98
  };
@@ -1,26 +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})`;
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;
45
+ },
46
+ async record(db, migration, checksum) {
47
+ await db`INSERT OR IGNORE INTO ${db.unsafe(table)} (migration, checksum)
48
+ VALUES (${migration}, ${checksum})`;
49
+ },
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
+ }),
24
60
  },
25
- });
61
+ table,
62
+ );
26
63
  }
package/src/index.ts CHANGED
@@ -1,29 +1,55 @@
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";
10
+ import { migrateStatus } from "./api/status.js";
4
11
  import { installMigrations } from "./api/install.js";
5
12
  import { createMigration } from "./api/create.js";
13
+ import { markMigrationsApplied } from "./api/mark.js";
6
14
  import {
15
+ type MigrateDownOptions,
7
16
  type MigrateDownResult,
17
+ type MarkOptions,
18
+ type MarkResult,
8
19
  type MigrateOptions,
20
+ type MigrateStatusResult,
21
+ type MigrateUpOptions,
9
22
  type MigrateUpResult,
10
23
  ChecksumDriftError,
11
24
  GitStageError,
25
+ MigrationLockError,
26
+ MigrationNotFoundError,
12
27
  } from "./api/options.js";
13
28
 
14
29
  export {
15
30
  createDriver,
16
31
  migrateUp,
17
32
  migrateDown,
33
+ migrateStatus,
18
34
  installMigrations,
19
35
  createMigration,
36
+ markMigrationsApplied,
20
37
  ChecksumDriftError,
21
38
  GitStageError,
39
+ InvalidIdentifierError,
40
+ MigrationLockError,
41
+ MigrationNotFoundError,
22
42
  };
23
43
  export type {
44
+ DriverTableOptions,
24
45
  ExecutedMigration,
25
46
  MigrationDriver,
26
47
  MigrateOptions,
48
+ MigrateUpOptions,
27
49
  MigrateUpResult,
50
+ MigrateDownOptions,
28
51
  MigrateDownResult,
52
+ MarkOptions,
53
+ MarkResult,
54
+ MigrateStatusResult,
29
55
  };