feat: update commands' types, add a hidden "to" command with a codemod target option

This commit is contained in:
Convly 2024-01-12 15:14:28 +01:00
parent 803724d019
commit 71336319dd
5 changed files with 91 additions and 28 deletions

View File

@ -1,12 +1,13 @@
import prompts from 'prompts'; import prompts from 'prompts';
import { loggerFactory } from '../../modules/logger'; import { loggerFactory } from '../../modules/logger';
import { Version } from '../../modules/version';
import { handleError } from '../errors'; import { handleError } from '../errors';
import * as tasks from '../../tasks'; import * as tasks from '../../tasks';
import type { Command } from '../types'; import type { CodemodsCommand } from '../types';
import type { Codemod } from '../../modules/codemod'; import type { Codemod } from '../../modules/codemod';
export const codemods: Command = async (options) => { export const codemods: CodemodsCommand = async (options) => {
try { try {
const { silent, debug } = options; const { silent, debug } = options;
const logger = loggerFactory({ silent, debug }); const logger = loggerFactory({ silent, debug });
@ -66,9 +67,9 @@ export const codemods: Command = async (options) => {
selectCodemods, selectCodemods,
dry: options.dry, dry: options.dry,
cwd: options.projectPath, cwd: options.projectPath,
target: options.target, target: Version.ReleaseType.Major,
}); });
} catch (err) { } catch (err) {
handleError(err); handleError(err, options.silent);
} }
}; };

View File

@ -4,9 +4,9 @@ import { loggerFactory } from '../../modules/logger';
import { handleError } from '../errors'; import { handleError } from '../errors';
import * as tasks from '../../tasks'; import * as tasks from '../../tasks';
import type { Command } from '../types'; import type { UpgradeCommand } from '../types';
export const upgrade: Command = async (options) => { export const upgrade: UpgradeCommand = async (options) => {
try { try {
const { silent, debug, yes } = options; const { silent, debug, yes } = options;
const logger = loggerFactory({ silent, debug }); const logger = loggerFactory({ silent, debug });
@ -36,8 +36,9 @@ export const upgrade: Command = async (options) => {
dry: options.dry, dry: options.dry,
cwd: options.projectPath, cwd: options.projectPath,
target: options.target, target: options.target,
codemodsTarget: options.codemodsTarget,
}); });
} catch (err) { } catch (err) {
handleError(err); handleError(err, options.silent);
} }
}; };

View File

@ -1,9 +1,12 @@
import chalk from 'chalk'; import chalk from 'chalk';
export const handleError = (err: unknown) => { export const handleError = (err: unknown, isSilent: boolean) => {
console.error( if (!isSilent) {
chalk.red(`[ERROR]\t[${new Date().toISOString()}]`), console.error(
err instanceof Error ? err.message : err chalk.red(`[ERROR]\t[${new Date().toISOString()}]`),
); err instanceof Error ? err.message : err
);
}
process.exit(1); process.exit(1);
}; };

View File

@ -1,11 +1,11 @@
import os from 'os'; import os from 'os';
import chalk from 'chalk'; import chalk from 'chalk';
import { Option, program } from 'commander'; import { InvalidArgumentError, Option, program } from 'commander';
import { version as packageJSONVersion } from '../../package.json'; import { version as packageJSONVersion } from '../../package.json';
import { Version } from '../modules/version'; import { isLiteralSemVer, isValidSemVer, semVerFactory, Version } from '../modules/version';
import type { CLIOptions } from './types'; import type { CLICodemodsOptions, CLIUpgradeOptions, CLIUpgradeToOptions } from './types';
const projectPathOption = new Option( const projectPathOption = new Option(
'-p, --project-path <project-path>', '-p, --project-path <project-path>',
@ -35,7 +35,7 @@ const addReleaseUpgradeCommand = (releaseType: Version.ReleaseType, description:
.addOption(debugOption) .addOption(debugOption)
.addOption(silentOption) .addOption(silentOption)
.addOption(automaticConfirmationOption) .addOption(automaticConfirmationOption)
.action(async (options: CLIOptions) => { .action(async (options: CLIUpgradeOptions) => {
const { upgrade } = await import('./commands/upgrade.js'); const { upgrade } = await import('./commands/upgrade.js');
return upgrade({ ...options, target: releaseType }); return upgrade({ ...options, target: releaseType });
@ -66,9 +66,45 @@ program
.addOption(dryOption) .addOption(dryOption)
.addOption(debugOption) .addOption(debugOption)
.addOption(silentOption) .addOption(silentOption)
.action(async (options) => { .action(async (options: CLICodemodsOptions) => {
const { codemods } = await import('./commands/codemods.js'); const { codemods } = await import('./commands/codemods.js');
return codemods({ ...options, target: Version.ReleaseType.Major }); return codemods(options);
});
// Defines the 'to' command to upgrade to a specific Strapi version,
// with various options including custom codemod target.
// This command is meant for internal use for now (and is thus hidden)
program
.command('to <target>', { hidden: true })
.description('Upgrade to the specified version of Strapi')
.addOption(projectPathOption)
.addOption(dryOption)
.addOption(debugOption)
.addOption(silentOption)
.addOption(automaticConfirmationOption)
.addOption(
new Option(
'-c, --codemods-target <codemodsTarget>',
'Use a custom target for the codemods execution. Useful when targeting pre-releases'
).argParser((codemodsTarget) => {
if (!isLiteralSemVer(codemodsTarget)) {
throw new InvalidArgumentError(
`Expected a version with the following format: "<number>.<number>.<number>"`
);
}
return semVerFactory(codemodsTarget);
})
)
.action(async (target: string, options: CLIUpgradeToOptions) => {
if (!isValidSemVer(target)) {
console.error(`Invalid target supplied, expected a valid semver but got "${target}"`);
process.exit(1);
}
const { upgrade } = await import('./commands/upgrade.js');
return upgrade({ ...options, target: semVerFactory(target) });
}); });
program program

View File

@ -1,16 +1,38 @@
import type { Version } from '../modules/version'; import type { Version } from '../modules/version';
import type { MaybePromise } from '../types'; import type { MaybePromise } from '../types';
export interface CLIOptions { // CLI
dry: boolean;
debug: boolean; type DryOption = { dry: boolean };
silent: boolean; type DebugOption = { debug: boolean };
yes?: boolean; type SilentOption = { silent: boolean };
projectPath?: string; type YesOption = { yes?: boolean };
type ProjectPathOption = { projectPath?: string };
export type CLIUpgradeOptions = DryOption &
DebugOption &
SilentOption &
YesOption &
ProjectPathOption;
export type CLIUpgradeToOptions = CLIUpgradeOptions & {
codemodsTarget?: Version.SemVer;
};
export type CLICodemodsOptions = DryOption & DebugOption & SilentOption & ProjectPathOption;
// COMMANDS OPTIONS
export interface UpgradeCommandOptions extends CLIUpgradeOptions {
target: Version.ReleaseType | Version.SemVer;
codemodsTarget?: Version.SemVer;
} }
export interface CommandOptions extends CLIOptions { export interface CodemodsCommandOptions extends CLICodemodsOptions {}
target: Version.ReleaseType;
}
export type Command = (options: CommandOptions) => MaybePromise<void>; // COMMANDS
export type Command<TOptions extends object> = (options: TOptions) => MaybePromise<void>;
export type UpgradeCommand = Command<UpgradeCommandOptions>;
export type CodemodsCommand = Command<CodemodsCommandOptions>;