Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(misc): create-nx-workspace errors should display properly #15988

Merged
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
50 changes: 25 additions & 25 deletions packages/create-nx-workspace/bin/create-nx-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const commandsObject: yargs.Argv<Arguments> = yargs
'strip-dashed': true,
'dot-notation': true,
})
.command(
.command<Arguments>(
// this is the default and only command
'$0 [name] [options]',
'Create a new Nx workspace',
Expand Down Expand Up @@ -152,7 +152,7 @@ export const commandsObject: yargs.Argv<Arguments> = yargs
throw error;
});
},
[normalizeArgsMiddleware]
[normalizeArgsMiddleware as yargs.MiddlewareFunction<{}>]
)
.help('help', chalk.dim`Show help`)
.updateLocale(yargsDecorator)
Expand Down Expand Up @@ -195,7 +195,7 @@ async function normalizeArgsMiddleware(
"Let's create a new workspace [https://nx.dev/getting-started/intro]",
});

let thirdPartyPreset: string;
let thirdPartyPreset: string | null;
try {
thirdPartyPreset = await getThirdPartyPreset(argv.preset);
} catch (e) {
Expand Down Expand Up @@ -262,7 +262,7 @@ async function normalizeArgsMiddleware(
}
} else {
name = await determineRepoName(argv);
appName = await determineAppName(preset, argv);
appName = await determineAppName(preset as Preset, argv);
if (preset === Preset.ReactMonorepo) {
bundler = await determineBundler(argv);
}
Expand All @@ -276,7 +276,7 @@ async function normalizeArgsMiddleware(
(argv.interactive ? await determineRouting(argv) : true);
}
}
style = await determineStyle(preset, argv);
style = await determineStyle(preset as Preset, argv);
}

const packageManager = await determinePackageManager(argv);
Expand Down Expand Up @@ -439,7 +439,7 @@ async function determinePackageManager(
],
},
])
.then((a: { packageManager }) => a.packageManager);
.then((a) => a.packageManager);
}

