Skip to content

Commit 5d51ed9

Browse files
authored
fix(misc): create-nx-workspace errors should display properly (#15988)
1 parent d24d850 commit 5d51ed9

16 files changed

+158
-109
lines changed

packages/create-nx-workspace/bin/create-nx-workspace.ts

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const commandsObject: yargs.Argv<Arguments> = yargs
4141
'strip-dashed': true,
4242
'dot-notation': true,
4343
})
44-
.command(
44+
.command<Arguments>(
4545
// this is the default and only command
4646
'$0 [name] [options]',
4747
'Create a new Nx workspace',
@@ -152,7 +152,7 @@ export const commandsObject: yargs.Argv<Arguments> = yargs
152152
throw error;
153153
});
154154
},
155-
[normalizeArgsMiddleware]
155+
[normalizeArgsMiddleware as yargs.MiddlewareFunction<{}>]
156156
)
157157
.help('help', chalk.dim`Show help`)
158158
.updateLocale(yargsDecorator)
@@ -195,7 +195,7 @@ async function normalizeArgsMiddleware(
195195
"Let's create a new workspace [https://nx.dev/getting-started/intro]",
196196
});
197197

198-
let thirdPartyPreset: string;
198+
let thirdPartyPreset: string | null;
199199
try {
200200
thirdPartyPreset = await getThirdPartyPreset(argv.preset);
201201
} catch (e) {
@@ -262,7 +262,7 @@ async function normalizeArgsMiddleware(
262262
}
263263
} else {
264264
name = await determineRepoName(argv);
265-
appName = await determineAppName(preset, argv);
265+
appName = await determineAppName(preset as Preset, argv);
266266
if (preset === Preset.ReactMonorepo) {
267267
bundler = await determineBundler(argv);
268268
}
@@ -276,7 +276,7 @@ async function normalizeArgsMiddleware(
276276
(argv.interactive ? await determineRouting(argv) : true);
277277
}
278278
}
279-
style = await determineStyle(preset, argv);
279+
style = await determineStyle(preset as Preset, argv);
280280
}
281281

282282
const packageManager = await determinePackageManager(argv);
@@ -439,7 +439,7 @@ async function determinePackageManager(
439439
],
440440
},
441441
])
442-
.then((a: { packageManager }) => a.packageManager);
442+
.then((a) => a.packageManager);
443443
}
444444

