280 lines
7 KiB
JavaScript
280 lines
7 KiB
JavaScript
#!/usr/bin/env node --enable-source-maps
|
|
import process from 'node:process';
|
|
import { parseArgs } from 'node:util';
|
|
import { ShowUsageError } from './errors.js';
|
|
import { getConfig } from './get-config.js';
|
|
|
|
type Action = (args: string[]) => Promise<void>;
|
|
|
|
const up: Action = async (args) => {
|
|
const config = await getConfig('up');
|
|
const { values } = parseArgs({
|
|
args,
|
|
options: {
|
|
help: {
|
|
type: 'boolean',
|
|
short: 'h',
|
|
},
|
|
directory: {
|
|
type: 'string',
|
|
short: 'd',
|
|
},
|
|
reporter: {
|
|
type: 'string',
|
|
short: 'r',
|
|
},
|
|
storage: {
|
|
type: 'string',
|
|
short: 's',
|
|
},
|
|
dry: {
|
|
type: 'boolean',
|
|
},
|
|
plugin: {
|
|
type: 'string',
|
|
short: 'p',
|
|
multiple: true,
|
|
default: [],
|
|
},
|
|
},
|
|
allowPositionals: false,
|
|
});
|
|
|
|
const usage = `Usage: emigrate up [options]
|
|
|
|
Run all pending migrations
|
|
|
|
Options:
|
|
|
|
-h, --help Show this help message and exit
|
|
-d, --directory The directory where the migration files are located (required)
|
|
-s, --storage The storage to use for where to store the migration history (required)
|
|
-p, --plugin The plugin(s) to use (can be specified multiple times)
|
|
-r, --reporter The reporter to use for reporting the migration progress
|
|
--dry List the pending migrations that would be run without actually running them
|
|
|
|
Examples:
|
|
|
|
emigrate up --directory src/migrations -s fs
|
|
emigrate up -d ./migrations --storage @emigrate/storage-mysql
|
|
emigrate up -d src/migrations -s postgres -r json --dry
|
|
`;
|
|
|
|
if (values.help) {
|
|
console.log(usage);
|
|
process.exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
const { directory = config.directory, storage = config.storage, reporter = config.reporter, dry } = values;
|
|
const plugins = [...(config.plugins ?? []), ...(values.plugin ?? [])];
|
|
|
|
try {
|
|
const { default: upCommand } = await import('./commands/up.js');
|
|
await upCommand({ storage, reporter, directory, plugins, dry });
|
|
} catch (error) {
|
|
if (error instanceof ShowUsageError) {
|
|
console.error(error.message, '\n');
|
|
console.log(usage);
|
|
process.exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
const newMigration: Action = async (args) => {
|
|
const config = await getConfig('new');
|
|
const { values, positionals } = parseArgs({
|
|
args,
|
|
options: {
|
|
help: {
|
|
type: 'boolean',
|
|
short: 'h',
|
|
},
|
|
directory: {
|
|
type: 'string',
|
|
short: 'd',
|
|
},
|
|
reporter: {
|
|
type: 'string',
|
|
short: 'r',
|
|
},
|
|
template: {
|
|
type: 'string',
|
|
short: 't',
|
|
},
|
|
extension: {
|
|
type: 'string',
|
|
short: 'e',
|
|
},
|
|
plugin: {
|
|
type: 'string',
|
|
short: 'p',
|
|
multiple: true,
|
|
default: [],
|
|
},
|
|
},
|
|
allowPositionals: true,
|
|
});
|
|
|
|
const usage = `Usage: emigrate new [options] <name>
|
|
|
|
Create a new migration file with the given name in the specified directory
|
|
|
|
Options:
|
|
|
|
-h, --help Show this help message and exit
|
|
-d, --directory The directory where the migration files are located (required)
|
|
-r, --reporter The reporter to use for reporting the migration file creation progress
|
|
-p, --plugin The plugin(s) to use (can be specified multiple times)
|
|
-t, --template A template file to use as contents for the new migration file
|
|
(if the extension option is not provided the template file's extension will be used)
|
|
-e, --extension The extension to use for the new migration file
|
|
(if no template or plugin is provided an empty migration file will be created with the given extension)
|
|
|
|
One of the --template, --extension or the --plugin options must be specified
|
|
|
|
Examples:
|
|
|
|
emigrate new -d src/migrations -t migration-template.js create users table
|
|
emigrate new --directory ./migrations --plugin @emigrate/plugin-generate-sql create_users_table
|
|
emigrate new -d ./migrations -e .sql create_users_table
|
|
emigrate new -d ./migrations -t .migration-template -e .sql "drop some table"
|
|
`;
|
|
|
|
if (values.help) {
|
|
console.log(usage);
|
|
process.exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
const {
|
|
directory = config.directory,
|
|
template = config.template,
|
|
extension = config.extension,
|
|
reporter = config.reporter,
|
|
} = values;
|
|
const plugins = [...(config.plugins ?? []), ...(values.plugin ?? [])];
|
|
const name = positionals.join(' ').trim();
|
|
|
|
try {
|
|
const { default: newCommand } = await import('./commands/new.js');
|
|
await newCommand({ directory, template, plugins, extension, reporter }, name);
|
|
} catch (error) {
|
|
if (error instanceof ShowUsageError) {
|
|
console.error(error.message, '\n');
|
|
console.log(usage);
|
|
process.exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
const list: Action = async (args) => {
|
|
const config = await getConfig('list');
|
|
const { values } = parseArgs({
|
|
args,
|
|
options: {
|
|
help: {
|
|
type: 'boolean',
|
|
short: 'h',
|
|
},
|
|
directory: {
|
|
type: 'string',
|
|
short: 'd',
|
|
},
|
|
reporter: {
|
|
type: 'string',
|
|
short: 'r',
|
|
},
|
|
storage: {
|
|
type: 'string',
|
|
short: 's',
|
|
},
|
|
},
|
|
allowPositionals: false,
|
|
});
|
|
|
|
const usage = `Usage: emigrate list [options]
|
|
|
|
List all migrations and their status. This command does not run any migrations.
|
|
|
|
Options:
|
|
|
|
-h, --help Show this help message and exit
|
|
-d, --directory The directory where the migration files are located (required)
|
|
-r, --reporter The reporter to use for reporting the migrations
|
|
-s, --storage The storage to use to get the migration history (required)
|
|
|
|
Examples:
|
|
|
|
emigrate list -d migrations -s fs
|
|
emigrate list --directory ./migrations --storage postgres --reporter json
|
|
`;
|
|
|
|
if (values.help) {
|
|
console.log(usage);
|
|
process.exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
const { directory = config.directory, storage = config.storage, reporter = config.reporter } = values;
|
|
|
|
try {
|
|
const { default: listCommand } = await import('./commands/list.js');
|
|
await listCommand({ directory, storage, reporter });
|
|
} catch (error) {
|
|
if (error instanceof ShowUsageError) {
|
|
console.error(error.message, '\n');
|
|
console.log(usage);
|
|
process.exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
const commands: Record<string, Action> = {
|
|
up,
|
|
list,
|
|
new: newMigration,
|
|
};
|
|
|
|
const command = process.argv[2]?.toLowerCase();
|
|
const action = command ? commands[command] : undefined;
|
|
|
|
if (!action) {
|
|
if (command) {
|
|
console.error(`Unknown command: ${command}\n`);
|
|
} else {
|
|
console.error('No command specified\n');
|
|
}
|
|
|
|
console.log(`Usage: emigrate <command>
|
|
|
|
Commands:
|
|
|
|
up Run all pending migrations
|
|
new Create a new migration file
|
|
list List all migrations
|
|
`);
|
|
process.exit(1);
|
|
}
|
|
|
|
try {
|
|
await action(process.argv.slice(3));
|
|
} catch (error) {
|
|
if (error instanceof Error) {
|
|
console.error(error.message);
|
|
if (error.cause instanceof Error) {
|
|
console.error(error.cause.stack);
|
|
}
|
|
} else {
|
|
console.error(error);
|
|
}
|
|
}
|