return Promise.resolve(detectInvokedPackageManager());
Expand All @@ -453,15 +453,15 @@ async function determineDefaultBase(
}
if (parsedArgs.allPrompts) {
return enquirer
.prompt([
.prompt<{ DefaultBase: string }>([
{
name: 'DefaultBase',
message: `Main branch name `,
initial: `main`,
type: 'input',
},
])
.then((a: { DefaultBase: string }) => {
.then((a) => {
if (!a.DefaultBase) {
output.error({
title: 'Invalid branch name',
Expand Down Expand Up @@ -524,14 +524,14 @@ async function determineAppName(
}

return enquirer
.prompt([
.prompt<{ AppName: string }>([
{
name: 'AppName',
message: `Application name `,
type: 'input',
},
])
.then((a: { AppName: string }) => {
.then((a) => {
if (!a.AppName) {
output.error({
title: 'Invalid name',
Expand Down Expand Up @@ -571,15 +571,15 @@ async function determineFramework(

if (!parsedArgs.framework) {
return enquirer
.prompt([
.prompt<{ framework: Framework }>([
{
message: 'What framework should be used?',
type: 'autocomplete',
name: 'framework',
choices: frameworkChoices,
},
])
.then((a: { framework: string }) => a.framework);
.then((a) => a.framework);
}

const foundFramework = frameworkChoices
Expand Down Expand Up @@ -607,7 +607,7 @@ async function determineStandaloneApi(
): Promise<boolean> {
if (parsedArgs.standaloneApi === undefined) {
return enquirer
.prompt([
.prompt<{ standaloneApi: 'Yes' | 'No' }>([
{
name: 'standaloneApi',
message:
Expand All @@ -625,7 +625,7 @@ async function determineStandaloneApi(
initial: 'No' as any,
},
])
.then((a: { standaloneApi: 'Yes' | 'No' }) => a.standaloneApi === 'Yes');
.then((a) => a.standaloneApi === 'Yes');
}

return parsedArgs.standaloneApi;
Expand All @@ -636,7 +636,7 @@ async function determineDockerfile(
): Promise<boolean> {
if (parsedArgs.docker === undefined) {
return enquirer
.prompt([
.prompt<{ docker: 'Yes' | 'No' }>([
{
name: 'docker',
message:
Expand All @@ -654,7 +654,7 @@ async function determineDockerfile(
initial: 'No' as any,
},
])
.then((a: { docker: 'Yes' | 'No' }) => a.docker === 'Yes');
.then((a) => a.docker === 'Yes');
} else {
return Promise.resolve(parsedArgs.docker);
}
Expand All @@ -663,7 +663,7 @@ async function determineDockerfile(
async function determineStyle(
preset: Preset,
parsedArgs: yargs.Arguments<Arguments>
): Promise<string> {
): Promise<string | null> {
if (
preset === Preset.Apps ||
preset === Preset.Core ||
Expand Down Expand Up @@ -727,7 +727,7 @@ async function determineStyle(

if (!parsedArgs.style) {
return enquirer
.prompt([
.prompt<{ style: string }>([
{
name: 'style',
message: `Default stylesheet format `,
Expand Down Expand Up @@ -762,7 +762,7 @@ async function determineRouting(
): Promise<boolean> {
if (!parsedArgs.routing) {
return enquirer
.prompt([
.prompt<{ routing: 'Yes' | 'No' }>([
{
name: 'routing',
message: 'Would you like to add routing?',
Expand All @@ -779,7 +779,7 @@ async function determineRouting(
initial: 'Yes' as any,
},
])
.then((a: { routing: 'Yes' | 'No' }) => a.routing === 'Yes');
.then((a) => a.routing === 'Yes');
}

return parsedArgs.routing;
Expand All @@ -801,7 +801,7 @@ async function determineBundler(

if (!parsedArgs.bundler) {
return enquirer
.prompt([
.prompt<{ bundler: Bundler }>([
{
name: 'bundler',
message: `Bundler to be used to build the application`,
Expand All @@ -810,7 +810,7 @@ async function determineBundler(
choices: choices,
},
])
.then((a: { bundler: 'vite' | 'webpack' }) => a.bundler);
.then((a) => a.bundler);
}

const foundBundler = choices.find(
Expand Down Expand Up @@ -838,7 +838,7 @@ async function determineNxCloud(
): Promise<boolean> {
if (parsedArgs.nxCloud === undefined) {
return enquirer
.prompt([
.prompt<{ NxCloud: 'Yes' | 'No' }>([
{
name: 'NxCloud',
message: messages.getPromptMessage('nxCloudCreation'),
Expand All @@ -856,7 +856,7 @@ async function determineNxCloud(
initial: 'Yes' as any,
},
])
.then((a: { NxCloud: 'Yes' | 'No' }) => a.NxCloud === 'Yes');
.then((a) => a.NxCloud === 'Yes');
} else {
return parsedArgs.nxCloud;
}
Expand Down Expand Up @@ -886,7 +886,7 @@ async function determineCI(
if (parsedArgs.allPrompts) {
return (
enquirer
.prompt([
.prompt<{ CI: string }>([
{
name: 'CI',
message: `CI workflow file to generate? `,
Expand Down
15 changes: 10 additions & 5 deletions packages/create-nx-workspace/src/create-empty-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import * as ora from 'ora';
import { join } from 'path';
import { CreateWorkspaceOptions } from './create-workspace-options';
import { execAndWait } from './utils/child-process-utils';
import { mapErrorToBodyLines } from './utils/error-utils';
import { output } from './utils/output';
import {
getPackageManagerCommand,
getPackageManagerVersion,
PackageManager,
} from './utils/package-manager';
import { getFileName, mapErrorToBodyLines } from './utils/string-utils';
import { getFileName } from './utils/string-utils';
import { unparse } from './utils/unparse';

/**
Expand Down Expand Up @@ -67,10 +68,14 @@ export async function createEmptyWorkspace<T extends CreateWorkspaceOptions>(
);
} catch (e) {
workspaceSetupSpinner.fail();
output.error({
title: `Nx failed to create a workspace.`,
bodyLines: mapErrorToBodyLines(e),
});
if (e instanceof Error) {
output.error({
title: `Nx failed to create a workspace.`,
bodyLines: mapErrorToBodyLines(e),
});
} else {
console.error(e);
}
process.exit(1);
} finally {
workspaceSetupSpinner.stop();
Expand Down
14 changes: 9 additions & 5 deletions packages/create-nx-workspace/src/create-sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {
} from './utils/package-manager';
import { execAndWait } from './utils/child-process-utils';
import { output } from './utils/output';
import { mapErrorToBodyLines } from './utils/string-utils';
import { nxVersion } from './utils/nx/nx-version';
import { mapErrorToBodyLines } from './utils/error-utils';

/**
* Creates a temporary directory and installs Nx in it.
Expand Down Expand Up @@ -44,10 +44,14 @@ export async function createSandbox(packageManager: PackageManager) {
installSpinner.succeed();
} catch (e) {
installSpinner.fail();
output.error({
title: `Nx failed to install dependencies`,
bodyLines: mapErrorToBodyLines(e),
});
if (e instanceof Error) {
output.error({
title: `Nx failed to install dependencies`,
bodyLines: mapErrorToBodyLines(e),
});
} else {
console.error(e);
}
process.exit(1);
} finally {
installSpinner.stop();
Expand Down
17 changes: 11 additions & 6 deletions packages/create-nx-workspace/src/create-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { messages, recordStat } from './utils/nx/ab-testing';
import { initializeGitRepo } from './utils/git/git';
import { nxVersion } from './utils/nx/nx-version';
import { getThirdPartyPreset } from './utils/preset/get-third-party-preset';
import { mapErrorToBodyLines } from './utils/error-utils';

export async function createWorkspace<T extends CreateWorkspaceOptions>(
preset: string,
Expand Down Expand Up @@ -59,23 +60,27 @@ export async function createWorkspace<T extends CreateWorkspaceOptions>(
name,
ci,
packageManager,
nxCloud && nxCloudInstallRes.code === 0
nxCloud && nxCloudInstallRes?.code === 0
);
}
if (!skipGit) {
try {
await initializeGitRepo(directory, { defaultBase, commit });
} catch (e) {
output.error({
title: 'Could not initialize git repository',
bodyLines: [e.message],
});
if (e instanceof Error) {
output.error({
title: 'Could not initialize git repository',
bodyLines: mapErrorToBodyLines(e),
});
} else {
console.error(e);
}
}
}

showNxWarning(name);

if (nxCloud && nxCloudInstallRes.code === 0) {
if (nxCloud && nxCloudInstallRes?.code === 0) {
printNxCloudSuccessMessage(nxCloudInstallRes.stdout);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { spawn, exec } from 'child_process';
import { writeFileSync } from 'fs';
import { join } from 'path';
import { CreateNxWorkspaceError } from './error-utils';

/**
* Use spawn only for interactive shells
Expand All @@ -24,15 +25,15 @@ export function spawnAndWait(command: string, args: string[], cwd: string) {
}

export function execAndWait(command: string, cwd: string) {
return new Promise((res, rej) => {
return new Promise<{ code: number; stdout: string }>((res, rej) => {
exec(
command,
{ cwd, env: { ...process.env, NX_DAEMON: 'false' } },
(error, stdout, stderr) => {
if (error) {
const logFile = join(cwd, 'error.log');
writeFileSync(logFile, `${stdout}\n${stderr}`);
rej({ code: error.code, logFile, logMessage: stderr });
rej(new CreateNxWorkspaceError(stderr, error.code, logFile));
} else {
res({ code: 0, stdout });
}
Expand Down
16 changes: 10 additions & 6 deletions packages/create-nx-workspace/src/utils/ci/setup-ci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import * as ora from 'ora';
import { join } from 'path';

import { execAndWait } from '../child-process-utils';
import { mapErrorToBodyLines } from '../error-utils';
import { output } from '../output';
import { getPackageManagerCommand, PackageManager } from '../package-manager';
import { getFileName, mapErrorToBodyLines } from '../string-utils';
import { getFileName } from '../string-utils';

export async function setupCI(
name: string,
Expand Down Expand Up @@ -32,11 +33,14 @@ export async function setupCI(
return res;
} catch (e) {
ciSpinner.fail();

output.error({
title: `Nx failed to generate CI workflow`,
bodyLines: mapErrorToBodyLines(e),
});
if (e instanceof Error) {
output.error({
title: `Nx failed to generate CI workflow`,
bodyLines: mapErrorToBodyLines(e),
});
} else {
console.error(e);
}

process.exit(1);
} finally {
Expand Down
Loading