feat(testing): remove tsConfig and copyFiles options from the @nx/cypress:cypress executor (#30870)

Removes the previously deprecated and unused `tsConfig` and `copyFiles`
options from the `@nx/cypress:cypress` executor.

BREAKING CHANGE: The previously deprecated and unused `tsConfig` and
`copyFiles` options from the `@nx/cypress:cypress` executor were
removed.
This commit is contained in:
Leosvel Pérez Espinosa 2025-04-29 17:12:47 +02:00 committed by GitHub
parent 9ae691ede8
commit 8d0c7f6349
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 593 additions and 35 deletions

View File

@ -1312,6 +1312,16 @@
}
},
"migrations": {
"/nx-api/cypress/migrations/remove-tsconfig-and-copy-files-options-from-cypress-executor": {
"description": "Removes the `tsConfig` and `copyFiles` options from the `@nx/cypress:cypress` executor.",
"file": "generated/packages/cypress/migrations/remove-tsconfig-and-copy-files-options-from-cypress-executor.json",
"hidden": false,
"name": "remove-tsconfig-and-copy-files-options-from-cypress-executor",
"version": "21.0.0-beta.10",
"originalFilePath": "/packages/cypress",
"path": "/nx-api/cypress/migrations/remove-tsconfig-and-copy-files-options-from-cypress-executor",
"type": "migration"
},
"/nx-api/cypress/migrations/set-inject-document-domain": {
"description": "Replaces the `experimentalSkipDomainInjection` configuration option with the new `injectDocumentDomain` configuration option.",
"file": "generated/packages/cypress/migrations/set-inject-document-domain.json",

View File

@ -1304,6 +1304,16 @@
}
],
"migrations": [
{
"description": "Removes the `tsConfig` and `copyFiles` options from the `@nx/cypress:cypress` executor.",
"file": "generated/packages/cypress/migrations/remove-tsconfig-and-copy-files-options-from-cypress-executor.json",
"hidden": false,
"name": "remove-tsconfig-and-copy-files-options-from-cypress-executor",
"version": "21.0.0-beta.10",
"originalFilePath": "/packages/cypress",
"path": "cypress/migrations/remove-tsconfig-and-copy-files-options-from-cypress-executor",
"type": "migration"
},
{
"description": "Replaces the `experimentalSkipDomainInjection` configuration option with the new `injectDocumentDomain` configuration option.",
"file": "generated/packages/cypress/migrations/set-inject-document-domain.json",

View File

@ -31,13 +31,6 @@
"description": "Recompile and run tests when files change.",
"default": false
},
"tsConfig": {
"x-deprecated": "This option no longer has any effect. Cypress supports typescript out of the box. Add any options directly to <projectRoot>/tsconfig.json or <projectRoot>/cypress/tsconfig.json",
"type": "string",
"description": "The path of the Cypress tsconfig configuration json file.",
"x-completion-type": "file",
"x-completion-glob": "tsconfig.*.json"
},
"devServerTarget": {
"type": "string",
"description": "Dev server target to run tests against."
@ -51,7 +44,7 @@
"type": "boolean",
"description": "Hide the browser instead of running headed.",
"default": false,
"x-deprecated": "Cypress runs headless by default. Use the --watch flag to control head/headless behavior instead."
"x-deprecated": "Cypress runs headless by default. Use the --watch flag to control head/headless behavior instead. It will be removed in Nx v22."
},
"exit": {
"type": "boolean",
@ -90,12 +83,6 @@
"type": "string",
"description": "A comma delimited glob string that is provided to the Cypress runner to specify which spec files to run. i.e. `**examples/**,**actions.spec**`."
},
"copyFiles": {
"type": "string",
"description": "A regex string that is used to choose what additional integration files to copy to the dist folder.",
"x-deprecated": "No longer used since cypress supports typescript out of the box. If specified, it will be ignored.",
"x-priority": "internal"
},
"ciBuildId": {
"oneOf": [{ "type": "string" }, { "type": "number" }],
"description": "A unique identifier for a run to enable grouping or parallelization."

View File

@ -0,0 +1,12 @@
{
"name": "remove-tsconfig-and-copy-files-options-from-cypress-executor",
"version": "21.0.0-beta.10",
"description": "Removes the `tsConfig` and `copyFiles` options from the `@nx/cypress:cypress` executor.",
"implementation": "/packages/cypress/src/migrations/update-21-0-0/remove-tsconfig-and-copy-files-options-from-cypress-executor.ts",
"aliases": [],
"hidden": false,
"path": "/packages/cypress",
"schema": null,
"type": "migration",
"examplesFile": "#### Remove `tsConfig` and `copyFiles` Options from Cypress Executor\n\nRemoves the previously deprecated and unused `tsConfig` and `copyFiles` options from the `@nx/cypress:cypress` executor configuration in all projects.\n\n#### Examples\n\nRemove the options from the project configuration:\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"apps/app1-e2e/project.json\" highlightLines=[7,8] %}\n{\n \"targets\": {\n \"e2e\": {\n \"executor\": \"@nx/cypress:cypress\",\n \"options\": {\n \"cypressConfig\": \"apps/app1-e2e/cypress.config.ts\",\n \"tsConfig\": \"apps/app1-e2e/tsconfig.json\",\n \"copyFiles\": \"**/*.spec.ts\",\n \"devServerTarget\": \"app1:serve\"\n }\n }\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"After\" %}\n\n```json {% fileName=\"apps/app1-e2e/project.json\" %}\n{\n \"targets\": {\n \"e2e\": {\n \"executor\": \"@nx/cypress:cypress\",\n \"options\": {\n \"cypressConfig\": \"apps/app1-e2e/cypress.config.ts\",\n \"devServerTarget\": \"app1:serve\"\n }\n }\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n\nRemove the options from a target default using the `@nx/cypress:cypress` executor:\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"nx.json\" highlightLines=[7,8] %}\n{\n \"targetDefaults\": {\n \"e2e\": {\n \"cache\": true,\n \"executor\": \"@nx/cypress:cypress\",\n \"options\": {\n \"tsConfig\": \"{projectRoot}/tsconfig.json\",\n \"copyFiles\": \"**/*.spec.ts\"\n }\n }\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"After\" %}\n\n```json {% fileName=\"nx.json\" %}\n{\n \"targetDefaults\": {\n \"e2e\": {\n \"cache\": true,\n \"executor\": \"@nx/cypress:cypress\"\n }\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n\nRemove the options from a target default using the `@nx/cypress:cypress` executor as the key:\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"nx.json\" highlightLines=[6,7] %}\n{\n \"targetDefaults\": {\n \"@nx/cypress:cypress\": {\n \"cache\": true,\n \"options\": {\n \"tsConfig\": \"{projectRoot}/tsconfig.json\",\n \"copyFiles\": \"**/*.spec.ts\"\n }\n }\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"After\" %}\n\n```json {% fileName=\"nx.json\" %}\n{\n \"targetDefaults\": {\n \"@nx/cypress:cypress\": {\n \"cache\": true\n }\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n"
}

View File

@ -41,6 +41,11 @@
},
"description": "Updates the module specifier for the Component Testing `mount` function.",
"implementation": "./src/migrations/update-20-8-0/update-component-testing-mount-imports"
},
"remove-tsconfig-and-copy-files-options-from-cypress-executor": {
"version": "21.0.0-beta.10",
"description": "Removes the `tsConfig` and `copyFiles` options from the `@nx/cypress:cypress` executor.",
"implementation": "./src/migrations/update-21-0-0/remove-tsconfig-and-copy-files-options-from-cypress-executor"
}
},
"packageJsonUpdates": {

View File

@ -22,7 +22,6 @@ describe('Cypress builder', () => {
const cypressOptions: CypressExecutorOptions = {
cypressConfig: 'apps/my-app-e2e/cypress.json',
parallel: false,
tsConfig: 'apps/my-app-e2e/tsconfig.json',
devServerTarget: 'my-app:serve',
exit: true,
record: false,
@ -270,7 +269,6 @@ A generator to migrate from v8 to v10 is provided. See https://nx.dev/cypress/v1
const { success } = await cypressExecutor(
{
cypressConfig: 'apps/my-app-e2e/cypress.json',
tsConfig: 'apps/my-app-e2e/tsconfig.json',
devServerTarget: undefined,
headless: true,
exit: true,

View File

@ -15,7 +15,8 @@ export interface CypressExecutorOptions extends Json {
devServerTarget?: string;
headed?: boolean;
/**
* @deprecated use watch instead
* @deprecated Cypress runs headless by default. Use the --watch flag to
* control head/headless behavior instead. It will be removed in Nx v22.
**/
headless?: boolean;
exit?: boolean;
@ -26,10 +27,6 @@ export interface CypressExecutorOptions extends Json {
browser?: string;
env?: Record<string, string>;
spec?: string;
/**
* @deprecated no longer used since cypress supports typescript out of the box
**/
copyFiles?: string;
ciBuildId?: string | number;
group?: string;
ignoreTestFiles?: string | string[];

View File

@ -31,13 +31,6 @@
"description": "Recompile and run tests when files change.",
"default": false
},
"tsConfig": {
"x-deprecated": "This option no longer has any effect. Cypress supports typescript out of the box. Add any options directly to <projectRoot>/tsconfig.json or <projectRoot>/cypress/tsconfig.json",
"type": "string",
"description": "The path of the Cypress tsconfig configuration json file.",
"x-completion-type": "file",
"x-completion-glob": "tsconfig.*.json"
},
"devServerTarget": {
"type": "string",
"description": "Dev server target to run tests against."
@ -51,7 +44,7 @@
"type": "boolean",
"description": "Hide the browser instead of running headed.",
"default": false,
"x-deprecated": "Cypress runs headless by default. Use the --watch flag to control head/headless behavior instead."
"x-deprecated": "Cypress runs headless by default. Use the --watch flag to control head/headless behavior instead. It will be removed in Nx v22."
},
"exit": {
"type": "boolean",
@ -90,12 +83,6 @@
"type": "string",
"description": "A comma delimited glob string that is provided to the Cypress runner to specify which spec files to run. i.e. `**examples/**,**actions.spec**`."
},
"copyFiles": {
"type": "string",
"description": "A regex string that is used to choose what additional integration files to copy to the dist folder.",
"x-deprecated": "No longer used since cypress supports typescript out of the box. If specified, it will be ignored.",
"x-priority": "internal"
},
"ciBuildId": {
"oneOf": [
{

View File

@ -0,0 +1,121 @@
#### Remove `tsConfig` and `copyFiles` Options from Cypress Executor
Removes the previously deprecated and unused `tsConfig` and `copyFiles` options from the `@nx/cypress:cypress` executor configuration in all projects.
#### Examples
Remove the options from the project configuration:
{% tabs %}
{% tab label="Before" %}
```json {% fileName="apps/app1-e2e/project.json" highlightLines=[7,8] %}
{
"targets": {
"e2e": {
"executor": "@nx/cypress:cypress",
"options": {
"cypressConfig": "apps/app1-e2e/cypress.config.ts",
"tsConfig": "apps/app1-e2e/tsconfig.json",
"copyFiles": "**/*.spec.ts",
"devServerTarget": "app1:serve"
}
}
}
}
```
{% /tab %}
{% tab label="After" %}
```json {% fileName="apps/app1-e2e/project.json" %}
{
"targets": {
"e2e": {
"executor": "@nx/cypress:cypress",
"options": {
"cypressConfig": "apps/app1-e2e/cypress.config.ts",
"devServerTarget": "app1:serve"
}
}
}
}
```
{% /tab %}
{% /tabs %}
Remove the options from a target default using the `@nx/cypress:cypress` executor:
{% tabs %}
{% tab label="Before" %}
```json {% fileName="nx.json" highlightLines=[7,8] %}
{
"targetDefaults": {
"e2e": {
"cache": true,
"executor": "@nx/cypress:cypress",
"options": {
"tsConfig": "{projectRoot}/tsconfig.json",
"copyFiles": "**/*.spec.ts"
}
}
}
}
```
{% /tab %}
{% tab label="After" %}
```json {% fileName="nx.json" %}
{
"targetDefaults": {
"e2e": {
"cache": true,
"executor": "@nx/cypress:cypress"
}
}
}
```
{% /tab %}
{% /tabs %}
Remove the options from a target default using the `@nx/cypress:cypress` executor as the key:
{% tabs %}
{% tab label="Before" %}
```json {% fileName="nx.json" highlightLines=[6,7] %}
{
"targetDefaults": {
"@nx/cypress:cypress": {
"cache": true,
"options": {
"tsConfig": "{projectRoot}/tsconfig.json",
"copyFiles": "**/*.spec.ts"
}
}
}
}
```
{% /tab %}
{% tab label="After" %}
```json {% fileName="nx.json" %}
{
"targetDefaults": {
"@nx/cypress:cypress": {
"cache": true
}
}
}
```
{% /tab %}
{% /tabs %}

View File

@ -0,0 +1,326 @@
import 'nx/src/internal-testing-utils/mock-project-graph';
import {
addProjectConfiguration,
readJson,
readProjectConfiguration,
updateJson,
type NxJsonConfiguration,
type ProjectConfiguration,
type Tree,
} from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import migration from './remove-tsconfig-and-copy-files-options-from-cypress-executor';
describe('remove-tsconfig-and-copy-files-options-from-cypress-executor', () => {
let tree: Tree;
beforeEach(() => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
});
it('should remove tsConfig and copyFiles from default options', async () => {
const projectConfig: ProjectConfiguration = {
root: 'apps/app1-e2e',
sourceRoot: 'apps/app1-e2e/src',
projectType: 'application',
targets: {
e2e: {
executor: '@nx/cypress:cypress',
options: {
cypressConfig: 'apps/app1-e2e/cypress.config.ts',
tsConfig: 'apps/app1-e2e/tsconfig.json',
copyFiles: '**/*.spec.ts',
devServerTarget: 'app1:serve',
},
},
},
};
addProjectConfiguration(tree, 'app1-e2e', projectConfig);
await migration(tree);
const updatedConfig = readProjectConfiguration(tree, 'app1-e2e');
expect(updatedConfig.targets.e2e.options).toEqual({
cypressConfig: 'apps/app1-e2e/cypress.config.ts',
devServerTarget: 'app1:serve',
});
expect('tsConfig' in updatedConfig.targets.e2e.options).toEqual(false);
expect('copyFiles' in updatedConfig.targets.e2e.options).toEqual(false);
});
it('should remove tsConfig and copyFiles from configurations', async () => {
const projectConfig: ProjectConfiguration = {
root: 'apps/app1-e2e',
sourceRoot: 'apps/app1-e2e/src',
projectType: 'application',
targets: {
e2e: {
executor: '@nx/cypress:cypress',
options: {
cypressConfig: 'apps/app1-e2e/cypress.config.ts',
devServerTarget: 'app1:serve',
},
configurations: {
production: {
devServerTarget: 'app1:serve:production',
tsConfig: 'apps/app1-e2e/tsconfig.prod.json',
copyFiles: '**/*.prod.spec.ts',
},
},
},
},
};
addProjectConfiguration(tree, 'app1-e2e', projectConfig);
await migration(tree);
const updatedConfig = readProjectConfiguration(tree, 'app1-e2e');
expect(updatedConfig.targets.e2e.configurations.production).toEqual({
devServerTarget: 'app1:serve:production',
});
expect(
'tsConfig' in updatedConfig.targets.e2e.configurations.production
).toEqual(false);
expect(
'copyFiles' in updatedConfig.targets.e2e.configurations.production
).toEqual(false);
});
it('should handle projects without the deprecated options', async () => {
const projectConfig: ProjectConfiguration = {
root: 'apps/app2-e2e',
sourceRoot: 'apps/app2-e2e/src',
projectType: 'application',
targets: {
e2e: {
executor: '@nx/cypress:cypress',
options: {
cypressConfig: 'apps/app2-e2e/cypress.config.ts',
devServerTarget: 'app2:serve',
},
},
},
};
addProjectConfiguration(tree, 'app2-e2e', projectConfig);
await migration(tree);
const updatedConfig = readProjectConfiguration(tree, 'app2-e2e');
expect(updatedConfig.targets.e2e.options).toEqual({
cypressConfig: 'apps/app2-e2e/cypress.config.ts',
devServerTarget: 'app2:serve',
});
});
it('should handle projects with multiple targets using cypress executor', async () => {
const projectConfig: ProjectConfiguration = {
root: 'apps/app3-e2e',
sourceRoot: 'apps/app3-e2e/src',
projectType: 'application',
targets: {
e2e: {
executor: '@nx/cypress:cypress',
options: {
cypressConfig: 'apps/app3-e2e/cypress.config.ts',
tsConfig: 'apps/app3-e2e/tsconfig.json',
devServerTarget: 'app3:serve',
},
},
ct: {
executor: '@nx/cypress:cypress',
options: {
cypressConfig: 'apps/app3-e2e/cypress.config.ts',
copyFiles: '**/*.ct.spec.ts',
devServerTarget: 'app3:serve-ct',
testingType: 'component',
},
},
},
};
addProjectConfiguration(tree, 'app3-e2e', projectConfig);
await migration(tree);
const updatedConfig = readProjectConfiguration(tree, 'app3-e2e');
expect(updatedConfig.targets.e2e.options).toEqual({
cypressConfig: 'apps/app3-e2e/cypress.config.ts',
devServerTarget: 'app3:serve',
});
expect(updatedConfig.targets.ct.options).toEqual({
cypressConfig: 'apps/app3-e2e/cypress.config.ts',
devServerTarget: 'app3:serve-ct',
testingType: 'component',
});
});
it('should remove tsConfig and copyFiles options in nx.json target defaults for a target with the cypress executor', async () => {
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
json.targetDefaults ??= {};
json.targetDefaults.e2e = {
executor: '@nx/cypress:cypress',
options: {
cypressConfig: '{projectRoot}/cypress.config.ts',
tsConfig: '{projectRoot}/tsconfig.json',
copyFiles: '**/*.spec.ts',
devServerTarget: '{projectName}:serve',
},
configurations: {
production: {
devServerTarget: '{projectName}:serve:production',
tsConfig: '{projectRoot}/tsconfig.prod.json',
copyFiles: '**/*.prod.spec.ts',
},
},
};
return json;
});
await migration(tree);
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(nxJson.targetDefaults.e2e.options).toStrictEqual({
cypressConfig: '{projectRoot}/cypress.config.ts',
devServerTarget: '{projectName}:serve',
});
expect(nxJson.targetDefaults.e2e.options.tsConfig).toBeUndefined();
expect(nxJson.targetDefaults.e2e.options.copyFiles).toBeUndefined();
expect(nxJson.targetDefaults.e2e.configurations.production).toStrictEqual({
devServerTarget: '{projectName}:serve:production',
});
expect(
nxJson.targetDefaults.e2e.configurations.production.tsConfig
).toBeUndefined();
expect(
nxJson.targetDefaults.e2e.configurations.production.copyFiles
).toBeUndefined();
});
it('should remove tsConfig and copyFiles options in nx.json target defaults for the cypress executor', async () => {
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
json.targetDefaults ??= {};
json.targetDefaults['@nx/cypress:cypress'] = {
options: {
cypressConfig: '{projectRoot}/cypress.config.ts',
tsConfig: '{projectRoot}/tsconfig.json',
copyFiles: '**/*.spec.ts',
devServerTarget: '{projectName}:serve',
},
configurations: {
production: {
devServerTarget: '{projectName}:serve:production',
tsConfig: '{projectRoot}/tsconfig.prod.json',
copyFiles: '**/*.prod.spec.ts',
},
},
};
return json;
});
await migration(tree);
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(nxJson.targetDefaults['@nx/cypress:cypress'].options).toStrictEqual({
cypressConfig: '{projectRoot}/cypress.config.ts',
devServerTarget: '{projectName}:serve',
});
expect(
nxJson.targetDefaults['@nx/cypress:cypress'].options.tsConfig
).toBeUndefined();
expect(
nxJson.targetDefaults['@nx/cypress:cypress'].options.copyFiles
).toBeUndefined();
expect(
nxJson.targetDefaults['@nx/cypress:cypress'].configurations.production
).toStrictEqual({
devServerTarget: '{projectName}:serve:production',
});
expect(
nxJson.targetDefaults['@nx/cypress:cypress'].configurations.production
.tsConfig
).toBeUndefined();
expect(
nxJson.targetDefaults['@nx/cypress:cypress'].configurations.production
.copyFiles
).toBeUndefined();
});
it('should remove empty options and configurations objects from project configuration', async () => {
const projectConfig: ProjectConfiguration = {
root: 'apps/app4-e2e',
sourceRoot: 'apps/app4-e2e/src',
projectType: 'application',
targets: {
e2e: {
executor: '@nx/cypress:cypress',
options: {
tsConfig: 'apps/app4-e2e/tsconfig.json',
copyFiles: '**/*.spec.ts',
},
configurations: {
production: {
tsConfig: 'apps/app4-e2e/tsconfig.prod.json',
copyFiles: '**/*.prod.spec.ts',
},
},
},
},
};
addProjectConfiguration(tree, 'app4-e2e', projectConfig);
await migration(tree);
const updatedConfig = readProjectConfiguration(tree, 'app4-e2e');
expect(updatedConfig.targets.e2e.options).toBeUndefined();
expect(updatedConfig.targets.e2e.configurations).toBeUndefined();
});
it('should remove empty targetDefault object from nx.json when using a target name as the key', async () => {
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
json.targetDefaults = {};
json.targetDefaults.e2e = {
executor: '@nx/cypress:cypress',
options: {
tsConfig: '{projectRoot}/tsconfig.json',
copyFiles: '**/*.spec.ts',
},
configurations: {
production: {
tsConfig: '{projectRoot}/tsconfig.prod.json',
copyFiles: '**/*.prod.spec.ts',
},
},
};
return json;
});
await migration(tree);
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(nxJson.targetDefaults).toBeUndefined();
});
it('should remove empty targetDefault object from nx.json when using the cypress executor as the key', async () => {
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
json.targetDefaults = {};
json.targetDefaults['@nx/cypress:cypress'] = {
options: {
tsConfig: '{projectRoot}/tsconfig.json',
copyFiles: '**/*.spec.ts',
},
configurations: {
production: {
tsConfig: '{projectRoot}/tsconfig.prod.json',
copyFiles: '**/*.prod.spec.ts',
},
},
};
return json;
});
await migration(tree);
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(nxJson.targetDefaults).toBeUndefined();
});
});

View File

@ -0,0 +1,105 @@
import {
formatFiles,
type ProjectConfiguration,
readNxJson,
readProjectConfiguration,
type TargetConfiguration,
type Tree,
updateNxJson,
updateProjectConfiguration,
} from '@nx/devkit';
import { forEachExecutorOptions } from '@nx/devkit/src/generators/executor-options-utils';
import type { CypressExecutorOptions } from '../../executors/cypress/cypress.impl';
const EXECUTOR_TO_MIGRATE = '@nx/cypress:cypress';
export default async function (tree: Tree) {
// update options from project configs
forEachExecutorOptions<CypressExecutorOptions>(
tree,
EXECUTOR_TO_MIGRATE,
(options, project, target, configuration) => {
if (options.tsConfig === undefined && options.copyFiles === undefined) {
return;
}
const projectConfiguration = readProjectConfiguration(tree, project);
if (configuration) {
updateConfiguration(
projectConfiguration.targets[target],
configuration
);
} else {
updateOptions(projectConfiguration.targets[target]);
}
updateProjectConfiguration(tree, project, projectConfiguration);
}
);
// update options from nx.json target defaults
const nxJson = readNxJson(tree);
if (nxJson.targetDefaults) {
for (const [targetOrExecutor, targetConfig] of Object.entries(
nxJson.targetDefaults
)) {
if (
targetOrExecutor !== EXECUTOR_TO_MIGRATE &&
targetConfig.executor !== EXECUTOR_TO_MIGRATE
) {
continue;
}
if (targetConfig.options) {
updateOptions(targetConfig);
}
Object.keys(targetConfig.configurations ?? {}).forEach((config) => {
updateConfiguration(targetConfig, config);
});
if (
!Object.keys(targetConfig).length ||
(Object.keys(targetConfig).length === 1 &&
Object.keys(targetConfig)[0] === 'executor')
) {
delete nxJson.targetDefaults[targetOrExecutor];
}
if (!Object.keys(nxJson.targetDefaults).length) {
delete nxJson.targetDefaults;
}
}
updateNxJson(tree, nxJson);
}
await formatFiles(tree);
}
function updateOptions(target: TargetConfiguration) {
delete target.options.tsConfig;
delete target.options.copyFiles;
if (!Object.keys(target.options).length) {
delete target.options;
}
}
function updateConfiguration(
target: TargetConfiguration,
configuration: string
) {
delete target.configurations[configuration].tsConfig;
delete target.configurations[configuration].copyFiles;
if (
!Object.keys(target.configurations[configuration]).length &&
(!target.defaultConfiguration ||
target.defaultConfiguration !== configuration)
) {
delete target.configurations[configuration];
}
if (!Object.keys(target.configurations).length) {
delete target.configurations;
}
}