445445
return Promise.resolve(detectInvokedPackageManager());
@@ -453,15 +453,15 @@ async function determineDefaultBase(
453453
}
454454
if (parsedArgs.allPrompts) {
455455
return enquirer
456-
.prompt([
456+
.prompt<{ DefaultBase: string }>([
457457
{
458458
name: 'DefaultBase',
459459
message: `Main branch name `,
460460
initial: `main`,
461461
type: 'input',
462462
},
463463
])
464-
.then((a: { DefaultBase: string }) => {
464+
.then((a) => {
465465
if (!a.DefaultBase) {
466466
output.error({
467467
title: 'Invalid branch name',
@@ -524,14 +524,14 @@ async function determineAppName(
524524
}
525525

526526
return enquirer
527-
.prompt([
527+
.prompt<{ AppName: string }>([
528528
{
529529
name: 'AppName',
530530
message: `Application name `,
531531
type: 'input',
532532
},
533533
])
534-
.then((a: { AppName: string }) => {
534+
.then((a) => {
535535
if (!a.AppName) {
536536
output.error({
537537
title: 'Invalid name',
@@ -571,15 +571,15 @@ async function determineFramework(
571571

572572
if (!parsedArgs.framework) {
573573
return enquirer
574-
.prompt([
574+
.prompt<{ framework: Framework }>([
575575
{
576576
message: 'What framework should be used?',
577577
type: 'autocomplete',
578578
name: 'framework',
579579
choices: frameworkChoices,
580580
},
581581
])
582-
.then((a: { framework: string }) => a.framework);
582+
.then((a) => a.framework);
583583
}
584584

585585
const foundFramework = frameworkChoices
@@ -607,7 +607,7 @@ async function determineStandaloneApi(
607607
): Promise<boolean> {
608608
if (parsedArgs.standaloneApi === undefined) {
609609
return enquirer
610-
.prompt([
610+
.prompt<{ standaloneApi: 'Yes' | 'No' }>([
611611
{
612612
name: 'standaloneApi',
613613
message:
@@ -625,7 +625,7 @@ async function determineStandaloneApi(
625625
initial: 'No' as any,
626626
},
627627
])
628-
.then((a: { standaloneApi: 'Yes' | 'No' }) => a.standaloneApi === 'Yes');
628+
.then((a) => a.standaloneApi === 'Yes');
629629
}
630630

631631
return parsedArgs.standaloneApi;
@@ -636,7 +636,7 @@ async function determineDockerfile(
636636
): Promise<boolean> {
637637
if (parsedArgs.docker === undefined) {
638638
return enquirer
639-
.prompt([
639+
.prompt<{ docker: 'Yes' | 'No' }>([
640640
{
641641
name: 'docker',
642642
message:
@@ -654,7 +654,7 @@ async function determineDockerfile(
654654
initial: 'No' as any,
655655
},
656656
])
657-
.then((a: { docker: 'Yes' | 'No' }) => a.docker === 'Yes');
657+
.then((a) => a.docker === 'Yes');
658658
} else {
659659
return Promise.resolve(parsedArgs.docker);
660660
}
@@ -663,7 +663,7 @@ async function determineDockerfile(
663663
async function determineStyle(
664664
preset: Preset,
665665
parsedArgs: yargs.Arguments<Arguments>
666-
): Promise<string> {
666+
): Promise<string | null> {
667667
if (
668668
preset === Preset.Apps ||
669669
preset === Preset.Core ||
@@ -727,7 +727,7 @@ async function determineStyle(
727727

728728
if (!parsedArgs.style) {
729729
return enquirer
730-
.prompt([
730+
.prompt<{ style: string }>([
731731
{
732732
name: 'style',
733733
message: `Default stylesheet format `,
@@ -762,7 +762,7 @@ async function determineRouting(
762762
): Promise<boolean> {
763763
if (!parsedArgs.routing) {
764764
return enquirer
765-
.prompt([
765+
.prompt<{ routing: 'Yes' | 'No' }>([
766766
{
767767
name: 'routing',
768768
message: 'Would you like to add routing?',
@@ -779,7 +779,7 @@ async function determineRouting(
779779
initial: 'Yes' as any,
780780
},
781781
])
782-
.then((a: { routing: 'Yes' | 'No' }) => a.routing === 'Yes');
782+
.then((a) => a.routing === 'Yes');
783783
}
784784

785785
return parsedArgs.routing;
@@ -801,7 +801,7 @@ async function determineBundler(
801801

802802
if (!parsedArgs.bundler) {
803803
return enquirer
804-
.prompt([
804+
.prompt<{ bundler: Bundler }>([
805805
{
806806
name: 'bundler',
807807
message: `Bundler to be used to build the application`,
@@ -810,7 +810,7 @@ async function determineBundler(
810810
choices: choices,
811811
},
812812
])
813-
.then((a: { bundler: 'vite' | 'webpack' }) => a.bundler);
813+
.then((a) => a.bundler);
814814
}
815815

816816
const foundBundler = choices.find(
@@ -838,7 +838,7 @@ async function determineNxCloud(
838838
): Promise<boolean> {
839839
if (parsedArgs.nxCloud === undefined) {
840840
return enquirer
841-
.prompt([
841+
.prompt<{ NxCloud: 'Yes' | 'No' }>([
842842
{
843843
name: 'NxCloud',
844844
message: messages.getPromptMessage('nxCloudCreation'),
@@ -856,7 +856,7 @@ async function determineNxCloud(
856856
initial: 'Yes' as any,
857857
},
858858
])
859-
.then((a: { NxCloud: 'Yes' | 'No' }) => a.NxCloud === 'Yes');
859+
.then((a) => a.NxCloud === 'Yes');
860860
} else {
861861
return parsedArgs.nxCloud;
862862
}
@@ -886,7 +886,7 @@ async function determineCI(
886886
if (parsedArgs.allPrompts) {
887887
return (
888888
enquirer
889-
.prompt([
889+
.prompt<{ CI: string }>([
890890
{
891891
name: 'CI',
892892
message: `CI workflow file to generate? `,

packages/create-nx-workspace/src/create-empty-workspace.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ import * as ora from 'ora';
22
import { join } from 'path';
33
import { CreateWorkspaceOptions } from './create-workspace-options';
44
import { execAndWait } from './utils/child-process-utils';
5+
import { mapErrorToBodyLines } from './utils/error-utils';
56
import { output } from './utils/output';
67
import {
78
getPackageManagerCommand,
89
getPackageManagerVersion,
910
PackageManager,
1011
} from './utils/package-manager';
11-
import { getFileName, mapErrorToBodyLines } from './utils/string-utils';
12+
import { getFileName } from './utils/string-utils';
1213
import { unparse } from './utils/unparse';
1314

1415
/**
@@ -67,10 +68,14 @@ export async function createEmptyWorkspace<T extends CreateWorkspaceOptions>(
6768
);
6869
} catch (e) {
6970
workspaceSetupSpinner.fail();
70-
output.error({
71-
title: `Nx failed to create a workspace.`,
72-
bodyLines: mapErrorToBodyLines(e),
73-
});
71+
if (e instanceof Error) {
72+
output.error({
73+
title: `Nx failed to create a workspace.`,
74+
bodyLines: mapErrorToBodyLines(e),
75+
});
76+
} else {
77+
console.error(e);
78+
}
7479
process.exit(1);
7580
} finally {
7681
workspaceSetupSpinner.stop();

packages/create-nx-workspace/src/create-sandbox.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import {
1010
} from './utils/package-manager';
1111
import { execAndWait } from './utils/child-process-utils';
1212
import { output } from './utils/output';
13-
import { mapErrorToBodyLines } from './utils/string-utils';
1413
import { nxVersion } from './utils/nx/nx-version';
14+
import { mapErrorToBodyLines } from './utils/error-utils';
1515

1616
/**
1717
* Creates a temporary directory and installs Nx in it.
@@ -44,10 +44,14 @@ export async function createSandbox(packageManager: PackageManager) {
4444
installSpinner.succeed();
4545
} catch (e) {
4646
installSpinner.fail();
47-
output.error({
48-
title: `Nx failed to install dependencies`,
49-
bodyLines: mapErrorToBodyLines(e),
50-
});
47+
if (e instanceof Error) {
48+
output.error({
49+
title: `Nx failed to install dependencies`,
50+
bodyLines: mapErrorToBodyLines(e),
51+
});
52+
} else {
53+
console.error(e);
54+
}
5155
process.exit(1);
5256
} finally {
5357
installSpinner.stop();

packages/create-nx-workspace/src/create-workspace.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { messages, recordStat } from './utils/nx/ab-testing';
1010
import { initializeGitRepo } from './utils/git/git';
1111
import { nxVersion } from './utils/nx/nx-version';
1212
import { getThirdPartyPreset } from './utils/preset/get-third-party-preset';
13+
import { mapErrorToBodyLines } from './utils/error-utils';
1314

1415
export async function createWorkspace<T extends CreateWorkspaceOptions>(
1516
preset: string,
@@ -59,23 +60,27 @@ export async function createWorkspace<T extends CreateWorkspaceOptions>(
5960
name,
6061
ci,
6162
packageManager,
62-
nxCloud && nxCloudInstallRes.code === 0
63+
nxCloud && nxCloudInstallRes?.code === 0
6364
);
6465
}
6566
if (!skipGit) {
6667
try {
6768
await initializeGitRepo(directory, { defaultBase, commit });
6869
} catch (e) {
69-
output.error({
70-
title: 'Could not initialize git repository',
71-
bodyLines: [e.message],
72-
});
70+
if (e instanceof Error) {
71+
output.error({
72+
title: 'Could not initialize git repository',
73+
bodyLines: mapErrorToBodyLines(e),
74+
});
75+
} else {
76+
console.error(e);
77+
}
7378
}
7479
}
7580

7681
showNxWarning(name);
7782

78-
if (nxCloud && nxCloudInstallRes.code === 0) {
83+
if (nxCloud && nxCloudInstallRes?.code === 0) {
7984
printNxCloudSuccessMessage(nxCloudInstallRes.stdout);
8085
}
8186

packages/create-nx-workspace/src/utils/child-process-utils.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { spawn, exec } from 'child_process';
22
import { writeFileSync } from 'fs';
33
import { join } from 'path';
4+
import { CreateNxWorkspaceError } from './error-utils';
45

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

2627
export function execAndWait(command: string, cwd: string) {
27-
return new Promise((res, rej) => {
28+
return new Promise<{ code: number; stdout: string }>((res, rej) => {
2829
exec(
2930
command,
3031
{ cwd, env: { ...process.env, NX_DAEMON: 'false' } },
3132
(error, stdout, stderr) => {
3233
if (error) {
3334
const logFile = join(cwd, 'error.log');
3435
writeFileSync(logFile, `${stdout}\n${stderr}`);
35-
rej({ code: error.code, logFile, logMessage: stderr });
36+
rej(new CreateNxWorkspaceError(stderr, error.code, logFile));
3637
} else {
3738
res({ code: 0, stdout });
3839
}

packages/create-nx-workspace/src/utils/ci/setup-ci.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import * as ora from 'ora';
22
import { join } from 'path';
33

44
import { execAndWait } from '../child-process-utils';
5+
import { mapErrorToBodyLines } from '../error-utils';
56
import { output } from '../output';
67
import { getPackageManagerCommand, PackageManager } from '../package-manager';
7-
import { getFileName, mapErrorToBodyLines } from '../string-utils';
8+
import { getFileName } from '../string-utils';
89

910
export async function setupCI(
1011
name: string,
@@ -32,11 +33,14 @@ export async function setupCI(
3233
return res;
3334
} catch (e) {
3435
ciSpinner.fail();
35-
36-
output.error({
37-
title: `Nx failed to generate CI workflow`,
38-
bodyLines: mapErrorToBodyLines(e),
39-
});
36+
if (e instanceof Error) {
37+
output.error({
38+
title: `Nx failed to generate CI workflow`,
39+
bodyLines: mapErrorToBodyLines(e),
40+
});
41+
} else {
42+
console.error(e);
43+
}
4044

4145
process.exit(1);
4246
} finally {

0 commit comments

Comments
 (0)