diff --git a/packages/cypress/src/generators/init/init.ts b/packages/cypress/src/generators/init/init.ts index f4d633d87049d..9836d72fd5e77 100644 --- a/packages/cypress/src/generators/init/init.ts +++ b/packages/cypress/src/generators/init/init.ts @@ -11,7 +11,7 @@ import { updateNxJson, } from '@nx/devkit'; import { - addPlugin as _addPlugin, + addPluginV1 as _addPlugin, generateCombinations, } from '@nx/devkit/src/utils/add-plugin'; import { createNodes } from '../../plugins/plugin'; diff --git a/packages/detox/src/generators/init/init.ts b/packages/detox/src/generators/init/init.ts index 8753d6ecf9836..47a4363bcd228 100644 --- a/packages/detox/src/generators/init/init.ts +++ b/packages/detox/src/generators/init/init.ts @@ -9,7 +9,7 @@ import { Tree, } from '@nx/devkit'; import { - addPlugin, + addPluginV1, generateCombinations, } from '@nx/devkit/src/utils/add-plugin'; import { createNodes, DetoxPluginOptions } from '../../plugins/plugin'; @@ -36,7 +36,7 @@ export async function detoxInitGeneratorInternal(host: Tree, schema: Schema) { } if (schema.addPlugin) { - await addPlugin( + await addPluginV1( host, await createProjectGraphAsync(), '@nx/detox/plugin', diff --git a/packages/devkit/src/utils/add-plugin.spec.ts b/packages/devkit/src/utils/add-plugin.spec.ts index 6a8135d929330..45b93c4cba02a 100644 --- a/packages/devkit/src/utils/add-plugin.spec.ts +++ b/packages/devkit/src/utils/add-plugin.spec.ts @@ -2,7 +2,7 @@ import { createTreeWithEmptyWorkspace } from 'nx/src/generators/testing-utils/cr import type { Tree } from 'nx/src/generators/tree'; import { readJson, writeJson } from 'nx/src/generators/utils/json'; import type { PackageJson } from 'nx/src/utils/package-json'; -import { CreateNodes } from 'nx/src/project-graph/plugins'; +import { CreateNodesV2 } from 'nx/src/project-graph/plugins'; import { ProjectGraph } from 'nx/src/devkit-exports'; import { TempFs } from 'nx/src/internal-testing-utils/temp-fs'; @@ -10,7 +10,7 @@ import { addPlugin, generateCombinations } from './add-plugin'; describe('addPlugin', () => { let tree: Tree; - let createNodes: CreateNodes<{ targetName: string }>; + let createNodes: CreateNodesV2<{ targetName: string }>; let graph: ProjectGraph; let fs: TempFs; @@ -55,22 +55,34 @@ describe('addPlugin', () => { }; createNodes = [ '**/next.config.{js,cjs,mjs}', - (_, { targetName }) => ({ - projects: { - app1: { - name: 'app1', - targets: { - [targetName]: { command: 'next build' }, + (_, { targetName }) => [ + [ + 'app1/next.config.js', + { + projects: { + app1: { + name: 'app1', + targets: { + [targetName]: { command: 'next build' }, + }, + }, }, }, - app2: { - name: 'app2', - targets: { - [targetName]: { command: 'next build' }, + ], + [ + 'app2/next.config.js', + { + projects: { + app2: { + name: 'app2', + targets: { + [targetName]: { command: 'next build' }, + }, + }, }, }, - }, - }), + ], + ], ]; await fs.createFiles({ @@ -217,19 +229,24 @@ describe('addPlugin', () => { createNodes = [ '**/cypress.config.{js,ts,mjs,mts,cjs,cts}', - () => ({ - projects: { - app1: { - name: 'app1', - targets: { - e2e: { - command: - 'cypress run --config-file cypress.config.ts --e2e', + () => [ + [ + 'app1/cypress.config.ts', + { + projects: { + app1: { + name: 'app1', + targets: { + e2e: { + command: + 'cypress run --config-file cypress.config.ts --e2e', + }, + }, }, }, }, - }, - }), + ], + ], ]; await addPlugin( @@ -284,18 +301,23 @@ describe('addPlugin', () => { createNodes = [ '**/next.config.{js,cjs,mjs}', - () => ({ - projects: { - app1: { - name: 'app1', - targets: { - build: { command: 'next build' }, - dev: { command: 'next dev' }, - start: { command: 'next start' }, + () => [ + [ + 'app1/next.config.js', + { + projects: { + app1: { + name: 'app1', + targets: { + build: { command: 'next build' }, + dev: { command: 'next dev' }, + start: { command: 'next start' }, + }, + }, }, }, - }, - }), + ], + ], ]; await addPlugin( @@ -328,16 +350,21 @@ describe('addPlugin', () => { createNodes = [ '**/tsconfig.json', - () => ({ - projects: { - app1: { - name: 'app1', - targets: { - build: { command: 'tsc' }, + () => [ + [ + 'app1/tsconfig.json', + { + projects: { + app1: { + name: 'app1', + targets: { + build: { command: 'tsc' }, + }, + }, }, }, - }, - }), + ], + ], ]; await addPlugin( @@ -370,16 +397,21 @@ describe('addPlugin', () => { createNodes = [ '**/tsconfig.json', - () => ({ - projects: { - app1: { - name: 'app1', - targets: { - build: { command: 'tsc' }, + () => [ + [ + 'app1/tsconfig.json', + { + projects: { + app1: { + name: 'app1', + targets: { + build: { command: 'tsc' }, + }, + }, }, }, - }, - }), + ], + ], ]; await addPlugin( diff --git a/packages/devkit/src/utils/add-plugin.ts b/packages/devkit/src/utils/add-plugin.ts index 79fcf70e0743b..19105b367ddf7 100644 --- a/packages/devkit/src/utils/add-plugin.ts +++ b/packages/devkit/src/utils/add-plugin.ts @@ -5,6 +5,7 @@ import * as yargs from 'yargs-parser'; import { CreateNodes, + CreateNodesV2, ProjectConfiguration, ProjectGraph, readJson, @@ -24,6 +25,41 @@ import { */ export async function addPlugin( + tree: Tree, + graph: ProjectGraph, + pluginName: string, + createNodesTuple: CreateNodesV2, + options: Partial< + Record + >, + shouldUpdatePackageJsonScripts: boolean +): Promise { + return _addPluginInternal( + tree, + graph, + pluginName, + (pluginOptions) => + new LoadedNxPlugin( + { + name: pluginName, + createNodesV2: createNodesTuple, + }, + { + plugin: pluginName, + options: pluginOptions, + } + ), + options, + shouldUpdatePackageJsonScripts + ); +} + +/** + * @deprecated Use `addPlugin` instead + * Iterates through various forms of plugin options to find the one which does not conflict with the current graph + + */ +export async function addPluginV1( tree: Tree, graph: ProjectGraph, pluginName: string, @@ -33,6 +69,36 @@ export async function addPlugin( >, shouldUpdatePackageJsonScripts: boolean ): Promise { + return _addPluginInternal( + tree, + graph, + pluginName, + (pluginOptions) => + new LoadedNxPlugin( + { + name: pluginName, + createNodes: createNodesTuple, + }, + { + plugin: pluginName, + options: pluginOptions, + } + ), + options, + shouldUpdatePackageJsonScripts + ); +} + +async function _addPluginInternal( + tree: Tree, + graph: ProjectGraph, + pluginName: string, + pluginFactory: (pluginOptions: PluginOptions) => LoadedNxPlugin, + options: Partial< + Record + >, + shouldUpdatePackageJsonScripts: boolean +) { const graphNodes = Object.values(graph.nodes); const nxJson = readNxJson(tree); @@ -56,18 +122,7 @@ export async function addPlugin( global.NX_GRAPH_CREATION = true; try { projConfigs = await retrieveProjectConfigurations( - [ - new LoadedNxPlugin( - { - name: pluginName, - createNodes: createNodesTuple, - }, - { - plugin: pluginName, - options: pluginOptions, - } - ), - ], + [pluginFactory(pluginOptions)], tree.root, nxJson ); diff --git a/packages/eslint/src/generators/init/init.ts b/packages/eslint/src/generators/init/init.ts index dfe622ea8cae5..ae271108cdd4e 100644 --- a/packages/eslint/src/generators/init/init.ts +++ b/packages/eslint/src/generators/init/init.ts @@ -8,7 +8,7 @@ import { Tree, updateNxJson, } from '@nx/devkit'; -import { addPlugin } from '@nx/devkit/src/utils/add-plugin'; +import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin'; import { eslintVersion, nxVersion } from '../../utils/versions'; import { findEslintFile } from '../utils/eslint-file'; import { createNodes } from '../../plugins/plugin'; @@ -73,7 +73,7 @@ export async function initEsLint( ]; if (rootEslintFile && options.addPlugin && !hasPlugin) { - await addPlugin( + await addPluginV1( tree, graph, '@nx/eslint/plugin', @@ -94,7 +94,7 @@ export async function initEsLint( updateProductionFileset(tree); if (options.addPlugin) { - await addPlugin( + await addPluginV1( tree, graph, '@nx/eslint/plugin', diff --git a/packages/expo/src/generators/init/init.ts b/packages/expo/src/generators/init/init.ts index da4a087481624..5e35458920d11 100644 --- a/packages/expo/src/generators/init/init.ts +++ b/packages/expo/src/generators/init/init.ts @@ -8,7 +8,7 @@ import { runTasksInSerial, Tree, } from '@nx/devkit'; -import { addPlugin } from '@nx/devkit/src/utils/add-plugin'; +import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin'; import { createNodes } from '../../../plugins/plugin'; import { expoCliVersion, @@ -36,7 +36,7 @@ export async function expoInitGeneratorInternal(host: Tree, schema: Schema) { addGitIgnoreEntry(host); if (schema.addPlugin) { - await addPlugin( + await addPluginV1( host, await createProjectGraphAsync(), '@nx/expo/plugin', diff --git a/packages/gradle/plugin.ts b/packages/gradle/plugin.ts index 558233345f7ae..c6345f3ebd7c4 100644 --- a/packages/gradle/plugin.ts +++ b/packages/gradle/plugin.ts @@ -1,2 +1,2 @@ export { createDependencies } from './src/plugin/dependencies'; -export { createNodes } from './src/plugin/nodes'; +export { createNodes, createNodesV2 } from './src/plugin/nodes'; diff --git a/packages/gradle/src/plugin/nodes.spec.ts b/packages/gradle/src/plugin/nodes.spec.ts index 496163e685030..11912c7819373 100644 --- a/packages/gradle/src/plugin/nodes.spec.ts +++ b/packages/gradle/src/plugin/nodes.spec.ts @@ -11,10 +11,10 @@ jest.mock('../utils/get-gradle-report.ts', () => { }; }); -import { createNodes } from './nodes'; +import { createNodesV2 } from './nodes'; describe('@nx/gradle/plugin', () => { - let createNodesFunction = createNodes[1]; + let createNodesFunction = createNodesV2[1]; let context: CreateNodesContext; let tempFs: TempFs; let cwd: string; @@ -59,47 +59,55 @@ describe('@nx/gradle/plugin', () => { }); it('should create nodes based on gradle', async () => { - const nodes = await createNodesFunction( - 'proj/gradle.build', + const results = await createNodesFunction( + ['proj/gradle.build'], { buildTargetName: 'build', }, context ); - expect(nodes.projects.proj).toMatchInlineSnapshot(` - { - "metadata": { - "targetGroups": { - "Test": [ - "test", - ], - }, - "technologies": [ - "gradle", - ], - }, - "name": "proj", - "targets": { - "test": { - "cache": false, - "command": "./gradlew proj:test", - "dependsOn": [ - "classes", - ], - "inputs": [ - "default", - "^production", - ], - "metadata": { - "technologies": [ - "gradle", - ], + expect(results).toMatchInlineSnapshot(` + [ + [ + "proj/gradle.build", + { + "projects": { + "proj": { + "metadata": { + "targetGroups": { + "Test": [ + "test", + ], + }, + "technologies": [ + "gradle", + ], + }, + "name": "proj", + "targets": { + "test": { + "cache": false, + "command": "./gradlew proj:test", + "dependsOn": [ + "classes", + ], + "inputs": [ + "default", + "^production", + ], + "metadata": { + "technologies": [ + "gradle", + ], + }, + }, + }, + }, }, - "outputs": undefined, }, - }, - } + ], + ] `); }); @@ -121,47 +129,55 @@ describe('@nx/gradle/plugin', () => { 'nested/nested/proj/gradle.build': ``, }); - const nodes = await createNodesFunction( - 'nested/nested/proj/gradle.build', + const results = await createNodesFunction( + ['nested/nested/proj/gradle.build'], { buildTargetName: 'build', }, context ); - expect(nodes.projects['nested/nested/proj']).toMatchInlineSnapshot(` - { - "metadata": { - "targetGroups": { - "Test": [ - "test", - ], - }, - "technologies": [ - "gradle", - ], - }, - "name": "proj", - "targets": { - "test": { - "cache": false, - "command": "./gradlew proj:test", - "dependsOn": [ - "classes", - ], - "inputs": [ - "default", - "^production", - ], - "metadata": { - "technologies": [ - "gradle", - ], + expect(results).toMatchInlineSnapshot(` + [ + [ + "nested/nested/proj/gradle.build", + { + "projects": { + "nested/nested/proj": { + "metadata": { + "targetGroups": { + "Test": [ + "test", + ], + }, + "technologies": [ + "gradle", + ], + }, + "name": "proj", + "targets": { + "test": { + "cache": false, + "command": "./gradlew proj:test", + "dependsOn": [ + "classes", + ], + "inputs": [ + "default", + "^production", + ], + "metadata": { + "technologies": [ + "gradle", + ], + }, + }, + }, + }, }, - "outputs": undefined, }, - }, - } + ], + ] `); }); }); diff --git a/packages/gradle/src/plugin/nodes.ts b/packages/gradle/src/plugin/nodes.ts index 9a52c7f601e52..9ae4ebed829c7 100644 --- a/packages/gradle/src/plugin/nodes.ts +++ b/packages/gradle/src/plugin/nodes.ts @@ -218,18 +218,23 @@ function createGradleTargets( const targetName = options?.[`${task.name}TargetName`] ?? task.name; const outputs = outputDirs.get(task.name); + targets[targetName] = { command: `${getGradleExecFile()} ${ gradleProject ? gradleProject + ':' : '' }${task.name}`, cache: cacheableTaskType.has(task.type), inputs: inputsMap[task.name], - outputs: outputs ? [outputs] : undefined, dependsOn: dependsOnMap[task.name], metadata: { technologies: ['gradle'], }, }; + + if (outputs) { + targets[targetName].outputs = [outputs]; + } + if (!targetGroups[task.type]) { targetGroups[task.type] = []; } diff --git a/packages/jest/src/generators/init/init.ts b/packages/jest/src/generators/init/init.ts index 72e3173ff1717..11c2602a402bb 100644 --- a/packages/jest/src/generators/init/init.ts +++ b/packages/jest/src/generators/init/init.ts @@ -9,7 +9,7 @@ import { type GeneratorCallback, type Tree, } from '@nx/devkit'; -import { addPlugin } from '@nx/devkit/src/utils/add-plugin'; +import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin'; import { createNodes } from '../../plugins/plugin'; import { getPresetExt, @@ -104,7 +104,7 @@ export async function jestInitGeneratorInternal( if (!tree.exists(`jest.preset.${presetExt}`)) { updateProductionFileSet(tree); if (options.addPlugin) { - await addPlugin( + await addPluginV1( tree, await createProjectGraphAsync(), '@nx/jest/plugin', diff --git a/packages/next/src/generators/init/init.ts b/packages/next/src/generators/init/init.ts index 7608702ef4b0b..edbd50efe80ff 100644 --- a/packages/next/src/generators/init/init.ts +++ b/packages/next/src/generators/init/init.ts @@ -7,7 +7,7 @@ import { readNxJson, createProjectGraphAsync, } from '@nx/devkit'; -import { addPlugin } from '@nx/devkit/src/utils/add-plugin'; +import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin'; import { reactDomVersion, reactVersion } from '@nx/react/src/utils/versions'; import { addGitIgnoreEntry } from '../../utils/add-gitignore-entry'; import { nextVersion, nxVersion } from '../../utils/versions'; @@ -53,7 +53,7 @@ export async function nextInitGeneratorInternal( schema.addPlugin ??= addPluginDefault; if (schema.addPlugin) { const { createNodes } = await import('../../plugins/plugin'); - await addPlugin( + await addPluginV1( host, await createProjectGraphAsync(), '@nx/next/plugin', diff --git a/packages/nuxt/src/generators/init/init.ts b/packages/nuxt/src/generators/init/init.ts index 819b22f609a5c..1bc971e19b904 100644 --- a/packages/nuxt/src/generators/init/init.ts +++ b/packages/nuxt/src/generators/init/init.ts @@ -1,12 +1,12 @@ import { createProjectGraphAsync, GeneratorCallback, Tree } from '@nx/devkit'; -import { addPlugin } from '@nx/devkit/src/utils/add-plugin'; +import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin'; import { createNodes } from '../../plugins/plugin'; import { InitSchema } from './schema'; import { updateDependencies } from './lib/utils'; export async function nuxtInitGenerator(host: Tree, schema: InitSchema) { - await addPlugin( + await addPluginV1( host, await createProjectGraphAsync(), '@nx/nuxt/plugin', diff --git a/packages/playwright/src/generators/init/init.ts b/packages/playwright/src/generators/init/init.ts index ae90ae3a95556..c4475a14d4fc2 100644 --- a/packages/playwright/src/generators/init/init.ts +++ b/packages/playwright/src/generators/init/init.ts @@ -7,7 +7,7 @@ import { runTasksInSerial, Tree, } from '@nx/devkit'; -import { addPlugin } from '@nx/devkit/src/utils/add-plugin'; +import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin'; import { createNodes } from '../../plugins/plugin'; import { nxVersion, playwrightVersion } from '../../utils/versions'; import { InitGeneratorSchema } from './schema'; @@ -45,7 +45,7 @@ export async function initGeneratorInternal( } if (options.addPlugin) { - await addPlugin( + await addPluginV1( tree, await createProjectGraphAsync(), '@nx/playwright/plugin', diff --git a/packages/react-native/src/generators/init/init.ts b/packages/react-native/src/generators/init/init.ts index be1331f55cf0e..34ed8938401e6 100644 --- a/packages/react-native/src/generators/init/init.ts +++ b/packages/react-native/src/generators/init/init.ts @@ -8,7 +8,7 @@ import { runTasksInSerial, Tree, } from '@nx/devkit'; -import { addPlugin } from '@nx/devkit/src/utils/add-plugin'; +import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin'; import { createNodes } from '../../../plugins/plugin'; import { nxVersion, @@ -39,7 +39,7 @@ export async function reactNativeInitGeneratorInternal( schema.addPlugin ??= addPluginDefault; if (schema.addPlugin) { - await addPlugin( + await addPluginV1( host, await createProjectGraphAsync(), '@nx/react-native/plugin', diff --git a/packages/remix/src/generators/init/init.ts b/packages/remix/src/generators/init/init.ts index 80e7214b18b66..2f2c9e591daec 100644 --- a/packages/remix/src/generators/init/init.ts +++ b/packages/remix/src/generators/init/init.ts @@ -8,7 +8,7 @@ import { createProjectGraphAsync, } from '@nx/devkit'; import { - addPlugin, + addPluginV1, generateCombinations, } from '@nx/devkit/src/utils/add-plugin'; import { createNodes } from '../../plugins/plugin'; @@ -44,7 +44,7 @@ export async function remixInitGeneratorInternal(tree: Tree, options: Schema) { nxJson.useInferencePlugins !== false; options.addPlugin ??= addPluginDefault; if (options.addPlugin) { - await addPlugin( + await addPluginV1( tree, await createProjectGraphAsync(), '@nx/remix/plugin', diff --git a/packages/rollup/src/generators/init/init.ts b/packages/rollup/src/generators/init/init.ts index 59be1a26d7e3a..0ae70887eea69 100644 --- a/packages/rollup/src/generators/init/init.ts +++ b/packages/rollup/src/generators/init/init.ts @@ -7,7 +7,7 @@ import { } from '@nx/devkit'; import { nxVersion } from '../../utils/versions'; import { Schema } from './schema'; -import { addPlugin } from '@nx/devkit/src/utils/add-plugin'; +import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin'; import { createNodes } from '../../plugins/plugin'; export async function rollupInitGenerator(tree: Tree, schema: Schema) { @@ -25,7 +25,7 @@ export async function rollupInitGenerator(tree: Tree, schema: Schema) { schema.addPlugin ??= process.env.NX_ADD_PLUGINS !== 'false'; if (schema.addPlugin) { - await addPlugin( + await addPluginV1( tree, await createProjectGraphAsync(), '@nx/rollup/plugin', diff --git a/packages/storybook/src/generators/init/init.ts b/packages/storybook/src/generators/init/init.ts index bc754beb73d24..90a5448eb5ccc 100644 --- a/packages/storybook/src/generators/init/init.ts +++ b/packages/storybook/src/generators/init/init.ts @@ -10,7 +10,7 @@ import { updateJson, updateNxJson, } from '@nx/devkit'; -import { addPlugin } from '@nx/devkit/src/utils/add-plugin'; +import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin'; import { gte } from 'semver'; import { createNodes } from '../../plugins/plugin'; import { @@ -102,7 +102,7 @@ export async function initGeneratorInternal(tree: Tree, schema: Schema) { schema.addPlugin ??= addPluginDefault; if (schema.addPlugin) { - await addPlugin( + await addPluginV1( tree, await createProjectGraphAsync(), '@nx/storybook/plugin', diff --git a/packages/vite/src/generators/init/init.ts b/packages/vite/src/generators/init/init.ts index 5d7fd3d60267a..c6210ac1ff74b 100644 --- a/packages/vite/src/generators/init/init.ts +++ b/packages/vite/src/generators/init/init.ts @@ -7,7 +7,7 @@ import { Tree, updateNxJson, } from '@nx/devkit'; -import { addPlugin } from '@nx/devkit/src/utils/add-plugin'; +import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin'; import { createNodes } from '../../plugins/plugin'; import { InitGeneratorSchema } from './schema'; @@ -60,7 +60,7 @@ export async function initGeneratorInternal( schema.addPlugin ??= addPluginDefault; if (schema.addPlugin) { - await addPlugin( + await addPluginV1( tree, await createProjectGraphAsync(), '@nx/vite/plugin', diff --git a/packages/webpack/src/generators/init/init.ts b/packages/webpack/src/generators/init/init.ts index b991bf0efe32c..24f10417e6036 100644 --- a/packages/webpack/src/generators/init/init.ts +++ b/packages/webpack/src/generators/init/init.ts @@ -6,7 +6,7 @@ import { readNxJson, Tree, } from '@nx/devkit'; -import { addPlugin } from '@nx/devkit/src/utils/add-plugin'; +import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin'; import { createNodes } from '../../plugins/plugin'; import { nxVersion, webpackCliVersion } from '../../utils/versions'; import { Schema } from './schema'; @@ -23,7 +23,7 @@ export async function webpackInitGeneratorInternal(tree: Tree, schema: Schema) { schema.addPlugin ??= addPluginDefault; if (schema.addPlugin) { - await addPlugin( + await addPluginV1( tree, await createProjectGraphAsync(), '@nx/webpack/plugin',