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:
parent
08654e1966
commit
85c8916087
@ -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';
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import 'nx/src/internal-testing-utils/mock-load-nx-plugin';
|
||||
|
||||
import {
|
||||
ProjectGraph,
|
||||
readJson,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
{
|
||||
|
||||
@ -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,
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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,
|
||||
{
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -38,7 +38,6 @@ export async function expoInitGeneratorInternal(host: Tree, schema: Schema) {
|
||||
if (schema.addPlugin) {
|
||||
await addPlugin(
|
||||
host,
|
||||
await createProjectGraphAsync(),
|
||||
'@nx/expo/plugin',
|
||||
createNodes,
|
||||
{
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import 'nx/src/internal-testing-utils/mock-project-graph';
|
||||
|
||||
import {
|
||||
type NxJsonConfiguration,
|
||||
readJson,
|
||||
|
||||
@ -103,7 +103,6 @@ export async function jestInitGeneratorInternal(
|
||||
if (options.addPlugin) {
|
||||
await addPlugin(
|
||||
tree,
|
||||
await createProjectGraphAsync(),
|
||||
'@nx/jest/plugin',
|
||||
createNodes,
|
||||
{
|
||||
|
||||
@ -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();
|
||||
});
|
||||
|
||||
|
||||
@ -55,7 +55,6 @@ export async function nextInitGeneratorInternal(
|
||||
const { createNodes } = await import('../../plugins/plugin');
|
||||
await addPlugin(
|
||||
host,
|
||||
await createProjectGraphAsync(),
|
||||
'@nx/next/plugin',
|
||||
createNodes,
|
||||
{
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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,
|
||||
{
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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({}), () => {}];
|
||||
}),
|
||||
}));
|
||||
@ -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) {
|
||||
|
||||
@ -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`
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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'] },
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import 'nx/src/internal-testing-utils/mock-project-graph';
|
||||
|
||||
import {
|
||||
Tree,
|
||||
getProjects,
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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,
|
||||
{
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 () => {
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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,
|
||||
{
|
||||
|
||||
@ -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' });
|
||||
});
|
||||
|
||||
|
||||
@ -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,
|
||||
{
|
||||
|
||||
@ -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' });
|
||||
});
|
||||
|
||||
|
||||
@ -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,
|
||||
{
|
||||
|
||||
@ -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', () => {
|
||||
|
||||
@ -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,
|
||||
{
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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';
|
||||
|
||||
|
||||
@ -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,
|
||||
{
|
||||
|
||||
@ -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';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user