From 4cac0fd27283bcc37381411323989443441e15db Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Tue, 18 Apr 2023 17:47:06 -0400 Subject: [PATCH] feat(nx-plugin): slim down default generated nx-plugin (#16168) --- docs/generated/manifests/packages.json | 2 +- docs/generated/packages-metadata.json | 2 +- .../nx-plugin/generators/e2e-project.json | 2 +- .../nx-plugin/generators/executor.json | 5 ++ .../nx-plugin/generators/generator.json | 11 ++++ .../nx-plugin/generators/migration.json | 5 ++ .../generators/plugin-lint-checks.json | 6 ++ .../packages/nx-plugin/generators/plugin.json | 8 +-- e2e/nx-plugin/src/nx-plugin.test.ts | 57 ++++++----------- e2e/utils/create-project-utils.ts | 8 +-- .../src/create-nx-plugin.test.ts | 14 ++-- packages/nx-plugin/generators.json | 6 +- .../src/generators/e2e-project/e2e.spec.ts | 18 ------ .../src/generators/e2e-project/e2e.ts | 1 - .../tests/__pluginName__.spec.ts__tmpl__ | 42 +++--------- .../src/generators/e2e-project/schema.d.ts | 1 - .../src/generators/executor/executor.spec.ts | 2 +- .../src/generators/executor/executor.ts | 29 +++++++-- .../hasher/__fileName__/hasher.ts__tmpl__ | 2 +- .../src/generators/executor/schema.d.ts | 1 + .../src/generators/executor/schema.json | 5 ++ .../generators/generator/generator.spec.ts | 17 ++++- .../src/generators/generator/generator.ts | 50 ++++++++++++--- .../src/generators/generator/schema.d.ts | 2 + .../src/generators/generator/schema.json | 11 ++++ .../generators/lint-checks/generator.spec.ts | 51 ++++++++++----- .../src/generators/lint-checks/generator.ts | 36 +++++++---- .../src/generators/lint-checks/schema.d.ts | 1 + .../src/generators/lint-checks/schema.json | 6 ++ .../__name__/__name__.spec.ts__tmpl__ | 17 +++++ .../src/generators/migration/schema.json | 5 ++ .../src/generators/plugin/plugin.spec.ts | 64 ++----------------- .../nx-plugin/src/generators/plugin/plugin.ts | 16 ----- .../src/generators/plugin/schema.d.ts | 1 - .../src/generators/plugin/schema.json | 10 +-- .../src/generators/preset/generator.spec.ts | 3 +- .../src/generators/preset/generator.ts | 10 +-- .../specify-output-capture.spec.ts | 9 ++- .../update-16-0-0/cli-in-schema-json.spec.ts | 8 +-- packages/nx-plugin/src/utils/has-generator.ts | 32 ++++++++++ 40 files changed, 316 insertions(+), 260 deletions(-) create mode 100644 packages/nx-plugin/src/generators/migration/files/migration/__name__/__name__.spec.ts__tmpl__ create mode 100644 packages/nx-plugin/src/utils/has-generator.ts diff --git a/docs/generated/manifests/packages.json b/docs/generated/manifests/packages.json index 7f59d6116e8b53..0677bcc53f8a07 100644 --- a/docs/generated/manifests/packages.json +++ b/docs/generated/manifests/packages.json @@ -1835,7 +1835,7 @@ "/packages/nx-plugin/generators/e2e-project": { "description": "Create a E2E application for a Nx Plugin.", "file": "generated/packages/nx-plugin/generators/e2e-project.json", - "hidden": true, + "hidden": false, "name": "e2e-project", "originalFilePath": "/packages/nx-plugin/src/generators/e2e-project/schema.json", "path": "/packages/nx-plugin/generators/e2e-project", diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index 037f6518e19d8f..687e95d7bb48bd 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -1813,7 +1813,7 @@ { "description": "Create a E2E application for a Nx Plugin.", "file": "generated/packages/nx-plugin/generators/e2e-project.json", - "hidden": true, + "hidden": false, "name": "e2e-project", "originalFilePath": "/packages/nx-plugin/src/generators/e2e-project/schema.json", "path": "nx-plugin/generators/e2e-project", diff --git a/docs/generated/packages/nx-plugin/generators/e2e-project.json b/docs/generated/packages/nx-plugin/generators/e2e-project.json index 84497269109df4..b3af7aa2c8eaa0 100644 --- a/docs/generated/packages/nx-plugin/generators/e2e-project.json +++ b/docs/generated/packages/nx-plugin/generators/e2e-project.json @@ -57,9 +57,9 @@ "presets": [] }, "description": "Create a E2E application for a Nx Plugin.", - "hidden": true, "implementation": "/packages/nx-plugin/src/generators/e2e-project/e2e.ts", "aliases": [], + "hidden": false, "path": "/packages/nx-plugin/src/generators/e2e-project/schema.json", "type": "generator" } diff --git a/docs/generated/packages/nx-plugin/generators/executor.json b/docs/generated/packages/nx-plugin/generators/executor.json index 9ee2bc4cc7f07a..bf88b95a5ab945 100644 --- a/docs/generated/packages/nx-plugin/generators/executor.json +++ b/docs/generated/packages/nx-plugin/generators/executor.json @@ -44,6 +44,11 @@ "type": "boolean", "default": false, "description": "Should the boilerplate for a custom hasher be generated?" + }, + "skipLintChecks": { + "type": "boolean", + "default": false, + "description": "Do not add an eslint configuration for plugin json files." } }, "required": ["project", "name"], diff --git a/docs/generated/packages/nx-plugin/generators/generator.json b/docs/generated/packages/nx-plugin/generators/generator.json index cf7f13dbe30731..c1b0e78ba7b8bd 100644 --- a/docs/generated/packages/nx-plugin/generators/generator.json +++ b/docs/generated/packages/nx-plugin/generators/generator.json @@ -40,6 +40,17 @@ "enum": ["jest", "none"], "description": "Test runner to use for unit tests.", "default": "jest" + }, + "skipLintChecks": { + "type": "boolean", + "default": false, + "description": "Do not add an eslint configuration for plugin json files." + }, + "skipFormat": { + "type": "boolean", + "default": false, + "description": "Do not format files with prettier.", + "x-priority": "internal" } }, "required": ["project", "name"], diff --git a/docs/generated/packages/nx-plugin/generators/migration.json b/docs/generated/packages/nx-plugin/generators/migration.json index 58582d0cff637f..9f95532c3e4f1c 100644 --- a/docs/generated/packages/nx-plugin/generators/migration.json +++ b/docs/generated/packages/nx-plugin/generators/migration.json @@ -45,6 +45,11 @@ "description": "Whether or not to include `package.json` updates.", "alias": "p", "default": false + }, + "skipLintChecks": { + "type": "boolean", + "default": false, + "description": "Do not eslint configuration for plugin json files." } }, "required": ["project", "packageVersion"], diff --git a/docs/generated/packages/nx-plugin/generators/plugin-lint-checks.json b/docs/generated/packages/nx-plugin/generators/plugin-lint-checks.json index 5ff3727e42ca2d..b8d94bed459657 100644 --- a/docs/generated/packages/nx-plugin/generators/plugin-lint-checks.json +++ b/docs/generated/packages/nx-plugin/generators/plugin-lint-checks.json @@ -14,6 +14,12 @@ "description": "Which project should be the configuration be added to?", "$default": { "$source": "projectName" }, "x-priority": "important" + }, + "skipFormat": { + "type": "boolean", + "x-priority": "internal", + "description": "Skip formatting files with prettier.", + "default": false } }, "required": ["projectName"], diff --git a/docs/generated/packages/nx-plugin/generators/plugin.json b/docs/generated/packages/nx-plugin/generators/plugin.json index e6df079e466627..2bbd845fbe5633 100644 --- a/docs/generated/packages/nx-plugin/generators/plugin.json +++ b/docs/generated/packages/nx-plugin/generators/plugin.json @@ -69,7 +69,7 @@ "type": "string", "enum": ["jest", "none"], "description": "Test runner to use for end to end (E2E) tests.", - "default": "jest" + "default": "none" }, "standaloneConfig": { "description": "Split the project configuration into `/project.json` rather than including it inside `workspace.json`.", @@ -87,15 +87,9 @@ "enum": ["tsc", "swc"], "default": "tsc", "description": "The compiler used by the build and test targets." - }, - "minimal": { - "type": "boolean", - "description": "Generate the plugin with a minimal setup. This would involve not generating a default executor and generator.", - "default": false } }, "required": ["name"], - "additionalProperties": false, "presets": [] }, "description": "Create a Nx Plugin.", diff --git a/e2e/nx-plugin/src/nx-plugin.test.ts b/e2e/nx-plugin/src/nx-plugin.test.ts index 18aa1e6e4dd6c8..5c32f5392e9293 100644 --- a/e2e/nx-plugin/src/nx-plugin.test.ts +++ b/e2e/nx-plugin/src/nx-plugin.test.ts @@ -36,48 +36,18 @@ describe('Nx Plugin', () => { const lintResults = runCLI(`lint ${plugin}`); expect(lintResults).toContain('All files pass linting.'); - expectTestsPass(await runCLIAsync(`test ${plugin}`)); - const buildResults = runCLI(`build ${plugin}`); expect(buildResults).toContain('Done compiling TypeScript files'); checkFilesExist( `dist/libs/${plugin}/package.json`, - `dist/libs/${plugin}/generators.json`, - `dist/libs/${plugin}/executors.json`, - `dist/libs/${plugin}/src/index.js`, - `dist/libs/${plugin}/src/generators/${plugin}/schema.json`, - `dist/libs/${plugin}/src/generators/${plugin}/schema.d.ts`, - `dist/libs/${plugin}/src/generators/${plugin}/generator.js`, - `dist/libs/${plugin}/src/generators/${plugin}/files/src/index.ts__template__`, - `dist/libs/${plugin}/src/executors/build/executor.js`, - `dist/libs/${plugin}/src/executors/build/schema.d.ts`, - `dist/libs/${plugin}/src/executors/build/schema.json` + `dist/libs/${plugin}/src/index.js` ); const project = readJson(`libs/${plugin}/project.json`); expect(project).toMatchObject({ tags: [], }); - const e2eProject = readJson(`apps/${plugin}-e2e/project.json`); - - expect(e2eProject).toMatchObject({ - tags: [], - implicitDependencies: [`${plugin}`], - }); }, 90000); - // the test invoke ensureNxProject, which points to @nrwl/workspace collection - // which walks up the directory to find it in the next repo itself, so it - // doesn't use the collection we are building - // we should change it to point to the right collection using relative path - // TODO: Re-enable this to work with pnpm - it(`should run the plugin's e2e tests`, async () => { - const plugin = uniq('plugin-name'); - runCLI(`generate @nrwl/nx-plugin:plugin ${plugin} --linter=eslint`); - const e2eResults = runCLI(`e2e ${plugin}-e2e`); - expect(e2eResults).toContain('Successfully ran target e2e'); - expect(await killPorts()).toBeTruthy(); - }, 250000); - it('should be able to generate a migration', async () => { const plugin = uniq('plugin'); const version = '1.0.0'; @@ -192,7 +162,9 @@ describe('Nx Plugin', () => { const plugin = uniq('plugin'); const goodGenerator = uniq('good-generator'); const goodExecutor = uniq('good-executor'); + const badExecutorBadImplPath = uniq('bad-executor'); const goodMigration = uniq('good-migration'); + const badFactoryPath = uniq('bad-generator'); const badMigrationVersion = uniq('bad-version'); const missingMigrationVersion = uniq('missing-version'); @@ -204,10 +176,18 @@ describe('Nx Plugin', () => { `generate @nrwl/nx-plugin:generator ${goodGenerator} --project=${plugin}` ); + runCLI( + `generate @nrwl/nx-plugin:generator ${badFactoryPath} --project=${plugin}` + ); + runCLI( `generate @nrwl/nx-plugin:executor ${goodExecutor} --project=${plugin}` ); + runCLI( + `generate @nrwl/nx-plugin:executor ${badExecutorBadImplPath} --project=${plugin}` + ); + runCLI( `generate @nrwl/nx-plugin:migration ${badMigrationVersion} --project=${plugin} --packageVersion="invalid"` ); @@ -223,7 +203,9 @@ describe('Nx Plugin', () => { updateFile(`libs/${plugin}/generators.json`, (f) => { const json = JSON.parse(f); // @proj/plugin:plugin has an invalid implementation path - json.generators[plugin].factory = `./generators/${plugin}/bad-path`; + json.generators[ + badFactoryPath + ].factory = `./generators/${plugin}/bad-path`; // @proj/plugin:non-existant has a missing implementation path amd schema json.generators['non-existant-generator'] = {}; return JSON.stringify(json); @@ -231,8 +213,9 @@ describe('Nx Plugin', () => { updateFile(`libs/${plugin}/executors.json`, (f) => { const json = JSON.parse(f); - // @proj/plugin:build has an invalid implementation path - json.executors['build'].implementation = './executors/build/bad-path'; + // @proj/plugin:badExecutorBadImplPath has an invalid implementation path + json.executors[badExecutorBadImplPath].implementation = + './executors/bad-path'; // @proj/plugin:non-existant has a missing implementation path amd schema json.executors['non-existant-executor'] = {}; return JSON.stringify(json); @@ -246,7 +229,7 @@ describe('Nx Plugin', () => { const results = runCLI(`lint ${plugin}`, { silenceError: true }); expect(results).toContain( - `${plugin}: Implementation path should point to a valid file` + `${badFactoryPath}: Implementation path should point to a valid file` ); expect(results).toContain( `non-existant-generator: Missing required property - \`schema\`` @@ -257,7 +240,7 @@ describe('Nx Plugin', () => { expect(results).not.toContain(goodGenerator); expect(results).toContain( - `build: Implementation path should point to a valid file` + `${badExecutorBadImplPath}: Implementation path should point to a valid file` ); expect(results).toContain( `non-existant-executor: Missing required property - \`schema\`` @@ -389,7 +372,7 @@ describe('Nx Plugin', () => { it('should create a plugin in the specified directory', () => { const plugin = uniq('plugin'); runCLI( - `generate @nrwl/nx-plugin:plugin ${plugin} --linter=eslint --directory subdir ` + `generate @nrwl/nx-plugin:plugin ${plugin} --linter=eslint --directory subdir --e2eTestRunner=jest` ); checkFilesExist(`libs/subdir/${plugin}/package.json`); const pluginProject = readProjectConfig(`subdir-${plugin}`); diff --git a/e2e/utils/create-project-utils.ts b/e2e/utils/create-project-utils.ts index 706edbc3a957e4..d60ac9e50e352d 100644 --- a/e2e/utils/create-project-utils.ts +++ b/e2e/utils/create-project-utils.ts @@ -215,12 +215,10 @@ export function runCreateWorkspace( export function runCreatePlugin( name: string, { - pluginName, packageManager, extraArgs, useDetectedPm = false, }: { - pluginName?: string; packageManager?: 'npm' | 'yarn' | 'pnpm'; extraArgs?: string; useDetectedPm?: boolean; @@ -232,11 +230,7 @@ export function runCreatePlugin( let command = `${ pm.runUninstalledPackage - } create-nx-plugin@${getPublishedVersion()} ${name}`; - - if (pluginName) { - command += ` --pluginName=${pluginName} --no-nxCloud`; - } + } create-nx-plugin@${getPublishedVersion()} ${name} --no-nxCloud`; if (packageManager && !useDetectedPm) { command += ` --package-manager=${packageManager}`; diff --git a/e2e/workspace-create/src/create-nx-plugin.test.ts b/e2e/workspace-create/src/create-nx-plugin.test.ts index 4611479b83609a..6ffb3b967eee84 100644 --- a/e2e/workspace-create/src/create-nx-plugin.test.ts +++ b/e2e/workspace-create/src/create-nx-plugin.test.ts @@ -14,13 +14,11 @@ describe('create-nx-plugin', () => { afterEach(() => cleanupProject()); - it('should be able to create a plugin repo and run plugin e2e', () => { - const wsName = uniq('ws-plugin'); + it('should be able to create a plugin repo build a plugin', () => { const pluginName = uniq('plugin'); - runCreatePlugin(wsName, { + runCreatePlugin(pluginName, { packageManager, - pluginName, }); checkFilesExist( @@ -31,6 +29,12 @@ describe('create-nx-plugin', () => { `executors.json` ); - expect(() => runCLI(`e2e e2e`)).not.toThrow(); + runCLI(`build ${pluginName}`); + + checkFilesExist( + `dist/package.json`, + `dist/generators.json`, + `dist/executors.json` + ); }); }); diff --git a/packages/nx-plugin/generators.json b/packages/nx-plugin/generators.json index ca7f38473fc1b7..3d13c99a32cb0a 100644 --- a/packages/nx-plugin/generators.json +++ b/packages/nx-plugin/generators.json @@ -11,8 +11,7 @@ "e2e-project": { "factory": "./src/generators/e2e-project/e2e", "schema": "./src/generators/e2e-project/schema.json", - "description": "Create a E2E application for a Nx Plugin.", - "hidden": true + "description": "Create a E2E application for a Nx Plugin." }, "migration": { "factory": "./src/generators/migration/migration", @@ -51,8 +50,7 @@ "e2e-project": { "factory": "./src/generators/e2e-project/e2e#e2eProjectSchematic", "schema": "./src/generators/e2e-project/schema.json", - "description": "Create a E2E application for a Nx Plugin.", - "hidden": true + "description": "Create a E2E application for a Nx Plugin." }, "migration": { "factory": "./src/generators/migration/migration#migrationSchematic", diff --git a/packages/nx-plugin/src/generators/e2e-project/e2e.spec.ts b/packages/nx-plugin/src/generators/e2e-project/e2e.spec.ts index 25577a106592ba..3dbd3dd2e5bde9 100644 --- a/packages/nx-plugin/src/generators/e2e-project/e2e.spec.ts +++ b/packages/nx-plugin/src/generators/e2e-project/e2e.spec.ts @@ -140,24 +140,6 @@ describe('NxPlugin e2e-project Generator', () => { expect(tree.exists('apps/my-plugin-e2e/jest.config.ts')).toBeTruthy(); }); - it('should not generate tests when minimal flag is passed', async () => { - // ARRANGE & ACT - await e2eProjectGenerator(tree, { - pluginName: 'my-plugin', - pluginOutputPath: `dist/libs/my-plugin`, - npmPackageName: '@proj/my-plugin', - minimal: true, - }); - - const { root } = readProjectConfiguration(tree, 'my-plugin-e2e'); - - // ASSERT - - expect( - tree.read(joinPathFragments(root, 'tests/my-plugin.spec.ts'), 'utf-8') - ).not.toContain("it('should create "); - }); - it('should setup the eslint builder', async () => { await e2eProjectGenerator(tree, { pluginName: 'my-plugin', diff --git a/packages/nx-plugin/src/generators/e2e-project/e2e.ts b/packages/nx-plugin/src/generators/e2e-project/e2e.ts index c4e5c071537514..63784a4b3c6f05 100644 --- a/packages/nx-plugin/src/generators/e2e-project/e2e.ts +++ b/packages/nx-plugin/src/generators/e2e-project/e2e.ts @@ -46,7 +46,6 @@ function normalizeOptions(host: Tree, options: Schema): NormalizedSchema { return { ...options, - minimal: options.minimal ?? false, projectName, linter: options.linter ?? Linter.EsLint, pluginPropertyName, diff --git a/packages/nx-plugin/src/generators/e2e-project/files/tests/__pluginName__.spec.ts__tmpl__ b/packages/nx-plugin/src/generators/e2e-project/files/tests/__pluginName__.spec.ts__tmpl__ index db259c61cc59e1..cd101be7877143 100644 --- a/packages/nx-plugin/src/generators/e2e-project/files/tests/__pluginName__.spec.ts__tmpl__ +++ b/packages/nx-plugin/src/generators/e2e-project/files/tests/__pluginName__.spec.ts__tmpl__ @@ -3,6 +3,7 @@ import { ensureNxProject, readJson, runNxCommandAsync, + runNxCommand, uniq, } from '@nx/nx-plugin/testing'; @@ -23,39 +24,14 @@ describe('<%= pluginName %> e2e', () => { runNxCommandAsync('reset'); }); - <% if(!minimal) { %> - it('should create <%= pluginName %>', async () => { - const project = uniq('<%= pluginName %>'); - await runNxCommandAsync( - `generate <%=npmPackageName%>:<%= pluginName %> ${project}` - ); - const result = await runNxCommandAsync(`build ${project}`); - expect(result.stdout).toContain('Executor ran'); - }, 120000); - - describe('--directory', () => { - it('should create src in the specified directory', async () => { - const project = uniq('<%= pluginName %>'); - await runNxCommandAsync( - `generate <%=npmPackageName%>:<%= pluginName %> ${project} --directory subdir` - ); - expect(() => - checkFilesExist(`libs/subdir/${project}/src/index.ts`) - ).not.toThrow(); - }, 120000); - }); - - describe('--tags', () => { - it('should add tags to the project', async () => { - const projectName = uniq('<%= pluginName %>'); - ensureNxProject('<%= npmPackageName %>', '<%= pluginOutputPath %>'); - await runNxCommandAsync( - `generate <%=npmPackageName%>:<%= pluginName %> ${projectName} --tags e2etag,e2ePackage` - ); - const project = readJson(`libs/${projectName}/project.json`); - expect(project.tags).toEqual(['e2etag', 'e2ePackage']); - }, 120000); + // Add some tests here to check that your plugin functionality works as expected. + // A sample test is included below to give you some ideas. + xit('should be able to build generated projects', async () => { + const name = uniq('proj'); + const generator = 'PLACEHOLDER'; + await runNxCommandAsync(`generate <%= npmPackageName %>:${generator} --name ${name}`); + expect(() => runNxCommand('build ${proj}')).not.toThrow(); + expect(() => checkFilesExist([`dist/${name}/index.js`])).not.toThrow(); }); - <% } %> }); diff --git a/packages/nx-plugin/src/generators/e2e-project/schema.d.ts b/packages/nx-plugin/src/generators/e2e-project/schema.d.ts index 124cd79bbc386c..1e43a456eae339 100644 --- a/packages/nx-plugin/src/generators/e2e-project/schema.d.ts +++ b/packages/nx-plugin/src/generators/e2e-project/schema.d.ts @@ -6,7 +6,6 @@ export interface Schema { projectDirectory?: string; pluginOutputPath?: string; jestConfig?: string; - minimal?: boolean; linter?: Linter; skipFormat?: boolean; rootProject?: boolean; diff --git a/packages/nx-plugin/src/generators/executor/executor.spec.ts b/packages/nx-plugin/src/generators/executor/executor.spec.ts index dfeca846f5a775..ba46b4227c6b59 100644 --- a/packages/nx-plugin/src/generators/executor/executor.spec.ts +++ b/packages/nx-plugin/src/generators/executor/executor.spec.ts @@ -158,7 +158,7 @@ describe('NxPlugin Executor Generator', () => { * you can consume workspace details from the context. */ export const myExecutorHasher: CustomHasher = async (task, context) => { - return context.hasher.hashTask(task) + return context.hasher.hashTask(task); }; export default myExecutorHasher; diff --git a/packages/nx-plugin/src/generators/executor/executor.ts b/packages/nx-plugin/src/generators/executor/executor.ts index ce91248d22c0a6..f24c6ece4b61cc 100644 --- a/packages/nx-plugin/src/generators/executor/executor.ts +++ b/packages/nx-plugin/src/generators/executor/executor.ts @@ -14,6 +14,7 @@ import type { Tree } from '@nx/devkit'; import type { Schema } from './schema'; import * as path from 'path'; import { PackageJson } from 'nx/src/utils/package-json'; +import pluginLintCheckGenerator from '../lint-checks/generator'; interface NormalizedSchema extends Schema { fileName: string; @@ -70,10 +71,15 @@ function addHasherFiles(host: Tree, options: NormalizedSchema) { } } -function createExecutorsJson(host: Tree, options: NormalizedSchema) { +export async function createExecutorsJson( + host: Tree, + projectRoot: string, + projectName: string, + skipLintChecks?: boolean +) { updateJson( host, - joinPathFragments(options.projectRoot, 'package.json'), + joinPathFragments(projectRoot, 'package.json'), (json) => { json.executors ??= './executors.json'; return json; @@ -81,18 +87,24 @@ function createExecutorsJson(host: Tree, options: NormalizedSchema) { ); writeJson( host, - joinPathFragments(options.projectRoot, 'executors.json'), + joinPathFragments(projectRoot, 'executors.json'), { executors: {}, } ); + if (!skipLintChecks) { + await pluginLintCheckGenerator(host, { + projectName, + }); + } } -function updateExecutorJson(host: Tree, options: NormalizedSchema) { +async function updateExecutorJson(host: Tree, options: NormalizedSchema) { const packageJson = readJson( host, joinPathFragments(options.projectRoot, 'package.json') ); + const packageJsonExecutors = packageJson.executors ?? packageJson.builders; let executorsPath = packageJsonExecutors ? joinPathFragments(options.projectRoot, packageJsonExecutors) @@ -102,7 +114,12 @@ function updateExecutorJson(host: Tree, options: NormalizedSchema) { executorsPath = joinPathFragments(options.projectRoot, 'executors.json'); } if (!host.exists(executorsPath)) { - createExecutorsJson(host, options); + await createExecutorsJson( + host, + options.projectRoot, + options.project, + options.skipLintChecks + ); } return updateJson(host, executorsPath, (json) => { @@ -158,7 +175,7 @@ export async function executorGenerator(host: Tree, schema: Schema) { addHasherFiles(host, options); } - updateExecutorJson(host, options); + await updateExecutorJson(host, options); } export default executorGenerator; diff --git a/packages/nx-plugin/src/generators/executor/files/hasher/__fileName__/hasher.ts__tmpl__ b/packages/nx-plugin/src/generators/executor/files/hasher/__fileName__/hasher.ts__tmpl__ index 96f2a77e130605..90639ebc53b6a3 100644 --- a/packages/nx-plugin/src/generators/executor/files/hasher/__fileName__/hasher.ts__tmpl__ +++ b/packages/nx-plugin/src/generators/executor/files/hasher/__fileName__/hasher.ts__tmpl__ @@ -6,7 +6,7 @@ import { CustomHasher } from '@nx/devkit'; * you can consume workspace details from the context. */ export const <%=propertyName%>Hasher: CustomHasher = async (task, context) => { - return context.hasher.hashTask(task) + return context.hasher.hashTask(task); }; export default <%=propertyName%>Hasher; diff --git a/packages/nx-plugin/src/generators/executor/schema.d.ts b/packages/nx-plugin/src/generators/executor/schema.d.ts index 7b67bda9197de6..6946c85d5bbba4 100644 --- a/packages/nx-plugin/src/generators/executor/schema.d.ts +++ b/packages/nx-plugin/src/generators/executor/schema.d.ts @@ -4,4 +4,5 @@ export interface Schema { description?: string; unitTestRunner: 'jest' | 'none'; includeHasher: boolean; + skipLintChecks?: boolean; } diff --git a/packages/nx-plugin/src/generators/executor/schema.json b/packages/nx-plugin/src/generators/executor/schema.json index 79050a4d5f723a..e7d3f1b9467a28 100644 --- a/packages/nx-plugin/src/generators/executor/schema.json +++ b/packages/nx-plugin/src/generators/executor/schema.json @@ -46,6 +46,11 @@ "type": "boolean", "default": false, "description": "Should the boilerplate for a custom hasher be generated?" + }, + "skipLintChecks": { + "type": "boolean", + "default": false, + "description": "Do not add an eslint configuration for plugin json files." } }, "required": ["project", "name"], diff --git a/packages/nx-plugin/src/generators/generator/generator.spec.ts b/packages/nx-plugin/src/generators/generator/generator.spec.ts index df19ec1ccc6634..96df48903232d3 100644 --- a/packages/nx-plugin/src/generators/generator/generator.spec.ts +++ b/packages/nx-plugin/src/generators/generator/generator.spec.ts @@ -65,6 +65,21 @@ describe('NxPlugin Generator Generator', () => { ); }); + it('should throw if recreating an existing generator', async () => { + await generatorGenerator(tree, { + project: projectName, + name: 'my-generator', + unitTestRunner: 'jest', + }); + expect( + generatorGenerator(tree, { + project: projectName, + name: 'my-generator', + unitTestRunner: 'jest', + }) + ).rejects.toThrow('Generator my-generator already exists'); + }); + it('should update generators.json with the same path as where the generator files folder is located', async () => { const generatorName = 'myGenerator'; const generatorFileName = 'my-generator'; @@ -179,8 +194,6 @@ describe('NxPlugin Generator Generator', () => { 'libs/my-plugin/generators.json' ); - console.log(generatorJson.generators['preset']); - expect( generatorJson.generators['preset']['x-use-standalone-layout'] ).toEqual(true); diff --git a/packages/nx-plugin/src/generators/generator/generator.ts b/packages/nx-plugin/src/generators/generator/generator.ts index 3602a9beb5362b..a54670b6d17941 100644 --- a/packages/nx-plugin/src/generators/generator/generator.ts +++ b/packages/nx-plugin/src/generators/generator/generator.ts @@ -1,4 +1,10 @@ -import { GeneratorsJson, joinPathFragments, Tree, writeJson } from '@nx/devkit'; +import { + formatFiles, + GeneratorsJson, + joinPathFragments, + Tree, + writeJson, +} from '@nx/devkit'; import { convertNxGenerator, generateFiles, @@ -10,6 +16,8 @@ import { } from '@nx/devkit'; import { PackageJson } from 'nx/src/utils/package-json'; import * as path from 'path'; +import { hasGenerator } from '../../utils/has-generator'; +import pluginLintCheckGenerator from '../lint-checks/generator'; import type { Schema } from './schema'; interface NormalizedSchema extends Schema { @@ -81,10 +89,16 @@ function addFiles(host: Tree, options: NormalizedSchema) { } } -function createGeneratorsJson(host: Tree, options: NormalizedSchema) { +export async function createGeneratorsJson( + host: Tree, + projectRoot: string, + projectName: string, + skipLintChecks?: boolean, + skipFormat?: boolean +) { updateJson( host, - joinPathFragments(options.projectRoot, 'package.json'), + joinPathFragments(projectRoot, 'package.json'), (json) => { json.generators ??= './generators.json'; return json; @@ -92,14 +106,20 @@ function createGeneratorsJson(host: Tree, options: NormalizedSchema) { ); writeJson( host, - joinPathFragments(options.projectRoot, 'generators.json'), + joinPathFragments(projectRoot, 'generators.json'), { generators: {}, } ); + if (!skipLintChecks) { + await pluginLintCheckGenerator(host, { + projectName, + skipFormat, + }); + } } -function updateGeneratorJson(host: Tree, options: NormalizedSchema) { +async function updateGeneratorJson(host: Tree, options: NormalizedSchema) { const packageJson = readJson( host, joinPathFragments(options.projectRoot, 'package.json') @@ -114,10 +134,16 @@ function updateGeneratorJson(host: Tree, options: NormalizedSchema) { generatorsPath = joinPathFragments(options.projectRoot, 'generators.json'); } if (!host.exists(generatorsPath)) { - createGeneratorsJson(host, options); + await createGeneratorsJson( + host, + options.projectRoot, + options.project, + options.skipLintChecks, + options.skipFormat + ); } - return updateJson(host, generatorsPath, (json) => { + updateJson(host, generatorsPath, (json) => { let generators = json.generators ?? json.schematics; generators = generators || {}; generators[options.name] = { @@ -130,17 +156,23 @@ function updateGeneratorJson(host: Tree, options: NormalizedSchema) { generators[options.name]['x-use-standalone-layout'] = true; } json.generators = generators; - return json; }); } export async function generatorGenerator(host: Tree, schema: Schema) { const options = normalizeOptions(host, schema); + if (hasGenerator(host, options.project, options.name)) { + throw new Error(`Generator ${options.name} already exists.`); + } addFiles(host, options); - updateGeneratorJson(host, options); + await updateGeneratorJson(host, options); + + if (!options.skipFormat) { + await formatFiles(host); + } } export default generatorGenerator; diff --git a/packages/nx-plugin/src/generators/generator/schema.d.ts b/packages/nx-plugin/src/generators/generator/schema.d.ts index c0088067da3af8..653e5d118012d4 100644 --- a/packages/nx-plugin/src/generators/generator/schema.d.ts +++ b/packages/nx-plugin/src/generators/generator/schema.d.ts @@ -3,4 +3,6 @@ export interface Schema { name: string; description?: string; unitTestRunner: 'jest' | 'none'; + skipLintChecks?: boolean; + skipFormat?: boolean; } diff --git a/packages/nx-plugin/src/generators/generator/schema.json b/packages/nx-plugin/src/generators/generator/schema.json index 046a5dc14ebd79..64797fec52f101 100644 --- a/packages/nx-plugin/src/generators/generator/schema.json +++ b/packages/nx-plugin/src/generators/generator/schema.json @@ -42,6 +42,17 @@ "enum": ["jest", "none"], "description": "Test runner to use for unit tests.", "default": "jest" + }, + "skipLintChecks": { + "type": "boolean", + "default": false, + "description": "Do not add an eslint configuration for plugin json files." + }, + "skipFormat": { + "type": "boolean", + "default": false, + "description": "Do not format files with prettier.", + "x-priority": "internal" } }, "required": ["project", "name"], diff --git a/packages/nx-plugin/src/generators/lint-checks/generator.spec.ts b/packages/nx-plugin/src/generators/lint-checks/generator.spec.ts index 8c1b59fbf37ee4..630fa4ea9ae857 100644 --- a/packages/nx-plugin/src/generators/lint-checks/generator.spec.ts +++ b/packages/nx-plugin/src/generators/lint-checks/generator.spec.ts @@ -9,19 +9,22 @@ import { } from '@nx/devkit'; import type { Linter as ESLint } from 'eslint'; +import { Linter } from '@nx/linter'; import { Schema as EsLintExecutorOptions } from '@nx/linter/src/executors/eslint/schema'; import generator from './generator'; import pluginGenerator from '../plugin/plugin'; -import { Linter } from '@nx/linter'; +import generatorGenerator from '../generator/generator'; +import executorGenerator from '../executor/executor'; + import { PackageJson } from 'nx/src/utils/package-json'; describe('lint-checks generator', () => { - let appTree: Tree; + let tree: Tree; beforeEach(async () => { - appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); - await pluginGenerator(appTree, { + tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); + await pluginGenerator(tree, { name: 'plugin', importPath: '@acme/plugin', compiler: 'tsc', @@ -31,14 +34,28 @@ describe('lint-checks generator', () => { skipLintChecks: true, // we manually call it s.t. we can update config files first unitTestRunner: 'jest', }); + await generatorGenerator(tree, { + name: 'my-generator', + project: 'plugin', + unitTestRunner: 'jest', + skipLintChecks: true, + }); + await executorGenerator(tree, { + name: 'my-executor', + project: 'plugin', + unitTestRunner: 'jest', + includeHasher: false, + skipLintChecks: true, + }); }); it('should update configuration files for default plugin', async () => { - await generator(appTree, { projectName: 'plugin' }); - const projectConfig = readProjectConfiguration(appTree, 'plugin'); + await generator(tree, { projectName: 'plugin' }); + + const projectConfig = readProjectConfiguration(tree, 'plugin'); const targetConfig = projectConfig.targets?.['lint']; const eslintConfig: ESLint.Config = readJson( - appTree, + tree, `${projectConfig.root}/.eslintrc.json` ); @@ -66,13 +83,13 @@ describe('lint-checks generator', () => { }); it('should not duplicate configuration', async () => { - await generator(appTree, { projectName: 'plugin' }); - await generator(appTree, { projectName: 'plugin' }); - const projectConfig = readProjectConfiguration(appTree, 'plugin'); + await generator(tree, { projectName: 'plugin' }); + await generator(tree, { projectName: 'plugin' }); + const projectConfig = readProjectConfiguration(tree, 'plugin'); const targetConfig = projectConfig.targets?.['lint'] .options as EsLintExecutorOptions; const eslintConfig: ESLint.Config = readJson( - appTree, + tree, `${projectConfig.root}/.eslintrc.json` ); @@ -88,9 +105,9 @@ describe('lint-checks generator', () => { }); it('should update configuration files for angular-style plugin', async () => { - const startingProjectConfig = readProjectConfiguration(appTree, 'plugin'); + const startingProjectConfig = readProjectConfiguration(tree, 'plugin'); updateJson( - appTree, + tree, joinPathFragments(startingProjectConfig.root, 'package.json'), (json: PackageJson) => { json.schematics = './collection.json'; @@ -102,15 +119,15 @@ describe('lint-checks generator', () => { } ); writeJson( - appTree, + tree, joinPathFragments(startingProjectConfig.root, 'migrations.json'), {} ); - await generator(appTree, { projectName: 'plugin' }); - const projectConfig = readProjectConfiguration(appTree, 'plugin'); + await generator(tree, { projectName: 'plugin' }); + const projectConfig = readProjectConfiguration(tree, 'plugin'); const targetConfig = projectConfig.targets?.['lint']; const eslintConfig: ESLint.Config = readJson( - appTree, + tree, `${projectConfig.root}/.eslintrc.json` ); diff --git a/packages/nx-plugin/src/generators/lint-checks/generator.ts b/packages/nx-plugin/src/generators/lint-checks/generator.ts index 56fd064972e2fb..8f0a43edd148c1 100644 --- a/packages/nx-plugin/src/generators/lint-checks/generator.ts +++ b/packages/nx-plugin/src/generators/lint-checks/generator.ts @@ -1,5 +1,6 @@ import { addDependenciesToPackageJson, + formatFiles, joinPathFragments, logger, ProjectConfiguration, @@ -60,6 +61,11 @@ export default async function pluginLintCheckGenerator( {}, { 'jsonc-eslint-parser': jsoncEslintParserVersion } ); + + if (!options.skipFormat) { + await formatFiles(host); + } + return () => installTask; } @@ -186,27 +192,35 @@ function updateProjectEslintConfig( const eslintPath = `${options.root}/.eslintrc.json`; const eslintConfig = readJson(host, eslintPath); eslintConfig.overrides ??= []; - if ( - !eslintConfig.overrides.some( + let entry: ESLint.ConfigOverride = + eslintConfig.overrides.find( (x) => Object.keys(x.rules ?? {}).includes('@nx/nx/nx-plugin-checks') || Object.keys(x.rules ?? {}).includes('@nrwl/nx/nx-plugin-checks') - ) - ) { - eslintConfig.overrides.push({ - files: [ + ); + const newentry = !entry; + entry ??= { files: [] }; + entry.files = [ + ...new Set([ + ...(entry.files ?? []), + ...[ './package.json', packageJson.generators, packageJson.executors, packageJson.schematics, packageJson.builders, ].filter((f) => !!f), - parser: 'jsonc-eslint-parser', - rules: { - '@nx/nx/nx-plugin-checks': 'error', - }, - }); + ]), + ]; + entry.parser = 'jsonc-eslint-parser'; + entry.rules ??= { + '@nx/nx/nx-plugin-checks': 'error', + }; + + if (newentry) { + eslintConfig.overrides.push(entry); } + writeJson(host, eslintPath, eslintConfig); } diff --git a/packages/nx-plugin/src/generators/lint-checks/schema.d.ts b/packages/nx-plugin/src/generators/lint-checks/schema.d.ts index e268defed66be8..055d6f4c2baeff 100644 --- a/packages/nx-plugin/src/generators/lint-checks/schema.d.ts +++ b/packages/nx-plugin/src/generators/lint-checks/schema.d.ts @@ -1,3 +1,4 @@ export interface PluginLintChecksGeneratorSchema { projectName: string; + skipFormat?: boolean; } diff --git a/packages/nx-plugin/src/generators/lint-checks/schema.json b/packages/nx-plugin/src/generators/lint-checks/schema.json index 8120a6bcf56538..a82390b6a3c525 100644 --- a/packages/nx-plugin/src/generators/lint-checks/schema.json +++ b/packages/nx-plugin/src/generators/lint-checks/schema.json @@ -13,6 +13,12 @@ "$source": "projectName" }, "x-priority": "important" + }, + "skipFormat": { + "type": "boolean", + "x-priority": "internal", + "description": "Skip formatting files with prettier.", + "default": false } }, "required": ["projectName"] diff --git a/packages/nx-plugin/src/generators/migration/files/migration/__name__/__name__.spec.ts__tmpl__ b/packages/nx-plugin/src/generators/migration/files/migration/__name__/__name__.spec.ts__tmpl__ new file mode 100644 index 00000000000000..70e86d21509628 --- /dev/null +++ b/packages/nx-plugin/src/generators/migration/files/migration/__name__/__name__.spec.ts__tmpl__ @@ -0,0 +1,17 @@ +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import { Tree } from '@nx/devkit'; + +import update from './<%= name %>'; + +describe('<%= name %> migration', () => { + let tree: Tree; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace({layout: 'apps-libs'}); + }); + + it('should run successfully', async () => { + await update(tree); + // ... expect changes made + }); +}); diff --git a/packages/nx-plugin/src/generators/migration/schema.json b/packages/nx-plugin/src/generators/migration/schema.json index 5c4b82f2ca4266..73c4282cc4636f 100644 --- a/packages/nx-plugin/src/generators/migration/schema.json +++ b/packages/nx-plugin/src/generators/migration/schema.json @@ -47,6 +47,11 @@ "description": "Whether or not to include `package.json` updates.", "alias": "p", "default": false + }, + "skipLintChecks": { + "type": "boolean", + "default": false, + "description": "Do not eslint configuration for plugin json files." } }, "required": ["project", "packageVersion"], diff --git a/packages/nx-plugin/src/generators/plugin/plugin.spec.ts b/packages/nx-plugin/src/generators/plugin/plugin.spec.ts index 715ad149fec9b8..ff26bacbb84fd8 100644 --- a/packages/nx-plugin/src/generators/plugin/plugin.spec.ts +++ b/packages/nx-plugin/src/generators/plugin/plugin.spec.ts @@ -30,7 +30,7 @@ describe('NxPlugin Plugin Generator', () => { tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); }); - it('should update the workspace.json file', async () => { + it('should update the project configuration', async () => { await pluginGenerator(tree, getSchema()); const project = readProjectConfiguration(tree, 'my-plugin'); expect(project.root).toEqual('libs/my-plugin'); @@ -72,9 +72,7 @@ describe('NxPlugin Plugin Generator', () => { options: { lintFilePatterns: expect.arrayContaining([ 'libs/my-plugin/**/*.ts', - 'libs/my-plugin/generators.json', 'libs/my-plugin/package.json', - 'libs/my-plugin/executors.json', ]), }, }); @@ -108,52 +106,6 @@ describe('NxPlugin Plugin Generator', () => { expect(projectE2e.root).toEqual('apps/plugins/my-plugin-e2e'); }); - it('should create schematic and builder files', async () => { - await pluginGenerator(tree, getSchema({ name: 'myPlugin' })); - - [ - 'libs/my-plugin/project.json', - 'libs/my-plugin/generators.json', - 'libs/my-plugin/executors.json', - 'libs/my-plugin/src/generators/my-plugin/schema.d.ts', - 'libs/my-plugin/src/generators/my-plugin/generator.ts', - 'libs/my-plugin/src/generators/my-plugin/generator.spec.ts', - 'libs/my-plugin/src/generators/my-plugin/schema.json', - 'libs/my-plugin/src/generators/my-plugin/schema.d.ts', - 'libs/my-plugin/src/generators/my-plugin/files/src/index.ts__template__', - 'libs/my-plugin/src/executors/build/executor.ts', - 'libs/my-plugin/src/executors/build/executor.spec.ts', - 'libs/my-plugin/src/executors/build/schema.json', - 'libs/my-plugin/src/executors/build/schema.d.ts', - ].forEach((path) => expect(tree.exists(path)).toBeTruthy()); - - expect( - tree.read( - 'libs/my-plugin/src/generators/my-plugin/files/src/index.ts__template__', - 'utf-8' - ) - ).toContain('const variable = "<%= projectName %>";'); - }); - - it('should not create generator and executor files for minimal setups', async () => { - await pluginGenerator(tree, getSchema({ name: 'myPlugin', minimal: true })); - - expect(tree.exists('libs/my-plugin/project.json')).toBeTruthy(); - - [ - 'libs/my-plugin/src/generators/my-plugin/schema.d.ts', - 'libs/my-plugin/src/generators/my-plugin/generator.ts', - 'libs/my-plugin/src/generators/my-plugin/generator.spec.ts', - 'libs/my-plugin/src/generators/my-plugin/schema.json', - 'libs/my-plugin/src/generators/my-plugin/schema.d.ts', - 'libs/my-plugin/src/generators/my-plugin/files/src/index.ts__template__', - 'libs/my-plugin/src/executors/build/executor.ts', - 'libs/my-plugin/src/executors/build/executor.spec.ts', - 'libs/my-plugin/src/executors/build/schema.json', - 'libs/my-plugin/src/executors/build/schema.d.ts', - ].forEach((path) => expect(tree.exists(path)).toBeFalsy()); - }); - describe('--unitTestRunner', () => { describe('none', () => { it('should not generate test files', async () => { @@ -165,15 +117,13 @@ describe('NxPlugin Plugin Generator', () => { }) ); - [ - 'libs/my-plugin/src/generators/my-plugin/generator.ts', - 'libs/my-plugin/src/executors/build/executor.ts', - ].forEach((path) => expect(tree.exists(path)).toBeTruthy()); + ['libs/my-plugin/jest.config.ts'].forEach((path) => + expect(tree.exists(path)).toBeFalsy() + ); - [ - 'libs/my-plugin/src/generators/my-plugin/generator.spec.ts', - 'libs/my-plugin/src/executors/build/executor.spec.ts', - ].forEach((path) => expect(tree.exists(path)).toBeFalsy()); + expect( + readProjectConfiguration(tree, 'my-plugin').targets.test + ).not.toBeDefined(); }); }); }); diff --git a/packages/nx-plugin/src/generators/plugin/plugin.ts b/packages/nx-plugin/src/generators/plugin/plugin.ts index d1b5b500ff3d3c..2d160d1f560c2f 100644 --- a/packages/nx-plugin/src/generators/plugin/plugin.ts +++ b/packages/nx-plugin/src/generators/plugin/plugin.ts @@ -37,21 +37,6 @@ async function addFiles(host: Tree, options: NormalizedSchema) { tmpl: '', } ); - - if (options.minimal) { - return; - } - await generatorGenerator(host, { - project: options.name, - name: options.name, - unitTestRunner: options.unitTestRunner, - }); - await executorGenerator(host, { - project: options.name, - name: 'build', - unitTestRunner: options.unitTestRunner, - includeHasher: false, - }); } function updatePluginConfig(host: Tree, options: NormalizedSchema) { @@ -126,7 +111,6 @@ export async function pluginGenerator(host: Tree, schema: Schema) { projectDirectory: options.projectDirectory, pluginOutputPath: `dist/${options.libsDir}/${options.projectDirectory}`, npmPackageName: options.npmPackageName, - minimal: options.minimal ?? false, skipFormat: true, rootProject: options.rootProject, }); diff --git a/packages/nx-plugin/src/generators/plugin/schema.d.ts b/packages/nx-plugin/src/generators/plugin/schema.d.ts index a8fbfb616e184b..5de5ce4613354e 100644 --- a/packages/nx-plugin/src/generators/plugin/schema.d.ts +++ b/packages/nx-plugin/src/generators/plugin/schema.d.ts @@ -13,6 +13,5 @@ export interface Schema { linter: Linter; setParserOptionsProject?: boolean; compiler: 'swc' | 'tsc'; - minimal?: boolean; rootProject?: boolean; } diff --git a/packages/nx-plugin/src/generators/plugin/schema.json b/packages/nx-plugin/src/generators/plugin/schema.json index e3fa9902bc4bb6..f8ef7fadfa248d 100644 --- a/packages/nx-plugin/src/generators/plugin/schema.json +++ b/packages/nx-plugin/src/generators/plugin/schema.json @@ -69,7 +69,7 @@ "type": "string", "enum": ["jest", "none"], "description": "Test runner to use for end to end (E2E) tests.", - "default": "jest" + "default": "none" }, "standaloneConfig": { "description": "Split the project configuration into `/project.json` rather than including it inside `workspace.json`.", @@ -87,13 +87,7 @@ "enum": ["tsc", "swc"], "default": "tsc", "description": "The compiler used by the build and test targets." - }, - "minimal": { - "type": "boolean", - "description": "Generate the plugin with a minimal setup. This would involve not generating a default executor and generator.", - "default": false } }, - "required": ["name"], - "additionalProperties": false + "required": ["name"] } diff --git a/packages/nx-plugin/src/generators/preset/generator.spec.ts b/packages/nx-plugin/src/generators/preset/generator.spec.ts index 0b1c1fb7021474..b6e401ffca9d15 100644 --- a/packages/nx-plugin/src/generators/preset/generator.spec.ts +++ b/packages/nx-plugin/src/generators/preset/generator.spec.ts @@ -23,8 +23,7 @@ describe('preset generator', () => { const config = readProjectConfiguration(tree, 'my-plugin'); expect(config).toBeDefined(); const packageJson = readJson(tree, 'package.json'); - expect(packageJson.generators).toEqual('./generators.json'); - expect(packageJson.executors).toEqual('./executors.json'); + expect(packageJson.dependencies).toHaveProperty('@nx/devkit'); expect(readNxJson(tree).npmScope).not.toBeDefined(); }); }); diff --git a/packages/nx-plugin/src/generators/preset/generator.ts b/packages/nx-plugin/src/generators/preset/generator.ts index fcdc3950f958f9..b374968a45f170 100644 --- a/packages/nx-plugin/src/generators/preset/generator.ts +++ b/packages/nx-plugin/src/generators/preset/generator.ts @@ -1,11 +1,4 @@ -import { - Tree, - readJson, - joinPathFragments, - updateJson, - updateNxJson, - readNxJson, -} from '@nx/devkit'; +import { Tree, updateJson, updateNxJson, readNxJson } from '@nx/devkit'; import { Linter } from '@nx/linter'; import { PackageJson } from 'nx/src/utils/package-json'; import { pluginGenerator } from '../plugin/plugin'; @@ -24,6 +17,7 @@ export default async function (tree: Tree, options: PresetGeneratorSchema) { unitTestRunner: 'jest', importPath: options.pluginName, rootProject: true, + e2eTestRunner: 'jest', }); removeNpmScope(tree); diff --git a/packages/nx-plugin/src/migrations/update-15-0-0/specify-output-capture.spec.ts b/packages/nx-plugin/src/migrations/update-15-0-0/specify-output-capture.spec.ts index 4a0f5c23fe7ded..abda3e71db84ae 100644 --- a/packages/nx-plugin/src/migrations/update-15-0-0/specify-output-capture.spec.ts +++ b/packages/nx-plugin/src/migrations/update-15-0-0/specify-output-capture.spec.ts @@ -2,12 +2,13 @@ import { readJson, updateJson } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { Linter } from '@nx/linter'; import { ExecutorConfig } from 'nx/src/config/misc-interfaces'; +import executorGenerator from '../../generators/executor/executor'; import pluginGenerator from '../../generators/plugin/plugin'; import update from './specify-output-capture'; const schemaPath = `libs/plugin/src/executors/build/schema.json`; -describe('update-14-2-0-split-create-empty-tree', () => { +describe('update-15-0-0-specify-output-capture', () => { it('should not change outputCapture if already present', async () => { const { tree } = await createTreeWithBoilerplate(); updateJson(tree, schemaPath, (json) => { @@ -62,5 +63,11 @@ async function createTreeWithBoilerplate() { skipTsConfig: false, unitTestRunner: 'jest', }); + await executorGenerator(tree, { + name: 'build', + project: 'plugin', + unitTestRunner: 'jest', + includeHasher: false, + }); return { tree }; } diff --git a/packages/nx-plugin/src/migrations/update-16-0-0/cli-in-schema-json.spec.ts b/packages/nx-plugin/src/migrations/update-16-0-0/cli-in-schema-json.spec.ts index b0303335615d30..9b75ae55fcc78e 100644 --- a/packages/nx-plugin/src/migrations/update-16-0-0/cli-in-schema-json.spec.ts +++ b/packages/nx-plugin/src/migrations/update-16-0-0/cli-in-schema-json.spec.ts @@ -134,7 +134,7 @@ describe('updateCliPropsForPlugins', () => { it('should remove cli property from executors', async () => { const tree = createTreeWithEmptyWorkspace(); const { root, name } = await createPlugin(tree); - executorGenerator(tree, { + await executorGenerator(tree, { name: 'my-executor', project: name, unitTestRunner: 'jest', @@ -156,7 +156,7 @@ describe('updateCliPropsForPlugins', () => { it('should remove cli property from builders', async () => { const tree = createTreeWithEmptyWorkspace(); const { root, name } = await createPlugin(tree); - executorGenerator(tree, { + await executorGenerator(tree, { name: 'my-executor', project: name, unitTestRunner: 'jest', @@ -187,7 +187,7 @@ describe('updateCliPropsForPlugins', () => { it('should remove cli property from generators', async () => { const tree = createTreeWithEmptyWorkspace(); const { root, name } = await createPlugin(tree); - generatorGenerator(tree, { + await generatorGenerator(tree, { name: 'my-generator', project: name, unitTestRunner: 'jest', @@ -208,7 +208,7 @@ describe('updateCliPropsForPlugins', () => { it('should remove cli property from schematics', async () => { const tree = createTreeWithEmptyWorkspace(); const { root, name } = await createPlugin(tree); - generatorGenerator(tree, { + await generatorGenerator(tree, { name: 'my-schematic', project: name, unitTestRunner: 'jest', diff --git a/packages/nx-plugin/src/utils/has-generator.ts b/packages/nx-plugin/src/utils/has-generator.ts new file mode 100644 index 00000000000000..9b1389af260fc1 --- /dev/null +++ b/packages/nx-plugin/src/utils/has-generator.ts @@ -0,0 +1,32 @@ +import { + GeneratorsJson, + joinPathFragments, + readJson, + readProjectConfiguration, + Tree, +} from '@nx/devkit'; +import { PackageJson } from 'nx/src/utils/package-json'; + +export function hasGenerator( + tree: Tree, + projectName: string, + generatorName: string +): boolean { + const project = readProjectConfiguration(tree, projectName); + const packageJson = readJson( + tree, + joinPathFragments(project.root, 'package.json') + ); + if (!packageJson.generators && !packageJson.schematics) { + return false; + } + const generatorsPath = joinPathFragments( + project.root, + packageJson.generators ?? packageJson.schematics + ); + const generatorsJson = readJson(tree, generatorsPath); + return ( + (generatorsJson.generators?.[generatorName] ?? + generatorsJson.schematics?.[generatorName]) !== undefined + ); +}