diff --git a/packages/create-nx-workspace/bin/create-nx-workspace.ts b/packages/create-nx-workspace/bin/create-nx-workspace.ts index 2e315217d33b7..770daf66659fe 100644 --- a/packages/create-nx-workspace/bin/create-nx-workspace.ts +++ b/packages/create-nx-workspace/bin/create-nx-workspace.ts @@ -10,7 +10,7 @@ import { nxVersion } from '../src/utils/nx/nx-version'; import { pointToTutorialAndCourse } from '../src/utils/preset/point-to-tutorial-and-course'; import { yargsDecorator } from './decorator'; -import { getThirdPartyPreset } from '../src/utils/preset/get-third-party-preset'; +import { getPackageNameFromThirdPartyPreset } from '../src/utils/preset/get-third-party-preset'; import { determineDefaultBase, determineNxCloud, @@ -26,6 +26,7 @@ import { import { showNxWarning } from '../src/utils/nx/show-nx-warning'; import { printNxCloudSuccessMessage } from '../src/utils/nx/nx-cloud'; import { messages, recordStat } from '../src/utils/nx/ab-testing'; +import { mapErrorToBodyLines } from '../src/utils/error-utils'; import { existsSync } from 'fs'; interface BaseArguments extends CreateWorkspaceOptions { @@ -256,29 +257,25 @@ async function normalizeArgsMiddleware( }); try { - let thirdPartyPreset: string | null; - - try { - thirdPartyPreset = await getThirdPartyPreset(argv.preset); - } catch (e) { - output.error({ - title: `Could not find preset "${argv.preset}"`, - }); - process.exit(1); - } - argv.name = await determineFolder(argv); - - if (thirdPartyPreset) { - Object.assign(argv, { - preset: thirdPartyPreset, - appName: '', - style: '', - }); - } else { + if (isKnownPreset(argv.preset)) { argv.stack = await determineStack(argv); const presetOptions = await determinePresetOptions(argv); Object.assign(argv, presetOptions); + } else { + try { + getPackageNameFromThirdPartyPreset(argv.preset); + } catch (e) { + if (e instanceof Error) { + output.error({ + title: `Could not find preset "${argv.preset}"`, + bodyLines: mapErrorToBodyLines(e), + }); + } else { + console.error(e); + } + process.exit(1); + } } const packageManager = await determinePackageManager(argv); diff --git a/packages/create-nx-workspace/src/create-workspace.ts b/packages/create-nx-workspace/src/create-workspace.ts index 54e8f3e3c3f7d..dbb0bd9da3f56 100644 --- a/packages/create-nx-workspace/src/create-workspace.ts +++ b/packages/create-nx-workspace/src/create-workspace.ts @@ -6,7 +6,7 @@ import { createEmptyWorkspace } from './create-empty-workspace'; import { createPreset } from './create-preset'; import { setupCI } from './utils/ci/setup-ci'; import { initializeGitRepo } from './utils/git/git'; -import { getThirdPartyPreset } from './utils/preset/get-third-party-preset'; +import { getPackageNameFromThirdPartyPreset } from './utils/preset/get-third-party-preset'; import { mapErrorToBodyLines } from './utils/error-utils'; export async function createWorkspace( @@ -40,9 +40,14 @@ export async function createWorkspace( // If the preset is a third-party preset, we need to call createPreset to install it // For first-party presets, it will be created by createEmptyWorkspace instead. // In createEmptyWorkspace, it will call `nx new` -> `@nx/workspace newGenerator` -> `@nx/workspace generatePreset`. - const thirdPartyPreset = await getThirdPartyPreset(preset); - if (thirdPartyPreset) { - await createPreset(thirdPartyPreset, options, packageManager, directory); + const thirdPartyPackageName = getPackageNameFromThirdPartyPreset(preset); + if (thirdPartyPackageName) { + await createPreset( + thirdPartyPackageName, + options, + packageManager, + directory + ); } let nxCloudInstallRes; diff --git a/packages/create-nx-workspace/src/utils/preset/get-third-party-preset.spec.ts b/packages/create-nx-workspace/src/utils/preset/get-third-party-preset.spec.ts new file mode 100644 index 0000000000000..3638a63e97d2e --- /dev/null +++ b/packages/create-nx-workspace/src/utils/preset/get-third-party-preset.spec.ts @@ -0,0 +1,21 @@ +import { getPackageNameFromThirdPartyPreset } from './get-third-party-preset'; + +describe('getPackageNameFromThirdPartyPreset', () => { + it('should throw an error if preset is invalid', () => { + expect(() => getPackageNameFromThirdPartyPreset('_random')).toThrow(); + }); + + it('should return undefined if preset is known nx preset', () => { + expect(getPackageNameFromThirdPartyPreset('react')).toBeUndefined(); + expect(getPackageNameFromThirdPartyPreset('angular')).toBeUndefined(); + }); + + it('should return package name if it is valid package', () => { + expect(getPackageNameFromThirdPartyPreset('@nx-go/nx-go')).toEqual( + '@nx-go/nx-go' + ); + expect(getPackageNameFromThirdPartyPreset('@nx-go/nx-go@19.0.0')).toEqual( + '@nx-go/nx-go' + ); + }); +}); diff --git a/packages/create-nx-workspace/src/utils/preset/get-third-party-preset.ts b/packages/create-nx-workspace/src/utils/preset/get-third-party-preset.ts index 4b5aa13a6b532..82def15d14c18 100644 --- a/packages/create-nx-workspace/src/utils/preset/get-third-party-preset.ts +++ b/packages/create-nx-workspace/src/utils/preset/get-third-party-preset.ts @@ -1,36 +1,31 @@ -import { output } from '../output'; import { validateNpmPackage } from '../validate-npm-package'; import { isKnownPreset } from './preset'; /** * This function is used to check if a preset is a third party preset. * @param preset - * @returns null if the preset is a known Nx preset or preset does not exist, the package name of preset otherwise. + * @returns + * - undefined if the preset is a known Nx preset or invalid. + * - packageName if the preset is a third party preset. + * - throws an error if the preset is invalid. */ -export async function getThirdPartyPreset( +export function getPackageNameFromThirdPartyPreset( preset?: string -): Promise { - if (preset && !isKnownPreset(preset)) { - // extract the package name from the preset - const packageName = preset.match(/.+@/) - ? preset[0] + preset.substring(1).split('@')[0] - : preset; - const validateResult = validateNpmPackage(packageName); - if (validateResult.validForNewPackages) { - return Promise.resolve(packageName); - } else { - //! Error here - output.error({ - title: 'Invalid preset npm package', - bodyLines: [ - `There was an error with the preset npm package you provided:`, - '', - ...(validateResult.errors ?? []), - ], - }); - throw new Error('Invalid preset npm package'); - } - } else { - return Promise.resolve(null); +): string | undefined { + if (!preset || isKnownPreset(preset)) { + return; } + // extract the package name from the preset + const packageName = preset.match(/.+@/) + ? preset[0] + preset.substring(1).split('@')[0] + : preset; + + const validateResult = validateNpmPackage(packageName); + if (!validateResult.validForNewPackages) { + throw new Error( + `Invalid preset npm package ${packageName}. There was an error with the preset npm package you provided: ` + + (validateResult.errors ?? []).join('\n') + ); + } + return packageName; }