From 678131672bf956d50944edea70f02a694a9309f5 Mon Sep 17 00:00:00 2001 From: Gabriel Miranda Date: Mon, 2 Dec 2024 12:16:05 -0300 Subject: [PATCH] feat(react-email): Improved error feedback on all CLI commands (#1784) --- .changeset/smooth-zebras-learn.md | 5 ++++ .../src/actions/render-email-by-path.tsx | 4 +-- .../react-email/src/cli/commands/build.ts | 8 +++--- packages/react-email/src/cli/commands/dev.ts | 3 +- .../react-email/src/cli/commands/export.ts | 18 ++++-------- .../react-email/src/cli/commands/start.ts | 5 ++-- .../src/cli/utils/preview/start-dev-server.ts | 4 +-- .../src/utils/close-ora-on-sigint.ts | 15 ---------- .../utils/register-spinner-autostopping.ts | 28 +++++++++++++++++++ 9 files changed, 52 insertions(+), 38 deletions(-) create mode 100644 .changeset/smooth-zebras-learn.md delete mode 100644 packages/react-email/src/utils/close-ora-on-sigint.ts create mode 100644 packages/react-email/src/utils/register-spinner-autostopping.ts diff --git a/.changeset/smooth-zebras-learn.md b/.changeset/smooth-zebras-learn.md new file mode 100644 index 0000000000..65518c0345 --- /dev/null +++ b/.changeset/smooth-zebras-learn.md @@ -0,0 +1,5 @@ +--- +"react-email": patch +--- + +Improve error messages for all CLI commands diff --git a/packages/react-email/src/actions/render-email-by-path.tsx b/packages/react-email/src/actions/render-email-by-path.tsx index 11fa54da33..ae9d2c319f 100644 --- a/packages/react-email/src/actions/render-email-by-path.tsx +++ b/packages/react-email/src/actions/render-email-by-path.tsx @@ -7,7 +7,7 @@ import chalk from 'chalk'; import { getEmailComponent } from '../utils/get-email-component'; import type { ErrorObject } from '../utils/types/error-object'; import { improveErrorWithSourceMap } from '../utils/improve-error-with-sourcemap'; -import { closeOraOnSIGNIT } from '../utils/close-ora-on-sigint'; +import { registerSpinnerAutostopping } from '../utils/register-spinner-autostopping'; export interface RenderedEmailMetadata { markup: string; @@ -33,7 +33,7 @@ export const renderEmailByPath = async ( text: `Rendering email template ${emailFilename}\n`, prefixText: ' ', }).start(); - closeOraOnSIGNIT(spinner); + registerSpinnerAutostopping(spinner); } const result = await getEmailComponent(emailPath); diff --git a/packages/react-email/src/cli/commands/build.ts b/packages/react-email/src/cli/commands/build.ts index 1cac3909b6..38b1e8c7eb 100644 --- a/packages/react-email/src/cli/commands/build.ts +++ b/packages/react-email/src/cli/commands/build.ts @@ -7,7 +7,7 @@ import { getEmailsDirectoryMetadata, } from '../../actions/get-emails-directory-metadata'; import { cliPacakgeLocation } from '../utils'; -import { closeOraOnSIGNIT } from '../../utils/close-ora-on-sigint'; +import { registerSpinnerAutostopping } from '../../utils/register-spinner-autostopping'; import logSymbols from 'log-symbols'; interface Args { @@ -224,11 +224,11 @@ export const build = async ({ text: 'Starting build process...', prefixText: ' ', }).start(); - closeOraOnSIGNIT(spinner); + registerSpinnerAutostopping(spinner); - spinner.text = 'Checking if emails folder exists'; + spinner.text = `Checking if ${emailsDirRelativePath} folder exists`; if (!fs.existsSync(emailsDirRelativePath)) { - throw new Error(`Missing ${emailsDirRelativePath} folder`); + process.exit(1); } const emailsDirPath = path.join(process.cwd(), emailsDirRelativePath); diff --git a/packages/react-email/src/cli/commands/dev.ts b/packages/react-email/src/cli/commands/dev.ts index 58952b613e..a9fc55b369 100644 --- a/packages/react-email/src/cli/commands/dev.ts +++ b/packages/react-email/src/cli/commands/dev.ts @@ -9,7 +9,8 @@ interface Args { export const dev = async ({ dir: emailsDirRelativePath, port }: Args) => { try { if (!fs.existsSync(emailsDirRelativePath)) { - throw new Error(`Missing ${emailsDirRelativePath} folder`); + console.error(`Missing ${emailsDirRelativePath} folder`); + process.exit(1); } const devServer = await startDevServer( diff --git a/packages/react-email/src/cli/commands/export.ts b/packages/react-email/src/cli/commands/export.ts index 35427c2ed6..9513f14175 100644 --- a/packages/react-email/src/cli/commands/export.ts +++ b/packages/react-email/src/cli/commands/export.ts @@ -7,7 +7,7 @@ import ora from 'ora'; import logSymbols from 'log-symbols'; import type { Options } from '@react-email/render'; import normalize from 'normalize-path'; -import { closeOraOnSIGNIT } from '../../utils/close-ora-on-sigint'; +import { registerSpinnerAutostopping } from '../../utils/register-spinner-autostopping'; import { tree } from '../utils'; import { EmailsDirectory, @@ -49,7 +49,7 @@ export const exportTemplates = async ( let spinner: ora.Ora | undefined; if (!options.silent) { spinner = ora('Preparing files...\n').start(); - closeOraOnSIGNIT(spinner); + registerSpinnerAutostopping(spinner); } const emailsDirectoryMetadata = await getEmailsDirectoryMetadata( @@ -90,14 +90,7 @@ export const exportTemplates = async ( text: 'Failed to build emails', }); } - - console.warn(buildFailure.warnings); - console.error(buildFailure.errors); - throw new Error( - `esbuild bundling process for email templates failed:\n${allTemplates - .map((p) => `- ${p}`) - .join('\n')}`, - ); + process.exit(1); } if (spinner) { @@ -144,7 +137,7 @@ export const exportTemplates = async ( }); } console.error(exception); - throw exception; + process.exit(1); } } if (spinner) { @@ -178,9 +171,10 @@ export const exportTemplates = async ( text: 'Failed to copy static files', }); } - throw new Error( + console.error( `Something went wrong while copying the file to ${pathToWhereEmailMarkupShouldBeDumped}/static, ${exception}`, ); + process.exit(1); } } diff --git a/packages/react-email/src/cli/commands/start.ts b/packages/react-email/src/cli/commands/start.ts index 4b5955fcda..cf16e8f7ce 100644 --- a/packages/react-email/src/cli/commands/start.ts +++ b/packages/react-email/src/cli/commands/start.ts @@ -10,9 +10,10 @@ export const start = async () => { './.react-email', ); if (!fs.existsSync(builtPreviewPath)) { - throw new Error( - "Could not find `.react-email`, maybe you haven't ran `email build`?", + console.error( + "Could not find .react-email, maybe you haven't ran email build?", ); + process.exit(1); } const nextStart = spawn('npm', ['start'], { diff --git a/packages/react-email/src/cli/utils/preview/start-dev-server.ts b/packages/react-email/src/cli/utils/preview/start-dev-server.ts index a8a37ae731..a0efeb0b08 100644 --- a/packages/react-email/src/cli/utils/preview/start-dev-server.ts +++ b/packages/react-email/src/cli/utils/preview/start-dev-server.ts @@ -6,7 +6,7 @@ import ora from 'ora'; import logSymbols from 'log-symbols'; import chalk from 'chalk'; import packageJson from '../../../../package.json'; -import { closeOraOnSIGNIT } from '../../../utils/close-ora-on-sigint'; +import { registerSpinnerAutostopping } from '../../../utils/register-spinner-autostopping'; import { serveStaticFile } from './serve-static-file'; import { getEnvVariablesForPreviewApp } from './get-env-variables-for-preview-app'; @@ -113,7 +113,7 @@ export const startDevServer = async ( prefixText: ' ', }).start(); - closeOraOnSIGNIT(spinner); + registerSpinnerAutostopping(spinner); const timeBeforeNextReady = performance.now(); // these environment variables are used on the next app diff --git a/packages/react-email/src/utils/close-ora-on-sigint.ts b/packages/react-email/src/utils/close-ora-on-sigint.ts deleted file mode 100644 index 0c127818dc..0000000000 --- a/packages/react-email/src/utils/close-ora-on-sigint.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Ora } from 'ora'; - -const spinners = new Set(); - -process.on('SIGINT', () => { - spinners.forEach((spinner) => { - if (spinner.isSpinning) { - spinner.stop(); - } - }); -}); - -export const closeOraOnSIGNIT = (spinner: Ora) => { - spinners.add(spinner); -}; diff --git a/packages/react-email/src/utils/register-spinner-autostopping.ts b/packages/react-email/src/utils/register-spinner-autostopping.ts new file mode 100644 index 0000000000..2a4a156b4d --- /dev/null +++ b/packages/react-email/src/utils/register-spinner-autostopping.ts @@ -0,0 +1,28 @@ +import logSymbols from 'log-symbols'; +import type { Ora } from 'ora'; + +const spinners = new Set(); + +process.on('SIGINT', () => { + spinners.forEach((spinner) => { + if (spinner.isSpinning) { + spinner.stop(); + } + }); +}); + +process.on('exit', (code) => { + if (code !== 0) { + spinners.forEach((spinner) => { + if (spinner.isSpinning) { + spinner.stopAndPersist({ + symbol: logSymbols.error, + }); + } + }); + } +}); + +export const registerSpinnerAutostopping = (spinner: Ora) => { + spinners.add(spinner); +};