feat(cli): implement the "list" command for listing migration history and pending migrations

This commit is contained in:
Joakim Carlstein 2023-11-22 14:19:10 +01:00
parent e79dd4bca9
commit 53cdb23237
8 changed files with 199 additions and 38 deletions

View file

@ -0,0 +1,82 @@
import process from 'node:process';
import path from 'node:path';
import { getOrLoadReporter, getOrLoadStorage } from '@emigrate/plugin-tools';
import { type MigrationMetadataFinished } from '@emigrate/plugin-tools/types';
import { BadOptionError, MigrationHistoryError, MissingOptionError } from '../errors.js';
import { type Config } from '../types.js';
import { withLeadingPeriod } from '../with-leading-period.js';
import { getMigrations } from '../get-migrations.js';
const lazyDefaultReporter = async () => import('../reporters/default.js');
export default async function listCommand({ directory, reporter: reporterConfig, storage: storageConfig }: Config) {
if (!directory) {
throw new MissingOptionError('directory');
}
const cwd = process.cwd();
const storagePlugin = await getOrLoadStorage([storageConfig]);
if (!storagePlugin) {
throw new BadOptionError('storage', 'No storage found, please specify a storage using the storage option');
}
const storage = await storagePlugin.initializeStorage();
const reporter = await getOrLoadReporter([reporterConfig ?? lazyDefaultReporter]);
if (!reporter) {
throw new BadOptionError(
'reporter',
'No reporter found, please specify an existing reporter using the reporter option',
);
}
await reporter.onInit?.({ command: 'list', cwd, dry: false, directory });
const migrationFiles = await getMigrations(cwd, directory);
let migrationHistoryError: MigrationHistoryError | undefined;
const finishedMigrations: MigrationMetadataFinished[] = [];
for await (const migrationHistoryEntry of storage.getHistory()) {
const filePath = path.resolve(cwd, directory, migrationHistoryEntry.name);
const finishedMigration: MigrationMetadataFinished = {
name: migrationHistoryEntry.name,
status: migrationHistoryEntry.status,
filePath,
relativeFilePath: path.relative(cwd, filePath),
extension: withLeadingPeriod(path.extname(migrationHistoryEntry.name)),
directory,
cwd,
duration: 0,
};
if (migrationHistoryEntry.status === 'failed') {
migrationHistoryError = new MigrationHistoryError(
`Migration ${migrationHistoryEntry.name} is in a failed state`,
migrationHistoryEntry,
);
await reporter.onMigrationError?.(finishedMigration, migrationHistoryError);
} else {
await reporter.onMigrationSuccess?.(finishedMigration);
}
finishedMigrations.push(finishedMigration);
const index = migrationFiles.findIndex((migrationFile) => migrationFile.name === migrationHistoryEntry.name);
if (index !== -1) {
migrationFiles.splice(index, 1);
}
}
for await (const migration of migrationFiles) {
const finishedMigration: MigrationMetadataFinished = { ...migration, status: 'pending', duration: 0 };
await reporter.onMigrationSkip?.(finishedMigration);
finishedMigrations.push(finishedMigration);
}
await reporter.onFinished?.(finishedMigrations, migrationHistoryError);
}

View file

@ -17,6 +17,7 @@ import {
import { type Config } from '../types.js';
import { withLeadingPeriod } from '../with-leading-period.js';
import pluginLoaderJs from '../plugin-loader-js.js';
import { getMigrations } from '../get-migrations.js';
type ExtraFlags = {
dry?: boolean;
@ -59,28 +60,7 @@ export default async function upCommand({
await reporter.onInit?.({ command: 'up', cwd, dry, directory });
const path = await import('node:path');
const fs = await import('node:fs/promises');
const allFilesInMigrationDirectory = await fs.readdir(path.resolve(process.cwd(), directory), {
withFileTypes: true,
});
const migrationFiles: MigrationMetadata[] = allFilesInMigrationDirectory
.filter((file) => file.isFile() && !file.name.startsWith('.') && !file.name.startsWith('_'))
.sort((a, b) => a.name.localeCompare(b.name))
.map(({ name }) => {
const filePath = path.resolve(process.cwd(), directory, name);
return {
name,
filePath,
relativeFilePath: path.relative(cwd, filePath),
extension: withLeadingPeriod(path.extname(name)),
directory,
cwd,
};
});
const migrationFiles = await getMigrations(cwd, directory);
let migrationHistoryError: MigrationHistoryError | undefined;