fix(core): addPlugin should not conflict on project.json targets (#23264)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

## Current Behavior
<!-- This is the behavior we have today -->
Calculating conflicts in target names does not consider if the
project.json defined targets will actually be impacted by the plugin
that wants to be added creating false negatives

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Calculating conflicts should be more accurate

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #22476
This commit is contained in:
Colum Ferry 2024-05-13 15:53:09 +01:00 committed by GitHub
parent 08654e1966
commit 85c8916087
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
59 changed files with 291 additions and 242 deletions

View File

@ -1,3 +1,5 @@
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
import type { Tree } from '@nx/devkit';
import * as devkit from '@nx/devkit';

View File

@ -1,3 +1,5 @@
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
import {
DependencyType,

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import { readJson, updateJson } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import {
getProjects,

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import type { Tree } from '@nx/devkit';
import { readJson } from '@nx/devkit';

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import type { Tree } from '@nx/devkit';
import { readJson } from '@nx/devkit';

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import type { Tree } from '@nx/devkit';
import * as devkit from '@nx/devkit';

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import { E2eTestRunner } from '../../utils/test-runners';
import {

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import scamGenerator from '../scam/scam';

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import {
readJson,

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import {
NxJsonConfiguration,

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
import type { Tree } from '@nx/devkit';

View File

@ -1,3 +1,5 @@
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
import type { Tree } from '@nx/devkit';
import { readJson, writeJson } from '@nx/devkit';

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import type { Tree } from '@nx/devkit';
import * as devkit from '@nx/devkit';

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import { readJson, updateJson } from '@nx/devkit';
import * as devkit from '@nx/devkit';

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import type { Tree } from '@nx/devkit';
import * as devkit from '@nx/devkit';

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import {
readJson,

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import * as devkit from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';

View File

@ -1,3 +1,5 @@
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import {
ProjectGraph,
readJson,

View File

@ -80,7 +80,7 @@ export async function configurationGeneratorInternal(
})
);
} else if (opts.addPlugin) {
await addPlugin(tree, projectGraph, false);
await addPlugin(tree, false);
}
const nxJson = readNxJson(tree);

View File

@ -1,23 +1,17 @@
import {
addDependenciesToPackageJson,
createProjectGraphAsync,
formatFiles,
GeneratorCallback,
ProjectGraph,
readNxJson,
removeDependenciesFromPackageJson,
runTasksInSerial,
Tree,
updateNxJson,
} from '@nx/devkit';
import {
addPlugin as _addPlugin,
generateCombinations,
} from '@nx/devkit/src/utils/add-plugin';
import { addPlugin as _addPlugin } from '@nx/devkit/src/utils/add-plugin';
import { createNodes } from '../../plugins/plugin';
import { cypressVersion, nxVersion } from '../../utils/versions';
import { Schema } from './schema';
import { CypressPluginOptions } from '../../plugins/plugin';
function setupE2ETargetDefaults(tree: Tree) {
const nxJson = readNxJson(tree);
@ -60,14 +54,9 @@ function updateDependencies(tree: Tree, options: Schema) {
return runTasksInSerial(...tasks);
}
export function addPlugin(
tree: Tree,
graph: ProjectGraph,
updatePackageScripts: boolean
) {
export function addPlugin(tree: Tree, updatePackageScripts: boolean) {
return _addPlugin(
tree,
graph,
'@nx/cypress/plugin',
createNodes,
{
@ -118,11 +107,7 @@ export async function cypressInitGeneratorInternal(
nxJson.useInferencePlugins !== false;
if (options.addPlugin) {
await addPlugin(
tree,
await createProjectGraphAsync(),
options.updatePackageScripts
);
await addPlugin(tree, options.updatePackageScripts);
} else {
setupE2ETargetDefaults(tree);
}

View File

@ -1,6 +1,5 @@
import {
addDependenciesToPackageJson,
createProjectGraphAsync,
formatFiles,
GeneratorCallback,
readNxJson,
@ -8,11 +7,8 @@ import {
runTasksInSerial,
Tree,
} from '@nx/devkit';
import {
addPlugin,
generateCombinations,
} from '@nx/devkit/src/utils/add-plugin';
import { createNodes, DetoxPluginOptions } from '../../plugins/plugin';
import { addPlugin } from '@nx/devkit/src/utils/add-plugin';
import { createNodes } from '../../plugins/plugin';
import { detoxVersion, nxVersion } from '../../utils/versions';
import { Schema } from './schema';
@ -38,7 +34,6 @@ export async function detoxInitGeneratorInternal(host: Tree, schema: Schema) {
if (schema.addPlugin) {
await addPlugin(
host,
await createProjectGraphAsync(),
'@nx/detox/plugin',
createNodes,
{

View File

@ -1,17 +1,50 @@
jest.mock('vite', () => ({
resolveConfig: jest.fn().mockImplementation(() => {
return Promise.resolve({
path: 'vite.config.ts',
config: {},
build: {},
dependencies: [],
});
}),
}));
jest.mock('@nx/vite/plugin', () => ({
createNodes: [
'**/vite.config.{js,cjs,mjs}',
(_, { targetName }) => ({
projects: {
app1: {
name: 'app1',
targets: {
[targetName]: { command: 'vite build' },
},
},
app2: {
name: 'app2',
targets: {
[targetName]: { command: 'vite build' },
},
},
},
}),
],
createDependencies: jest.fn(),
}));
import { createTreeWithEmptyWorkspace } from 'nx/src/generators/testing-utils/create-tree-with-empty-workspace';
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 { ProjectGraph } from 'nx/src/devkit-exports';
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
import { addPlugin, generateCombinations } from './add-plugin';
import { updateNxJson } from 'nx/src/generators/utils/nx-json';
describe('addPlugin', () => {
let tree: Tree;
let createNodes: CreateNodes<{ targetName: string }>;
let graph: ProjectGraph;
let fs: TempFs;
beforeEach(async () => {
@ -20,39 +53,6 @@ describe('addPlugin', () => {
fs = new TempFs('add-plugin');
tree.root = fs.tempDir;
graph = {
nodes: {
app1: {
name: 'app1',
type: 'app',
data: {
root: 'app1',
targets: {},
},
},
app2: {
name: 'app2',
type: 'app',
data: {
root: 'app2',
targets: {},
},
},
app3: {
name: 'app3',
type: 'app',
data: {
root: 'app3',
targets: {},
},
},
},
dependencies: {
app1: [],
app2: [],
app3: [],
},
};
createNodes = [
'**/next.config.{js,cjs,mjs}',
(_, { targetName }) => ({
@ -84,41 +84,148 @@ describe('addPlugin', () => {
});
describe('adding the plugin', () => {
it('should not conflicting with the existing graph', async () => {
graph.nodes.app1.data.targets.build = {};
graph.nodes.app2.data.targets.build1 = {};
// app 3 doesn't have a next config, so it having this
// target should not affect the plugin options
graph.nodes.app3.data.targets.build2 = {};
it('should not conflicting with the existing plugins', async () => {
// ARRANGE
const nxJson = readJson(tree, 'nx.json');
nxJson.plugins ??= [];
nxJson.plugins.push({
plugin: '@nx/vite/plugin',
options: { targetName: 'build' },
});
updateNxJson(tree, nxJson);
fs.createFilesSync({
'app1/vite.config.js': '',
'app2/vite.config.js': '',
});
// ACT
await addPlugin(
tree,
graph,
'@nx/next/plugin',
createNodes,
{
targetName: ['build', 'build1', 'build2'],
targetName: ['build', 'build1'],
},
true
);
expect(readJson(tree, 'nx.json').plugins).toContainEqual({
// ASSERT
expect(
readJson(tree, 'nx.json').plugins.find(
(p) => p.plugin === '@nx/next/plugin'
)
).toEqual({
plugin: '@nx/next/plugin',
options: {
targetName: 'build2',
targetName: 'build1',
},
});
});
it('should not conflicting with existing project.json with executor and run-commands in plugin', async () => {
// ARRANGE
fs.createFilesSync({
'app1/project.json': JSON.stringify({
targets: { build: { executor: '@nx/next:build' } },
}),
});
// ACT
await addPlugin(
tree,
'@nx/next/plugin',
createNodes,
{
targetName: ['build'],
},
true
);
// ASSERT
expect(
readJson(tree, 'nx.json').plugins.find(
(p) => p.plugin === '@nx/next/plugin'
)
).toEqual({
plugin: '@nx/next/plugin',
options: {
targetName: 'build',
},
});
});
it('should not conflicting with existing project.json with executor and executor in plugin', async () => {
// ARRANGE
fs.createFilesSync({
'app1/project.json': JSON.stringify({
targets: { build: { executor: '@nx/next:build' } },
}),
});
createNodes = [
'**/next.config.{js,cjs,mjs}',
(_, { targetName }) => ({
projects: {
app1: {
name: 'app1',
targets: {
[targetName]: { executor: '@nx/next:build' },
},
},
app2: {
name: 'app2',
targets: {
[targetName]: { executor: '@nx/next:build' },
},
},
},
}),
];
// ACT
await addPlugin(
tree,
'@nx/next/plugin',
createNodes,
{
targetName: ['build'],
},
true
);
// ASSERT
expect(
readJson(tree, 'nx.json').plugins.find(
(p) => p.plugin === '@nx/next/plugin'
)
).toEqual({
plugin: '@nx/next/plugin',
options: {
targetName: 'build',
},
});
});
});
it('should throw an error if no non-conflicting options are provided', async () => {
graph.nodes.app1.data.targets.build = {};
const nxJson = readJson(tree, 'nx.json');
nxJson.plugins ??= [];
nxJson.plugins.push({
plugin: '@nx/vite/plugin',
options: { targetName: 'build' },
});
updateNxJson(tree, nxJson);
fs.createFilesSync({
'app1/vite.config.js': '',
'app2/vite.config.js': '',
});
try {
await addPlugin(
tree,
graph,
'@nx/next/plugin',
createNodes,
@ -147,7 +254,6 @@ describe('addPlugin', () => {
await addPlugin(
tree,
graph,
'@nx/next/plugin',
createNodes,
@ -185,7 +291,6 @@ describe('addPlugin', () => {
await addPlugin(
tree,
graph,
'@nx/next/plugin',
createNodes,
@ -234,7 +339,6 @@ describe('addPlugin', () => {
await addPlugin(
tree,
graph,
'@nx/cypress/plugin',
createNodes,
@ -259,7 +363,6 @@ describe('addPlugin', () => {
await addPlugin(
tree,
graph,
'@nx/next/plugin',
createNodes,
@ -300,7 +403,6 @@ describe('addPlugin', () => {
await addPlugin(
tree,
graph,
'@nx/next/plugin',
createNodes,
@ -342,7 +444,6 @@ describe('addPlugin', () => {
await addPlugin(
tree,
graph,
'@nx/next/plugin',
createNodes,
@ -384,7 +485,6 @@ describe('addPlugin', () => {
await addPlugin(
tree,
graph,
'@nx/next/plugin',
createNodes,

View File

@ -1,12 +1,12 @@
import type { PackageJson } from 'nx/src/utils/package-json';
import type { ConfigurationResult } from 'nx/src/project-graph/utils/project-configuration-utils';
import * as yargs from 'yargs-parser';
import {
CreateNodes,
NxJsonConfiguration,
ProjectConfiguration,
ProjectGraph,
readJson,
readNxJson,
Tree,
@ -15,6 +15,10 @@ import {
} from 'nx/src/devkit-exports';
import {
LoadedNxPlugin,
loadNxPlugins,
isCompatibleTarget,
mergeTargetConfigurations,
deepEquals,
ProjectConfigurationsError,
retrieveProjectConfigurations,
} from 'nx/src/devkit-internals';
@ -25,7 +29,6 @@ import {
*/
export async function addPlugin<PluginOptions>(
tree: Tree,
graph: ProjectGraph,
pluginName: string,
createNodesTuple: CreateNodes<PluginOptions>,
options: Partial<
@ -33,11 +36,12 @@ export async function addPlugin<PluginOptions>(
>,
shouldUpdatePackageJsonScripts: boolean
): Promise<void> {
const graphNodes = Object.values(graph.nodes);
const nxJson = readNxJson(tree);
let pluginOptions: PluginOptions;
let projConfigs: ConfigurationResult;
let projConfigsWithExistingNxJsonPlugins: ConfigurationResult;
let projConfigsWithNewPlugin: ConfigurationResult;
let projConfigsWithCorePlugins: ConfigurationResult;
const combinations = generateCombinations(options);
optionsLoop: for (const _pluginOptions of combinations) {
pluginOptions = _pluginOptions as PluginOptions;
@ -54,8 +58,21 @@ export async function addPlugin<PluginOptions>(
return;
}
global.NX_GRAPH_CREATION = true;
try {
projConfigs = await retrieveProjectConfigurations(
const [nxJsonPlugins] = await loadNxPlugins(
nxJson.plugins,
tree.root,
true
);
projConfigsWithExistingNxJsonPlugins =
await retrieveProjectConfigurationsWithPartialResult(
nxJsonPlugins,
tree.root,
nxJson
);
projConfigsWithNewPlugin =
await retrieveProjectConfigurationsWithPartialResult(
[
new LoadedNxPlugin(
{
@ -71,27 +88,38 @@ export async function addPlugin<PluginOptions>(
tree.root,
nxJson
);
} catch (e) {
// Errors are okay for this because we're only running 1 plugin
if (e instanceof ProjectConfigurationsError) {
projConfigs = e.partialProjectConfigurationsResult;
} else {
throw e;
}
}
global.NX_GRAPH_CREATION = false;
for (const projConfig of Object.values(projConfigs.projects)) {
const node = graphNodes.find(
(node) => node.data.root === projConfig.root
const [corePlugins] = await loadNxPlugins([], tree.root);
projConfigsWithCorePlugins =
await retrieveProjectConfigurationsWithPartialResult(
corePlugins,
tree.root,
nxJson
);
if (!node) {
continue;
}
global.NX_GRAPH_CREATION = false;
for (const projConfig of Object.values(projConfigsWithNewPlugin.projects)) {
for (const targetName in projConfig.targets) {
if (node.data.targets[targetName]) {
const existingPluginCreatedTarget =
projConfigsWithExistingNxJsonPlugins?.projects?.[projConfig.root]
?.targets?.[targetName];
const corePluginsCreatedTarget =
projConfigsWithCorePlugins?.projects?.[projConfig.root]?.targets?.[
targetName
];
if (
existingPluginCreatedTarget ||
(corePluginsCreatedTarget &&
!deepEquals(
corePluginsCreatedTarget,
mergeTargetConfigurations(
corePluginsCreatedTarget,
projConfig.targets[targetName]
)
))
) {
// Conflicting Target Name, check the next one
pluginOptions = null;
continue optionsLoop;
@ -116,7 +144,7 @@ export async function addPlugin<PluginOptions>(
updateNxJson(tree, nxJson);
if (shouldUpdatePackageJsonScripts) {
updatePackageScripts(tree, projConfigs);
updatePackageScripts(tree, projConfigsWithNewPlugin);
}
}
@ -353,3 +381,26 @@ function _generateCombinations<T>(input: T[][]): T[][] {
);
}
}
export async function retrieveProjectConfigurationsWithPartialResult(
plugins: LoadedNxPlugin[],
workspaceRoot: string,
nxJson: NxJsonConfiguration
): Promise<ConfigurationResult> {
let projConfigs: ConfigurationResult;
try {
projConfigs = await retrieveProjectConfigurations(
plugins,
workspaceRoot,
nxJson
);
} catch (e) {
// Errors are okay for this because we're only running 1 plugin
if (e instanceof ProjectConfigurationsError) {
projConfigs = e.partialProjectConfigurationsResult;
} else {
throw e;
}
}
return projConfigs;
}

View File

@ -1,3 +1,5 @@
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import { Tree, readJson, writeJson } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from 'nx/src/devkit-testing-exports';
import { WORKSPACE_PLUGIN_DIR } from '../../constants';

View File

@ -1,5 +1,3 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import { NxJsonConfiguration, readJson, Tree, updateJson } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { LinterInitOptions, lintInitGenerator } from './init';

View File

@ -61,8 +61,6 @@ export async function initEsLint(
const hasPlugin = hasEslintPlugin(tree);
const rootEslintFile = findEslintFile(tree);
const graph = await createProjectGraphAsync();
const lintTargetNames = [
'lint',
'eslint:lint',
@ -75,7 +73,6 @@ export async function initEsLint(
if (rootEslintFile && options.addPlugin && !hasPlugin) {
await addPlugin(
tree,
graph,
'@nx/eslint/plugin',
createNodes,
{
@ -96,7 +93,6 @@ export async function initEsLint(
if (options.addPlugin) {
await addPlugin(
tree,
graph,
'@nx/eslint/plugin',
createNodes,
{

View File

@ -1,5 +1,3 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import { readJson, Tree } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { expoInitGenerator } from './init';

View File

@ -38,7 +38,6 @@ export async function expoInitGeneratorInternal(host: Tree, schema: Schema) {
if (schema.addPlugin) {
await addPlugin(
host,
await createProjectGraphAsync(),
'@nx/expo/plugin',
createNodes,
{

View File

@ -1,5 +1,3 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import {
type NxJsonConfiguration,
readJson,

View File

@ -103,7 +103,6 @@ export async function jestInitGeneratorInternal(
if (options.addPlugin) {
await addPlugin(
tree,
await createProjectGraphAsync(),
'@nx/jest/plugin',
createNodes,
{

View File

@ -1,23 +1,12 @@
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { readJson, Tree, ProjectGraph } from '@nx/devkit';
import { readJson, Tree } from '@nx/devkit';
import { nextInitGenerator } from './init';
let projectGraph: ProjectGraph;
jest.mock('@nx/devkit', () => ({
...jest.requireActual<any>('@nx/devkit'),
createProjectGraphAsync: jest.fn().mockImplementation(async () => {
return projectGraph;
}),
}));
describe('init', () => {
let tree: Tree;
beforeEach(() => {
projectGraph = {
nodes: {},
dependencies: {},
};
tree = createTreeWithEmptyWorkspace();
});

View File

@ -55,7 +55,6 @@ export async function nextInitGeneratorInternal(
const { createNodes } = await import('../../plugins/plugin');
await addPlugin(
host,
await createProjectGraphAsync(),
'@nx/next/plugin',
createNodes,
{

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import * as devkit from '@nx/devkit';
import {

View File

@ -1,5 +1,3 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import { readJson, readNxJson, Tree } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { nuxtInitGenerator } from './init';

View File

@ -8,7 +8,6 @@ import { updateDependencies } from './lib/utils';
export async function nuxtInitGenerator(host: Tree, schema: InitSchema) {
await addPlugin(
host,
await createProjectGraphAsync(),
'@nx/nuxt/plugin',
createNodes,
{

View File

@ -4,12 +4,16 @@
* These may not be available in certain version of Nx, so be sure to check them first.
*/
export { createTempNpmDirectory } from './utils/package-manager';
export { deepEquals } from './utils/json-diff';
export { getExecutorInformation } from './command-line/run/executor-utils';
export { readNxJson as readNxJsonFromDisk } from './config/nx-json';
export { calculateDefaultProjectName } from './config/calculate-default-project-name';
export { retrieveProjectConfigurationsWithAngularProjects } from './project-graph/utils/retrieve-workspace-files';
export { mergeTargetConfigurations } from './project-graph/utils/project-configuration-utils';
export { readProjectConfigurationsFromRootMap } from './project-graph/utils/project-configuration-utils';
export {
readProjectConfigurationsFromRootMap,
isCompatibleTarget,
} from './project-graph/utils/project-configuration-utils';
export { splitTarget } from './utils/split-target';
export { combineOptionsForExecutor } from './utils/params';
export { sortObjectByKeys } from './utils/object-sort';
@ -23,6 +27,9 @@ export {
findProjectForPath,
} from './project-graph/utils/find-project-for-path';
export { retrieveProjectConfigurations } from './project-graph/utils/retrieve-workspace-files';
export { LoadedNxPlugin } from './project-graph/plugins/internal-api';
export {
LoadedNxPlugin,
loadNxPlugins,
} from './project-graph/plugins/internal-api';
export * from './project-graph/error-types';
export { registerTsProject } from './plugins/js/utils/register';

View File

@ -0,0 +1,6 @@
jest.mock('nx/src/project-graph/plugins/loader', () => ({
...jest.requireActual('nx/src/project-graph/plugins/loader'),
loadNxPlugin: jest.fn().mockImplementation(() => {
return [Promise.resolve({}), () => {}];
}),
}));

View File

@ -98,7 +98,8 @@ export const nxPluginCache: Map<
export async function loadNxPlugins(
plugins: PluginConfiguration[],
root = workspaceRoot
root = workspaceRoot,
skipDefaultPlugins = false
): Promise<[LoadedNxPlugin[], () => void]> {
const result: Promise<LoadedNxPlugin>[] = [];
@ -107,7 +108,9 @@ export async function loadNxPlugins(
? loadNxPluginInIsolation
: loadNxPlugin;
plugins = await normalizePlugins(plugins, root);
plugins = skipDefaultPlugins
? plugins ?? []
: await normalizePlugins(plugins, root);
const cleanupFunctions: Array<() => void> = [];
for (const plugin of plugins) {

View File

@ -16,6 +16,7 @@ import {
} from '../../utils/workspace-context';
import { buildAllWorkspaceFiles } from './build-all-workspace-files';
import { join } from 'path';
import { ProjectConfigurationsError } from '../error-types';
/**
* Walks the workspace directory to create the `projectFileMap`, `ProjectConfigurations` and `allWorkspaceFiles`

View File

@ -1,24 +1,12 @@
import { ProjectGraph, readNxJson, Tree, updateNxJson } from '@nx/devkit';
import { readNxJson, Tree, updateNxJson } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { initGenerator } from './init';
let projectGraph: ProjectGraph;
jest.mock('@nx/devkit', () => ({
...jest.requireActual<any>('@nx/devkit'),
createProjectGraphAsync: jest.fn().mockImplementation(async () => {
return projectGraph;
}),
}));
describe('@nx/playwright:init', () => {
let tree: Tree;
beforeEach(() => {
projectGraph = {
nodes: {},
dependencies: {},
};
tree = createTreeWithEmptyWorkspace();
});
@ -43,7 +31,7 @@ describe('@nx/playwright:init', () => {
it('should not overwrite existing plugins', async () => {
updateNxJson(tree, {
plugins: ['foo'],
plugins: ['@nx/vite/plugin'],
});
await initGenerator(tree, {
skipFormat: true,
@ -53,7 +41,7 @@ describe('@nx/playwright:init', () => {
const nxJson = readNxJson(tree);
expect(nxJson.plugins).toMatchInlineSnapshot(`
[
"foo",
"@nx/vite/plugin",
{
"options": {
"targetName": "e2e",

View File

@ -47,7 +47,6 @@ export async function initGeneratorInternal(
if (options.addPlugin) {
await addPlugin(
tree,
await createProjectGraphAsync(),
'@nx/playwright/plugin',
createNodes,
{ targetName: ['e2e', 'playwright:e2e', 'playwright-e2e'] },

View File

@ -1,5 +1,3 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import {
Tree,
getProjects,

View File

@ -1,5 +1,3 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import { Tree, readJson } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { reactNativeInitGenerator } from './init';

View File

@ -1,6 +1,5 @@
import {
addDependenciesToPackageJson,
createProjectGraphAsync,
formatFiles,
GeneratorCallback,
readNxJson,
@ -41,7 +40,6 @@ export async function reactNativeInitGeneratorInternal(
if (schema.addPlugin) {
await addPlugin(
host,
await createProjectGraphAsync(),
'@nx/react-native/plugin',
createNodes,
{

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
import {

View File

@ -472,9 +472,6 @@ describe('React:CypressComponentTestConfiguration', () => {
buildTarget: 'my-app:build',
});
}).resolves;
expect(require('@nx/devkit').createProjectGraphAsync).toHaveBeenCalledTimes(
1
);
});
it('should setup cypress config files correctly', async () => {

View File

@ -1,5 +1,3 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { readJson } from '@nx/devkit';
import initGenerator from './init';

View File

@ -5,12 +5,8 @@ import {
readNxJson,
addDependenciesToPackageJson,
runTasksInSerial,
createProjectGraphAsync,
} from '@nx/devkit';
import {
addPlugin,
generateCombinations,
} from '@nx/devkit/src/utils/add-plugin';
import { addPlugin } from '@nx/devkit/src/utils/add-plugin';
import { createNodes } from '../../plugins/plugin';
import { nxVersion, remixVersion } from '../../utils/versions';
import { type Schema } from './schema';
@ -46,7 +42,6 @@ export async function remixInitGeneratorInternal(tree: Tree, options: Schema) {
if (options.addPlugin) {
await addPlugin(
tree,
await createProjectGraphAsync(),
'@nx/remix/plugin',
createNodes,
{

View File

@ -1,27 +1,13 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import { Tree, readJson, ProjectGraph } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { nxVersion } from '../../utils/versions';
import { rollupInitGenerator } from './init';
let projectGraph: ProjectGraph;
jest.mock('@nx/devkit', () => ({
...jest.requireActual<any>('@nx/devkit'),
createProjectGraphAsync: jest.fn().mockImplementation(async () => {
return projectGraph;
}),
}));
describe('rollupInitGenerator', () => {
let tree: Tree;
beforeEach(async () => {
projectGraph = {
nodes: {},
dependencies: {},
};
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
});

View File

@ -1,6 +1,5 @@
import {
addDependenciesToPackageJson,
createProjectGraphAsync,
formatFiles,
GeneratorCallback,
Tree,
@ -27,7 +26,6 @@ export async function rollupInitGenerator(tree: Tree, schema: Schema) {
if (schema.addPlugin) {
await addPlugin(
tree,
await createProjectGraphAsync(),
'@nx/rollup/plugin',
createNodes,
{

View File

@ -1,27 +1,11 @@
import {
readJson,
type NxJsonConfiguration,
type Tree,
ProjectGraph,
} from '@nx/devkit';
import { readJson, type NxJsonConfiguration, type Tree } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { initGenerator } from './init';
let projectGraph: ProjectGraph;
jest.mock('@nx/devkit', () => ({
...jest.requireActual<any>('@nx/devkit'),
createProjectGraphAsync: jest.fn().mockImplementation(async () => {
return projectGraph;
}),
}));
describe('@nx/storybook:init', () => {
let tree: Tree;
beforeEach(() => {
projectGraph = {
nodes: {},
dependencies: {},
};
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
});

View File

@ -1,6 +1,5 @@
import {
addDependenciesToPackageJson,
createProjectGraphAsync,
formatFiles,
GeneratorCallback,
installPackagesTask,
@ -104,7 +103,6 @@ export async function initGeneratorInternal(tree: Tree, schema: Schema) {
if (schema.addPlugin) {
await addPlugin(
tree,
await createProjectGraphAsync(),
'@nx/storybook/plugin',
createNodes,
{

View File

@ -1,7 +1,6 @@
import {
addDependenciesToPackageJson,
NxJsonConfiguration,
ProjectGraph,
readJson,
readNxJson,
Tree,
@ -10,14 +9,6 @@ import {
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { nxVersion } from '../../utils/versions';
let projectGraph: ProjectGraph;
jest.mock('@nx/devkit', () => ({
...jest.requireActual<any>('@nx/devkit'),
createProjectGraphAsync: jest.fn().mockImplementation(async () => {
return projectGraph;
}),
}));
import { initGenerator } from './init';
describe('@nx/vite:init', () => {
@ -25,10 +16,6 @@ describe('@nx/vite:init', () => {
beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
projectGraph = {
nodes: {},
dependencies: {},
};
});
describe('dependencies for package.json', () => {

View File

@ -1,5 +1,4 @@
import {
createProjectGraphAsync,
formatFiles,
GeneratorCallback,
readNxJson,
@ -62,7 +61,6 @@ export async function initGeneratorInternal(
if (schema.addPlugin) {
await addPlugin(
tree,
await createProjectGraphAsync(),
'@nx/vite/plugin',
createNodes,
{

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
import { readProjectConfiguration, Tree } from '@nx/devkit';

View File

@ -1,5 +1,3 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import { readJson, Tree } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';

View File

@ -1,6 +1,5 @@
import {
addDependenciesToPackageJson,
createProjectGraphAsync,
formatFiles,
GeneratorCallback,
readNxJson,
@ -25,7 +24,6 @@ export async function webpackInitGeneratorInternal(tree: Tree, schema: Schema) {
if (schema.addPlugin) {
await addPlugin(
tree,
await createProjectGraphAsync(),
'@nx/webpack/plugin',
createNodes,
{

View File

@ -1,4 +1,4 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
import { readProjectConfiguration, Tree } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';