@deterministic-code/migraters 0.0.0-stage → 0.0.1
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/bundle.yaml +262 -0
- package/dist/abstractions/migrater.d.ts +28 -0
- package/dist/abstractions/migrater.js +1 -0
- package/dist/abstractions/sql-dialect-base.d.ts +16 -0
- package/dist/abstractions/sql-dialect-base.js +19 -0
- package/dist/abstractions/sql-dialect-factory.d.ts +8 -0
- package/dist/abstractions/sql-dialect-factory.js +22 -0
- package/dist/abstractions/sql-dialect.d.ts +16 -0
- package/dist/abstractions/sql-dialect.js +1 -0
- package/dist/bin/migrate-create.d.ts +2 -0
- package/dist/bin/migrate-create.js +71 -0
- package/dist/bin/migrate-down.d.ts +2 -0
- package/dist/bin/migrate-down.js +135 -0
- package/dist/bin/migrate-init.d.ts +2 -0
- package/dist/bin/migrate-init.js +77 -0
- package/dist/bin/migrate-setup.d.ts +2 -0
- package/dist/bin/migrate-setup.js +87 -0
- package/dist/bin/migrate-up.d.ts +2 -0
- package/dist/bin/migrate-up.js +97 -0
- package/dist/cli-contract.d.ts +6 -0
- package/dist/cli-contract.js +19 -0
- package/dist/cli-spec.d.ts +24 -0
- package/dist/cli-spec.js +33 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.js +41 -0
- package/dist/create-sequence.d.ts +4 -0
- package/dist/create-sequence.js +16 -0
- package/dist/datasource-migrate.d.ts +31 -0
- package/dist/datasource-migrate.js +206 -0
- package/dist/dialects/mysql-dialect.d.ts +12 -0
- package/dist/dialects/mysql-dialect.js +56 -0
- package/dist/dialects/oracle-dialect.d.ts +18 -0
- package/dist/dialects/oracle-dialect.js +76 -0
- package/dist/dialects/postgres-dialect.d.ts +11 -0
- package/dist/dialects/postgres-dialect.js +58 -0
- package/dist/dialects/sqlite-dialect.d.ts +13 -0
- package/dist/dialects/sqlite-dialect.js +96 -0
- package/dist/dialects/sqlserver-dialect.d.ts +12 -0
- package/dist/dialects/sqlserver-dialect.js +73 -0
- package/dist/help.d.ts +2 -0
- package/dist/help.js +10 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6 -0
- package/dist/infrastructure/connection-resolver.d.ts +7 -0
- package/dist/infrastructure/connection-resolver.js +19 -0
- package/dist/infrastructure/default-factory.d.ts +4 -0
- package/dist/infrastructure/default-factory.js +15 -0
- package/dist/infrastructure/interop-default.d.ts +3 -0
- package/dist/infrastructure/interop-default.js +1 -0
- package/dist/infrastructure/message-templates.d.ts +3 -0
- package/dist/infrastructure/message-templates.js +18 -0
- package/dist/infrastructure/split-on-go.d.ts +2 -0
- package/dist/infrastructure/split-on-go.js +20 -0
- package/dist/infrastructure/sql-templates.d.ts +2 -0
- package/dist/infrastructure/sql-templates.js +4 -0
- package/dist/infrastructure/templates-root.d.ts +2 -0
- package/dist/infrastructure/templates-root.js +11 -0
- package/dist/init-select.d.ts +12 -0
- package/dist/init-select.js +52 -0
- package/dist/migrater.d.ts +12 -0
- package/dist/migrater.js +84 -0
- package/dist/migration-client.d.ts +21 -0
- package/dist/migration-client.js +1 -0
- package/dist/path-exists.d.ts +1 -0
- package/dist/path-exists.js +10 -0
- package/dist/sql.d.ts +3 -0
- package/dist/sql.js +15 -0
- package/dist/templates/help/create.txt +16 -0
- package/dist/templates/help/down.txt +42 -0
- package/dist/templates/help/init.txt +13 -0
- package/dist/templates/help/setup.txt +41 -0
- package/dist/templates/help/up.txt +43 -0
- package/dist/templates/messages/checksum-drift-line.txt +1 -0
- package/dist/templates/messages/checksum-drift.txt +11 -0
- package/dist/templates/messages/down/confirm-mismatch.txt +1 -0
- package/dist/templates/messages/down/confirm-prompt.txt +1 -0
- package/dist/templates/messages/down/confirm-stdin-failed.txt +1 -0
- package/dist/templates/messages/down/confirm-token-mismatch.txt +1 -0
- package/dist/templates/messages/down/confirm-tty-required.txt +1 -0
- package/dist/templates/messages/down/destructive-header.txt +3 -0
- package/dist/templates/messages/errors/invalid-name.txt +1 -0
- package/dist/templates/messages/errors/migrate-path-not-dir.txt +1 -0
- package/dist/templates/messages/errors/missing-connection.txt +1 -0
- package/dist/templates/messages/errors/missing-name-hint.txt +1 -0
- package/dist/templates/messages/errors/missing-name.txt +1 -0
- package/dist/templates/messages/errors/missing-provider-hint.txt +1 -0
- package/dist/templates/messages/errors/missing-provider.txt +1 -0
- package/dist/templates/messages/errors/missing-value-for-flag.txt +1 -0
- package/dist/templates/messages/errors/rollback-no-down-sibling.txt +1 -0
- package/dist/templates/messages/errors/rollback-no-rollback-sibling.txt +1 -0
- package/dist/templates/messages/errors/rollback-not-in-path.txt +1 -0
- package/dist/templates/messages/errors/sqlite-prerequisite.txt +1 -0
- package/dist/templates/messages/errors/unknown-arg.txt +1 -0
- package/dist/templates/messages/errors/unsupported-provider.txt +1 -0
- package/dist/templates/messages/setup-complete.txt +9 -0
- package/dist/templates/messages/status/applied.txt +1 -0
- package/dist/templates/messages/status/created.txt +1 -0
- package/dist/templates/messages/status/no-more-pending.txt +1 -0
- package/dist/templates/messages/status/no-pending.txt +1 -0
- package/dist/templates/messages/status/no-rollback.txt +1 -0
- package/dist/templates/messages/status/rolled-back.txt +1 -0
- package/dist/templates/scaffold/down.sql +1 -0
- package/dist/templates/scaffold/up.sql +1 -0
- package/dist/templates/sql/mysql/migrate_logs.sql +11 -0
- package/dist/templates/sql/mysql/migrates.sql +7 -0
- package/dist/templates/sql/oracle/migrate_logs.sql +14 -0
- package/dist/templates/sql/oracle/migrates.sql +10 -0
- package/dist/templates/sql/postgres/migrate_logs.sql +11 -0
- package/dist/templates/sql/postgres/migrates.sql +7 -0
- package/dist/templates/sql/sqlite/migrate_logs.sql +11 -0
- package/dist/templates/sql/sqlite/migrates.sql +7 -0
- package/dist/templates/sql/sqlserver/migrate_logs.sql +12 -0
- package/dist/templates/sql/sqlserver/migrates.sql +8 -0
- package/package.json +78 -4
- package/src/abstractions/migrater.ts +13 -0
- package/src/abstractions/sql-dialect-base.ts +36 -0
- package/src/abstractions/sql-dialect-factory.ts +29 -0
- package/src/abstractions/sql-dialect.ts +17 -0
- package/src/bin/migrate-create.ts +80 -0
- package/src/bin/migrate-down.ts +163 -0
- package/src/bin/migrate-init.ts +88 -0
- package/src/bin/migrate-setup.ts +98 -0
- package/src/bin/migrate-up.ts +111 -0
- package/src/cli-contract.ts +25 -0
- package/src/cli-spec.ts +64 -0
- package/src/cli.ts +52 -0
- package/src/create-sequence.ts +17 -0
- package/src/datasource-migrate.ts +314 -0
- package/src/dialects/mysql-dialect.test.ts +93 -0
- package/src/dialects/mysql-dialect.ts +67 -0
- package/src/dialects/oracle-dialect.test.ts +118 -0
- package/src/dialects/oracle-dialect.ts +91 -0
- package/src/dialects/postgres-dialect.test.ts +80 -0
- package/src/dialects/postgres-dialect.ts +65 -0
- package/src/dialects/sqlite-dialect.rollback.test.ts +30 -0
- package/src/dialects/sqlite-dialect.test.ts +77 -0
- package/src/dialects/sqlite-dialect.ts +96 -0
- package/src/dialects/sqlserver-dialect.test.ts +99 -0
- package/src/dialects/sqlserver-dialect.ts +87 -0
- package/src/generate-help.test.ts +33 -0
- package/src/generate-help.ts +173 -0
- package/src/help.test.ts +48 -0
- package/src/help.ts +12 -0
- package/src/index.ts +23 -0
- package/src/infrastructure/connection-resolver.ts +18 -0
- package/src/infrastructure/default-factory.test.ts +18 -0
- package/src/infrastructure/default-factory.ts +17 -0
- package/src/infrastructure/interop-default.test.ts +9 -0
- package/src/infrastructure/interop-default.ts +2 -0
- package/src/infrastructure/message-templates.ts +30 -0
- package/src/infrastructure/split-on-go.ts +19 -0
- package/src/infrastructure/sql-templates.ts +10 -0
- package/src/infrastructure/templates-root.ts +13 -0
- package/src/init-select.test.ts +26 -0
- package/src/init-select.ts +73 -0
- package/src/migrater.ts +92 -0
- package/src/migration-client.ts +21 -0
- package/src/path-exists.ts +10 -0
- package/src/setup-sql.test.ts +16 -0
- package/src/sql.ts +17 -0
- package/tsconfig.build.json +19 -0
- package/README.md +0 -3
package/dist/migrater.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { mkdir, readdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { isMigrationName, nextSequence, pad4 } from "./create-sequence.js";
|
|
3
|
+
import { applyOneDown, applyOneUp, discoverMigrations } from "./datasource-migrate.js";
|
|
4
|
+
import { defaultDialectFactory } from "./infrastructure/default-factory.js";
|
|
5
|
+
import { fillTemplate, loadMessage, loadScaffold } from "./infrastructure/message-templates.js";
|
|
6
|
+
const invalidNameTpl = await loadMessage('errors/invalid-name');
|
|
7
|
+
export class Migrater {
|
|
8
|
+
dialect;
|
|
9
|
+
constructor(dialect) {
|
|
10
|
+
this.dialect = dialect;
|
|
11
|
+
}
|
|
12
|
+
get name() {
|
|
13
|
+
return this.dialect.name;
|
|
14
|
+
}
|
|
15
|
+
async setup({ connection, migrationsPath }) {
|
|
16
|
+
await this.dialect.prepareSetup(connection);
|
|
17
|
+
const client = await this.dialect.createClient(connection);
|
|
18
|
+
try {
|
|
19
|
+
await client.exec(this.dialect.migratesDdl);
|
|
20
|
+
await client.exec(this.dialect.migrateLogsDdl);
|
|
21
|
+
await mkdir(migrationsPath, { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
await client.close();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async up({ connection, migrationsPath, one = false }) {
|
|
28
|
+
const client = await this.dialect.createClient(connection);
|
|
29
|
+
try {
|
|
30
|
+
const migrations = await discoverMigrations({
|
|
31
|
+
migratePath: migrationsPath,
|
|
32
|
+
dialect: this.dialect.name,
|
|
33
|
+
});
|
|
34
|
+
const applied = [];
|
|
35
|
+
for (;;) {
|
|
36
|
+
const result = await applyOneUp({ client, migrations });
|
|
37
|
+
if (!result.applied || result.name == null)
|
|
38
|
+
break;
|
|
39
|
+
applied.push(result.name);
|
|
40
|
+
if (one)
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
return applied;
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
await client.close();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async down({ connection, migrationsPath }) {
|
|
50
|
+
const client = await this.dialect.createClient(connection);
|
|
51
|
+
try {
|
|
52
|
+
const migrations = await discoverMigrations({
|
|
53
|
+
migratePath: migrationsPath,
|
|
54
|
+
dialect: this.dialect.name,
|
|
55
|
+
});
|
|
56
|
+
const result = await applyOneDown({ client, migrations });
|
|
57
|
+
return result.rolledBack ? result.name : null;
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
await client.close();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async create({ name, migrationsPath }) {
|
|
64
|
+
if (!isMigrationName(name)) {
|
|
65
|
+
throw new Error(fillTemplate(invalidNameTpl, { name }));
|
|
66
|
+
}
|
|
67
|
+
await mkdir(migrationsPath, { recursive: true });
|
|
68
|
+
let entries = [];
|
|
69
|
+
try {
|
|
70
|
+
entries = await readdir(migrationsPath);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
if (!(err instanceof Error && 'code' in err && err.code === 'ENOENT'))
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
const seq = pad4(nextSequence(entries));
|
|
77
|
+
const upName = `${seq}_${name}_up.sql`;
|
|
78
|
+
const downName = `${seq}_${name}_down.sql`;
|
|
79
|
+
await writeFile(`${migrationsPath}/${upName}`, await loadScaffold('up', { name }));
|
|
80
|
+
await writeFile(`${migrationsPath}/${downName}`, await loadScaffold('down', { name }));
|
|
81
|
+
return { upName, downName };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export const getMigrater = (provider) => new Migrater(defaultDialectFactory.get(provider));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type MigrationRowValue = string | number | bigint | boolean | Date | null;
|
|
2
|
+
export type MigrationRow = Record<string, MigrationRowValue>;
|
|
3
|
+
export type MigrationSqlParam = string | number | bigint | boolean | Date | null;
|
|
4
|
+
/** The subset of a better-sqlite3 Database that `insertLogStarted` reaches through `_raw` when a caller injects a synchronous handle. */
|
|
5
|
+
export interface SqliteRawDatabase {
|
|
6
|
+
prepare(source: string): {
|
|
7
|
+
run(...params: MigrationSqlParam[]): {
|
|
8
|
+
lastInsertRowid: number | bigint;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/** Provider-agnostic migration client used by IMigrater.up, IMigrater.down, and IMigrater.setup. */
|
|
13
|
+
export interface MigrationClient {
|
|
14
|
+
dialect: import('./sql.ts').SqlDialect;
|
|
15
|
+
exec(sql: string): Promise<void>;
|
|
16
|
+
query(sql: string, params?: MigrationSqlParam[]): Promise<MigrationRow[]>;
|
|
17
|
+
run(sql: string, params?: MigrationSqlParam[]): Promise<void>;
|
|
18
|
+
transaction<T>(fn: () => Promise<T>): Promise<T>;
|
|
19
|
+
close(): Promise<void>;
|
|
20
|
+
_raw?: SqliteRawDatabase;
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const pathExists: (p: string) => Promise<boolean>;
|
package/dist/sql.d.ts
ADDED
package/dist/sql.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { cliSpec } from "./cli-spec.js";
|
|
2
|
+
const stripKey = (raw) => raw.toLowerCase().replace(/[\s_\-]/g, '');
|
|
3
|
+
export const normalizeDialect = (raw) => {
|
|
4
|
+
if (!raw)
|
|
5
|
+
return null;
|
|
6
|
+
const key = stripKey(raw);
|
|
7
|
+
if (cliSpec.providers.includes(key))
|
|
8
|
+
return key;
|
|
9
|
+
for (const [alias, canonical] of Object.entries(cliSpec.provider_aliases ?? {})) {
|
|
10
|
+
if (stripKey(alias) === key)
|
|
11
|
+
return canonical;
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
};
|
|
15
|
+
export { pathExists } from "./path-exists.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{{usage}}
|
|
2
|
+
|
|
3
|
+
Creates a new <NNNN>_<name>_up.sql + <NNNN>_<name>_down.sql pair scaffolded
|
|
4
|
+
with TODO placeholders. NNNN is one greater than the highest 1-4-digit
|
|
5
|
+
sequence prefix already present in the migrations directory (starts at 0001).
|
|
6
|
+
Legacy timestamp-prefixed filenames are ignored for numbering.
|
|
7
|
+
|
|
8
|
+
--provider Database dialect. Required.
|
|
9
|
+
--name snake_case slug for the new migration. Required. Must
|
|
10
|
+
match /^[a-z][a-z0-9_]*$/.
|
|
11
|
+
--migrations-path Migrations directory (default: ./sql/<dialect>/migrations).
|
|
12
|
+
Created with mkdir -p if it does not exist.
|
|
13
|
+
|
|
14
|
+
Examples:
|
|
15
|
+
{{command}} --provider sqlite --name add_users
|
|
16
|
+
{{command}} --provider postgres --name backfill_email_lower --migrations-path ./db/changes/postgres
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{{usage}}
|
|
2
|
+
|
|
3
|
+
Rolls back the MOST RECENTLY applied migration (one step). DESTRUCTIVE: prints a
|
|
4
|
+
random 4-letter uppercase token on stderr and refuses to proceed unless the
|
|
5
|
+
operator types it back on stdin (or passes --confirm <TOKEN> matching it).
|
|
6
|
+
|
|
7
|
+
--provider Database dialect. Required.
|
|
8
|
+
--connection Connection string. Required (or set the per-dialect env var below).
|
|
9
|
+
--migrations-path Full path to the migrations directory.
|
|
10
|
+
--migrations-root Root prefix; the script then looks at <migrations-root>/<dialect>/migrations.
|
|
11
|
+
Defaults to 'sql'. Ignored when --migrations-path is also set.
|
|
12
|
+
--confirm Skip the interactive prompt. The TOKEN must match the value
|
|
13
|
+
printed on stderr at runtime — there is no fixed bypass value.
|
|
14
|
+
|
|
15
|
+
Examples:
|
|
16
|
+
# sqlite — bare path or sqlite:// URL.
|
|
17
|
+
{{command}} --provider sqlite --connection ./app.sqlite
|
|
18
|
+
{{command}} --provider sqlite --connection sqlite:///absolute/path/app.sqlite
|
|
19
|
+
|
|
20
|
+
# postgres — URL or keyword form.
|
|
21
|
+
{{command}} --provider postgres --connection postgresql://user:pass@host:5432/dbname
|
|
22
|
+
|
|
23
|
+
# mysql — URL form.
|
|
24
|
+
{{command}} --provider mysql --connection mysql://user:pass@host:3306/dbname
|
|
25
|
+
|
|
26
|
+
# sqlserver / oracle — pass a driver-native connection string.
|
|
27
|
+
{{command}} --provider sqlserver --connection "Server=host;Database=dbname;User Id=user;Password=pass;"
|
|
28
|
+
{{command}} --provider oracle --connection "user/pass@host:1521/service"
|
|
29
|
+
|
|
30
|
+
# env-var fallback when --connection is omitted:
|
|
31
|
+
SQLITE_PATH=./app.sqlite {{command}} --provider sqlite
|
|
32
|
+
DATABASE_URL=postgresql://... {{command}} --provider postgres
|
|
33
|
+
|
|
34
|
+
# custom migrations layout (default looks under sql/<dialect>/migrations):
|
|
35
|
+
{{command}} --provider sqlite --connection ./app.sqlite --migrations-path ./db/changes/sqlite
|
|
36
|
+
|
|
37
|
+
Per-dialect env vars consulted when --connection is omitted:
|
|
38
|
+
sqlite SQLITE_PATH, DB_PATH
|
|
39
|
+
postgres PG_CONNECTION_STRING, DATABASE_URL
|
|
40
|
+
mysql MYSQL_URL, DATABASE_URL
|
|
41
|
+
sqlserver MSSQL_URL, DATABASE_URL
|
|
42
|
+
oracle ORACLE_CONNECT_STRING, DATABASE_URL
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{{usage}}
|
|
2
|
+
|
|
3
|
+
Selects the dialects this tree will compile and install. Repeat --dialect
|
|
4
|
+
once per provider. Re-running replaces the previous set. --all restores
|
|
5
|
+
every dialect. Does not take --connection.
|
|
6
|
+
|
|
7
|
+
--dialect Dialect to enable. Repeat for each dialect. Aliases from this file apply.
|
|
8
|
+
--all Enable every dialect. Restores the committed full-provider set.
|
|
9
|
+
|
|
10
|
+
Examples:
|
|
11
|
+
{{command}} --dialect sqlite --dialect postgres
|
|
12
|
+
{{command}} --dialect oracle
|
|
13
|
+
{{command}} --all
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{{usage}}
|
|
2
|
+
|
|
3
|
+
Creates the bookkeeping tables (migrates, migrate_logs) for the chosen dialect
|
|
4
|
+
and the migrations directory (mkdir -p). Idempotent — re-running against an
|
|
5
|
+
already-setup database is a no-op. For sqlite, also mkdir -p of the parent
|
|
6
|
+
directory of --connection so a fresh-tree path like ./.test/foo.sqlite works.
|
|
7
|
+
|
|
8
|
+
--provider Database dialect. Required.
|
|
9
|
+
--connection Connection string. Required (or set the per-dialect env var below).
|
|
10
|
+
--migrations-path Migrations directory (default: ./sql/<dialect>/migrations).
|
|
11
|
+
--and-up After setup, immediately invoke migrate-up so the chain is applied in one step.
|
|
12
|
+
|
|
13
|
+
Examples:
|
|
14
|
+
# sqlite — bare path or sqlite:// URL; both create a file on disk.
|
|
15
|
+
{{command}} --provider sqlite --connection ./app.sqlite
|
|
16
|
+
{{command}} --provider sqlite --connection sqlite:///absolute/path/app.sqlite
|
|
17
|
+
|
|
18
|
+
# postgres — URL or keyword form.
|
|
19
|
+
{{command}} --provider postgres --connection postgresql://user:pass@host:5432/dbname
|
|
20
|
+
|
|
21
|
+
# mysql — URL form.
|
|
22
|
+
{{command}} --provider mysql --connection mysql://user:pass@host:3306/dbname
|
|
23
|
+
|
|
24
|
+
# sqlserver / oracle — pass a driver-native connection string.
|
|
25
|
+
{{command}} --provider sqlserver --connection "Server=host;Database=dbname;User Id=user;Password=pass;"
|
|
26
|
+
{{command}} --provider oracle --connection "user/pass@host:1521/service"
|
|
27
|
+
|
|
28
|
+
# env-var fallback when --connection is omitted:
|
|
29
|
+
SQLITE_PATH=./app.sqlite {{command}} --provider sqlite
|
|
30
|
+
DATABASE_URL=postgresql://... {{command}} --provider postgres
|
|
31
|
+
DATABASE_URL=mysql://... {{command}} --provider mysql
|
|
32
|
+
|
|
33
|
+
# explicit in-memory sqlite:
|
|
34
|
+
{{command}} --provider sqlite --connection :memory:
|
|
35
|
+
|
|
36
|
+
Per-dialect env vars consulted when --connection is omitted:
|
|
37
|
+
sqlite SQLITE_PATH, DB_PATH
|
|
38
|
+
postgres PG_CONNECTION_STRING, DATABASE_URL
|
|
39
|
+
mysql MYSQL_URL, DATABASE_URL
|
|
40
|
+
sqlserver MSSQL_URL, DATABASE_URL
|
|
41
|
+
oracle ORACLE_CONNECT_STRING, DATABASE_URL
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{{usage}}
|
|
2
|
+
|
|
3
|
+
Applies ALL pending migrations in sequence, each in its own transaction.
|
|
4
|
+
|
|
5
|
+
--provider Database dialect. Required.
|
|
6
|
+
--connection Connection string. Required (or set the per-dialect env var below).
|
|
7
|
+
--migrations-path Full path to the migrations directory (e.g. sql/sqlite/migrations).
|
|
8
|
+
--migrations-root Root prefix; the script then looks at <migrations-root>/<dialect>/migrations.
|
|
9
|
+
Defaults to 'sql'. Ignored when --migrations-path is also set.
|
|
10
|
+
--one Apply only the next pending migration, then exit. Default is to apply all pending migrations.
|
|
11
|
+
|
|
12
|
+
Examples:
|
|
13
|
+
# sqlite — bare path or sqlite:// URL; both create a file on disk.
|
|
14
|
+
{{command}} --provider sqlite --connection ./app.sqlite
|
|
15
|
+
{{command}} --provider sqlite --connection sqlite:///absolute/path/app.sqlite
|
|
16
|
+
|
|
17
|
+
# postgres — URL or keyword form.
|
|
18
|
+
{{command}} --provider postgres --connection postgresql://user:pass@host:5432/dbname
|
|
19
|
+
|
|
20
|
+
# mysql — URL form.
|
|
21
|
+
{{command}} --provider mysql --connection mysql://user:pass@host:3306/dbname
|
|
22
|
+
|
|
23
|
+
# sqlserver / oracle — pass a driver-native connection string.
|
|
24
|
+
{{command}} --provider sqlserver --connection "Server=host;Database=dbname;User Id=user;Password=pass;"
|
|
25
|
+
{{command}} --provider oracle --connection "user/pass@host:1521/service"
|
|
26
|
+
|
|
27
|
+
# env-var fallback when --connection is omitted:
|
|
28
|
+
SQLITE_PATH=./app.sqlite {{command}} --provider sqlite
|
|
29
|
+
DATABASE_URL=postgresql://... {{command}} --provider postgres
|
|
30
|
+
|
|
31
|
+
# custom migrations layout (default looks under sql/<dialect>/migrations):
|
|
32
|
+
{{command}} --provider sqlite --connection ./app.sqlite --migrations-path ./db/changes/sqlite
|
|
33
|
+
{{command}} --provider sqlite --connection ./app.sqlite --migrations-root ./db/changes
|
|
34
|
+
|
|
35
|
+
# one-shot: apply the next pending migration only, then exit.
|
|
36
|
+
{{command}} --provider sqlite --connection ./app.sqlite --one
|
|
37
|
+
|
|
38
|
+
Per-dialect env vars consulted when --connection is omitted:
|
|
39
|
+
sqlite SQLITE_PATH, DB_PATH
|
|
40
|
+
postgres PG_CONNECTION_STRING, DATABASE_URL
|
|
41
|
+
mysql MYSQL_URL, DATABASE_URL
|
|
42
|
+
sqlserver MSSQL_URL, DATABASE_URL
|
|
43
|
+
oracle ORACLE_CONNECT_STRING, DATABASE_URL
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{name}}: stored {{stored}}..., current {{current}}...
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Migration checksum drift detected — the migration file changed AFTER it was applied:
|
|
2
|
+
{{lines}}
|
|
3
|
+
|
|
4
|
+
The DB and source disagree about the schema you're running. Either the codegen
|
|
5
|
+
regenerated an already-applied migration in place (the canonical bug — emit a NEW
|
|
6
|
+
migration file instead), or the migrate state was hand-edited.
|
|
7
|
+
|
|
8
|
+
Recovery options:
|
|
9
|
+
1. Emit a new migration that brings the DB up to the current schema, then deploy.
|
|
10
|
+
2. For showcase/dev DBs with no real data: wipe the DB file and let migrate:up re-run from scratch.
|
|
11
|
+
3. If you've verified the DB matches the new file: MIGRATE_ALLOW_CHECKSUM_DRIFT=1 npm run migrate:up
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--confirm value ({{supplied}}) does not match the token printed above ({{token}}). Aborting.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Type {{token}} to confirm rollback:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
failed to read confirmation from stdin — aborting.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Confirmation token did not match — aborting.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
migrate-down requires interactive confirmation when stdin is not a TTY — pass --confirm {{token}} (this exact token, printed above) to proceed.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--name must be snake_case: lowercase letter then [a-z0-9_] (got "{{name}}")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
migrate-path is not a directory: {{path}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
missing --connection — pass --connection <url> (e.g. ./app.sqlite for sqlite) or set one of: {{envVars}}. Run with --help for examples.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
missing --name — pass --name <snake_case_slug>.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
missing --name
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
missing --provider — pass --provider <{{providers}}>. Run with --help for examples.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
missing --provider
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
missing value for {{flag}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Cannot roll back "{{name}}": no <stem>_down.sql sibling found
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Cannot roll back "{{name}}": no rollback_*.sql sibling found
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Most recently applied migration is not present under --migrate-path
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sqlite file: {{path}} does not exist — run 'migrate-setup --provider sqlite --connection {{path}}' to create it
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
unknown arg: {{arg}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
unsupported provider: {{provider}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Applied: {{name}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Created: {{file}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
No more pending migrations.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
No pending migrations.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
No applied migrations to roll back.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Rolled back: {{name}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
-- TODO: write the down migration for "{{name}}"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
-- TODO: write the up migration for "{{name}}"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS `migrate_logs` (
|
|
2
|
+
`id` BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
3
|
+
`migrate_name` VARCHAR(255) NOT NULL,
|
|
4
|
+
`direction` VARCHAR(8) NOT NULL,
|
|
5
|
+
`status` VARCHAR(16) NOT NULL,
|
|
6
|
+
`finished_at` TIMESTAMP NULL,
|
|
7
|
+
`duration_ms` INT,
|
|
8
|
+
`error_message` TEXT,
|
|
9
|
+
`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
10
|
+
`updated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
11
|
+
);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS `migrates` (
|
|
2
|
+
`id` BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
3
|
+
`name` VARCHAR(255) NOT NULL UNIQUE,
|
|
4
|
+
`checksum` VARCHAR(64),
|
|
5
|
+
`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
6
|
+
`updated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
7
|
+
);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
BEGIN
|
|
2
|
+
EXECUTE IMMEDIATE 'CREATE TABLE "migrate_logs" (
|
|
3
|
+
"id" NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
4
|
+
"migrate_name" VARCHAR2(255) NOT NULL,
|
|
5
|
+
"direction" VARCHAR2(8) NOT NULL,
|
|
6
|
+
"status" VARCHAR2(16) NOT NULL,
|
|
7
|
+
"finished_at" TIMESTAMP,
|
|
8
|
+
"duration_ms" NUMBER(10),
|
|
9
|
+
"error_message" CLOB,
|
|
10
|
+
"created" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
11
|
+
"updated" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
|
|
12
|
+
)';
|
|
13
|
+
EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF;
|
|
14
|
+
END;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
BEGIN
|
|
2
|
+
EXECUTE IMMEDIATE 'CREATE TABLE "migrates" (
|
|
3
|
+
"id" NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
4
|
+
"name" VARCHAR2(255) NOT NULL UNIQUE,
|
|
5
|
+
"checksum" VARCHAR2(64),
|
|
6
|
+
"created" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
7
|
+
"updated" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
|
|
8
|
+
)';
|
|
9
|
+
EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF;
|
|
10
|
+
END;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS "migrate_logs" (
|
|
2
|
+
"id" BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
3
|
+
"migrate_name" VARCHAR(255) NOT NULL,
|
|
4
|
+
"direction" VARCHAR(8) NOT NULL,
|
|
5
|
+
"status" VARCHAR(16) NOT NULL,
|
|
6
|
+
"finished_at" TIMESTAMPTZ,
|
|
7
|
+
"duration_ms" INTEGER,
|
|
8
|
+
"error_message" TEXT,
|
|
9
|
+
"created" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
10
|
+
"updated" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
11
|
+
);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS "migrate_logs" (
|
|
2
|
+
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3
|
+
"migrate_name" VARCHAR(255) NOT NULL,
|
|
4
|
+
"direction" VARCHAR(8) NOT NULL,
|
|
5
|
+
"status" VARCHAR(16) NOT NULL,
|
|
6
|
+
"finished_at" DATETIME,
|
|
7
|
+
"duration_ms" INTEGER,
|
|
8
|
+
"error_message" TEXT,
|
|
9
|
+
"created" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
10
|
+
"updated" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
11
|
+
);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
IF OBJECT_ID('dbo.migrate_logs', 'U') IS NULL
|
|
2
|
+
CREATE TABLE [migrate_logs] (
|
|
3
|
+
[id] BIGINT IDENTITY(1,1) PRIMARY KEY,
|
|
4
|
+
[migrate_name] NVARCHAR(255) NOT NULL,
|
|
5
|
+
[direction] NVARCHAR(8) NOT NULL,
|
|
6
|
+
[status] NVARCHAR(16) NOT NULL,
|
|
7
|
+
[finished_at] DATETIME2,
|
|
8
|
+
[duration_ms] INT,
|
|
9
|
+
[error_message] NVARCHAR(MAX),
|
|
10
|
+
[created] DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),
|
|
11
|
+
[updated] DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
|
|
12
|
+
);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
IF OBJECT_ID('dbo.migrates', 'U') IS NULL
|
|
2
|
+
CREATE TABLE [migrates] (
|
|
3
|
+
[id] BIGINT IDENTITY(1,1) PRIMARY KEY,
|
|
4
|
+
[name] NVARCHAR(255) NOT NULL UNIQUE,
|
|
5
|
+
[checksum] NVARCHAR(64),
|
|
6
|
+
[created] DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),
|
|
7
|
+
[updated] DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
|
|
8
|
+
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,80 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deterministic-code/migraters",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "TypeScript migrate executables for deterministic-code.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./package.json": "./package.json"
|
|
12
|
+
},
|
|
13
|
+
"bin": {
|
|
14
|
+
"migrate-up": "./dist/bin/migrate-up.js",
|
|
15
|
+
"migrate-down": "./dist/bin/migrate-down.js",
|
|
16
|
+
"migrate-setup": "./dist/bin/migrate-setup.js",
|
|
17
|
+
"migrate-create": "./dist/bin/migrate-create.js",
|
|
18
|
+
"migrate-init": "./dist/bin/migrate-init.js"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"src",
|
|
23
|
+
"cli.yaml",
|
|
24
|
+
"bundle.yaml",
|
|
25
|
+
"tsconfig.build.json"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && cp -R ../shared/templates dist/templates",
|
|
29
|
+
"prepare": "npm run build",
|
|
30
|
+
"typecheck": "tsc -p tsconfig.build.json --noEmit",
|
|
31
|
+
"test": "vitest run --coverage",
|
|
32
|
+
"test:proof": "vitest run --config vitest.proof.config.ts",
|
|
33
|
+
"test:coverage": "vitest run --coverage",
|
|
34
|
+
"generate:help": "node --experimental-strip-types src/generate-help.ts",
|
|
35
|
+
"format": "prettier --write ."
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"yaml": "^2.9.0"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"better-sqlite3": "^12.10.0",
|
|
42
|
+
"mssql": "^12.5.0",
|
|
43
|
+
"mysql2": "^3.22.2",
|
|
44
|
+
"oracledb": "^6.10.0",
|
|
45
|
+
"pg": "^8.13.0"
|
|
46
|
+
},
|
|
47
|
+
"peerDependenciesMeta": {
|
|
48
|
+
"better-sqlite3": {
|
|
49
|
+
"optional": true
|
|
50
|
+
},
|
|
51
|
+
"mssql": {
|
|
52
|
+
"optional": true
|
|
53
|
+
},
|
|
54
|
+
"mysql2": {
|
|
55
|
+
"optional": true
|
|
56
|
+
},
|
|
57
|
+
"oracledb": {
|
|
58
|
+
"optional": true
|
|
59
|
+
},
|
|
60
|
+
"pg": {
|
|
61
|
+
"optional": true
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/better-sqlite3": "^7.6.11",
|
|
66
|
+
"better-sqlite3": "^12.10.0",
|
|
67
|
+
"@types/mssql": "^12.3.0",
|
|
68
|
+
"@types/node": "^22.10.0",
|
|
69
|
+
"@types/oracledb": "^6.10.3",
|
|
70
|
+
"@types/pg": "^8.11.10",
|
|
71
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
72
|
+
"mssql": "^12.5.0",
|
|
73
|
+
"mysql2": "^3.22.2",
|
|
74
|
+
"oracledb": "^6.10.0",
|
|
75
|
+
"pg": "^8.13.0",
|
|
76
|
+
"prettier": "^3.9.6",
|
|
77
|
+
"typescript": "^5.8.0",
|
|
78
|
+
"vitest": "^3.2.4"
|
|
79
|
+
}
|
|
80
|
+
}
|