Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/commands/migrate.meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ export const meta = {
name: 'migrate',
description: 'Migrate from a package to a more performant alternative.',
args: {
all: {
type: 'boolean',
default: false,
description:
'Migrate all fixable replacements that exist in project dependencies.'
},
'dry-run': {
type: 'boolean',
default: false,
Expand Down
60 changes: 41 additions & 19 deletions src/commands/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {getPackageJson} from '../utils/package-json.js';

export async function run(ctx: CommandContext<typeof meta>) {
const [_commandName, ...targetModules] = ctx.positionals;
const all = ctx.values.all === true;
const dryRun = ctx.values['dry-run'] === true;
const interactive = ctx.values.interactive === true;
const include = ctx.values.include;
Expand All @@ -37,7 +38,7 @@ export async function run(ctx: CommandContext<typeof meta>) {
.map((rep) => rep.from)
);

if (interactive) {
if (interactive && !all) {
const additionalTargets = await prompts.autocompleteMultiselect({
message: 'Select packages to migrate',
maxItems: 10,
Expand All @@ -60,34 +61,50 @@ export async function run(ctx: CommandContext<typeof meta>) {
}
}

if (targetModules.length === 0) {
prompts.cancel(
'Error: Please specify a package to migrate. For example, `migrate chalk`'
);
return;
}
let selectedReplacements: Replacement[];

const selectedReplacements: Replacement[] = [];

for (const targetModule of targetModules) {
const replacement = fixableReplacements.find(
(rep) => rep.from === targetModule
if (all) {
selectedReplacements = fixableReplacements.filter((rep) =>
fixableReplacementsTargets.has(rep.from)
);
if (!replacement) {
} else {
if (targetModules.length === 0) {
prompts.cancel(
`Error: Target package has no available migrations (${targetModule})`
'Error: Please specify a package to migrate. For example, `migrate chalk`'
);
return;
}

selectedReplacements.push(replacement);
selectedReplacements = [];

for (const targetModule of targetModules) {
if (!fixableReplacementsTargets.has(targetModule)) {
prompts.cancel(
`Error: Target package is not in project dependencies (${targetModule})`
);
return;
}

const replacement = fixableReplacements.find(
(rep) => rep.from === targetModule
);
if (!replacement) {
prompts.cancel(
`Error: Target package has no available migrations (${targetModule})`
);
return;
}

selectedReplacements.push(replacement);
}
}

if (!interactive) {
const targetNames = selectedReplacements.map((r) => r.from);
const targetModuleSummary =
targetModules.length > 6
? `${targetModules.slice(0, 6).join(', ')} and ${targetModules.length - 6} more`
: targetModules.join(', ');
targetNames.length > 6
? `${targetNames.slice(0, 6).join(', ')} and ${targetNames.length - 6} more`
: targetNames.join(', ');
prompts.log.message(`Targets: ${styleText('dim', targetModuleSummary)}`);
}

Expand All @@ -106,6 +123,8 @@ export async function run(ctx: CommandContext<typeof meta>) {
return;
}

let filesMigratedCount = 0;

for (const filename of files) {
const log = prompts.taskLog({
title: `${filename}...`,
Expand Down Expand Up @@ -140,10 +159,13 @@ export async function run(ctx: CommandContext<typeof meta>) {
}
totalMigrations++;
}
if (totalMigrations > 0) {
filesMigratedCount++;
}
log.success(
`${filename} ${styleText('dim', `(${totalMigrations} migrated)`)}`
);
}

prompts.outro('Migration complete.');
prompts.outro(`Migration complete - ${filesMigratedCount} files migrated.`);
}
30 changes: 30 additions & 0 deletions src/test/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,33 @@ describe('CLI', () => {
expect(normalizeStderr(stderr)).toMatchSnapshot();
});
});

const basicChalkFixture = path.join(
__dirname,
'../../test/fixtures/basic-chalk'
);

describe('migrate --all', () => {
it('should migrate all fixable replacements with --all --dry-run when project has fixable deps', async () => {
const {stdout, stderr, code} = await runCliProcess(
['migrate', '--all', '--dry-run'],
basicChalkFixture
);
expect(code).toBe(0);
const output = stdout + stderr;
expect(output).toContain('Migration complete');
expect(output).toContain('files migrated');
expect(output).toContain('chalk');
});

it('should run to completion and show Migration complete when --all has no fixable replacements', async () => {
const {stdout, stderr, code} = await runCliProcess(
['migrate', '--all'],
tempDir
);
const output = stdout + stderr;
expect(code).toBe(0);
expect(output).toContain('Migration complete');
expect(output).toContain('0 files migrated');
});
});
Loading