@nx/devkit 19.0.0-canary.20240423-b37bfdb → 19.0.0-canary.20240425-cec57c4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/devkit",
3
- "version": "19.0.0-canary.20240423-b37bfdb",
3
+ "version": "19.0.0-canary.20240425-cec57c4",
4
4
  "private": false,
5
5
  "description": "The Nx Devkit is used to customize Nx for different technologies and use cases. It contains many utility functions for reading and writing files, updating configuration, working with Abstract Syntax Trees(ASTs), and more. Learn more about [extending Nx by leveraging the Nx Devkit](https://nx.dev/extending-nx/intro/getting-started) on our docs.",
6
6
  "repository": {
@@ -35,7 +35,8 @@
35
35
  "tslib": "^2.3.0",
36
36
  "semver": "^7.5.3",
37
37
  "yargs-parser": "21.1.1",
38
- "@nrwl/devkit": "19.0.0-canary.20240423-b37bfdb"
38
+ "minimatch": "9.0.3",
39
+ "@nrwl/devkit": "19.0.0-canary.20240425-cec57c4"
39
40
  },
40
41
  "peerDependencies": {
41
42
  "nx": ">= 16 <= 19"
@@ -0,0 +1,9 @@
1
+ import type { TargetConfiguration } from 'nx/src/config/workspace-json-project-json';
2
+ import type { Tree } from 'nx/src/generators/tree';
3
+ import type { CreateNodes } from 'nx/src/project-graph/plugins';
4
+ import type { ProjectGraph } from 'nx/src/config/project-graph';
5
+ type PluginOptionsBuilder<T> = (targetName: string) => T;
6
+ type PostTargetTransformer = (targetConfiguration: TargetConfiguration) => TargetConfiguration;
7
+ type SkipTargetFilter = (targetConfiguration: TargetConfiguration) => [boolean, string];
8
+ export declare function migrateExecutorToPlugin<T>(tree: Tree, projectGraph: ProjectGraph, executor: string, pluginPath: string, pluginOptionsBuilder: PluginOptionsBuilder<T>, postTargetTransformer: PostTargetTransformer, createNodes: CreateNodes<T>, specificProjectToMigrate?: string, skipTargetFilter?: SkipTargetFilter): Promise<void>;
9
+ export {};
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ var _ExecutorToPluginMigrator_instances, _ExecutorToPluginMigrator_projectGraph, _ExecutorToPluginMigrator_executor, _ExecutorToPluginMigrator_pluginPath, _ExecutorToPluginMigrator_pluginOptionsBuilder, _ExecutorToPluginMigrator_postTargetTransformer, _ExecutorToPluginMigrator_skipTargetFilter, _ExecutorToPluginMigrator_specificProjectToMigrate, _ExecutorToPluginMigrator_nxJson, _ExecutorToPluginMigrator_targetDefaultsForExecutor, _ExecutorToPluginMigrator_targetAndProjectsToMigrate, _ExecutorToPluginMigrator_pluginToAddForTarget, _ExecutorToPluginMigrator_createNodes, _ExecutorToPluginMigrator_configFiles, _ExecutorToPluginMigrator_createNodesResultsForTargets, _ExecutorToPluginMigrator_init, _ExecutorToPluginMigrator_migrateTarget, _ExecutorToPluginMigrator_migrateProject, _ExecutorToPluginMigrator_addPlugins, _ExecutorToPluginMigrator_getTargetAndProjectsToMigrate, _ExecutorToPluginMigrator_getTargetDefaultsForExecutor, _ExecutorToPluginMigrator_getCreatedTargetForProjectRoot, _ExecutorToPluginMigrator_getCreateNodesResults;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.migrateExecutorToPlugin = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const minimatch_1 = require("minimatch");
7
+ const executor_options_utils_1 = require("../executor-options-utils");
8
+ const plugin_migration_utils_1 = require("./plugin-migration-utils");
9
+ const nx_1 = require("../../../nx");
10
+ const { glob, readNxJson, updateNxJson, mergeTargetConfigurations, updateProjectConfiguration, readProjectConfiguration, retrieveProjectConfigurations, LoadedNxPlugin, ProjectConfigurationsError, } = (0, nx_1.requireNx)();
11
+ class ExecutorToPluginMigrator {
12
+ constructor(tree, projectGraph, executor, pluginPath, pluginOptionsBuilder, postTargetTransformer, createNodes, specificProjectToMigrate, skipTargetFilter) {
13
+ _ExecutorToPluginMigrator_instances.add(this);
14
+ _ExecutorToPluginMigrator_projectGraph.set(this, void 0);
15
+ _ExecutorToPluginMigrator_executor.set(this, void 0);
16
+ _ExecutorToPluginMigrator_pluginPath.set(this, void 0);
17
+ _ExecutorToPluginMigrator_pluginOptionsBuilder.set(this, void 0);
18
+ _ExecutorToPluginMigrator_postTargetTransformer.set(this, void 0);
19
+ _ExecutorToPluginMigrator_skipTargetFilter.set(this, void 0);
20
+ _ExecutorToPluginMigrator_specificProjectToMigrate.set(this, void 0);
21
+ _ExecutorToPluginMigrator_nxJson.set(this, void 0);
22
+ _ExecutorToPluginMigrator_targetDefaultsForExecutor.set(this, void 0);
23
+ _ExecutorToPluginMigrator_targetAndProjectsToMigrate.set(this, void 0);
24
+ _ExecutorToPluginMigrator_pluginToAddForTarget.set(this, void 0);
25
+ _ExecutorToPluginMigrator_createNodes.set(this, void 0);
26
+ _ExecutorToPluginMigrator_configFiles.set(this, void 0);
27
+ _ExecutorToPluginMigrator_createNodesResultsForTargets.set(this, void 0);
28
+ this.tree = tree;
29
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_projectGraph, projectGraph, "f");
30
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_executor, executor, "f");
31
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_pluginPath, pluginPath, "f");
32
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_pluginOptionsBuilder, pluginOptionsBuilder, "f");
33
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_postTargetTransformer, postTargetTransformer, "f");
34
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_createNodes, createNodes, "f");
35
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_specificProjectToMigrate, specificProjectToMigrate, "f");
36
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_skipTargetFilter, skipTargetFilter ?? ((...args) => [false, '']), "f");
37
+ }
38
+ async run() {
39
+ await tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_instances, "m", _ExecutorToPluginMigrator_init).call(this);
40
+ for (const targetName of tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_targetAndProjectsToMigrate, "f").keys()) {
41
+ tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_instances, "m", _ExecutorToPluginMigrator_migrateTarget).call(this, targetName);
42
+ }
43
+ tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_instances, "m", _ExecutorToPluginMigrator_addPlugins).call(this);
44
+ }
45
+ }
46
+ _ExecutorToPluginMigrator_projectGraph = new WeakMap(), _ExecutorToPluginMigrator_executor = new WeakMap(), _ExecutorToPluginMigrator_pluginPath = new WeakMap(), _ExecutorToPluginMigrator_pluginOptionsBuilder = new WeakMap(), _ExecutorToPluginMigrator_postTargetTransformer = new WeakMap(), _ExecutorToPluginMigrator_skipTargetFilter = new WeakMap(), _ExecutorToPluginMigrator_specificProjectToMigrate = new WeakMap(), _ExecutorToPluginMigrator_nxJson = new WeakMap(), _ExecutorToPluginMigrator_targetDefaultsForExecutor = new WeakMap(), _ExecutorToPluginMigrator_targetAndProjectsToMigrate = new WeakMap(), _ExecutorToPluginMigrator_pluginToAddForTarget = new WeakMap(), _ExecutorToPluginMigrator_createNodes = new WeakMap(), _ExecutorToPluginMigrator_configFiles = new WeakMap(), _ExecutorToPluginMigrator_createNodesResultsForTargets = new WeakMap(), _ExecutorToPluginMigrator_instances = new WeakSet(), _ExecutorToPluginMigrator_init = async function _ExecutorToPluginMigrator_init() {
47
+ const nxJson = readNxJson(this.tree);
48
+ nxJson.plugins ??= [];
49
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_nxJson, nxJson, "f");
50
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_targetAndProjectsToMigrate, new Map(), "f");
51
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_pluginToAddForTarget, new Map(), "f");
52
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_createNodesResultsForTargets, new Map(), "f");
53
+ tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_instances, "m", _ExecutorToPluginMigrator_getTargetDefaultsForExecutor).call(this);
54
+ tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_instances, "m", _ExecutorToPluginMigrator_getTargetAndProjectsToMigrate).call(this);
55
+ await tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_instances, "m", _ExecutorToPluginMigrator_getCreateNodesResults).call(this);
56
+ }, _ExecutorToPluginMigrator_migrateTarget = function _ExecutorToPluginMigrator_migrateTarget(targetName) {
57
+ const include = [];
58
+ for (const projectName of tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_targetAndProjectsToMigrate, "f").get(targetName)) {
59
+ include.push(tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_instances, "m", _ExecutorToPluginMigrator_migrateProject).call(this, projectName, targetName));
60
+ }
61
+ tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_pluginToAddForTarget, "f").set(targetName, {
62
+ plugin: tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_pluginPath, "f"),
63
+ options: tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_pluginOptionsBuilder, "f").call(this, targetName),
64
+ include,
65
+ });
66
+ }, _ExecutorToPluginMigrator_migrateProject = function _ExecutorToPluginMigrator_migrateProject(projectName, targetName) {
67
+ const projectFromGraph = tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_projectGraph, "f").nodes[projectName];
68
+ const projectConfig = readProjectConfiguration(this.tree, projectName);
69
+ const createdTarget = tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_instances, "m", _ExecutorToPluginMigrator_getCreatedTargetForProjectRoot).call(this, targetName, projectFromGraph.data.root);
70
+ let projectTarget = projectConfig.targets[targetName];
71
+ projectTarget = mergeTargetConfigurations(projectTarget, tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_targetDefaultsForExecutor, "f"));
72
+ delete projectTarget.executor;
73
+ (0, plugin_migration_utils_1.deleteMatchingProperties)(projectTarget, createdTarget);
74
+ projectTarget = tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_postTargetTransformer, "f").call(this, projectTarget);
75
+ if (projectTarget.options &&
76
+ Object.keys(projectTarget.options).length === 0) {
77
+ delete projectTarget.options;
78
+ }
79
+ if (Object.keys(projectTarget).length > 0) {
80
+ projectConfig.targets[targetName] = projectTarget;
81
+ }
82
+ else {
83
+ delete projectConfig.targets[targetName];
84
+ }
85
+ updateProjectConfiguration(this.tree, projectName, projectConfig);
86
+ return `${projectFromGraph.data.root}/**/*`;
87
+ }, _ExecutorToPluginMigrator_addPlugins = function _ExecutorToPluginMigrator_addPlugins() {
88
+ for (const [targetName, plugin] of tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_pluginToAddForTarget, "f").entries()) {
89
+ const pluginOptions = tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_pluginOptionsBuilder, "f").call(this, targetName);
90
+ const existingPlugin = tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_nxJson, "f").plugins.find((plugin) => {
91
+ if (typeof plugin === 'string' ||
92
+ plugin.plugin !== tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_pluginPath, "f")) {
93
+ return;
94
+ }
95
+ for (const key in plugin.options) {
96
+ if (plugin.options[key] !== pluginOptions[key]) {
97
+ return false;
98
+ }
99
+ }
100
+ return true;
101
+ });
102
+ if (existingPlugin?.include) {
103
+ for (const pluginIncludes of existingPlugin.include) {
104
+ for (const projectPath of plugin.include) {
105
+ if (!(0, minimatch_1.minimatch)(projectPath, pluginIncludes, { dot: true })) {
106
+ existingPlugin.include.push(projectPath);
107
+ }
108
+ }
109
+ }
110
+ const allConfigFilesAreIncluded = tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_configFiles, "f").every((configFile) => {
111
+ for (const includePattern of existingPlugin.include) {
112
+ if ((0, minimatch_1.minimatch)(configFile, includePattern, { dot: true })) {
113
+ return true;
114
+ }
115
+ }
116
+ return false;
117
+ });
118
+ if (allConfigFilesAreIncluded) {
119
+ existingPlugin.include = undefined;
120
+ }
121
+ }
122
+ if (!existingPlugin) {
123
+ tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_nxJson, "f").plugins.push(plugin);
124
+ }
125
+ }
126
+ updateNxJson(this.tree, tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_nxJson, "f"));
127
+ }, _ExecutorToPluginMigrator_getTargetAndProjectsToMigrate = function _ExecutorToPluginMigrator_getTargetAndProjectsToMigrate() {
128
+ (0, executor_options_utils_1.forEachExecutorOptions)(this.tree, tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_executor, "f"), (targetConfiguration, projectName, targetName, configurationName) => {
129
+ if (configurationName) {
130
+ return;
131
+ }
132
+ if (tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_specificProjectToMigrate, "f") &&
133
+ projectName !== tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_specificProjectToMigrate, "f")) {
134
+ return;
135
+ }
136
+ const [skipTarget, reasonTargetWasSkipped] = tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_skipTargetFilter, "f").call(this, targetConfiguration);
137
+ if (skipTarget) {
138
+ const errorMsg = `${targetName} target on project "${projectName}" cannot be migrated. ${reasonTargetWasSkipped}`;
139
+ if (tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_specificProjectToMigrate, "f")) {
140
+ throw new Error(errorMsg);
141
+ }
142
+ else {
143
+ console.warn(errorMsg);
144
+ }
145
+ return;
146
+ }
147
+ if (tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_targetAndProjectsToMigrate, "f").has(targetName)) {
148
+ tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_targetAndProjectsToMigrate, "f").get(targetName).add(projectName);
149
+ }
150
+ else {
151
+ tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_targetAndProjectsToMigrate, "f").set(targetName, new Set([projectName]));
152
+ }
153
+ });
154
+ if (tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_targetAndProjectsToMigrate, "f").size === 0) {
155
+ const errorMsg = tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_specificProjectToMigrate, "f")
156
+ ? `Project "${tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_specificProjectToMigrate, "f")}" does not contain any targets using the "${tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_executor, "f")}" executor. Please select a project that does.`
157
+ : `Could not find any targets using the "${tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_executor, "f")}" executor.`;
158
+ throw new Error(errorMsg);
159
+ }
160
+ }, _ExecutorToPluginMigrator_getTargetDefaultsForExecutor = function _ExecutorToPluginMigrator_getTargetDefaultsForExecutor() {
161
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_targetDefaultsForExecutor, tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_nxJson, "f").targetDefaults?.[tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_executor, "f")], "f");
162
+ }, _ExecutorToPluginMigrator_getCreatedTargetForProjectRoot = function _ExecutorToPluginMigrator_getCreatedTargetForProjectRoot(targetName, projectRoot) {
163
+ const createdProject = Object.entries(tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_createNodesResultsForTargets, "f").get(targetName)?.projects ?? {}).find(([root]) => root === projectRoot)[1];
164
+ const createdTarget = createdProject.targets[targetName];
165
+ delete createdTarget.command;
166
+ delete createdTarget.options?.cwd;
167
+ return createdTarget;
168
+ }, _ExecutorToPluginMigrator_getCreateNodesResults = async function _ExecutorToPluginMigrator_getCreateNodesResults() {
169
+ for (const targetName of tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_targetAndProjectsToMigrate, "f").keys()) {
170
+ const loadedPlugin = new LoadedNxPlugin({
171
+ createNodes: tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_createNodes, "f"),
172
+ name: tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_pluginPath, "f"),
173
+ }, {
174
+ plugin: tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_pluginPath, "f"),
175
+ options: tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_pluginOptionsBuilder, "f").call(this, targetName),
176
+ });
177
+ let projectConfigs;
178
+ try {
179
+ projectConfigs = await retrieveProjectConfigurations([loadedPlugin], this.tree.root, tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_nxJson, "f"));
180
+ }
181
+ catch (e) {
182
+ if (e instanceof ProjectConfigurationsError) {
183
+ projectConfigs = e.partialProjectConfigurationsResult;
184
+ }
185
+ else {
186
+ throw e;
187
+ }
188
+ }
189
+ tslib_1.__classPrivateFieldSet(this, _ExecutorToPluginMigrator_configFiles, Array.from(projectConfigs.matchingProjectFiles), "f");
190
+ tslib_1.__classPrivateFieldGet(this, _ExecutorToPluginMigrator_createNodesResultsForTargets, "f").set(targetName, projectConfigs);
191
+ }
192
+ };
193
+ async function migrateExecutorToPlugin(tree, projectGraph, executor, pluginPath, pluginOptionsBuilder, postTargetTransformer, createNodes, specificProjectToMigrate, skipTargetFilter) {
194
+ const migrator = new ExecutorToPluginMigrator(tree, projectGraph, executor, pluginPath, pluginOptionsBuilder, postTargetTransformer, createNodes, specificProjectToMigrate, skipTargetFilter);
195
+ await migrator.run();
196
+ }
197
+ exports.migrateExecutorToPlugin = migrateExecutorToPlugin;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Iterate through the current target in the project.json and its options comparing it to the target created by the Plugin itself
3
+ * Delete matching properties from current target.
4
+ *
5
+ * _Note: Deletes by reference_
6
+ *
7
+ * @example
8
+ * // Run the plugin to get all the projects
9
+ * const { projects } = await createNodes[1](
10
+ * playwrightConfigPath,
11
+ * { targetName, ciTargetName: 'e2e-ci' },
12
+ * { workspaceRoot: tree.root, nxJsonConfiguration, configFiles }
13
+ * );
14
+ *
15
+ * // Find the project that matches the one that is being migrated
16
+ * const createdProject = Object.entries(projects ?? {}).find(
17
+ * ([root]) => root === projectFromGraph.data.root
18
+ * )[1];
19
+ *
20
+ * // Get the created TargetConfiguration for the target being migrated
21
+ * const createdTarget: TargetConfiguration<RunCommandsOptions> =
22
+ * createdProject.targets[targetName];
23
+ *
24
+ * // Delete specific run-commands options
25
+ * delete createdTarget.command;
26
+ * delete createdTarget.options?.cwd;
27
+ *
28
+ * // Get the TargetConfiguration for the target being migrated from project.json
29
+ * const projectConfig = readProjectConfiguration(tree, projectName);
30
+ * let targetToMigrate = projectConfig.targets[targetName];
31
+ *
32
+ * // Merge the target defaults for the executor to the target being migrated
33
+ * target = mergeTargetConfigurations(targetToMigrate, targetDefaultsForExecutor);
34
+ *
35
+ * // Delete executor and any additional options that are no longer necessary
36
+ * delete target.executor;
37
+ * delete target.options?.config;
38
+ *
39
+ * // Run deleteMatchingProperties to delete further options that match what the plugin creates
40
+ * deleteMatchingProperties(target, createdTarget);
41
+ *
42
+ * // Delete the target if it is now empty, otherwise, set it to the updated TargetConfiguration
43
+ * if (Object.keys(target).length > 0) {
44
+ * projectConfig.targets[targetName] = target;
45
+ * } else {
46
+ * delete projectConfig.targets[targetName];
47
+ * }
48
+ *
49
+ * updateProjectConfiguration(tree, projectName, projectConfig);
50
+ *
51
+ * @param targetToMigrate The target from project.json
52
+ * @param createdTarget The target created by the Plugin
53
+ */
54
+ export declare function deleteMatchingProperties(targetToMigrate: object, createdTarget: object): void;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteMatchingProperties = void 0;
4
+ /**
5
+ * Iterate through the current target in the project.json and its options comparing it to the target created by the Plugin itself
6
+ * Delete matching properties from current target.
7
+ *
8
+ * _Note: Deletes by reference_
9
+ *
10
+ * @example
11
+ * // Run the plugin to get all the projects
12
+ * const { projects } = await createNodes[1](
13
+ * playwrightConfigPath,
14
+ * { targetName, ciTargetName: 'e2e-ci' },
15
+ * { workspaceRoot: tree.root, nxJsonConfiguration, configFiles }
16
+ * );
17
+ *
18
+ * // Find the project that matches the one that is being migrated
19
+ * const createdProject = Object.entries(projects ?? {}).find(
20
+ * ([root]) => root === projectFromGraph.data.root
21
+ * )[1];
22
+ *
23
+ * // Get the created TargetConfiguration for the target being migrated
24
+ * const createdTarget: TargetConfiguration<RunCommandsOptions> =
25
+ * createdProject.targets[targetName];
26
+ *
27
+ * // Delete specific run-commands options
28
+ * delete createdTarget.command;
29
+ * delete createdTarget.options?.cwd;
30
+ *
31
+ * // Get the TargetConfiguration for the target being migrated from project.json
32
+ * const projectConfig = readProjectConfiguration(tree, projectName);
33
+ * let targetToMigrate = projectConfig.targets[targetName];
34
+ *
35
+ * // Merge the target defaults for the executor to the target being migrated
36
+ * target = mergeTargetConfigurations(targetToMigrate, targetDefaultsForExecutor);
37
+ *
38
+ * // Delete executor and any additional options that are no longer necessary
39
+ * delete target.executor;
40
+ * delete target.options?.config;
41
+ *
42
+ * // Run deleteMatchingProperties to delete further options that match what the plugin creates
43
+ * deleteMatchingProperties(target, createdTarget);
44
+ *
45
+ * // Delete the target if it is now empty, otherwise, set it to the updated TargetConfiguration
46
+ * if (Object.keys(target).length > 0) {
47
+ * projectConfig.targets[targetName] = target;
48
+ * } else {
49
+ * delete projectConfig.targets[targetName];
50
+ * }
51
+ *
52
+ * updateProjectConfiguration(tree, projectName, projectConfig);
53
+ *
54
+ * @param targetToMigrate The target from project.json
55
+ * @param createdTarget The target created by the Plugin
56
+ */
57
+ function deleteMatchingProperties(targetToMigrate, createdTarget) {
58
+ for (const key in targetToMigrate) {
59
+ if (Array.isArray(targetToMigrate[key])) {
60
+ if (targetToMigrate[key].every((v) => createdTarget[key]?.includes(v)) &&
61
+ targetToMigrate[key].length === createdTarget[key]?.length) {
62
+ delete targetToMigrate[key];
63
+ }
64
+ }
65
+ else if (typeof targetToMigrate[key] === 'object' &&
66
+ typeof createdTarget[key] === 'object') {
67
+ deleteMatchingProperties(targetToMigrate[key], createdTarget[key]);
68
+ }
69
+ else if (targetToMigrate[key] === createdTarget[key]) {
70
+ delete targetToMigrate[key];
71
+ }
72
+ if (typeof targetToMigrate[key] === 'object' &&
73
+ Object.keys(targetToMigrate[key]).length === 0) {
74
+ delete targetToMigrate[key];
75
+ }
76
+ }
77
+ }
78
+ exports.deleteMatchingProperties = deleteMatchingProperties;
@@ -17,7 +17,9 @@ async function addPlugin(tree, graph, pluginName, createNodesTuple, options, sho
17
17
  optionsLoop: for (const _pluginOptions of combinations) {
18
18
  pluginOptions = _pluginOptions;
19
19
  nxJson.plugins ??= [];
20
- if (nxJson.plugins.some((p) => typeof p === 'string' ? p === pluginName : p.plugin === pluginName)) {
20
+ if (nxJson.plugins.some((p) => typeof p === 'string'
21
+ ? p === pluginName
22
+ : p.plugin === pluginName && !p.include)) {
21
23
  // Plugin has already been added
22
24
  return;
23
25
  }
@@ -2,7 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.convertNxExecutor = void 0;
4
4
  const nx_1 = require("../../nx");
5
- const { Workspaces, readNxJsonFromDisk, retrieveProjectConfigurationsWithAngularProjects, } = (0, nx_1.requireNx)();
5
+ const package_json_1 = require("./package-json");
6
+ const semver_1 = require("semver");
7
+ const { Workspaces, readNxJsonFromDisk, retrieveProjectConfigurationsWithAngularProjects, readProjectConfigurationsFromRootMap, } = (0, nx_1.requireNx)();
6
8
  /**
7
9
  * Convert an Nx Executor into an Angular Devkit Builder
8
10
  *
@@ -20,7 +22,20 @@ function convertNxExecutor(executor) {
20
22
  const projectsConfigurations = retrieveProjectConfigurationsWithAngularProjects
21
23
  ? {
22
24
  version: 2,
23
- projects: await retrieveProjectConfigurationsWithAngularProjects(builderContext.workspaceRoot, nxJsonConfiguration).then((p) => p.projectNodes ?? p.projects),
25
+ projects: await retrieveProjectConfigurationsWithAngularProjects(builderContext.workspaceRoot, nxJsonConfiguration).then((p) => {
26
+ if (p.projectNodes) {
27
+ return p.projectNodes;
28
+ }
29
+ // v18.3.4 changed projects to be keyed by root
30
+ // rather than project name
31
+ if ((0, semver_1.lt)(package_json_1.NX_VERSION, '18.3.4')) {
32
+ return p.projects;
33
+ }
34
+ if (readProjectConfigurationsFromRootMap) {
35
+ return readProjectConfigurationsFromRootMap(p.projects);
36
+ }
37
+ throw new Error('Unable to successfully map Nx executor -> Angular Builder');
38
+ }),
24
39
  }
25
40
  : // TODO(v19): remove retrieveProjectConfigurations. This is to be backwards compatible with Nx 16.5 and below.
26
41
  workspaces.readProjectsConfigurations({