@deterministic-code/migraters 0.0.1 → 0.0.2
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 +1 -0
- package/cli.yaml +264 -0
- package/dist/bin/migrate-create.js +0 -0
- package/dist/bin/migrate-down.js +0 -0
- package/dist/bin/migrate-init.js +0 -0
- package/dist/bin/migrate-setup.js +0 -0
- package/dist/bin/migrate-up.js +0 -0
- package/package.json +7 -6
- package/src/abstractions/migrater.ts +0 -13
- package/src/abstractions/sql-dialect-base.ts +0 -36
- package/src/abstractions/sql-dialect-factory.ts +0 -29
- package/src/abstractions/sql-dialect.ts +0 -17
- package/src/bin/migrate-create.ts +0 -80
- package/src/bin/migrate-down.ts +0 -163
- package/src/bin/migrate-init.ts +0 -88
- package/src/bin/migrate-setup.ts +0 -98
- package/src/bin/migrate-up.ts +0 -111
- package/src/cli-contract.ts +0 -25
- package/src/cli-spec.ts +0 -64
- package/src/cli.ts +0 -52
- package/src/create-sequence.ts +0 -17
- package/src/datasource-migrate.ts +0 -314
- package/src/dialects/mysql-dialect.test.ts +0 -93
- package/src/dialects/mysql-dialect.ts +0 -67
- package/src/dialects/oracle-dialect.test.ts +0 -118
- package/src/dialects/oracle-dialect.ts +0 -91
- package/src/dialects/postgres-dialect.test.ts +0 -80
- package/src/dialects/postgres-dialect.ts +0 -65
- package/src/dialects/sqlite-dialect.rollback.test.ts +0 -30
- package/src/dialects/sqlite-dialect.test.ts +0 -77
- package/src/dialects/sqlite-dialect.ts +0 -96
- package/src/dialects/sqlserver-dialect.test.ts +0 -99
- package/src/dialects/sqlserver-dialect.ts +0 -87
- package/src/generate-help.test.ts +0 -33
- package/src/generate-help.ts +0 -173
- package/src/help.test.ts +0 -48
- package/src/help.ts +0 -12
- package/src/index.ts +0 -23
- package/src/infrastructure/connection-resolver.ts +0 -18
- package/src/infrastructure/default-factory.test.ts +0 -18
- package/src/infrastructure/default-factory.ts +0 -17
- package/src/infrastructure/interop-default.test.ts +0 -9
- package/src/infrastructure/interop-default.ts +0 -2
- package/src/infrastructure/message-templates.ts +0 -30
- package/src/infrastructure/split-on-go.ts +0 -19
- package/src/infrastructure/sql-templates.ts +0 -10
- package/src/infrastructure/templates-root.ts +0 -13
- package/src/init-select.test.ts +0 -26
- package/src/init-select.ts +0 -73
- package/src/migrater.ts +0 -92
- package/src/migration-client.ts +0 -21
- package/src/path-exists.ts +0 -10
- package/src/setup-sql.test.ts +0 -16
- package/src/sql.ts +0 -17
- package/tsconfig.build.json +0 -19
package/src/bin/migrate-init.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawnSync } from 'node:child_process';
|
|
3
|
-
import { loadHelp } from '../help.ts';
|
|
4
|
-
import { loadSelectedPackages, resolveInitDialects } from '../init-select.ts';
|
|
5
|
-
|
|
6
|
-
const HELP_TEXT = await loadHelp('migrate-init');
|
|
7
|
-
|
|
8
|
-
const takeFlag = (
|
|
9
|
-
rest: string[],
|
|
10
|
-
i: number,
|
|
11
|
-
arg: string,
|
|
12
|
-
flag: string,
|
|
13
|
-
): { value: string; next: number } | undefined => {
|
|
14
|
-
const eq = `${flag}=`;
|
|
15
|
-
if (arg === flag) {
|
|
16
|
-
const value = rest[i + 1];
|
|
17
|
-
if (value === undefined) return undefined;
|
|
18
|
-
return { value, next: i + 1 };
|
|
19
|
-
}
|
|
20
|
-
if (arg.startsWith(eq)) return { value: arg.slice(eq.length), next: i };
|
|
21
|
-
return undefined;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const parseArgs = (argv: string[]) => {
|
|
25
|
-
const dialects: string[] = [];
|
|
26
|
-
let all = false;
|
|
27
|
-
const rest = argv.slice(2);
|
|
28
|
-
for (let i = 0; i < rest.length; i++) {
|
|
29
|
-
const a = rest[i] as string;
|
|
30
|
-
if (a === '-h' || a === '--help') {
|
|
31
|
-
process.stderr.write(HELP_TEXT);
|
|
32
|
-
process.exit(0);
|
|
33
|
-
}
|
|
34
|
-
if (a === '--all') {
|
|
35
|
-
all = true;
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
const taken = takeFlag(rest, i, a, '--dialect');
|
|
39
|
-
if (taken) {
|
|
40
|
-
dialects.push(taken.value);
|
|
41
|
-
i = taken.next;
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
process.stderr.write(`unknown arg: ${a}\n`);
|
|
45
|
-
process.exit(2);
|
|
46
|
-
}
|
|
47
|
-
return { dialects, all };
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const npmFlags = ['--no-audit', '--no-fund', '--loglevel=error'];
|
|
51
|
-
|
|
52
|
-
const npm = (args: string[]): void => {
|
|
53
|
-
const cmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
54
|
-
const result = spawnSync(cmd, args, { stdio: 'inherit', cwd: process.cwd() });
|
|
55
|
-
if (result.status !== 0) {
|
|
56
|
-
process.exit(result.status ?? 1);
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const main = async () => {
|
|
61
|
-
const args = parseArgs(process.argv);
|
|
62
|
-
let names: string[];
|
|
63
|
-
try {
|
|
64
|
-
names = resolveInitDialects(args.dialects, args.all);
|
|
65
|
-
} catch (e) {
|
|
66
|
-
const err = e as Error;
|
|
67
|
-
process.stderr.write(`${err.message}\n`);
|
|
68
|
-
process.exit(2);
|
|
69
|
-
}
|
|
70
|
-
const selected = await loadSelectedPackages(names);
|
|
71
|
-
const specs = selected.packages.map((p) => `${p.name}@${p.version}`);
|
|
72
|
-
if (specs.length > 0) {
|
|
73
|
-
npm(['install', ...npmFlags, ...specs]);
|
|
74
|
-
}
|
|
75
|
-
const remove = selected.allDriverPackages.filter(
|
|
76
|
-
(name) => !selected.packages.some((p) => p.name === name),
|
|
77
|
-
);
|
|
78
|
-
if (remove.length > 0) {
|
|
79
|
-
npm(['uninstall', ...npmFlags, ...remove]);
|
|
80
|
-
}
|
|
81
|
-
process.stdout.write(`Enabled dialects: ${selected.names.join(', ')}\n`);
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
main().catch((e: unknown) => {
|
|
85
|
-
const err = e as Error;
|
|
86
|
-
process.stderr.write(`${err?.stack ?? err?.message ?? String(e)}\n`);
|
|
87
|
-
process.exit(1);
|
|
88
|
-
});
|
package/src/bin/migrate-setup.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Idempotent migrate-setup — creates the migrates + migrate_logs tracking tables per dialect.
|
|
3
|
-
|
|
4
|
-
import { missingProviderMsg, requireConnection, requireDialect, takeFlag } from '../cli.ts';
|
|
5
|
-
import { fillTemplate, loadMessage } from '../infrastructure/message-templates.ts';
|
|
6
|
-
import { loadHelp, Migrater } from '../index.ts';
|
|
7
|
-
|
|
8
|
-
const [HELP_TEXT, unknownArgTpl, setupCompleteTpl] = await Promise.all([
|
|
9
|
-
loadHelp('migrate-setup'),
|
|
10
|
-
loadMessage('errors/unknown-arg'),
|
|
11
|
-
loadMessage('setup-complete'),
|
|
12
|
-
]);
|
|
13
|
-
|
|
14
|
-
const parseArgs = (argv: string[]) => {
|
|
15
|
-
const args: {
|
|
16
|
-
provider: string | null;
|
|
17
|
-
connection: string | null;
|
|
18
|
-
migrationsPath: string | null;
|
|
19
|
-
andUp: boolean;
|
|
20
|
-
} = {
|
|
21
|
-
provider: null,
|
|
22
|
-
connection: null,
|
|
23
|
-
migrationsPath: null,
|
|
24
|
-
andUp: false,
|
|
25
|
-
};
|
|
26
|
-
const rest = argv.slice(2);
|
|
27
|
-
for (let i = 0; i < rest.length; i++) {
|
|
28
|
-
const a = rest[i] as string;
|
|
29
|
-
if (a === '-h' || a === '--help') {
|
|
30
|
-
process.stderr.write(HELP_TEXT);
|
|
31
|
-
process.exit(0);
|
|
32
|
-
}
|
|
33
|
-
if (a === '--and-up') {
|
|
34
|
-
args.andUp = true;
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
let taken;
|
|
38
|
-
if ((taken = takeFlag(rest, i, a, '--provider'))) {
|
|
39
|
-
args.provider = taken.value;
|
|
40
|
-
i = taken.next;
|
|
41
|
-
} else if ((taken = takeFlag(rest, i, a, '--connection'))) {
|
|
42
|
-
args.connection = taken.value;
|
|
43
|
-
i = taken.next;
|
|
44
|
-
} else if (
|
|
45
|
-
(taken = takeFlag(rest, i, a, '--migrations-path')) ||
|
|
46
|
-
(taken = takeFlag(rest, i, a, '--migrate-path'))
|
|
47
|
-
) {
|
|
48
|
-
args.migrationsPath = taken.value;
|
|
49
|
-
i = taken.next;
|
|
50
|
-
} else {
|
|
51
|
-
process.stderr.write(fillTemplate(unknownArgTpl, { arg: a }));
|
|
52
|
-
process.exit(2);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return args;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const main = async () => {
|
|
59
|
-
const args = parseArgs(process.argv);
|
|
60
|
-
if (!args.provider) {
|
|
61
|
-
process.stderr.write(missingProviderMsg);
|
|
62
|
-
process.exit(2);
|
|
63
|
-
}
|
|
64
|
-
const dialect = requireDialect(args.provider);
|
|
65
|
-
const connection = requireConnection(dialect, args.connection);
|
|
66
|
-
|
|
67
|
-
const migrationsPath = args.migrationsPath ?? `./sql/${dialect.name}/migrations`;
|
|
68
|
-
const migrater = new Migrater(dialect);
|
|
69
|
-
await migrater.setup({ connection, migrationsPath });
|
|
70
|
-
process.stdout.write(
|
|
71
|
-
fillTemplate(setupCompleteTpl, {
|
|
72
|
-
dialect: dialect.name,
|
|
73
|
-
migrationsPath,
|
|
74
|
-
createExample: ` migrate-create --provider ${dialect.name} --name add_users`,
|
|
75
|
-
upExample: ` migrate-up --provider ${dialect.name} --connection ${connection}`,
|
|
76
|
-
}),
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
if (args.andUp) {
|
|
80
|
-
const names = await migrater.up({ connection, migrationsPath });
|
|
81
|
-
const [noPendingMsg, noMorePendingMsg, appliedTpl] = await Promise.all([
|
|
82
|
-
loadMessage('status/no-pending'),
|
|
83
|
-
loadMessage('status/no-more-pending'),
|
|
84
|
-
loadMessage('status/applied'),
|
|
85
|
-
]);
|
|
86
|
-
if (names.length === 0) process.stdout.write(noPendingMsg);
|
|
87
|
-
else {
|
|
88
|
-
for (const name of names) process.stdout.write(fillTemplate(appliedTpl, { name }));
|
|
89
|
-
process.stdout.write(noMorePendingMsg);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
main().catch((e: unknown) => {
|
|
95
|
-
const err = e as Error;
|
|
96
|
-
process.stderr.write(`${err?.stack ?? err?.message ?? String(e)}\n`);
|
|
97
|
-
process.exit(1);
|
|
98
|
-
});
|
package/src/bin/migrate-up.ts
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Default: applies ALL pending migrations in sequence, each in its own transaction. Pass --one to apply only the next pending migration (legacy one-shot behavior; useful when wrapping in an external loop or when you want to inspect state between steps).
|
|
3
|
-
|
|
4
|
-
import { resolve } from 'node:path';
|
|
5
|
-
import { missingProviderMsg, requireConnection, requireDialect, takeFlag } from '../cli.ts';
|
|
6
|
-
import { fillTemplate, loadMessage } from '../infrastructure/message-templates.ts';
|
|
7
|
-
import { loadHelp, Migrater } from '../index.ts';
|
|
8
|
-
|
|
9
|
-
const [HELP_TEXT, unknownArgTpl, noPendingMsg, noMorePendingMsg, appliedTpl] = await Promise.all([
|
|
10
|
-
loadHelp('migrate-up'),
|
|
11
|
-
loadMessage('errors/unknown-arg'),
|
|
12
|
-
loadMessage('status/no-pending'),
|
|
13
|
-
loadMessage('status/no-more-pending'),
|
|
14
|
-
loadMessage('status/applied'),
|
|
15
|
-
]);
|
|
16
|
-
|
|
17
|
-
const parseArgs = (argv: string[]) => {
|
|
18
|
-
const args: {
|
|
19
|
-
provider: string | null;
|
|
20
|
-
migratePath: string | null;
|
|
21
|
-
migrateRoot: string | null;
|
|
22
|
-
connection: string | null;
|
|
23
|
-
one: boolean;
|
|
24
|
-
} = {
|
|
25
|
-
provider: null,
|
|
26
|
-
migratePath: null,
|
|
27
|
-
migrateRoot: null,
|
|
28
|
-
connection: null,
|
|
29
|
-
one: false,
|
|
30
|
-
};
|
|
31
|
-
const rest = argv.slice(2);
|
|
32
|
-
for (let i = 0; i < rest.length; i++) {
|
|
33
|
-
const a = rest[i] as string;
|
|
34
|
-
if (a === '-h' || a === '--help') {
|
|
35
|
-
process.stderr.write(HELP_TEXT);
|
|
36
|
-
process.exit(0);
|
|
37
|
-
}
|
|
38
|
-
if (a === '--one') {
|
|
39
|
-
args.one = true;
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
let taken;
|
|
43
|
-
if ((taken = takeFlag(rest, i, a, '--provider'))) {
|
|
44
|
-
args.provider = taken.value;
|
|
45
|
-
i = taken.next;
|
|
46
|
-
} else if (
|
|
47
|
-
(taken = takeFlag(rest, i, a, '--migrations-path')) ||
|
|
48
|
-
(taken = takeFlag(rest, i, a, '--migrate-path'))
|
|
49
|
-
) {
|
|
50
|
-
args.migratePath = taken.value;
|
|
51
|
-
i = taken.next;
|
|
52
|
-
} else if (
|
|
53
|
-
(taken = takeFlag(rest, i, a, '--migrations-root')) ||
|
|
54
|
-
(taken = takeFlag(rest, i, a, '--migrate-root'))
|
|
55
|
-
) {
|
|
56
|
-
args.migrateRoot = taken.value;
|
|
57
|
-
i = taken.next;
|
|
58
|
-
} else if ((taken = takeFlag(rest, i, a, '--connection'))) {
|
|
59
|
-
args.connection = taken.value;
|
|
60
|
-
i = taken.next;
|
|
61
|
-
} else {
|
|
62
|
-
process.stderr.write(fillTemplate(unknownArgTpl, { arg: a }));
|
|
63
|
-
process.exit(2);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return args;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const resolveMigratePath = (
|
|
70
|
-
args: { migratePath: string | null; migrateRoot: string | null },
|
|
71
|
-
dialect: string,
|
|
72
|
-
): string => {
|
|
73
|
-
if (args.migratePath) return args.migratePath;
|
|
74
|
-
const root = args.migrateRoot ?? 'sql';
|
|
75
|
-
return `${root}/${dialect}/migrations`;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const main = async () => {
|
|
79
|
-
const args = parseArgs(process.argv);
|
|
80
|
-
if (!args.provider) {
|
|
81
|
-
process.stderr.write(missingProviderMsg);
|
|
82
|
-
process.exit(2);
|
|
83
|
-
}
|
|
84
|
-
const dialect = requireDialect(args.provider);
|
|
85
|
-
const connection = requireConnection(dialect, args.connection);
|
|
86
|
-
|
|
87
|
-
const missing = await dialect.prerequisiteError(connection);
|
|
88
|
-
if (missing !== null) {
|
|
89
|
-
process.stderr.write(`${missing}\n`);
|
|
90
|
-
process.exit(2);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const migratePath = resolve(resolveMigratePath(args, dialect.name));
|
|
94
|
-
const names = await new Migrater(dialect).up({
|
|
95
|
-
connection,
|
|
96
|
-
migrationsPath: migratePath,
|
|
97
|
-
one: args.one,
|
|
98
|
-
});
|
|
99
|
-
if (names.length === 0) {
|
|
100
|
-
process.stdout.write(noPendingMsg);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
for (const name of names) process.stdout.write(fillTemplate(appliedTpl, { name }));
|
|
104
|
-
if (!args.one) process.stdout.write(noMorePendingMsg);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
main().catch((e: unknown) => {
|
|
108
|
-
const err = e as Error;
|
|
109
|
-
process.stderr.write(`${err?.stack ?? err?.message ?? String(e)}\n`);
|
|
110
|
-
process.exit(1);
|
|
111
|
-
});
|
package/src/cli-contract.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export type { MigrateVerb } from './cli-spec.ts';
|
|
2
|
-
export { migrateCommand, usageLine, programUsageText } from './cli-spec.ts';
|
|
3
|
-
import { usageLine, type MigrateVerb } from './cli-spec.ts';
|
|
4
|
-
import { fillTemplate } from './infrastructure/message-templates.ts';
|
|
5
|
-
|
|
6
|
-
export const MIGRATE_VERBS = ['setup', 'up', 'down', 'create'] as const;
|
|
7
|
-
|
|
8
|
-
export const verbFromCommand = (command: string): MigrateVerb => {
|
|
9
|
-
const verb = command.replace(/^migrate-/, '');
|
|
10
|
-
if (
|
|
11
|
-
verb !== 'init' &&
|
|
12
|
-
verb !== 'setup' &&
|
|
13
|
-
verb !== 'up' &&
|
|
14
|
-
verb !== 'down' &&
|
|
15
|
-
verb !== 'create'
|
|
16
|
-
) {
|
|
17
|
-
throw new Error(`Unknown migrate command "${command}"`);
|
|
18
|
-
}
|
|
19
|
-
return verb;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export const fillHelpTemplate = (text: string, command: string): string => {
|
|
23
|
-
const usage = usageLine(verbFromCommand(command));
|
|
24
|
-
return fillTemplate(text, { command, usage });
|
|
25
|
-
};
|
package/src/cli-spec.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
|
-
import { readFile } from 'node:fs/promises';
|
|
3
|
-
import { dirname, join } from 'node:path';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { parse } from 'yaml';
|
|
6
|
-
|
|
7
|
-
export type MigrateVerb = 'init' | 'setup' | 'up' | 'down' | 'create';
|
|
8
|
-
|
|
9
|
-
export type CliArg = {
|
|
10
|
-
flag: string;
|
|
11
|
-
placeholder?: string;
|
|
12
|
-
required: boolean;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export type CliCommand = {
|
|
16
|
-
verb: MigrateVerb;
|
|
17
|
-
args: CliArg[];
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export type CliSpec = {
|
|
21
|
-
command: string;
|
|
22
|
-
providers: string[];
|
|
23
|
-
provider_aliases: Record<string, string>;
|
|
24
|
-
aliases: Record<string, string>;
|
|
25
|
-
env_var_list_separator: string;
|
|
26
|
-
connection_environment: Record<string, string[]>;
|
|
27
|
-
commands: CliCommand[];
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export const cliYamlPath = (): string => {
|
|
31
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
32
|
-
const candidates = [
|
|
33
|
-
join(here, '..', 'cli.yaml'),
|
|
34
|
-
join(here, '..', '..', 'cli.yaml'),
|
|
35
|
-
join(process.cwd(), 'cli.yaml'),
|
|
36
|
-
];
|
|
37
|
-
const found = candidates.find((candidate) => existsSync(candidate));
|
|
38
|
-
if (!found) {
|
|
39
|
-
throw new Error('cli.yaml not found');
|
|
40
|
-
}
|
|
41
|
-
return found;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export const cliSpec = parse(await readFile(cliYamlPath(), 'utf8')) as CliSpec;
|
|
45
|
-
|
|
46
|
-
export const migrateCommand = (verb: MigrateVerb): string =>
|
|
47
|
-
cliSpec.command.replace('{verb}', verb);
|
|
48
|
-
|
|
49
|
-
const providers = cliSpec.providers.join('|');
|
|
50
|
-
|
|
51
|
-
const argUsage = (arg: CliArg): string => {
|
|
52
|
-
const ph = arg.placeholder === 'providers' ? providers : arg.placeholder;
|
|
53
|
-
const body = ph ? `${arg.flag} <${ph}>` : arg.flag;
|
|
54
|
-
return arg.required ? body : `[${body}]`;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export const usageLine = (verb: MigrateVerb): string => {
|
|
58
|
-
const command = cliSpec.commands.find((c) => c.verb === verb);
|
|
59
|
-
if (!command) throw new Error(`cli.yaml: missing command ${verb}`);
|
|
60
|
-
return `Usage: ${migrateCommand(verb)} ${command.args.map(argUsage).join(' ')}`;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export const programUsageText = (): string =>
|
|
64
|
-
`${cliSpec.commands.map((c) => usageLine(c.verb)).join('\n')}\n`;
|
package/src/cli.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { connectionResolver, defaultDialectFactory } from './infrastructure/default-factory.ts';
|
|
2
|
-
import type { ISqlDialect } from './abstractions/sql-dialect.ts';
|
|
3
|
-
import { cliSpec } from './cli-spec.ts';
|
|
4
|
-
import { fillTemplate, loadMessage } from './infrastructure/message-templates.ts';
|
|
5
|
-
|
|
6
|
-
const missingProviderMsg = await loadMessage('errors/missing-provider');
|
|
7
|
-
const unsupportedProviderTpl = await loadMessage('errors/unsupported-provider');
|
|
8
|
-
const missingConnectionTpl = await loadMessage('errors/missing-connection');
|
|
9
|
-
|
|
10
|
-
export { missingProviderMsg };
|
|
11
|
-
|
|
12
|
-
export const requireDialect = (provider: string | null): ISqlDialect => {
|
|
13
|
-
if (!provider) {
|
|
14
|
-
process.stderr.write(missingProviderMsg);
|
|
15
|
-
process.exit(2);
|
|
16
|
-
}
|
|
17
|
-
const dialect = defaultDialectFactory.tryGet(provider);
|
|
18
|
-
if (!dialect) {
|
|
19
|
-
process.stderr.write(fillTemplate(unsupportedProviderTpl, { provider }));
|
|
20
|
-
process.exit(2);
|
|
21
|
-
}
|
|
22
|
-
return dialect;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export const requireConnection = (dialect: ISqlDialect, fromFlag: string | null): string => {
|
|
26
|
-
const connection = connectionResolver.resolve(dialect, fromFlag);
|
|
27
|
-
if (!connection) {
|
|
28
|
-
process.stderr.write(
|
|
29
|
-
fillTemplate(missingConnectionTpl, {
|
|
30
|
-
envVars: dialect.connectionEnvironmentVariables.join(cliSpec.env_var_list_separator),
|
|
31
|
-
}),
|
|
32
|
-
);
|
|
33
|
-
process.exit(2);
|
|
34
|
-
}
|
|
35
|
-
return connection;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export const takeFlag = (
|
|
39
|
-
rest: string[],
|
|
40
|
-
i: number,
|
|
41
|
-
arg: string,
|
|
42
|
-
flag: string,
|
|
43
|
-
): { value: string; next: number } | undefined => {
|
|
44
|
-
const eq = `${flag}=`;
|
|
45
|
-
if (arg === flag) {
|
|
46
|
-
const value = rest[i + 1];
|
|
47
|
-
if (value === undefined) return undefined;
|
|
48
|
-
return { value, next: i + 1 };
|
|
49
|
-
}
|
|
50
|
-
if (arg.startsWith(eq)) return { value: arg.slice(eq.length), next: i };
|
|
51
|
-
return undefined;
|
|
52
|
-
};
|
package/src/create-sequence.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export const MIGRATION_NAME_RE = /^[a-z][a-z0-9_]*$/;
|
|
2
|
-
const SEQ_RE = /^(\d{1,4})_.*_up\.sql$/;
|
|
3
|
-
|
|
4
|
-
export const isMigrationName = (name: string): boolean => MIGRATION_NAME_RE.test(name);
|
|
5
|
-
|
|
6
|
-
export const nextSequence = (filenames: Iterable<string>): number => {
|
|
7
|
-
let max = 0;
|
|
8
|
-
for (const name of filenames) {
|
|
9
|
-
const m = SEQ_RE.exec(name);
|
|
10
|
-
if (!m) continue;
|
|
11
|
-
const n = Number.parseInt(m[1] as string, 10);
|
|
12
|
-
if (n > max) max = n;
|
|
13
|
-
}
|
|
14
|
-
return max + 1;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export const pad4 = (n: number): string => String(n).padStart(4, '0');
|