From 934847ba330e18ccb50802727faa5ca9eacea2b2 Mon Sep 17 00:00:00 2001 From: Emily Xiong Date: Wed, 12 Apr 2023 14:33:59 -0400 Subject: [PATCH] feat(misc): update pr with comments --- docs/generated/manifests/packages.json | 2 +- docs/generated/packages-metadata.json | 2 +- .../nx-plugin/generators/create-package.json | 8 +- .../packages/nx-plugin/generators/preset.json | 5 +- .../src/create-nx-plugin.test.ts | 2 + .../create-nx-plugin/bin/create-nx-plugin.ts | 23 ++++- .../create-nx-workspace/src/create-preset.ts | 4 +- .../src/create-workspace-options.ts | 1 + packages/nx-plugin/generators.json | 4 +- .../nx-plugin/src/executors/e2e/e2e.impl.ts | 2 +- .../create-package/create-package.spec.ts | 1 + .../create-package/create-package.ts | 93 ++++++++++++------- .../bin/index.ts__tmpl__ | 7 ++ .../files/e2e/__name__.spec.ts__tmpl__ | 39 ++++---- .../src/generators/create-package/schema.d.ts | 6 +- .../src/generators/create-package/schema.json | 6 ++ .../nx-plugin/src/generators/plugin/plugin.ts | 1 - .../src/generators/preset/generator.ts | 29 +++--- .../src/generators/preset/schema.d.ts | 2 +- .../src/generators/preset/schema.json | 5 +- .../src/utils/testing-utils/async-commands.ts | 4 +- .../src/utils/testing-utils/commands.ts | 5 +- .../utils/testing-utils/create-package-cli.ts | 61 ++++++++---- .../src/utils/testing-utils/nx-project.ts | 4 +- .../src/utils/testing-utils/paths.ts | 8 +- .../src/utils/testing-utils/utils.ts | 10 +- .../src/generators/new/generate-preset.ts | 5 +- packages/workspace/src/generators/new/new.ts | 1 + 28 files changed, 220 insertions(+), 120 deletions(-) diff --git a/docs/generated/manifests/packages.json b/docs/generated/manifests/packages.json index 8d547cf0ecd2e..1cfe447e55c0c 100644 --- a/docs/generated/manifests/packages.json +++ b/docs/generated/manifests/packages.json @@ -1833,7 +1833,7 @@ "type": "generator" }, "/packages/nx-plugin/generators/create-package": { - "description": "Create a framework package that uses Nx CLI", + "description": "Create a package which can be used by npx to create a new workspace", "file": "generated/packages/nx-plugin/generators/create-package.json", "hidden": false, "name": "create-package", diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index 81e87d4cf8bd5..d7c210a9b1933 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -1811,7 +1811,7 @@ "type": "generator" }, { - "description": "Create a framework package that uses Nx CLI", + "description": "Create a package which can be used by npx to create a new workspace", "file": "generated/packages/nx-plugin/generators/create-package.json", "hidden": false, "name": "create-package", diff --git a/docs/generated/packages/nx-plugin/generators/create-package.json b/docs/generated/packages/nx-plugin/generators/create-package.json index eee1fea878be0..720abcaa8a2bf 100644 --- a/docs/generated/packages/nx-plugin/generators/create-package.json +++ b/docs/generated/packages/nx-plugin/generators/create-package.json @@ -70,12 +70,18 @@ "importPath": { "type": "string", "description": "How the plugin will be published, like `create-framework-app`. Note this must be a valid NPM name. Will use name if not provided." + }, + "e2eTestRunner": { + "type": "string", + "enum": ["jest", "none"], + "description": "Test runner to use for end to end (E2E) tests.", + "default": "jest" } }, "required": ["name", "project"], "presets": [] }, - "description": "Create a framework package that uses Nx CLI", + "description": "Create a package which can be used by npx to create a new workspace", "implementation": "/packages/nx-plugin/src/generators/create-package/create-package.ts", "aliases": [], "hidden": false, diff --git a/docs/generated/packages/nx-plugin/generators/preset.json b/docs/generated/packages/nx-plugin/generators/preset.json index bf7c16ce8c2ba..082117d91b888 100644 --- a/docs/generated/packages/nx-plugin/generators/preset.json +++ b/docs/generated/packages/nx-plugin/generators/preset.json @@ -14,10 +14,9 @@ "description": "Plugin name", "aliases": ["name"] }, - "cliName": { + "createPackageName": { "type": "string", - "description": "Name of cli command to create workspace with plugin", - "aliases": ["name"] + "description": "Name of package which creates a workspace" } }, "required": ["pluginName"], diff --git a/e2e/workspace-create/src/create-nx-plugin.test.ts b/e2e/workspace-create/src/create-nx-plugin.test.ts index 312606ba4fe37..ab825957c285e 100644 --- a/e2e/workspace-create/src/create-nx-plugin.test.ts +++ b/e2e/workspace-create/src/create-nx-plugin.test.ts @@ -21,6 +21,7 @@ describe('create-nx-plugin', () => { runCreatePlugin(pluginName, { packageManager, + extraArgs: `--createPackageName=create-${wsName}-package`, }); checkFilesExist( @@ -53,5 +54,6 @@ describe('create-nx-plugin', () => { checkFilesExist(`dist/create-${pluginName}-package/bin/index.js`); expect(() => runCLI(`e2e e2e`)).not.toThrow(); + expect(() => runCLI(`e2e create-${wsName}-package-e2e`)).not.toThrow(); }); }); diff --git a/packages/create-nx-plugin/bin/create-nx-plugin.ts b/packages/create-nx-plugin/bin/create-nx-plugin.ts index 2114aa52f36ed..5dc3121b6c1ae 100644 --- a/packages/create-nx-plugin/bin/create-nx-plugin.ts +++ b/packages/create-nx-plugin/bin/create-nx-plugin.ts @@ -68,9 +68,26 @@ async function determinePluginName( return results.pluginName; } +async function determineCreatePackageName( + parsedArgs: CreateNxPluginArguments +): Promise { + if (parsedArgs.createPackageName) { + return Promise.resolve(parsedArgs.createPackageName); + } + + const results = await enquirer.prompt<{ createPackageName: string }>([ + { + name: 'createPackageName', + message: `Create package name (optional) `, + type: 'input', + }, + ]); + return results.createPackageName; +} + interface CreateNxPluginArguments { pluginName: string; - cliName?: string; + createPackageName?: string; packageManager: PackageManager; ci: CI; allPrompts: boolean; @@ -95,7 +112,7 @@ export const commandsObject: yargs.Argv = yargs type: 'string', alias: ['name'], }) - .option('cliName', { + .option('createPackageName', { describe: 'Name of the CLI package to create workspace with plugin', type: 'string', }), @@ -170,6 +187,7 @@ async function normalizeArgsMiddleware( ): Promise { try { const pluginName = await determinePluginName(argv); + const createPackageName = await determineCreatePackageName(argv); const packageManager = await determinePackageManager(argv); const defaultBase = await determineDefaultBase(argv); const nxCloud = await determineNxCloud(argv); @@ -177,6 +195,7 @@ async function normalizeArgsMiddleware( Object.assign(argv, { pluginName, + createPackageName, nxCloud, packageManager, defaultBase, diff --git a/packages/create-nx-workspace/src/create-preset.ts b/packages/create-nx-workspace/src/create-preset.ts index fa108393f7193..8d9722b864322 100644 --- a/packages/create-nx-workspace/src/create-preset.ts +++ b/packages/create-nx-workspace/src/create-preset.ts @@ -39,7 +39,9 @@ export async function createPreset( } } - if (process.env.NX_VERBOSE_LOGGING !== 'true') { + if ( + !(process.env.NX_VERBOSE_LOGGING === 'true' || args.includes('--verbose')) + ) { args = '--quiet ' + args; } const command = `g ${preset}:preset ${args}`; diff --git a/packages/create-nx-workspace/src/create-workspace-options.ts b/packages/create-nx-workspace/src/create-workspace-options.ts index 3ada0b0678176..54284061d7f5d 100644 --- a/packages/create-nx-workspace/src/create-workspace-options.ts +++ b/packages/create-nx-workspace/src/create-workspace-options.ts @@ -5,6 +5,7 @@ export interface CreateWorkspaceOptions { name: string; // Workspace name (e.g. org name) packageManager: PackageManager; // Package manager to use nxCloud: boolean; // Enable Nx Cloud + presetVersion?: string; // Version of the preset to use /** * @description Enable interactive mode with presets * @default true diff --git a/packages/nx-plugin/generators.json b/packages/nx-plugin/generators.json index ca43c9bbb4b0d..365be5458f412 100644 --- a/packages/nx-plugin/generators.json +++ b/packages/nx-plugin/generators.json @@ -11,7 +11,7 @@ "create-package": { "factory": "./src/generators/create-package/create-package", "schema": "./src/generators/create-package/schema.json", - "description": "Create a framework package that uses Nx CLI" + "description": "Create a package which can be used by npx to create a new workspace" }, "e2e-project": { "factory": "./src/generators/e2e-project/e2e", @@ -55,7 +55,7 @@ "create-package": { "factory": "./src/generators/create-package/create-package#createPackageSchematic", "schema": "./src/generators/create-package/schema.json", - "description": "Create a framework package that uses Nx CLI" + "description": "Create a package which can be used by npx to create a new workspace" }, "e2e-project": { "factory": "./src/generators/e2e-project/e2e#e2eProjectSchematic", diff --git a/packages/nx-plugin/src/executors/e2e/e2e.impl.ts b/packages/nx-plugin/src/executors/e2e/e2e.impl.ts index 9d0f5bae29060..d3f2c82eb699f 100644 --- a/packages/nx-plugin/src/executors/e2e/e2e.impl.ts +++ b/packages/nx-plugin/src/executors/e2e/e2e.impl.ts @@ -59,7 +59,7 @@ async function runTests( context: ExecutorContext ): Promise { const { success } = await jestExecutor( - { ...jestOptions, watch: false, runInBand: true }, + { runInBand: true, ...jestOptions, watch: false }, context ); diff --git a/packages/nx-plugin/src/generators/create-package/create-package.spec.ts b/packages/nx-plugin/src/generators/create-package/create-package.spec.ts index ca8cdb5ecb619..5e51ddda15ed1 100644 --- a/packages/nx-plugin/src/generators/create-package/create-package.spec.ts +++ b/packages/nx-plugin/src/generators/create-package/create-package.spec.ts @@ -56,6 +56,7 @@ describe('NxPlugin Create Package Generator', () => { assets: [], buildableProjectDepsInPackageJsonType: 'dependencies', }, + dependsOn: ['^build'], }); }); diff --git a/packages/nx-plugin/src/generators/create-package/create-package.ts b/packages/nx-plugin/src/generators/create-package/create-package.ts index 298e06df69acf..16023e4f245b0 100644 --- a/packages/nx-plugin/src/generators/create-package/create-package.ts +++ b/packages/nx-plugin/src/generators/create-package/create-package.ts @@ -7,6 +7,9 @@ import { convertNxGenerator, formatFiles, updateProjectConfiguration, + updateJson, + GeneratorCallback, + runTasksInSerial, } from '@nrwl/devkit'; import { libraryGenerator as jsLibraryGenerator } from '@nrwl/js'; import { join } from 'path'; @@ -14,11 +17,14 @@ import { nxVersion } from '../../utils/versions'; import generatorGenerator from '../generator/generator'; import { CreatePackageSchema } from './schema'; import { NormalizedSchema, normalizeSchema } from './utils/normalize-schema'; +import e2eProjectGenerator from '../e2e-project/e2e'; export async function createPackageGenerator( host: Tree, schema: CreatePackageSchema ) { + const tasks: GeneratorCallback[] = []; + const options = normalizeSchema(host, schema); const pluginPackageName = await addPresetGenerator(host, { ...options, @@ -27,20 +33,23 @@ export async function createPackageGenerator( const installTask = addDependenciesToPackageJson( host, - {}, { 'create-nx-workspace': nxVersion, - } + }, + {} ); + tasks.push(installTask); await createCliPackage(host, options, pluginPackageName); - addTestsToE2eProject(host, options, pluginPackageName); + if (options.e2eTestRunner !== 'none') { + tasks.push(await addE2eProject(host, options, pluginPackageName)); + } if (!options.skipFormat) { await formatFiles(host); } - return installTask; + return runTasksInSerial(...tasks); } /** @@ -74,24 +83,24 @@ async function createCliPackage( ...options, rootProject: false, config: 'project', - buildable: true, publishable: true, bundler: options.bundler, importPath: options.importPath, + skipTsConfig: true, }); host.delete(join(options.projectRoot, 'src')); // Add the bin entry to the package.json - const packageJsonPath = join(options.projectRoot, 'package.json'); - const packageJson = readJson(host, packageJsonPath); - packageJson.bin = { - [options.name]: './bin/index.js', - }; - packageJson.dependencies = { - 'create-nx-workspace': nxVersion, - }; - host.write(packageJsonPath, JSON.stringify(packageJson)); + updateJson(host, join(options.projectRoot, 'package.json'), (packageJson) => { + packageJson.bin = { + [options.name]: './bin/index.js', + }; + packageJson.dependencies = { + 'create-nx-workspace': nxVersion, + }; + return packageJson; + }); // update project build target to use the bin entry const projectConfiguration = readProjectConfiguration( @@ -105,13 +114,19 @@ async function createCliPackage( ); projectConfiguration.targets.build.options.buildableProjectDepsInPackageJsonType = 'dependencies'; + projectConfiguration.targets.build.dependsOn = ['^build']; + projectConfiguration.implicitDependencies = [options.project]; updateProjectConfiguration(host, options.projectName, projectConfiguration); // Add bin files to tsconfg.lib.json - const tsConfigPath = join(options.projectRoot, 'tsconfig.lib.json'); - const tsConfig = readJson(host, tsConfigPath); - tsConfig.include.push('bin/**/*.ts'); - host.write(tsConfigPath, JSON.stringify(tsConfig)); + updateJson( + host, + join(options.projectRoot, 'tsconfig.lib.json'), + (tsConfig) => { + tsConfig.include.push('bin/**/*.ts'); + return tsConfig; + } + ); generateFiles( host, @@ -125,21 +140,13 @@ async function createCliPackage( ); } -function getE2eProjectConfiguration(host: Tree, e2eProjectName: string) { - try { - return readProjectConfiguration(host, e2eProjectName); - } catch (e) { - return; - } -} - /** * Add a test file to plugin e2e project * @param host * @param options * @returns */ -function addTestsToE2eProject( +async function addE2eProject( host: Tree, options: NormalizedSchema, pluginPackageName: string @@ -158,12 +165,30 @@ function addTestsToE2eProject( const cliOutputPath = cliProjectConfiguration.targets.build.options.outputPath; - const e2eProjectConfiguration = - getE2eProjectConfiguration(host, 'e2e') ?? - getE2eProjectConfiguration(host, `${options.project}-e2e`); - if (!e2eProjectConfiguration) { - return; // e2e project does not exist, do not add tests - } + const e2eTask = await e2eProjectGenerator(host, { + pluginName: options.projectName, + projectDirectory: options.projectDirectory, + pluginOutputPath, + npmPackageName: options.name, + minimal: false, + skipFormat: true, + rootProject: false, + }); + + const e2eProjectConfiguration = readProjectConfiguration( + host, + `${options.projectName}-e2e` + ); + e2eProjectConfiguration.targets.e2e.dependsOn = ['^build']; + updateProjectConfiguration( + host, + e2eProjectConfiguration.name, + e2eProjectConfiguration + ); + + // delete the default e2e test file + host.delete(e2eProjectConfiguration.sourceRoot); + generateFiles( host, join(__dirname, './files/e2e'), @@ -176,6 +201,8 @@ function addTestsToE2eProject( tmpl: '', } ); + + return e2eTask; } export default createPackageGenerator; diff --git a/packages/nx-plugin/src/generators/create-package/files/create-framework-package/bin/index.ts__tmpl__ b/packages/nx-plugin/src/generators/create-package/files/create-framework-package/bin/index.ts__tmpl__ index 06b25a34bf3a0..6d03412ec1bc6 100644 --- a/packages/nx-plugin/src/generators/create-package/files/create-framework-package/bin/index.ts__tmpl__ +++ b/packages/nx-plugin/src/generators/create-package/files/create-framework-package/bin/index.ts__tmpl__ @@ -4,11 +4,18 @@ import { createWorkspace } from 'create-nx-workspace'; async function main() { const name = process.argv[2]; // TODO: use libraries like yargs or enquirer to set your workspace name + if (!name) { + throw new Error('Please provide a name for the workspace'); + } + // TODO: update below to customize the workspace await createWorkspace('<%= preset %>', { name, nxCloud: false, packageManager: 'npm', + // This assumes "<%= preset %>" and "<%= projectName %>" are at the same version + // eslint-disable-next-line @typescript-eslint/no-var-requires + presetVersion: require('../package.json').version, }); console.log(`Successfully created the workspace: ${name}.`); diff --git a/packages/nx-plugin/src/generators/create-package/files/e2e/__name__.spec.ts__tmpl__ b/packages/nx-plugin/src/generators/create-package/files/e2e/__name__.spec.ts__tmpl__ index e73b45d135b4a..fe6751532999b 100644 --- a/packages/nx-plugin/src/generators/create-package/files/e2e/__name__.spec.ts__tmpl__ +++ b/packages/nx-plugin/src/generators/create-package/files/e2e/__name__.spec.ts__tmpl__ @@ -1,36 +1,29 @@ import { - ensureNxProject, uniq, runCreatePackageCli, - runNxCommandAsync + removeTmpProject, } from '@nrwl/nx-plugin/testing'; describe('<%= name %> e2e', () => { - // Setting up individual workspaces per - // test can cause e2e runs to take a long time. - // For this reason, we recommend each suite only - // consumes 1 workspace. The tests should each operate - // on a unique project in the workspace, such that they - // are not dependant on one another. - beforeAll(() => { - ensureNxProject('<%= pluginPackageName %>', '<%= pluginOutputPath %>'); - }); + const project = uniq('<%= name %>'); + let createPackageResult; - afterAll(() => { - // `nx reset` kills the daemon, and performs - // some work which can help clean up e2e leftovers - runNxCommandAsync('reset'); - }); - - it('should run <%= name %>', () => { - const project = uniq('<%= name %>'); - const result = runCreatePackageCli( + beforeAll(async () => { + // Create project using CLI command + createPackageResult = await runCreatePackageCli( '<%= pluginPackageName %>', '<%= pluginOutputPath %>', - '<%= name %>', '<%= cliOutputPath %>', project ); - expect(result).toContain('Successfully created'); - }, 120000); + }, 240_000); + + afterAll(() => { + // Remove the generated project from the file system + removeTmpProject(project); + }); + + it('should create project using <%= name %>', () => { + expect(createPackageResult).toContain('Successfully created'); + }); }); diff --git a/packages/nx-plugin/src/generators/create-package/schema.d.ts b/packages/nx-plugin/src/generators/create-package/schema.d.ts index b1c97caf33079..10cfc1e904186 100644 --- a/packages/nx-plugin/src/generators/create-package/schema.d.ts +++ b/packages/nx-plugin/src/generators/create-package/schema.d.ts @@ -1,3 +1,5 @@ +import type { Linter } from '@nrwl/linter'; + export interface CreatePackageSchema { name: string; project: string; @@ -12,5 +14,7 @@ export interface CreatePackageSchema { setParserOptionsProject?: boolean; compiler: 'swc' | 'tsc'; importPath?: string; - rootProject?: boolean; + + // options to create e2e project, passed to e2e project generator + e2eTestRunner?: 'jest' | 'none'; } diff --git a/packages/nx-plugin/src/generators/create-package/schema.json b/packages/nx-plugin/src/generators/create-package/schema.json index 1ee36f38b6d69..682ea3459c436 100644 --- a/packages/nx-plugin/src/generators/create-package/schema.json +++ b/packages/nx-plugin/src/generators/create-package/schema.json @@ -72,6 +72,12 @@ "importPath": { "type": "string", "description": "How the plugin will be published, like `create-framework-app`. Note this must be a valid NPM name. Will use name if not provided." + }, + "e2eTestRunner": { + "type": "string", + "enum": ["jest", "none"], + "description": "Test runner to use for end to end (E2E) tests.", + "default": "jest" } }, "required": ["name", "project"] diff --git a/packages/nx-plugin/src/generators/plugin/plugin.ts b/packages/nx-plugin/src/generators/plugin/plugin.ts index 5c566e67bc97a..318f9835acc75 100644 --- a/packages/nx-plugin/src/generators/plugin/plugin.ts +++ b/packages/nx-plugin/src/generators/plugin/plugin.ts @@ -81,7 +81,6 @@ export async function pluginGenerator(host: Tree, schema: Schema) { ...schema, config: 'project', bundler: options.bundler, - buildable: true, publishable: true, importPath: options.npmPackageName, skipFormat: true, diff --git a/packages/nx-plugin/src/generators/preset/generator.ts b/packages/nx-plugin/src/generators/preset/generator.ts index d4a99112b543d..db52f95d30e77 100644 --- a/packages/nx-plugin/src/generators/preset/generator.ts +++ b/packages/nx-plugin/src/generators/preset/generator.ts @@ -5,6 +5,7 @@ import { readNxJson, formatFiles, runTasksInSerial, + GeneratorCallback, } from '@nx/devkit'; import { Linter } from '@nx/linter'; import { PackageJson } from 'nx/src/utils/package-json'; @@ -13,6 +14,7 @@ import { PresetGeneratorSchema } from './schema'; import createPackageGenerator from '../create-package/create-package'; export default async function (tree: Tree, options: PresetGeneratorSchema) { + const tasks: GeneratorCallback[] = []; const pluginTask = await pluginGenerator(tree, { compiler: 'tsc', linter: Linter.EsLint, @@ -27,25 +29,28 @@ export default async function (tree: Tree, options: PresetGeneratorSchema) { rootProject: true, e2eTestRunner: 'jest', }); + tasks.push(pluginTask); removeNpmScope(tree); moveNxPluginToDevDeps(tree); - const cliTask = await createPackageGenerator(tree, { - name: options.cliName ?? `create-${options.pluginName}-package`, - project: options.pluginName, - skipFormat: true, - skipTsConfig: false, - unitTestRunner: 'jest', - linter: Linter.EsLint, - setParserOptionsProject: false, - compiler: 'tsc', - rootProject: true, - }); + if (options.createPackageName) { + const cliTask = await createPackageGenerator(tree, { + name: options.createPackageName, + project: options.pluginName, + skipFormat: true, + skipTsConfig: false, + unitTestRunner: 'jest', + linter: Linter.EsLint, + setParserOptionsProject: false, + compiler: 'tsc', + }); + tasks.push(cliTask); + } await formatFiles(tree); - return runTasksInSerial(pluginTask, cliTask); + return runTasksInSerial(...tasks); } function removeNpmScope(tree: Tree) { diff --git a/packages/nx-plugin/src/generators/preset/schema.d.ts b/packages/nx-plugin/src/generators/preset/schema.d.ts index 897d0b7e10c5a..b7ed9dfbb5367 100644 --- a/packages/nx-plugin/src/generators/preset/schema.d.ts +++ b/packages/nx-plugin/src/generators/preset/schema.d.ts @@ -1,4 +1,4 @@ export interface PresetGeneratorSchema { pluginName: string; - cliName?: string; + createPackageName?: string; } diff --git a/packages/nx-plugin/src/generators/preset/schema.json b/packages/nx-plugin/src/generators/preset/schema.json index edb0cdf69a84b..b59a3f317c6e7 100644 --- a/packages/nx-plugin/src/generators/preset/schema.json +++ b/packages/nx-plugin/src/generators/preset/schema.json @@ -11,10 +11,9 @@ "description": "Plugin name", "aliases": ["name"] }, - "cliName": { + "createPackageName": { "type": "string", - "description": "Name of cli command to create workspace with plugin", - "aliases": ["name"] + "description": "Name of package which creates a workspace" } }, "required": ["pluginName"] diff --git a/packages/nx-plugin/src/utils/testing-utils/async-commands.ts b/packages/nx-plugin/src/utils/testing-utils/async-commands.ts index 08785b3240fdd..718b061df54ec 100644 --- a/packages/nx-plugin/src/utils/testing-utils/async-commands.ts +++ b/packages/nx-plugin/src/utils/testing-utils/async-commands.ts @@ -13,14 +13,13 @@ export function runCommandAsync( command: string, opts: { silenceError?: boolean; env?: NodeJS.ProcessEnv; cwd?: string } = { silenceError: false, - cwd: tmpProjPath(), } ): Promise<{ stdout: string; stderr: string }> { return new Promise((resolve, reject) => { exec( command, { - cwd: opts.cwd, + cwd: opts.cwd ?? tmpProjPath(), env: { ...process.env, ...opts.env }, }, (err, stdout, stderr) => { @@ -42,7 +41,6 @@ export function runNxCommandAsync( command: string, opts: { silenceError?: boolean; env?: NodeJS.ProcessEnv; cwd?: string } = { silenceError: false, - cwd: tmpProjPath(), } ): Promise<{ stdout: string; stderr: string }> { if (fileExists(tmpProjPath('package.json'))) { diff --git a/packages/nx-plugin/src/utils/testing-utils/commands.ts b/packages/nx-plugin/src/utils/testing-utils/commands.ts index 7fc27d1ad9e43..1cbbee3b9755a 100644 --- a/packages/nx-plugin/src/utils/testing-utils/commands.ts +++ b/packages/nx-plugin/src/utils/testing-utils/commands.ts @@ -14,7 +14,6 @@ export function runNxCommand( command?: string, opts: { silenceError?: boolean; env?: NodeJS.ProcessEnv; cwd?: string } = { silenceError: false, - cwd: tmpProjPath(), } ): string { function _runNxCommand(c) { @@ -51,11 +50,11 @@ export function runNxCommand( export function runCommand( command: string, - opts: { env?: NodeJS.ProcessEnv; cwd?: string } = { cwd: tmpProjPath() } + opts: { env?: NodeJS.ProcessEnv; cwd?: string } ): string { try { return execSync(command, { - cwd: opts.cwd, + cwd: opts.cwd ?? tmpProjPath(), stdio: ['pipe', 'pipe', 'pipe'], env: { ...process.env, ...opts?.env }, }).toString(); diff --git a/packages/nx-plugin/src/utils/testing-utils/create-package-cli.ts b/packages/nx-plugin/src/utils/testing-utils/create-package-cli.ts index fc4c660e9586f..4efff9a20b0b1 100644 --- a/packages/nx-plugin/src/utils/testing-utils/create-package-cli.ts +++ b/packages/nx-plugin/src/utils/testing-utils/create-package-cli.ts @@ -1,6 +1,6 @@ -import { workspaceRoot } from '@nrwl/devkit'; -import { runCommand, runNxCommand } from './commands'; -import { tmpProjPath } from './paths'; +import { names, workspaceRoot } from '@nrwl/devkit'; +import { tmpFolder } from './paths'; +import { fork } from 'child_process'; /** * This function is used to run the create package CLI command. @@ -8,7 +8,6 @@ import { tmpProjPath } from './paths'; * It needs to be ran inside an Nx project. It would assume that an Nx project already exists. * @param pluginLibraryName e.g. my-plugin * @param pluginLibraryBuildPath e.g. dist/packages/my-plugin - * @param createPackageLibraryName e.g. create-my-plugin-package * @param createPackageLibraryBuildPath e.g. dist/packages/create-my-plugin-package * @param projectToBeCreated project name to be created using the cli * @returns results for the create package command @@ -16,24 +15,50 @@ import { tmpProjPath } from './paths'; export function runCreatePackageCli( pluginLibraryName: string, pluginLibraryBuildPath: string, - createPackageLibraryName: string, createPackageLibraryBuildPath: string, projectToBeCreated: string -) { - runNxCommand(`build ${createPackageLibraryName}`, { - cwd: process.cwd(), +): Promise { + return new Promise((resolve, reject) => { + const childProcess = fork( + `${workspaceRoot}/${createPackageLibraryBuildPath}/bin/index.js`, + [projectToBeCreated, '--verbose'], + { + stdio: ['pipe', 'pipe', 'pipe', 'ipc'], + env: { + ...process.env, + [`NX_E2E_${ + names(pluginLibraryName).constantName + }_VERSION`]: `file:${workspaceRoot}/${pluginLibraryBuildPath}`, + NX_VERBOSE_LOGGING: 'true', + }, + cwd: tmpFolder(), + } + ); + + // Ensure the child process is killed when the parent exits + process.on('exit', () => childProcess.kill()); + process.on('SIGTERM', () => childProcess.kill()); + + let allMessages = ''; + childProcess.on('message', (message) => { + allMessages += message; + }); + childProcess.stdout.on('data', (data) => { + allMessages += data; + }); + childProcess.on('error', (error) => { + reject(error); + }); + childProcess.on('exit', (code) => { + if (code === 0) { + resolve(allMessages); + } else { + reject(allMessages); + } + }); }); - return runCommand( - `node ${workspaceRoot}/${createPackageLibraryBuildPath}/bin/index.js ${projectToBeCreated} --verbose`, - { - env: { - [pluginLibraryName]: `file:${workspaceRoot}/${pluginLibraryBuildPath}`, - }, - cwd: tmpProjPath(), - } - ); } export function generatedPackagePath(projectToBeCreated: string) { - return `${tmpProjPath}/${projectToBeCreated}`; + return `${tmpFolder()}/${projectToBeCreated}`; } diff --git a/packages/nx-plugin/src/utils/testing-utils/nx-project.ts b/packages/nx-plugin/src/utils/testing-utils/nx-project.ts index 06a252f06e9ae..9e58900297788 100644 --- a/packages/nx-plugin/src/utils/testing-utils/nx-project.ts +++ b/packages/nx-plugin/src/utils/testing-utils/nx-project.ts @@ -69,9 +69,7 @@ export function newNxProject( pluginDistPath: string ): void { cleanup(); - if (!directoryExists(tmpProjPath())) { - runNxNewCommand('', true); - } + runNxNewCommand('', true); patchPackageJsonForPlugin(npmPackageName, pluginDistPath); runPackageManagerInstall(); } diff --git a/packages/nx-plugin/src/utils/testing-utils/paths.ts b/packages/nx-plugin/src/utils/testing-utils/paths.ts index a743052272173..8defb9e6e0b3e 100644 --- a/packages/nx-plugin/src/utils/testing-utils/paths.ts +++ b/packages/nx-plugin/src/utils/testing-utils/paths.ts @@ -1,3 +1,7 @@ +export function tmpFolder() { + return `${process.cwd()}/tmp`; +} + /** * The directory where the e2e workspace resides in. * @@ -6,8 +10,8 @@ */ export function tmpProjPath(path?: string) { return path - ? `${process.cwd()}/tmp/nx-e2e/proj/${path}` - : `${process.cwd()}/tmp/nx-e2e/proj`; + ? `${tmpFolder()}/nx-e2e/proj/${path}` + : `${tmpFolder()}/nx-e2e/proj`; } /** diff --git a/packages/nx-plugin/src/utils/testing-utils/utils.ts b/packages/nx-plugin/src/utils/testing-utils/utils.ts index efb9502082085..33e1c1a341d5a 100644 --- a/packages/nx-plugin/src/utils/testing-utils/utils.ts +++ b/packages/nx-plugin/src/utils/testing-utils/utils.ts @@ -9,7 +9,7 @@ import { writeFileSync, } from 'fs-extra'; import { dirname, isAbsolute } from 'path'; -import { tmpProjPath } from './paths'; +import { tmpFolder, tmpProjPath } from './paths'; import { parseJson } from '@nx/devkit'; import type { JsonParseOptions } from '@nx/devkit'; import { directoryExists, fileExists } from 'nx/src/utils/fileutils'; @@ -125,9 +125,7 @@ export function readFile(path: string): string { * Deletes the e2e directory */ export function cleanup(): void { - try { - removeSync(tmpProjPath()); - } catch (e) {} + removeSync(tmpProjPath()); } /** @@ -137,6 +135,10 @@ export function rmDist(): void { removeSync(`${tmpProjPath()}/dist`); } +export function removeTmpProject(project: string): void { + removeSync(`${tmpFolder()}/${project}`); +} + /** * Get the currend `cwd` in the process */ diff --git a/packages/workspace/src/generators/new/generate-preset.ts b/packages/workspace/src/generators/new/generate-preset.ts index a52f2a9dc5b46..6ea3b6752260a 100644 --- a/packages/workspace/src/generators/new/generate-preset.ts +++ b/packages/workspace/src/generators/new/generate-preset.ts @@ -2,6 +2,7 @@ import { addDependenciesToPackageJson, getPackageManagerCommand, Tree, + names, } from '@nx/devkit'; import { Preset } from '../utils/presets'; import { @@ -150,7 +151,9 @@ function getPresetDependencies({ default: { presetVersion = - presetVersion ?? getNpmPackageVersion(preset) ?? process.env?.[preset]; // read from env variable for e2e testing + process.env?.[`NX_E2E_${names(preset).constantName}_VERSION`] ?? // read from env variable for e2e testing + presetVersion ?? + getNpmPackageVersion(preset); return { dev: {}, dependencies: { diff --git a/packages/workspace/src/generators/new/new.ts b/packages/workspace/src/generators/new/new.ts index bb9e7b1397826..006245e161e52 100644 --- a/packages/workspace/src/generators/new/new.ts +++ b/packages/workspace/src/generators/new/new.ts @@ -30,6 +30,7 @@ interface Schema { standaloneApi?: boolean; routing?: boolean; packageManager?: PackageManager; + presetVersion?: string; } export interface NormalizedSchema extends Schema {