mirror of
https://github.com/strapi/strapi.git
synced 2026-01-05 19:52:15 +00:00
chore: improve logs
This commit is contained in:
parent
c641525963
commit
b686fa9e04
@ -4,7 +4,6 @@ import chalk from 'chalk';
|
||||
import execa from 'execa';
|
||||
import fse from 'fs-extra';
|
||||
|
||||
import { stopProcess } from './utils/stop-process';
|
||||
import { copyTemplate } from './utils/template';
|
||||
import { tryGitInit } from './utils/git';
|
||||
import { trackUsage } from './utils/usage';
|
||||
@ -13,6 +12,7 @@ import { generateDotEnv } from './utils/dot-env';
|
||||
import { isStderrError } from './types';
|
||||
|
||||
import type { Scope } from './types';
|
||||
import { logger } from './utils/logger';
|
||||
|
||||
async function createStrapi(scope: Scope) {
|
||||
const { rootPath } = scope;
|
||||
@ -41,7 +41,7 @@ async function createApp(scope: Scope) {
|
||||
|
||||
await trackUsage({ event: 'willCreateProject', scope });
|
||||
|
||||
console.log(`Creating a new Strapi application at ${chalk.green(rootPath)}.`);
|
||||
logger.title('Strapi', `Creating a new application at ${chalk.green(rootPath)}`);
|
||||
|
||||
if (!isQuickstart) {
|
||||
await trackUsage({ event: 'didChooseCustomDatabase', scope });
|
||||
@ -62,19 +62,21 @@ async function createApp(scope: Scope) {
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
console.log(`Using template: ${chalk.green(template)}`);
|
||||
logger.info(`${chalk.cyan('Installing template')} ${template}`);
|
||||
|
||||
await copyTemplate(scope, rootPath);
|
||||
console.log('Template copied successfully.');
|
||||
|
||||
logger.success('Template copied successfully.');
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
throw new Error(`⛔️ Template installation failed: ${error.message}`);
|
||||
logger.fatal(`Template installation failed: ${error.message}`);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (!fse.existsSync(join(rootPath, 'package.json'))) {
|
||||
throw new Error('Missing package.json in template');
|
||||
logger.fatal(`Missing ${chalk.bold('package.json')} in template`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,13 +101,15 @@ async function createApp(scope: Scope) {
|
||||
|
||||
if (installDependencies) {
|
||||
try {
|
||||
logger.title('deps', `Installing dependencies with ${chalk.cyan(packageManager)}`);
|
||||
|
||||
await trackUsage({ event: 'willInstallProjectDependencies', scope });
|
||||
console.log(`Installing dependencies with ${chalk.bold(packageManager)}\n`);
|
||||
|
||||
await runInstall(scope);
|
||||
|
||||
console.log(`Dependencies installed ${chalk.green('successfully')}.`);
|
||||
await trackUsage({ event: 'didInstallProjectDependencies', scope });
|
||||
|
||||
logger.success(`Dependencies installed`);
|
||||
} catch (error) {
|
||||
const stderr = isStderrError(error) ? error.stderr : '';
|
||||
|
||||
@ -115,20 +119,17 @@ async function createApp(scope: Scope) {
|
||||
error: stderr.slice(-1024),
|
||||
});
|
||||
|
||||
console.log(
|
||||
logger.fatal([
|
||||
chalk.bold(
|
||||
'Oh, it seems that you encountered errors while installing dependencies in your project.'
|
||||
)
|
||||
);
|
||||
console.log(`Don't give up, your project was created correctly.`);
|
||||
console.log(
|
||||
`Fix the issues mentioned in the installation errors and try to run the following command`
|
||||
);
|
||||
console.log();
|
||||
console.log(`cd ${chalk.green(rootPath)} && ${chalk.cyan(packageManager)} install`);
|
||||
console.log();
|
||||
|
||||
stopProcess();
|
||||
'Oh, it seems that you encountered an error while installing dependencies in your project'
|
||||
),
|
||||
'',
|
||||
`Don't give up, your project was created correctly`,
|
||||
'',
|
||||
`Fix the issues mentioned in the installation errors and try to run the following command:`,
|
||||
'',
|
||||
`cd ${chalk.green(rootPath)} && ${chalk.cyan(packageManager)} install`,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,54 +137,48 @@ async function createApp(scope: Scope) {
|
||||
|
||||
// Init git
|
||||
if (gitInit) {
|
||||
console.log('Initializing git repository.');
|
||||
logger.title('git', 'Initializing git repository.');
|
||||
await tryGitInit(rootPath);
|
||||
console.log('Initialized a git repository.');
|
||||
console.log();
|
||||
logger.success('Initialized a git repository.');
|
||||
}
|
||||
|
||||
console.log();
|
||||
console.log(`Your application was created at ${chalk.green(rootPath)}.\n`);
|
||||
logger.title('Strapi', `Your application was created!`);
|
||||
|
||||
const cmd = chalk.cyan(`${packageManager} run`);
|
||||
|
||||
console.log('Available commands in your project:');
|
||||
console.log();
|
||||
console.log(` ${cmd} develop`);
|
||||
console.log(
|
||||
' Start Strapi in watch mode. (Changes in Strapi project files will trigger a server restart)'
|
||||
);
|
||||
console.log();
|
||||
console.log(` ${cmd} start`);
|
||||
console.log(' Start Strapi without watch mode.');
|
||||
console.log();
|
||||
console.log(` ${cmd} build`);
|
||||
console.log(' Build Strapi admin panel.');
|
||||
console.log();
|
||||
console.log(` ${cmd} deploy`);
|
||||
console.log(' Deploy Strapi project.');
|
||||
console.log();
|
||||
console.log(` ${cmd} strapi`);
|
||||
console.log(` Display all available commands.`);
|
||||
console.log();
|
||||
logger.log([
|
||||
'Available commands in your project:',
|
||||
'',
|
||||
'Start Strapi in watch mode. (Changes in Strapi project files will trigger a server restart)',
|
||||
`${cmd} develop`,
|
||||
'',
|
||||
'Start Strapi without watch mode.',
|
||||
`${cmd} start`,
|
||||
'',
|
||||
'Build Strapi admin panel.',
|
||||
`${cmd} build`,
|
||||
'',
|
||||
'Deploy Strapi project.',
|
||||
`${cmd} deploy`,
|
||||
'',
|
||||
'Display all available commands.',
|
||||
`${cmd} strapi\n`,
|
||||
]);
|
||||
|
||||
if (installDependencies) {
|
||||
console.log('You can start by doing:');
|
||||
console.log();
|
||||
console.log(` ${chalk.cyan('cd')} ${rootPath}`);
|
||||
console.log(` ${cmd} develop`);
|
||||
console.log();
|
||||
logger.log(['To get start run', '', `${chalk.cyan('cd')} ${rootPath}`, `${cmd} develop`]);
|
||||
} else {
|
||||
console.log('You can start by doing:');
|
||||
console.log();
|
||||
console.log(` ${chalk.cyan('cd')} ${rootPath}`);
|
||||
console.log(` ${chalk.cyan(packageManager)} install`);
|
||||
console.log(` ${cmd} develop`);
|
||||
console.log();
|
||||
logger.log([
|
||||
'To get start run',
|
||||
'',
|
||||
`${chalk.cyan('cd')} ${rootPath}`,
|
||||
`${chalk.cyan(packageManager)} install`,
|
||||
`${cmd} develop`,
|
||||
]);
|
||||
}
|
||||
|
||||
if (runApp && installDependencies) {
|
||||
console.log(`Running your Strapi application.`);
|
||||
logger.title('Starting', 'Running your Strapi application');
|
||||
|
||||
try {
|
||||
await trackUsage({ event: 'willStartServer', scope });
|
||||
@ -204,7 +199,7 @@ async function createApp(scope: Scope) {
|
||||
});
|
||||
}
|
||||
|
||||
stopProcess();
|
||||
logger.fatal('Failed to start your Strapi application');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -231,7 +226,9 @@ function runInstall({ rootPath, packageManager }: Scope) {
|
||||
installArguments.push(...(installArgumentsMap[packageManager] ?? []));
|
||||
}
|
||||
|
||||
return execa(packageManager, installArguments, options);
|
||||
const proc = execa(packageManager, installArguments, options);
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
export { createStrapi };
|
||||
|
||||
@ -15,7 +15,7 @@ import { trackError } from './utils/usage';
|
||||
import { addDatabaseDependencies, getDatabaseInfos } from './utils/database';
|
||||
|
||||
import type { Options, Scope } from './types';
|
||||
import { stopProcess } from './utils/stop-process';
|
||||
import { logger } from './utils/logger';
|
||||
|
||||
const command = new commander.Command('create-strapi-app')
|
||||
.version(version)
|
||||
@ -69,18 +69,49 @@ async function run(args: string[]): Promise<void> {
|
||||
const options = command.parse(args).opts<Options>();
|
||||
const directory = command.args[0];
|
||||
|
||||
console.log(
|
||||
`\n${chalk.bgBlueBright(` ${chalk.black('Strapi')} `)} ${chalk.green(
|
||||
chalk.bold(`v${version}`)
|
||||
)} ${chalk.bold("🚀 Let's create your new project")}`
|
||||
logger.title(
|
||||
'Strapi',
|
||||
`${chalk.green(chalk.bold(`v${version}`))} ${chalk.bold("🚀 Let's create your new project")}\n`
|
||||
);
|
||||
|
||||
checkNodeRequirements();
|
||||
if (
|
||||
(options.javascript !== undefined || options.typescript !== undefined) &&
|
||||
options.template !== undefined
|
||||
) {
|
||||
logger.fatal(
|
||||
`You cannot use ${chalk.bold('--javascript')} or ${chalk.bold('--typescript')} with ${chalk.bold('--template')}`
|
||||
);
|
||||
}
|
||||
|
||||
if (options.javascript === true && options.typescript === true) {
|
||||
logger.fatal(
|
||||
`You cannot use both ${chalk.bold('--typescript')} (--ts) and ${chalk.bold('--javascript')} (--js) flags together`
|
||||
);
|
||||
}
|
||||
|
||||
// Only prompt the example app option if there is no template option
|
||||
if (options.example === true && options.template !== undefined) {
|
||||
logger.fatal(`You cannot use ${chalk.bold('--example')} with ${chalk.bold('--template')}`);
|
||||
}
|
||||
|
||||
if (options.template !== undefined && options.template.startsWith('-')) {
|
||||
logger.fatal(`Template name ${chalk.bold(`"${options.template}"`)} is invalid`);
|
||||
}
|
||||
|
||||
if ([options.useNpm, options.usePnpm, options.useYarn].filter(Boolean).length > 1) {
|
||||
logger.fatal(
|
||||
`You cannot specify multiple package managers at the same time ${chalk.bold('(--use-npm, --use-pnpm, --use-yarn)')}`
|
||||
);
|
||||
}
|
||||
|
||||
if (options.quickstart && !directory) {
|
||||
stopProcess('Please specify the <directory> of your project when using --quickstart');
|
||||
logger.fatal(
|
||||
`Please specify the ${chalk.bold('<directory>')} of your project when using ${chalk.bold('--quickstart')}`
|
||||
);
|
||||
}
|
||||
|
||||
checkNodeRequirements();
|
||||
|
||||
const appDirectory = directory || (await prompts.directory());
|
||||
|
||||
const rootPath = await checkInstallPath(appDirectory);
|
||||
@ -123,27 +154,6 @@ async function run(args: string[]): Promise<void> {
|
||||
},
|
||||
};
|
||||
|
||||
if ((options.javascript !== undefined || options.typescript) && options.template !== undefined) {
|
||||
stopProcess('You cannot use --javascript or --typescript with --template');
|
||||
}
|
||||
|
||||
if (options.javascript === true && options.typescript === true) {
|
||||
stopProcess('You cannot use both --typescript (--ts) and --javascript (--js) flags together');
|
||||
}
|
||||
|
||||
// Only prompt the example app option if there is no template option
|
||||
if (options.example === true && options.template !== undefined) {
|
||||
stopProcess('You cannot use --example with --template');
|
||||
}
|
||||
|
||||
// Only prompt the example app option if there is no template option
|
||||
if (
|
||||
(options.javascript === true || options.typescript === true) &&
|
||||
options.template !== undefined
|
||||
) {
|
||||
stopProcess('You cannot use --javascript or --typescript with --template');
|
||||
}
|
||||
|
||||
if (options.template !== undefined) {
|
||||
scope.useExampleApp = false;
|
||||
} else if (options.example === true || options.quickstart) {
|
||||
@ -199,17 +209,11 @@ async function run(args: string[]): Promise<void> {
|
||||
|
||||
await trackError({ scope, error });
|
||||
|
||||
stopProcess(`Error: ${error.message}`);
|
||||
logger.fatal(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function getPkgManager(options: Options) {
|
||||
if ([options.useNpm, options.usePnpm, options.useYarn].filter(Boolean).length > 1) {
|
||||
stopProcess(
|
||||
'You cannot specify multiple package managers at the same time (--use-npm, --use-pnpm, --use-yarn)'
|
||||
);
|
||||
}
|
||||
|
||||
if (options.useNpm === true) {
|
||||
return 'npm';
|
||||
}
|
||||
|
||||
@ -1,23 +1,18 @@
|
||||
import { resolve } from 'node:path';
|
||||
import chalk from 'chalk';
|
||||
import fse from 'fs-extra';
|
||||
|
||||
import { stopProcess } from './stop-process';
|
||||
import { logger } from './logger';
|
||||
|
||||
// Checks if the an empty directory exists at rootPath
|
||||
export async function checkInstallPath(directory: string): Promise<string> {
|
||||
if (!directory) {
|
||||
stopProcess(`⛔️ Please provide a project name.`);
|
||||
}
|
||||
|
||||
const rootPath = resolve(directory);
|
||||
|
||||
if (await fse.pathExists(rootPath)) {
|
||||
const stat = await fse.stat(rootPath);
|
||||
|
||||
if (!stat.isDirectory()) {
|
||||
stopProcess(
|
||||
`⛔️ ${chalk.green(
|
||||
logger.fatal(
|
||||
`${chalk.green(
|
||||
rootPath
|
||||
)} is not a directory. Make sure to create a Strapi application in an empty directory.`
|
||||
);
|
||||
@ -25,11 +20,10 @@ export async function checkInstallPath(directory: string): Promise<string> {
|
||||
|
||||
const files = await fse.readdir(rootPath);
|
||||
if (files.length > 1) {
|
||||
stopProcess(
|
||||
`⛔️ You can only create a Strapi app in an empty directory.\nMake sure ${chalk.green(
|
||||
rootPath
|
||||
)} is empty.`
|
||||
);
|
||||
logger.fatal([
|
||||
'You can only create a Strapi app in an empty directory',
|
||||
`Make sure ${chalk.green(rootPath)} is empty.`,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,26 +2,25 @@ import chalk from 'chalk';
|
||||
import semver from 'semver';
|
||||
|
||||
import { engines } from './engines';
|
||||
import { stopProcess } from './stop-process';
|
||||
import { logger } from './logger';
|
||||
|
||||
export function checkNodeRequirements() {
|
||||
const currentNodeVersion = process.versions.node;
|
||||
|
||||
// error if the node version isn't supported
|
||||
if (!semver.satisfies(currentNodeVersion, engines.node)) {
|
||||
console.error(chalk.red(`You are running ${chalk.bold(`Node.js ${currentNodeVersion}`)}`));
|
||||
console.error(`Strapi requires ${chalk.bold(chalk.green(`Node.js ${engines.node}`))}`);
|
||||
console.error('Please make sure to use the right version of Node.');
|
||||
stopProcess();
|
||||
logger.fatal([
|
||||
chalk.red(`You are running ${chalk.bold(`Node.js ${currentNodeVersion}`)}`),
|
||||
`Strapi requires ${chalk.bold(chalk.green(`Node.js ${engines.node}`))}`,
|
||||
'Please make sure to use the right version of Node.',
|
||||
]);
|
||||
}
|
||||
|
||||
// warn if not using a LTS version
|
||||
else if (semver.major(currentNodeVersion) % 2 !== 0) {
|
||||
console.warn(chalk.yellow(`You are running ${chalk.bold(`Node.js ${currentNodeVersion}`)}`));
|
||||
console.warn(
|
||||
`Strapi only supports ${chalk.bold(
|
||||
chalk.green('LTS versions of Node.js')
|
||||
)}, other versions may not be compatible.`
|
||||
);
|
||||
logger.warn([
|
||||
chalk.yellow(`You are running ${chalk.bold(`Node.js ${currentNodeVersion}`)}`),
|
||||
`Strapi only supports ${chalk.bold(chalk.green('LTS versions of Node.js'))}, other versions may not be compatible.`,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import inquirer from 'inquirer';
|
||||
import type { Question } from 'inquirer';
|
||||
|
||||
import type { Scope, Options, DBClient, DBConfig } from '../types';
|
||||
import { stopProcess } from './stop-process';
|
||||
import { logger } from './logger';
|
||||
|
||||
const DBOptions = ['dbclient', 'dbhost', 'dbport', 'dbname', 'dbusername', 'dbpassword'];
|
||||
|
||||
@ -55,7 +55,7 @@ export async function getDatabaseInfos(options: Options): Promise<DBConfig> {
|
||||
}
|
||||
|
||||
if (options.dbclient && !VALID_CLIENTS.includes(options.dbclient)) {
|
||||
stopProcess(
|
||||
logger.fatal(
|
||||
`Invalid --dbclient: ${options.dbclient}, expected one of ${VALID_CLIENTS.join(', ')}`
|
||||
);
|
||||
}
|
||||
@ -68,7 +68,7 @@ export async function getDatabaseInfos(options: Options): Promise<DBConfig> {
|
||||
matchingArgs.length !== DBOptions.length &&
|
||||
options.dbclient !== 'sqlite'
|
||||
) {
|
||||
stopProcess(`Required database arguments are missing: ${missingArgs.join(', ')}.`);
|
||||
logger.fatal(`Required database arguments are missing: ${missingArgs.join(', ')}.`);
|
||||
}
|
||||
|
||||
const hasDBOptions = DBOptions.some((key) => key in options);
|
||||
@ -82,7 +82,7 @@ export async function getDatabaseInfos(options: Options): Promise<DBConfig> {
|
||||
}
|
||||
|
||||
if (!options.dbclient) {
|
||||
stopProcess('Please specify the database client');
|
||||
return logger.fatal('Please specify the database client');
|
||||
}
|
||||
|
||||
const database: DBConfig = {
|
||||
|
||||
61
packages/cli/create-strapi-app/src/utils/logger.ts
Normal file
61
packages/cli/create-strapi-app/src/utils/logger.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import chalk from 'chalk';
|
||||
import type { ChalkFunction } from 'chalk';
|
||||
|
||||
const MAX_PREFIX_LENGTH = 8;
|
||||
|
||||
const badge = (text: string, bgColor: ChalkFunction, textColor: ChalkFunction = chalk.black) => {
|
||||
const wrappedText = ` ${text} `;
|
||||
|
||||
return ' '.repeat(MAX_PREFIX_LENGTH - wrappedText.length) + bgColor(textColor(wrappedText));
|
||||
};
|
||||
|
||||
const textIndent = (
|
||||
text: string | string[],
|
||||
indentFirst = true,
|
||||
indent: number = MAX_PREFIX_LENGTH + 2
|
||||
) => {
|
||||
const parts = Array.isArray(text) ? text : [text];
|
||||
|
||||
return parts
|
||||
.map((part, i) => {
|
||||
if (i === 0 && !indentFirst) {
|
||||
return part;
|
||||
}
|
||||
|
||||
return ' '.repeat(indent) + part;
|
||||
})
|
||||
.join('\n');
|
||||
};
|
||||
|
||||
export const logger = {
|
||||
log(message: string | string[]): void {
|
||||
console.log(textIndent(message));
|
||||
},
|
||||
title(title: string, message: string): void {
|
||||
const prefix = badge(title, chalk.bgBlueBright);
|
||||
console.log(`\n${prefix} ${message}`);
|
||||
},
|
||||
info(message: string): void {
|
||||
console.log(`${' '.repeat(7)}${chalk.cyan('●')} ${message}`);
|
||||
},
|
||||
success(message: string): void {
|
||||
console.log(`\n${' '.repeat(7)}${chalk.green('✓')} ${chalk.green(message)}`);
|
||||
},
|
||||
fatal(message?: string | string[]): never {
|
||||
const prefix = badge('Error', chalk.bgRed);
|
||||
|
||||
if (message) {
|
||||
console.error(`\n${prefix} ${textIndent(message, false)}\n`);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
},
|
||||
error(message: string | string[]): void {
|
||||
const prefix = badge('Error', chalk.bgRed);
|
||||
console.error(`\n${prefix} ${textIndent(message, false)}\n`);
|
||||
},
|
||||
warn(message: string | string[]): void {
|
||||
const prefix = badge('Warn', chalk.bgYellow);
|
||||
console.warn(`\n${prefix} ${textIndent(message, false)}\n`);
|
||||
},
|
||||
};
|
||||
@ -1,7 +0,0 @@
|
||||
export function stopProcess(message?: string): never {
|
||||
if (message) {
|
||||
console.error(message);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user