From 79cf69b4e4adc687043cd064a37367086267d67f Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Thu, 14 Oct 2021 09:42:47 -0500 Subject: [PATCH] feat(core): consolidate nx.json and workspace.json (#6642) * feat(core): consolidate settings between workspace.json + nx.json workspace.json (and linked project.json files) now contain all project specific settings. nx.json now contains all settings that affect the whole workspace. * chore(core): fix angular unit tests w/ new config * chore(core): fix failing tests * chore(core): fix formatting * chore(core): fix more tests * chore(core): normalize-nx-json feedback * chore(core): Fix more unit tests * chore(core): fix remaining tests in workspace * chore(linter): fix remaining linter tests * chore(core): fix remaining spec + build issues * chore(core): formatting fixes * feat(core): migration script to move config options to new locations * chore(core): fix e2e tests * chore(core): run format * chore(react-native): fix failing tests Signed-off-by: AgentEnder * feat(core): move properties to new location during format step Signed-off-by: AgentEnder * feat(core): initial pass on ngcli-adapter for property consolidation Signed-off-by: AgentEnder * chore(misc): fix tests Signed-off-by: AgentEnder * docs(core): update docs with changes * chore(misc): fix tests * chore(core): code review changes updateWorkspaceJson -> updateWorkspace, no longer uses updater function Signed-off-by: AgentEnder * chore(core): fix bug in ngcli impl * fix(core): fix bug in ngcli-adapter Signed-off-by: AgentEnder * fix(core): fix ngcli-adapter Signed-off-by: AgentEnder * chore(core): fix workspace e2e * chore(core): fix nx-plugin e2e * fix(core): move defaultProject to nx.json * chore(core): fix broken workspace test * chore(core): formatting * chore(core): fix workspace format * chore(core): add nxJson to ExecutorContext Signed-off-by: AgentEnder * chore(core): remove all references ot `NxProjectConfiguration` from our code * chore(core): Review Changes * fix(core): update new config locations v13 migration --- docs/angular/api-nx-devkit/index.md | 48 +-- docs/node/api-nx-devkit/index.md | 48 +-- docs/react/api-nx-devkit/index.md | 48 +-- e2e/nx-plugin/src/nx-plugin.test.ts | 15 +- e2e/workspace-core/src/aux-commands.test.ts | 91 ++-- .../src/create-nx-workspace.test.ts | 4 +- .../src/workspace-aux-commands.test.ts | 3 - .../src/workspace.test.ts | 16 +- .../__snapshots__/application.spec.ts.snap | 10 + .../application/application.spec.ts | 64 +-- .../application/lib/add-protractor.ts | 17 +- .../application/lib/update-config-files.ts | 24 +- .../application/lib/update-e2e-project.ts | 2 + .../angular/src/generators/init/init.spec.ts | 54 +-- .../generators/library/lib/update-project.ts | 12 +- .../src/generators/library/library.spec.ts | 67 +-- .../generators/setup-mfe/setup-mfe.spec.ts | 9 +- .../generators/stories/lib/get-e2e-project.ts | 4 +- ...-browser-build-target-to-delegate-build.ts | 5 +- .../update-invalid-import-paths.ts | 8 +- .../angular/src/utils/nx-devkit/testing.ts | 8 +- packages/cli/lib/init-local.ts | 2 + .../cli/lib/parse-run-one-options.spec.ts | 28 +- packages/cli/lib/parse-run-one-options.ts | 47 ++- .../cypress-project/cypress-project.spec.ts | 12 +- .../cypress-project/cypress-project.ts | 3 +- .../devkit/src/generators/format-files.ts | 40 +- .../generators/project-configuration.spec.ts | 42 -- .../src/generators/project-configuration.ts | 143 ++----- .../tests/create-tree-with-empty-workspace.ts | 1 - .../devkit/src/utils/convert-nx-executor.ts | 5 +- .../express/src/generators/init/init.spec.ts | 10 +- .../application/application.spec.ts | 66 +-- .../generators/application/lib/add-project.ts | 11 +- .../gatsby/src/generators/init/init.spec.ts | 6 +- .../jest/src/executors/jest/jest.impl.spec.ts | 1 + .../linter/src/executors/eslint/hasher.ts | 5 +- .../src/executors/eslint/lint.impl.spec.ts | 1 + .../src/executors/lint/lint.impl.spec.ts | 1 + ...rc-json-to-workspace-implicit-deps.spec.ts | 1 - .../project-converter.spec.ts.snap | 397 ++++++++---------- .../project-converter.spec.ts | 47 ++- .../project-converter.ts | 8 +- .../nest/src/generators/init/init.spec.ts | 11 +- .../src/generators/library/library.spec.ts | 18 +- .../application/application.spec.ts | 13 +- .../generators/application/lib/add-project.ts | 7 +- .../next/src/generators/init/init.spec.ts | 6 +- .../src/executors/build/build.impl.spec.ts | 1 + .../executors/execute/execute.impl.spec.ts | 1 + .../executors/package/package.impl.spec.ts | 1 + .../application/application.spec.ts | 20 +- .../src/generators/application/application.ts | 3 +- .../node/src/generators/init/init.spec.ts | 11 +- .../src/generators/library/library.spec.ts | 18 +- .../src/generators/e2e-project/e2e.spec.ts | 15 +- .../tests/__pluginName__.spec.ts__tmpl__ | 6 +- .../application/application.spec.ts | 11 +- .../generators/application/lib/add-project.ts | 7 +- .../src/generators/init/init.spec.ts | 10 +- .../src/generators/library/library.spec.ts | 21 +- .../application/application.spec.ts | 12 +- .../generators/application/lib/add-project.ts | 7 +- .../react/src/generators/init/init.spec.ts | 11 +- .../src/generators/library/library.spec.ts | 45 +- .../build-storybook.impl.spec.ts | 1 + .../storybook/storybook.impl.spec.ts | 1 + .../src/generators/init/init.spec.ts | 13 +- packages/tao/src/commands/generate.ts | 7 +- packages/tao/src/commands/migrate.ts | 3 +- packages/tao/src/commands/ngcli-adapter.ts | 208 ++++++--- packages/tao/src/commands/run.ts | 3 +- packages/tao/src/shared/nx.ts | 40 +- packages/tao/src/shared/params.ts | 8 +- packages/tao/src/shared/workspace.ts | 71 ++-- .../executors/package/package.impl.spec.ts | 1 + .../application/application.spec.ts | 17 +- .../src/generators/application/application.ts | 3 +- packages/web/src/generators/init/init.spec.ts | 11 +- packages/workspace/migrations.json | 6 + packages/workspace/package.json | 3 + packages/workspace/project.json | 2 +- packages/workspace/src/command-line/format.ts | 76 +++- .../workspace/src/command-line/utils.spec.ts | 3 - .../affected-project-graph.spec.ts | 23 +- .../affected-project-graph.ts | 15 +- .../locators/implicit-json-changes.spec.ts | 1 - .../locators/npm-packages.spec.ts | 4 - .../locators/nx-json-changes.spec.ts | 218 ---------- .../locators/nx-json-changes.ts | 58 --- .../locators/tsconfig-json-changes.spec.ts | 5 - .../locators/workspace-json-changes.spec.ts | 5 - .../core/assert-workspace-validity.spec.ts | 65 +-- .../src/core/assert-workspace-validity.ts | 30 +- packages/workspace/src/core/file-utils.ts | 15 - .../workspace/src/core/hasher/hasher.spec.ts | 22 +- packages/workspace/src/core/hasher/hasher.ts | 4 +- .../src/core/normalize-nx-json.spec.ts | 31 +- .../workspace/src/core/normalize-nx-json.ts | 16 +- .../src/core/nx-deps/nx-deps-cache.spec.ts | 1 - ...explicit-package-json-dependencies.spec.ts | 3 - .../explicit-project-dependencies.spec.ts | 3 - .../project-graph/build-project-graph.spec.ts | 21 +- .../core/project-graph/build-project-graph.ts | 6 +- .../src/core/target-project-locator.spec.ts | 3 - .../src/executors/tsc/tsc.impl.spec.ts | 1 + .../convert-to-nx-project.spec.ts | 6 +- .../convert-to-nx-project.ts | 9 +- .../init/__snapshots__/init.spec.ts.snap | 15 +- .../src/generators/init/init.spec.ts | 4 +- .../workspace/src/generators/init/init.ts | 46 +- .../src/generators/library/library.spec.ts | 18 +- .../src/generators/library/library.ts | 4 +- .../lib/move-project-configuration.spec.ts | 8 +- .../move/lib/move-project-configuration.ts | 3 +- .../move/lib/update-implicit-dependencies.ts | 24 +- .../new/__snapshots__/new.spec.ts.snap | 7 +- .../workspace/src/generators/new/new.spec.ts | 6 +- packages/workspace/src/generators/new/new.ts | 22 +- .../src/generators/preset/preset.spec.ts | 34 +- ...__.json => __workspaceFile__.json__tmpl__} | 5 +- .../workspace/files/nx.json__tmpl__ | 7 +- .../src/generators/workspace/schema.d.ts | 1 + .../src/generators/workspace/schema.json | 5 + .../generators/workspace/workspace.spec.ts | 4 +- .../src/generators/workspace/workspace.ts | 1 + .../config-locations/config-locations.spec.ts | 50 +++ .../config-locations/config-locations.ts | 31 ++ .../add-implicit-e2e-deps.spec.ts | 17 +- .../update-8-12-0/add-implicit-e2e-deps.ts | 38 +- .../update-enforce-boundary-lint-rule.spec.ts | 2 +- .../src/tasks-runner/run-command.spec.ts | 1 - .../src/tasks-runner/tasks-schedule.spec.ts | 1 + .../src/utilities/cache-directory.ts | 3 +- .../src/utilities/set-default-collection.ts | 2 +- packages/workspace/src/utils/ast-utils.ts | 22 +- .../src/utils/rules/workspace.spec.ts | 8 + 137 files changed, 1411 insertions(+), 1709 deletions(-) delete mode 100644 packages/workspace/src/core/affected-project-graph/locators/nx-json-changes.spec.ts delete mode 100644 packages/workspace/src/core/affected-project-graph/locators/nx-json-changes.ts rename packages/workspace/src/generators/workspace/files/{__workspaceFile__.json => __workspaceFile__.json__tmpl__} (60%) create mode 100644 packages/workspace/src/migrations/update-13-0-0/config-locations/config-locations.spec.ts create mode 100644 packages/workspace/src/migrations/update-13-0-0/config-locations/config-locations.ts diff --git a/docs/angular/api-nx-devkit/index.md b/docs/angular/api-nx-devkit/index.md index 566f9e361d..957552d69f 100644 --- a/docs/angular/api-nx-devkit/index.md +++ b/docs/angular/api-nx-devkit/index.md @@ -346,7 +346,7 @@ It only uses language primitives and immutable objects ### WorkspaceConfiguration -Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../angular/nx-devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<`Omit`<[`NxJsonConfiguration`](../../angular/nx-devkit/index#nxjsonconfiguration), `"projects"`\>\> +Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../angular/nx-devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<[`NxJsonConfiguration`](../../angular/nx-devkit/index#nxjsonconfiguration)\> --- @@ -549,17 +549,17 @@ Callback to install dependencies only if necessary. undefined is returned if cha Adds project configuration to the Nx workspace. -The project configuration is stored in workspace.json and nx.json. The utility will update -both files. +The project configuration is stored in workspace.json or the associated project.json file. +The utility will update either files. #### Parameters -| Name | Type | Default value | Description | -| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------ | :----------------------------------------------------------------------------------------- | -| `tree` | [`Tree`](../../angular/nx-devkit/index#tree) | `undefined` | the file system tree | -| `projectName` | `string` | `undefined` | unique name. Often directories are part of the name (e.g., mydir-mylib) | -| `projectConfiguration` | [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../angular/nx-devkit/index#nxjsonprojectconfiguration) | `undefined` | project configuration | -| `standalone` | `boolean` | `false` | should the project use package.json? If false, the project config is inside workspace.json | +| Name | Type | Default value | Description | +| :--------------------- | :--------------------------------------------------------------------------- | :------------ | :----------------------------------------------------------------------------------------- | +| `tree` | [`Tree`](../../angular/nx-devkit/index#tree) | `undefined` | the file system tree | +| `projectName` | `string` | `undefined` | unique name. Often directories are part of the name (e.g., mydir-mylib) | +| `projectConfiguration` | [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) | `undefined` | project configuration | +| `standalone` | `boolean` | `false` | should the project use package.json? If false, the project config is inside workspace.json | #### Returns @@ -808,7 +808,7 @@ but it can also be passed in explicitly. ### getProjects -▸ **getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../angular/nx-devkit/index#nxjsonprojectconfiguration)\> +▸ **getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration)\> Get a map of all projects in a workspace. @@ -822,7 +822,7 @@ Use [readProjectConfiguration](../../angular/nx-devkit/index#readprojectconfigur #### Returns -`Map`<`string`, [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../angular/nx-devkit/index#nxjsonprojectconfiguration)\> +`Map`<`string`, [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration)\> --- @@ -1135,12 +1135,12 @@ Object the JSON content of the file represents ### readProjectConfiguration -▸ **readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../angular/nx-devkit/index#nxjsonprojectconfiguration) +▸ **readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) Reads a project configuration. -The project configuration is stored in workspace.json and nx.json. The utility will read -both files. +The project configuration is stored in workspace.json or the associated project.json file. +The utility will read from either file. **`throws`** If supplied projectName cannot be found @@ -1153,7 +1153,7 @@ both files. #### Returns -[`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../angular/nx-devkit/index#nxjsonprojectconfiguration) +[`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) --- @@ -1241,8 +1241,8 @@ Callback to uninstall dependencies only if necessary. undefined is returned if c Removes the configuration of an existing project. -The project configuration is stored in workspace.json and nx.json. -The utility will update both files. +The project configuration is stored in workspace.json or the associated project.json file. +The utility will update either file. #### Parameters @@ -1460,16 +1460,16 @@ Updates a JSON value to the file system tree Updates the configuration of an existing project. -The project configuration is stored in workspace.json and nx.json. The utility will update -both files. +The project configuration is stored in workspace.json or the associated project.json file. +The utility will update either files. #### Parameters -| Name | Type | Description | -| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------- | -| `tree` | [`Tree`](../../angular/nx-devkit/index#tree) | the file system tree | -| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) | -| `projectConfiguration` | [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../angular/nx-devkit/index#nxjsonprojectconfiguration) | project configuration | +| Name | Type | Description | +| :--------------------- | :--------------------------------------------------------------------------- | :---------------------------------------------------------------------- | +| `tree` | [`Tree`](../../angular/nx-devkit/index#tree) | the file system tree | +| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) | +| `projectConfiguration` | [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) | project configuration | #### Returns diff --git a/docs/node/api-nx-devkit/index.md b/docs/node/api-nx-devkit/index.md index e72b9a82f8..68a1216d80 100644 --- a/docs/node/api-nx-devkit/index.md +++ b/docs/node/api-nx-devkit/index.md @@ -346,7 +346,7 @@ It only uses language primitives and immutable objects ### WorkspaceConfiguration -Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../node/nx-devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<`Omit`<[`NxJsonConfiguration`](../../node/nx-devkit/index#nxjsonconfiguration), `"projects"`\>\> +Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../node/nx-devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<[`NxJsonConfiguration`](../../node/nx-devkit/index#nxjsonconfiguration)\> --- @@ -549,17 +549,17 @@ Callback to install dependencies only if necessary. undefined is returned if cha Adds project configuration to the Nx workspace. -The project configuration is stored in workspace.json and nx.json. The utility will update -both files. +The project configuration is stored in workspace.json or the associated project.json file. +The utility will update either files. #### Parameters -| Name | Type | Default value | Description | -| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------ | :----------------------------------------------------------------------------------------- | -| `tree` | [`Tree`](../../node/nx-devkit/index#tree) | `undefined` | the file system tree | -| `projectName` | `string` | `undefined` | unique name. Often directories are part of the name (e.g., mydir-mylib) | -| `projectConfiguration` | [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../node/nx-devkit/index#nxjsonprojectconfiguration) | `undefined` | project configuration | -| `standalone` | `boolean` | `false` | should the project use package.json? If false, the project config is inside workspace.json | +| Name | Type | Default value | Description | +| :--------------------- | :------------------------------------------------------------------------ | :------------ | :----------------------------------------------------------------------------------------- | +| `tree` | [`Tree`](../../node/nx-devkit/index#tree) | `undefined` | the file system tree | +| `projectName` | `string` | `undefined` | unique name. Often directories are part of the name (e.g., mydir-mylib) | +| `projectConfiguration` | [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) | `undefined` | project configuration | +| `standalone` | `boolean` | `false` | should the project use package.json? If false, the project config is inside workspace.json | #### Returns @@ -808,7 +808,7 @@ but it can also be passed in explicitly. ### getProjects -▸ **getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../node/nx-devkit/index#nxjsonprojectconfiguration)\> +▸ **getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration)\> Get a map of all projects in a workspace. @@ -822,7 +822,7 @@ Use [readProjectConfiguration](../../node/nx-devkit/index#readprojectconfigurati #### Returns -`Map`<`string`, [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../node/nx-devkit/index#nxjsonprojectconfiguration)\> +`Map`<`string`, [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration)\> --- @@ -1135,12 +1135,12 @@ Object the JSON content of the file represents ### readProjectConfiguration -▸ **readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../node/nx-devkit/index#nxjsonprojectconfiguration) +▸ **readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) Reads a project configuration. -The project configuration is stored in workspace.json and nx.json. The utility will read -both files. +The project configuration is stored in workspace.json or the associated project.json file. +The utility will read from either file. **`throws`** If supplied projectName cannot be found @@ -1153,7 +1153,7 @@ both files. #### Returns -[`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../node/nx-devkit/index#nxjsonprojectconfiguration) +[`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) --- @@ -1241,8 +1241,8 @@ Callback to uninstall dependencies only if necessary. undefined is returned if c Removes the configuration of an existing project. -The project configuration is stored in workspace.json and nx.json. -The utility will update both files. +The project configuration is stored in workspace.json or the associated project.json file. +The utility will update either file. #### Parameters @@ -1460,16 +1460,16 @@ Updates a JSON value to the file system tree Updates the configuration of an existing project. -The project configuration is stored in workspace.json and nx.json. The utility will update -both files. +The project configuration is stored in workspace.json or the associated project.json file. +The utility will update either files. #### Parameters -| Name | Type | Description | -| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------- | -| `tree` | [`Tree`](../../node/nx-devkit/index#tree) | the file system tree | -| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) | -| `projectConfiguration` | [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../node/nx-devkit/index#nxjsonprojectconfiguration) | project configuration | +| Name | Type | Description | +| :--------------------- | :------------------------------------------------------------------------ | :---------------------------------------------------------------------- | +| `tree` | [`Tree`](../../node/nx-devkit/index#tree) | the file system tree | +| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) | +| `projectConfiguration` | [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) | project configuration | #### Returns diff --git a/docs/react/api-nx-devkit/index.md b/docs/react/api-nx-devkit/index.md index 31831923ce..857cac9c67 100644 --- a/docs/react/api-nx-devkit/index.md +++ b/docs/react/api-nx-devkit/index.md @@ -346,7 +346,7 @@ It only uses language primitives and immutable objects ### WorkspaceConfiguration -Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../react/nx-devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<`Omit`<[`NxJsonConfiguration`](../../react/nx-devkit/index#nxjsonconfiguration), `"projects"`\>\> +Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../react/nx-devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<[`NxJsonConfiguration`](../../react/nx-devkit/index#nxjsonconfiguration)\> --- @@ -549,17 +549,17 @@ Callback to install dependencies only if necessary. undefined is returned if cha Adds project configuration to the Nx workspace. -The project configuration is stored in workspace.json and nx.json. The utility will update -both files. +The project configuration is stored in workspace.json or the associated project.json file. +The utility will update either files. #### Parameters -| Name | Type | Default value | Description | -| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------ | :----------------------------------------------------------------------------------------- | -| `tree` | [`Tree`](../../react/nx-devkit/index#tree) | `undefined` | the file system tree | -| `projectName` | `string` | `undefined` | unique name. Often directories are part of the name (e.g., mydir-mylib) | -| `projectConfiguration` | [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../react/nx-devkit/index#nxjsonprojectconfiguration) | `undefined` | project configuration | -| `standalone` | `boolean` | `false` | should the project use package.json? If false, the project config is inside workspace.json | +| Name | Type | Default value | Description | +| :--------------------- | :------------------------------------------------------------------------- | :------------ | :----------------------------------------------------------------------------------------- | +| `tree` | [`Tree`](../../react/nx-devkit/index#tree) | `undefined` | the file system tree | +| `projectName` | `string` | `undefined` | unique name. Often directories are part of the name (e.g., mydir-mylib) | +| `projectConfiguration` | [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) | `undefined` | project configuration | +| `standalone` | `boolean` | `false` | should the project use package.json? If false, the project config is inside workspace.json | #### Returns @@ -808,7 +808,7 @@ but it can also be passed in explicitly. ### getProjects -▸ **getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../react/nx-devkit/index#nxjsonprojectconfiguration)\> +▸ **getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration)\> Get a map of all projects in a workspace. @@ -822,7 +822,7 @@ Use [readProjectConfiguration](../../react/nx-devkit/index#readprojectconfigurat #### Returns -`Map`<`string`, [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../react/nx-devkit/index#nxjsonprojectconfiguration)\> +`Map`<`string`, [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration)\> --- @@ -1135,12 +1135,12 @@ Object the JSON content of the file represents ### readProjectConfiguration -▸ **readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../react/nx-devkit/index#nxjsonprojectconfiguration) +▸ **readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) Reads a project configuration. -The project configuration is stored in workspace.json and nx.json. The utility will read -both files. +The project configuration is stored in workspace.json or the associated project.json file. +The utility will read from either file. **`throws`** If supplied projectName cannot be found @@ -1153,7 +1153,7 @@ both files. #### Returns -[`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../react/nx-devkit/index#nxjsonprojectconfiguration) +[`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) --- @@ -1241,8 +1241,8 @@ Callback to uninstall dependencies only if necessary. undefined is returned if c Removes the configuration of an existing project. -The project configuration is stored in workspace.json and nx.json. -The utility will update both files. +The project configuration is stored in workspace.json or the associated project.json file. +The utility will update either file. #### Parameters @@ -1460,16 +1460,16 @@ Updates a JSON value to the file system tree Updates the configuration of an existing project. -The project configuration is stored in workspace.json and nx.json. The utility will update -both files. +The project configuration is stored in workspace.json or the associated project.json file. +The utility will update either files. #### Parameters -| Name | Type | Description | -| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------- | -| `tree` | [`Tree`](../../react/nx-devkit/index#tree) | the file system tree | -| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) | -| `projectConfiguration` | [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../react/nx-devkit/index#nxjsonprojectconfiguration) | project configuration | +| Name | Type | Description | +| :--------------------- | :------------------------------------------------------------------------- | :---------------------------------------------------------------------- | +| `tree` | [`Tree`](../../react/nx-devkit/index#tree) | the file system tree | +| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) | +| `projectConfiguration` | [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) | project configuration | #### Returns diff --git a/e2e/nx-plugin/src/nx-plugin.test.ts b/e2e/nx-plugin/src/nx-plugin.test.ts index 772a4688c7..749cab7b26 100644 --- a/e2e/nx-plugin/src/nx-plugin.test.ts +++ b/e2e/nx-plugin/src/nx-plugin.test.ts @@ -38,9 +38,9 @@ describe('Nx Plugin', () => { `dist/libs/${plugin}/src/executors/build/schema.d.ts`, `dist/libs/${plugin}/src/executors/build/schema.json` ); - const nxJson = readJson('nx.json'); + const nxJson = readJson('workspace.json'); expect(nxJson).toMatchObject({ - projects: expect.objectContaining({ + projects: { [plugin]: { tags: [], }, @@ -48,7 +48,7 @@ describe('Nx Plugin', () => { tags: [], implicitDependencies: [`${plugin}`], }, - }), + }, }); }, 90000); @@ -188,13 +188,16 @@ describe('Nx Plugin', () => { }, 90000); }); describe('--tags', () => { - it('should add tags to nx.json', async () => { + it('should add tags to workspace.json', async () => { const plugin = uniq('plugin'); runCLI( `generate @nrwl/nx-plugin:plugin ${plugin} --linter=eslint --tags=e2etag,e2ePackage` ); - const nxJson = readJson('nx.json'); - expect(nxJson.projects[plugin].tags).toEqual(['e2etag', 'e2ePackage']); + const workspaceJson = readJson('workspace.json'); + expect(workspaceJson.projects[plugin].tags).toEqual([ + 'e2etag', + 'e2ePackage', + ]); }, 90000); }); }); diff --git a/e2e/workspace-core/src/aux-commands.test.ts b/e2e/workspace-core/src/aux-commands.test.ts index 6a6507d3f7..3bfffb62aa 100644 --- a/e2e/workspace-core/src/aux-commands.test.ts +++ b/e2e/workspace-core/src/aux-commands.test.ts @@ -1,4 +1,3 @@ -import { NxJsonConfiguration } from '@nrwl/devkit'; import { checkFilesExist, exists, @@ -12,7 +11,7 @@ import { updateFile, workspaceConfigName, } from '@nrwl/e2e/utils'; - +import type { WorkspaceJsonConfiguration } from '@nrwl/devkit'; let proj; beforeAll(() => { @@ -107,14 +106,13 @@ describe('workspace-generator', () => { ); expect(exists(`libs/dir/${workspace}/src/index.ts`)).toEqual(false); expect(dryRunOutput).toContain(`UPDATE ${workspaceConfigName()}`); - expect(dryRunOutput).toContain('UPDATE nx.json'); const output = runCLI( `workspace-generator ${custom} ${workspace} --no-interactive --directory=dir` ); checkFilesExist(`libs/dir/${workspace}/src/index.ts`); expect(output).toContain(`UPDATE ${workspaceConfigName()}`); - expect(output).toContain('UPDATE nx.json'); + expect(output).not.toContain('UPDATE nx.json'); const jsonFailing = readJson(`tools/generators/${failing}/schema.json`); jsonFailing.properties = {}; @@ -234,9 +232,11 @@ describe('move project', () => { */ runCLI(`generate @nrwl/workspace:lib ${lib3}`); - let nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration; - nxJson.projects[lib3].implicitDependencies = [`${lib1}-data-access`]; - updateFile(`nx.json`, JSON.stringify(nxJson)); + let workspaceJson = JSON.parse( + readFile('workspace.json') + ) as WorkspaceJsonConfiguration; + workspaceJson.projects[lib3].implicitDependencies = [`${lib1}-data-access`]; + updateFile(`workspace.json`, JSON.stringify(workspaceJson)); /** * Now try to move lib1 @@ -292,13 +292,14 @@ describe('move project', () => { expect(moveOutput).toContain(`CREATE ${rootClassPath}`); checkFilesExist(rootClassPath); - expect(moveOutput).toContain('UPDATE nx.json'); - nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration; - expect(nxJson.projects[`${lib1}-data-access`]).toBeUndefined(); - expect(nxJson.projects[newName]).toEqual({ + workspaceJson = JSON.parse( + readFile('workspace.json') + ) as WorkspaceJsonConfiguration; + expect(workspaceJson.projects[`${lib1}-data-access`]).toBeUndefined(); + expect(workspaceJson.projects[newName]).toMatchObject({ tags: [], }); - expect(nxJson.projects[lib3].implicitDependencies).toEqual([ + expect(workspaceJson.projects[lib3].implicitDependencies).toEqual([ `shared-${lib1}-data-access`, ]); @@ -312,7 +313,7 @@ describe('move project', () => { ).toEqual([`libs/shared/${lib1}/data-access/src/index.ts`]); expect(moveOutput).toContain(`UPDATE workspace.json`); - const workspaceJson = readJson(`workspace.json`); + workspaceJson = readJson(`workspace.json`); expect(workspaceJson.projects[`${lib1}-data-access`]).toBeUndefined(); const project = workspaceJson.projects[newName]; expect(project).toBeTruthy(); @@ -370,9 +371,11 @@ describe('move project', () => { */ runCLI(`generate @nrwl/workspace:lib ${lib3}`); - let nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration; - nxJson.projects[lib3].implicitDependencies = [`${lib1}-data-access`]; - updateFile(`nx.json`, JSON.stringify(nxJson)); + let workspaceJson = JSON.parse( + readFile('workspace.json') + ) as WorkspaceJsonConfiguration; + workspaceJson.projects[lib3].implicitDependencies = [`${lib1}-data-access`]; + updateFile(`workspace.json`, JSON.stringify(workspaceJson)); /** * Now try to move lib1 @@ -428,16 +431,6 @@ describe('move project', () => { expect(moveOutput).toContain(`CREATE ${rootClassPath}`); checkFilesExist(rootClassPath); - expect(moveOutput).toContain('UPDATE nx.json'); - nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration; - expect(nxJson.projects[`${lib1}-data-access`]).toBeUndefined(); - expect(nxJson.projects[newName]).toEqual({ - tags: [], - }); - expect(nxJson.projects[lib3].implicitDependencies).toEqual([ - `shared-${lib1}-data-access`, - ]); - expect(moveOutput).toContain('UPDATE tsconfig.base.json'); const rootTsConfig = readJson('tsconfig.base.json'); expect( @@ -448,12 +441,16 @@ describe('move project', () => { ).toEqual([`libs/shared/${lib1}/data-access/src/index.ts`]); expect(moveOutput).toContain(`UPDATE workspace.json`); - const workspaceJson = readJson(`workspace.json`); + workspaceJson = readJson(`workspace.json`); expect(workspaceJson.projects[`${lib1}-data-access`]).toBeUndefined(); const project = workspaceJson.projects[newName]; expect(project).toBeTruthy(); expect(project.root).toBe(newPath); expect(project.sourceRoot).toBe(`${newPath}/src`); + expect(project.tags).toEqual([]); + expect(workspaceJson.projects[lib3].implicitDependencies).toEqual([ + newName, + ]); expect(project.targets.lint.options.lintFilePatterns).toEqual([ `libs/shared/${lib1}/data-access/**/*.ts`, @@ -509,9 +506,11 @@ describe('move project', () => { */ runCLI(`generate @nrwl/workspace:lib ${lib3}`); - nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration; - nxJson.projects[lib3].implicitDependencies = [`${lib1}-data-access`]; - updateFile(`nx.json`, JSON.stringify(nxJson)); + let workspaceJson = JSON.parse( + readFile('workspace.json') + ) as WorkspaceJsonConfiguration; + workspaceJson.projects[lib3].implicitDependencies = [`${lib1}-data-access`]; + updateFile(`workspace.json`, JSON.stringify(workspaceJson)); /** * Now try to move lib1 @@ -567,16 +566,6 @@ describe('move project', () => { expect(moveOutput).toContain(`CREATE ${rootClassPath}`); checkFilesExist(rootClassPath); - expect(moveOutput).toContain('UPDATE nx.json'); - nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration; - expect(nxJson.projects[`${lib1}-data-access`]).toBeUndefined(); - expect(nxJson.projects[newName]).toEqual({ - tags: [], - }); - expect(nxJson.projects[lib3].implicitDependencies).toEqual([ - `shared-${lib1}-data-access`, - ]); - expect(moveOutput).toContain('UPDATE tsconfig.base.json'); const rootTsConfig = readJson('tsconfig.base.json'); expect( @@ -587,7 +576,7 @@ describe('move project', () => { ).toEqual([`packages/shared/${lib1}/data-access/src/index.ts`]); expect(moveOutput).toContain(`UPDATE workspace.json`); - const workspaceJson = readJson(`workspace.json`); + workspaceJson = readJson(`workspace.json`); expect(workspaceJson.projects[`${lib1}-data-access`]).toBeUndefined(); const project = workspaceJson.projects[newName]; expect(project).toBeTruthy(); @@ -596,6 +585,7 @@ describe('move project', () => { expect(project.targets.lint.options.lintFilePatterns).toEqual([ `packages/shared/${lib1}/data-access/**/*.ts`, ]); + expect(project.tags).toEqual([]); /** * Check that the import in lib2 has been updated @@ -629,9 +619,11 @@ describe('remove project', () => { */ runCLI(`generate @nrwl/workspace:lib ${lib2}`); - let nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration; - nxJson.projects[lib2].implicitDependencies = [lib1]; - updateFile(`nx.json`, JSON.stringify(nxJson)); + let workspaceJson = JSON.parse( + readFile('workspace.json') + ) as WorkspaceJsonConfiguration; + workspaceJson.projects[lib2].implicitDependencies = [lib1]; + updateFile(`workspace.json`, JSON.stringify(workspaceJson)); /** * Try removing the project (should fail) @@ -661,13 +653,14 @@ describe('remove project', () => { expect(removeOutputForced).toContain(`DELETE libs/${lib1}`); expect(exists(tmpProjPath(`libs/${lib1}`))).toBeFalsy(); - expect(removeOutputForced).toContain(`UPDATE nx.json`); - nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration; - expect(nxJson.projects[`${lib1}`]).toBeUndefined(); - expect(nxJson.projects[lib2].implicitDependencies).toEqual([]); + expect(removeOutputForced).not.toContain(`UPDATE nx.json`); + workspaceJson = JSON.parse( + readFile('workspace.json') + ) as WorkspaceJsonConfiguration; + expect(workspaceJson.projects[`${lib1}`]).toBeUndefined(); + expect(workspaceJson.projects[lib2].implicitDependencies).toEqual([]); expect(removeOutputForced).toContain(`UPDATE workspace.json`); - const workspaceJson = readJson(`workspace.json`); expect(workspaceJson.projects[`${lib1}`]).toBeUndefined(); }); }); diff --git a/e2e/workspace-create/src/create-nx-workspace.test.ts b/e2e/workspace-create/src/create-nx-workspace.test.ts index 9429ee5c1f..26c3d9f37f 100644 --- a/e2e/workspace-create/src/create-nx-workspace.test.ts +++ b/e2e/workspace-create/src/create-nx-workspace.test.ts @@ -236,8 +236,8 @@ describe('create-nx-workspace', () => { cli: 'angular', }); - const workspaceJson = readJson('angular.json'); - expect(workspaceJson.cli.packageManager).toEqual('yarn'); + const nxJson = readJson('nx.json'); + expect(nxJson.cli.packageManager).toEqual('yarn'); checkFilesExist('yarn.lock'); checkFilesDoNotExist('package-lock.json'); process.env.SELECTED_PM = packageManager; diff --git a/e2e/workspace-integrations/src/workspace-aux-commands.test.ts b/e2e/workspace-integrations/src/workspace-aux-commands.test.ts index 2eaff04991..47c596132c 100644 --- a/e2e/workspace-integrations/src/workspace-aux-commands.test.ts +++ b/e2e/workspace-integrations/src/workspace-aux-commands.test.ts @@ -1,7 +1,6 @@ import * as path from 'path'; import { checkFilesExist, - exists, isNotWindows, isWindows, newProject, @@ -10,11 +9,9 @@ import { removeProject, runCLI, runCLIAsync, - tmpProjPath, uniq, updateFile, } from '@nrwl/e2e/utils'; -import type { NxJsonConfiguration } from '@nrwl/devkit'; import { classify } from '@nrwl/workspace/src/utils/strings'; let proj: string; diff --git a/e2e/workspace-integrations/src/workspace.test.ts b/e2e/workspace-integrations/src/workspace.test.ts index 772019b5c3..f1d8497123 100644 --- a/e2e/workspace-integrations/src/workspace.test.ts +++ b/e2e/workspace-integrations/src/workspace.test.ts @@ -1,4 +1,7 @@ -import type { NxJsonConfiguration } from '@nrwl/devkit'; +import type { + NxJsonConfiguration, + WorkspaceJsonConfiguration, +} from '@nrwl/devkit'; import { getPackageManagerCommand, isNotWindows, @@ -534,14 +537,15 @@ describe('affected (with git)', () => { } }, 1000000); - it('should detect changes to projects based on the nx.json', () => { + it('should detect changes to projects based on tags changes', () => { // TODO: investigate why affected gives different results on windows if (isNotWindows()) { generateAll(); - const nxJson: NxJsonConfiguration = readJson('nx.json'); + const workspaceJson: WorkspaceJsonConfiguration = + readJson('workspace.json'); - nxJson.projects[myapp].tags = ['tag']; - updateFile('nx.json', JSON.stringify(nxJson)); + workspaceJson.projects[myapp].tags = ['tag']; + updateFile('workspace.json', JSON.stringify(workspaceJson)); expect(runCLI('affected:apps')).toContain(myapp); expect(runCLI('affected:apps')).not.toContain(myapp2); @@ -571,8 +575,6 @@ describe('affected (with git)', () => { delete workspaceJson.projects[mylib]; updateFile(workspaceConfigName(), JSON.stringify(workspaceJson)); - delete nxJson.projects[mylib]; - updateFile('nx.json', JSON.stringify(nxJson)); expect(runCLI('affected:apps')).toContain(myapp); expect(runCLI('affected:apps')).toContain(myapp2); diff --git a/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap b/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap index 2838171013..d6ab5344d1 100644 --- a/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap +++ b/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap @@ -327,6 +327,7 @@ Object { "projectType": "application", "root": "apps/my-dir/my-app", "sourceRoot": "apps/my-dir/my-app/src", + "tags": Array [], } `; @@ -357,9 +358,13 @@ Object { ], }, }, + "implicitDependencies": Array [ + "my-dir-my-app", + ], "projectType": "application", "root": "apps/my-dir/my-app-e2e", "sourceRoot": "apps/my-dir/my-app-e2e/src", + "tags": Array [], } `; @@ -489,6 +494,7 @@ Object { "projectType": "application", "root": "apps/my-app", "sourceRoot": "apps/my-app/src", + "tags": Array [], } `; @@ -519,8 +525,12 @@ Object { ], }, }, + "implicitDependencies": Array [ + "my-app", + ], "projectType": "application", "root": "apps/my-app-e2e", "sourceRoot": "apps/my-app-e2e/src", + "tags": Array [], } `; diff --git a/packages/angular/src/generators/application/application.spec.ts b/packages/angular/src/generators/application/application.spec.ts index 31ea5d2489..e94553e4a0 100644 --- a/packages/angular/src/generators/application/application.spec.ts +++ b/packages/angular/src/generators/application/application.spec.ts @@ -42,21 +42,25 @@ describe('app', () => { expect(workspaceJson.projects['my-app'].architect.e2e).not.toBeDefined(); }); - it('should update nx.json', async () => { + it('should update tags + implicit dependencies', async () => { // ACT await generateApp(appTree, 'myApp', { tags: 'one,two,my-app' }); // ASSERT - const nxJson = readJson(appTree, '/nx.json'); - expect(nxJson.projects).toEqual({ - 'my-app': { - tags: ['one', 'two', 'my-app'], - }, - 'my-app-e2e': { - implicitDependencies: ['my-app'], - tags: [], - }, - }); + const projects = devkit.getProjects(appTree); + expect(projects).toEqual( + new Map( + Object.entries({ + 'my-app': expect.objectContaining({ + tags: ['one', 'two', 'my-app'], + }), + 'my-app-e2e': expect.objectContaining({ + implicitDependencies: ['my-app'], + tags: [], + }), + }) + ) + ); }); it('should generate files', async () => { @@ -187,21 +191,25 @@ describe('app', () => { expect(workspaceJson.projects['my-dir-my-app-e2e']).toMatchSnapshot(); }); - it('should update nx.json', async () => { + it('should update tags + implicit dependencies', async () => { await generateApp(appTree, 'myApp', { directory: 'myDir', tags: 'one,two,my-dir-my-app', }); - const nxJson = readJson(appTree, '/nx.json'); - expect(nxJson.projects).toEqual({ - 'my-dir-my-app': { - tags: ['one', 'two', 'my-dir-my-app'], - }, - 'my-dir-my-app-e2e': { - implicitDependencies: ['my-dir-my-app'], - tags: [], - }, - }); + const projects = devkit.getProjects(appTree); + expect(projects).toEqual( + new Map( + Object.entries({ + 'my-dir-my-app': expect.objectContaining({ + tags: ['one', 'two', 'my-dir-my-app'], + }), + 'my-dir-my-app-e2e': expect.objectContaining({ + implicitDependencies: ['my-dir-my-app'], + tags: [], + }), + }) + ) + ); }); it('should generate files', async () => { @@ -596,6 +604,8 @@ describe('app', () => { }, }, }, + implicitDependencies: ['my-app'], + tags: [], }); }); @@ -720,9 +730,9 @@ describe('app', () => { } // should not update workspace configuration since --strict=true is the default - const workspaceJson = readJson(appTree, 'workspace.json'); + const nxJson = readJson(appTree, 'nx.json'); expect( - workspaceJson.schematics['@nrwl/angular:application'].strict + nxJson.generators['@nrwl/angular:application'].strict ).not.toBeDefined(); }); @@ -731,10 +741,8 @@ describe('app', () => { // check to see if the workspace configuration has been updated to turn off // strict mode by default in future applications - const workspaceJson = readJson(appTree, 'workspace.json'); - expect(workspaceJson.schematics['@nrwl/angular:application'].strict).toBe( - false - ); + const nxJson = readJson(appTree, 'nx.json'); + expect(nxJson.generators['@nrwl/angular:application'].strict).toBe(false); }); }); diff --git a/packages/angular/src/generators/application/lib/add-protractor.ts b/packages/angular/src/generators/application/lib/add-protractor.ts index ea5b739f12..2dfa2e6e27 100644 --- a/packages/angular/src/generators/application/lib/add-protractor.ts +++ b/packages/angular/src/generators/application/lib/add-protractor.ts @@ -1,17 +1,10 @@ -import type { Tree } from '@nrwl/devkit'; +import { Tree } from '@nrwl/devkit'; import type { NormalizedSchema } from './normalized-schema'; -import { - moveFilesToNewDirectory, - getWorkspaceLayout, - joinPathFragments, -} from '@nrwl/devkit'; +import { moveFilesToNewDirectory, joinPathFragments } from '@nrwl/devkit'; import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter'; -import { convertToNxProjectGenerator } from '@nrwl/workspace'; export async function addProtractor(host: Tree, options: NormalizedSchema) { - const { standaloneAsDefault } = getWorkspaceLayout(host); - const protractorSchematic = wrapAngularDevkitSchematic( '@schematics/angular', 'e2e' @@ -22,12 +15,6 @@ export async function addProtractor(host: Tree, options: NormalizedSchema) { rootSelector: `${options.prefix}-root`, }); - if (options.standaloneConfig || standaloneAsDefault) { - await convertToNxProjectGenerator(host, { - project: options.e2eProjectName, - }); - } - moveFilesToNewDirectory( host, joinPathFragments(options.appProjectRoot, 'e2e'), diff --git a/packages/angular/src/generators/application/lib/update-config-files.ts b/packages/angular/src/generators/application/lib/update-config-files.ts index fd02f0bcbd..074cbbb82c 100644 --- a/packages/angular/src/generators/application/lib/update-config-files.ts +++ b/packages/angular/src/generators/application/lib/update-config-files.ts @@ -19,23 +19,13 @@ export function updateConfigFiles(host: Tree, options: NormalizedSchema) { } function addProjectToNx(host: Tree, options: NormalizedSchema) { - // nx.json - updateJson(host, '/nx.json', (json) => { - const resultJson = { - ...json, - projects: { - ...json.projects, - [options.name]: { tags: options.parsedTags }, - }, - }; - if (options.e2eTestRunner === 'protractor') { - resultJson.projects[options.e2eProjectName] = { tags: [] }; - resultJson.projects[options.e2eProjectName].implicitDependencies = [ - options.name, - ]; - } - return resultJson; - }); + // tags, implicit dependencies + const projectConfig = readProjectConfiguration(host, options.name); + const resultJson = { + ...projectConfig, + tags: options.parsedTags, + }; + updateProjectConfiguration(host, options.name, resultJson); } function updateTsConfigCompilerOptions(host: Tree, options: NormalizedSchema) { diff --git a/packages/angular/src/generators/application/lib/update-e2e-project.ts b/packages/angular/src/generators/application/lib/update-e2e-project.ts index ae1653a389..518b658456 100644 --- a/packages/angular/src/generators/application/lib/update-e2e-project.ts +++ b/packages/angular/src/generators/application/lib/update-e2e-project.ts @@ -30,6 +30,8 @@ export function updateE2eProject(tree: Tree, options: NormalizedSchema) { targets: { e2e: proj.targets.e2e, }, + implicitDependencies: [options.name], + tags: [], }; project.targets.e2e.options.protractorConfig = `${options.e2eProjectRoot}/protractor.conf.js`; // update workspace.json / angular.json diff --git a/packages/angular/src/generators/init/init.spec.ts b/packages/angular/src/generators/init/init.spec.ts index 9ac1215da8..4d3691780a 100644 --- a/packages/angular/src/generators/init/init.spec.ts +++ b/packages/angular/src/generators/init/init.spec.ts @@ -1,4 +1,4 @@ -import { readJson, Tree } from '@nrwl/devkit'; +import { NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { Linter } from '@nrwl/linter'; @@ -104,13 +104,13 @@ describe('init', () => { skipFormat: false, }); - const { schematics } = readJson(host, 'workspace.json'); + const { generators } = readJson(host, 'nx.json'); // ASSERT - expect(schematics['@nrwl/angular:application'].unitTestRunner).toEqual( + expect(generators['@nrwl/angular:application'].unitTestRunner).toEqual( 'karma' ); - expect(schematics['@nrwl/angular:library'].unitTestRunner).toEqual( + expect(generators['@nrwl/angular:library'].unitTestRunner).toEqual( 'karma' ); }); @@ -155,13 +155,13 @@ describe('init', () => { skipFormat: false, }); - const { schematics } = readJson(host, 'workspace.json'); + const { generators } = readJson(host, 'nx.json'); // ASSERT - expect(schematics['@nrwl/angular:application'].unitTestRunner).toEqual( + expect(generators['@nrwl/angular:application'].unitTestRunner).toEqual( 'jest' ); - expect(schematics['@nrwl/angular:library'].unitTestRunner).toEqual( + expect(generators['@nrwl/angular:library'].unitTestRunner).toEqual( 'jest' ); }); @@ -195,10 +195,10 @@ describe('init', () => { skipFormat: false, }); - const { schematics } = readJson(host, 'workspace.json'); + const { generators } = readJson(host, 'nx.json'); // ASSERT - expect(schematics['@nrwl/angular:application'].e2eTestRunner).toEqual( + expect(generators['@nrwl/angular:application'].e2eTestRunner).toEqual( 'cypress' ); }); @@ -233,10 +233,10 @@ describe('init', () => { skipFormat: false, }); - const { schematics } = readJson(host, 'workspace.json'); + const { generators } = readJson(host, 'nx.json'); // ASSERT - expect(schematics['@nrwl/angular:application'].e2eTestRunner).toEqual( + expect(generators['@nrwl/angular:application'].e2eTestRunner).toEqual( 'protractor' ); }); @@ -253,15 +253,13 @@ describe('init', () => { skipFormat: false, }); - const workspaceJson = readJson(host, 'workspace.json'); + const { generators } = readJson(host, 'nx.json'); // ASSERT - expect( - workspaceJson.schematics['@nrwl/angular:application'].linter - ).toEqual('eslint'); - expect( - workspaceJson.schematics['@nrwl/angular:library'].linter - ).toEqual('eslint'); + expect(generators['@nrwl/angular:application'].linter).toEqual( + 'eslint' + ); + expect(generators['@nrwl/angular:library'].linter).toEqual('eslint'); }); }); @@ -274,15 +272,11 @@ describe('init', () => { skipFormat: false, }); - const workspaceJson = readJson(host, 'workspace.json'); + const { generators } = readJson(host, 'nx.json'); // ASSERT - expect( - workspaceJson.schematics['@nrwl/angular:application'].linter - ).toEqual('none'); - expect( - workspaceJson.schematics['@nrwl/angular:library'].linter - ).toEqual('none'); + expect(generators['@nrwl/angular:application'].linter).toEqual('none'); + expect(generators['@nrwl/angular:library'].linter).toEqual('none'); }); }); }); @@ -297,10 +291,10 @@ describe('init', () => { skipFormat: false, }); - const workspaceJson = readJson(host, 'workspace.json'); + const { cli } = readJson(host, 'nx.json'); // ASSERT - expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/angular'); + expect(cli.defaultCollection).toEqual('@nrwl/angular'); }); it.each(['css', 'scss', 'less'])( @@ -315,12 +309,10 @@ describe('init', () => { style, }); - const workspaceJson = readJson(host, 'workspace.json'); + const { generators } = readJson(host, 'nx.json'); // ASSERT - expect( - workspaceJson.schematics['@nrwl/angular:component']['style'] - ).toBe(style); + expect(generators['@nrwl/angular:component']['style']).toBe(style); } ); }); diff --git a/packages/angular/src/generators/library/lib/update-project.ts b/packages/angular/src/generators/library/lib/update-project.ts index 692e91173e..b36b77c97b 100644 --- a/packages/angular/src/generators/library/lib/update-project.ts +++ b/packages/angular/src/generators/library/lib/update-project.ts @@ -13,7 +13,6 @@ import { NormalizedSchema } from './normalized-schema'; import { updateNgPackage } from './update-ng-package'; export async function updateProject(host: Tree, options: NormalizedSchema) { - updateNxConfigWithProject(host, options); createFiles(host, options); updateProjectTsConfig(host, options); fixProjectWorkspaceConfig(host, options); @@ -119,6 +118,7 @@ function createFiles(host: Tree, options: NormalizedSchema) { function fixProjectWorkspaceConfig(host: Tree, options: NormalizedSchema) { const project = readProjectConfiguration(host, options.name); + project.tags = options.parsedTags; const fixedProject = replaceAppNameWithPath( project, @@ -172,13 +172,3 @@ function updateProjectTsConfig(host: Tree, options: NormalizedSchema) { }; }); } - -function updateNxConfigWithProject(host: Tree, options: NormalizedSchema) { - updateJson(host, `/nx.json`, (json) => ({ - ...json, - projects: { - ...json.projects, - [options.name]: { tags: options.parsedTags }, - }, - })); -} diff --git a/packages/angular/src/generators/library/library.spec.ts b/packages/angular/src/generators/library/library.spec.ts index c37d2e7522..7e7a2f9e45 100644 --- a/packages/angular/src/generators/library/library.spec.ts +++ b/packages/angular/src/generators/library/library.spec.ts @@ -1,9 +1,10 @@ import { - NxJsonConfiguration, readJson, Tree, updateJson, parseJson, + getProjects, + NxJsonConfiguration, } from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { Linter } from '@nrwl/linter'; @@ -153,7 +154,7 @@ describe('lib', () => { expect(libProdConfig).toBeFalsy(); }); - it('should update nx.json', async () => { + it('should update tags', async () => { // ACT await runLibraryGeneratorWithOpts({ publishable: false, @@ -162,11 +163,11 @@ describe('lib', () => { }); // ASSERT - const nxJson = readJson(appTree, '/nx.json'); - expect(nxJson.projects).toEqual({ - 'my-lib': { + const projects = Object.fromEntries(getProjects(appTree)); + expect(projects).toEqual({ + 'my-lib': expect.objectContaining({ tags: ['one', 'two'], - }, + }), }); }); @@ -213,20 +214,24 @@ describe('lib', () => { }); }); - it('should check for existance of spec files before deleting them', async () => { + it('should check for existence of spec files before deleting them', async () => { // ARRANGE - updateJson(appTree, '/workspace.json', (workspaceJSON) => { - workspaceJSON.schematics = { - '@schematics/angular:service': { - skipTests: true, - }, - '@schematics/angular:component': { - skipTests: true, - }, - }; + updateJson( + appTree, + '/nx.json', + (nxJson) => { + nxJson.generators = { + '@schematics/angular:service': { + skipTests: true, + }, + '@schematics/angular:component': { + skipTests: true, + }, + }; - return workspaceJSON; - }); + return nxJson; + } + ); // ACT await runLibraryGeneratorWithOpts(); @@ -371,7 +376,7 @@ describe('lib', () => { }); describe('nested', () => { - it('should update nx.json', async () => { + it('should update tags', async () => { // ACT await runLibraryGeneratorWithOpts({ tags: 'one', directory: 'my-dir' }); await runLibraryGeneratorWithOpts({ @@ -381,15 +386,15 @@ describe('lib', () => { }); // ASSERT - const nxJson = readJson(appTree, '/nx.json'); + const projects = Object.fromEntries(getProjects(appTree)); - expect(nxJson.projects).toEqual({ - 'my-dir-my-lib': { + expect(projects).toEqual({ + 'my-dir-my-lib': expect.objectContaining({ tags: ['one'], - }, - 'my-dir-my-lib2': { + }), + 'my-dir-my-lib2': expect.objectContaining({ tags: ['one', 'two'], - }, + }), }); }); @@ -1020,7 +1025,7 @@ describe('lib', () => { appTree, 'libs/my-lib/tsconfig.json' ); - const workspaceJson = readJson(appTree, 'workspace.json'); + const { generators } = readJson(appTree, 'nx.json'); // check that the TypeScript compiler options have been updated expect(compilerOptions.forceConsistentCasingInFileNames).toBe(true); @@ -1034,9 +1039,7 @@ describe('lib', () => { // check to see if the workspace configuration has been updated to use strict // mode by default in future libraries - expect( - workspaceJson.schematics['@nrwl/angular:library'].strict - ).not.toBeDefined(); + expect(generators['@nrwl/angular:library'].strict).not.toBeDefined(); }); it('should set defaults when --strict=false', async () => { @@ -1050,10 +1053,8 @@ describe('lib', () => { // ASSERT // check to see if the workspace configuration has been updated to turn off // strict mode by default in future libraries - const workspaceJson = readJson(appTree, 'workspace.json'); - expect(workspaceJson.schematics['@nrwl/angular:library'].strict).toBe( - false - ); + const { generators } = readJson(appTree, 'nx.json'); + expect(generators['@nrwl/angular:library'].strict).toBe(false); }); }); diff --git a/packages/angular/src/generators/setup-mfe/setup-mfe.spec.ts b/packages/angular/src/generators/setup-mfe/setup-mfe.spec.ts index 188e7610b9..3761d220b7 100644 --- a/packages/angular/src/generators/setup-mfe/setup-mfe.spec.ts +++ b/packages/angular/src/generators/setup-mfe/setup-mfe.spec.ts @@ -1,4 +1,4 @@ -import type { NxJsonConfiguration, Tree } from '@nrwl/devkit'; +import type { ProjectConfiguration, Tree } from '@nrwl/devkit'; import { readJson, readProjectConfiguration } from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; @@ -163,9 +163,12 @@ describe('Init MFE', () => { }); // ASSERT - const nxJson: NxJsonConfiguration = readJson(host, 'nx.json'); + const projectConfig: ProjectConfiguration = readProjectConfiguration( + host, + 'app1' + ); - expect(nxJson.projects['app1'].implicitDependencies).toContain('remote1'); + expect(projectConfig.implicitDependencies).toContain('remote1'); }); it('should add a remote application and add it to a specified host applications webpack config when no other remote has been added to it', async () => { diff --git a/packages/angular/src/generators/stories/lib/get-e2e-project.ts b/packages/angular/src/generators/stories/lib/get-e2e-project.ts index 23ecf4e464..b3250d8fe2 100644 --- a/packages/angular/src/generators/stories/lib/get-e2e-project.ts +++ b/packages/angular/src/generators/stories/lib/get-e2e-project.ts @@ -8,8 +8,8 @@ import { readProjectConfiguration } from '@nrwl/devkit'; export function getE2EProject( tree: Tree, e2eProjectName: string -): ProjectConfiguration & NxJsonProjectConfiguration { - let e2eProject: ProjectConfiguration & NxJsonProjectConfiguration; +): ProjectConfiguration { + let e2eProject: ProjectConfiguration; try { e2eProject = readProjectConfiguration(tree, e2eProjectName); } catch { diff --git a/packages/angular/src/migrations/update-12-3-0/convert-webpack-browser-build-target-to-delegate-build.ts b/packages/angular/src/migrations/update-12-3-0/convert-webpack-browser-build-target-to-delegate-build.ts index 25e430bdc2..d363690692 100644 --- a/packages/angular/src/migrations/update-12-3-0/convert-webpack-browser-build-target-to-delegate-build.ts +++ b/packages/angular/src/migrations/update-12-3-0/convert-webpack-browser-build-target-to-delegate-build.ts @@ -1,7 +1,6 @@ import { formatFiles, getProjects, - NxJsonProjectConfiguration, parseTargetString, ProjectConfiguration, Target, @@ -104,7 +103,7 @@ function getTargetConfigurationOptions( } function updateTargetsConfigurations( - project: ProjectConfiguration & NxJsonProjectConfiguration, + project: ProjectConfiguration, projectName: string, target: TargetConfiguration, buildTargetName: string, @@ -144,7 +143,7 @@ function updateTargetsConfigurations( } function updateTargetsOptions( - project: ProjectConfiguration & NxJsonProjectConfiguration, + project: ProjectConfiguration, target: TargetConfiguration, buildTargetName: string ) { diff --git a/packages/angular/src/migrations/update-12-9-0/update-invalid-import-paths.ts b/packages/angular/src/migrations/update-12-9-0/update-invalid-import-paths.ts index 801305b42b..adee010f9a 100644 --- a/packages/angular/src/migrations/update-12-9-0/update-invalid-import-paths.ts +++ b/packages/angular/src/migrations/update-12-9-0/update-invalid-import-paths.ts @@ -1,8 +1,4 @@ -import type { - NxJsonProjectConfiguration, - ProjectConfiguration, - Tree, -} from '@nrwl/devkit'; +import type { ProjectConfiguration, Tree } from '@nrwl/devkit'; import { formatFiles, getProjects, @@ -12,7 +8,7 @@ import { logger, } from '@nrwl/devkit'; -type AffectedLib = ProjectConfiguration & NxJsonProjectConfiguration; +type AffectedLib = ProjectConfiguration; type InvalidLibs = { buildableLibs: AffectedLib[]; publishableLibs: AffectedLib[]; diff --git a/packages/angular/src/utils/nx-devkit/testing.ts b/packages/angular/src/utils/nx-devkit/testing.ts index b6b89d603f..2557c379cd 100644 --- a/packages/angular/src/utils/nx-devkit/testing.ts +++ b/packages/angular/src/utils/nx-devkit/testing.ts @@ -97,17 +97,11 @@ export function createApp( options: {}, }, }, + tags: [], }, }, }) ); - updateJson(tree, './nx.json', (json) => ({ - ...json, - projects: { - ...json.projects, - [appName]: { tags: [] }, - }, - })); } export function createLib(tree: Tree, libName: string) { diff --git a/packages/cli/lib/init-local.ts b/packages/cli/lib/init-local.ts index 059131f2b3..91285aaba9 100644 --- a/packages/cli/lib/init-local.ts +++ b/packages/cli/lib/init-local.ts @@ -89,10 +89,12 @@ function runOneOptions( workspace.type === 'nx' ? 'workspace.json' : 'angular.json' ) ); + const nxJson = readJsonFile(path.join(workspace.dir, 'nx.json')); return parseRunOneOptions( workspace.dir, workspaceConfigJson, + nxJson, process.argv.slice(2) ); } catch { diff --git a/packages/cli/lib/parse-run-one-options.spec.ts b/packages/cli/lib/parse-run-one-options.spec.ts index b1cb843a29..86d0074615 100644 --- a/packages/cli/lib/parse-run-one-options.spec.ts +++ b/packages/cli/lib/parse-run-one-options.spec.ts @@ -8,10 +8,11 @@ describe('parseRunOneOptions', () => { }, }, }; + const nxJson = {}; const args = ['build', 'myproj', '--configuration=production', '--flag=true']; it('should work', () => { - expect(parseRunOneOptions('root', workspaceJson, args)).toEqual({ + expect(parseRunOneOptions('root', workspaceJson, nxJson, args)).toEqual({ project: 'myproj', target: 'build', configuration: 'production', @@ -21,7 +22,7 @@ describe('parseRunOneOptions', () => { it('should work with --prod', () => { expect( - parseRunOneOptions('root', workspaceJson, [ + parseRunOneOptions('root', workspaceJson, nxJson, [ 'build', 'myproj', '--prod', @@ -37,7 +38,7 @@ describe('parseRunOneOptions', () => { it('should override --prod with --configuration', () => { expect( - parseRunOneOptions('root', workspaceJson, [ + parseRunOneOptions('root', workspaceJson, nxJson, [ 'build', 'myproj', '--prod', @@ -55,7 +56,7 @@ describe('parseRunOneOptions', () => { it('should work with run syntax', () => { expect( - parseRunOneOptions('root', workspaceJson, [ + parseRunOneOptions('root', workspaceJson, nxJson, [ 'run', 'myproj:build:staging', '--flag=true', @@ -72,7 +73,8 @@ describe('parseRunOneOptions', () => { expect( parseRunOneOptions( 'root', - { ...workspaceJson, cli: { defaultProjectName: 'myproj' } }, + { ...workspaceJson }, + { cli: { defaultProjectName: 'myproj' } }, ['build', '--flag=true'] ) ).toEqual({ @@ -85,7 +87,7 @@ describe('parseRunOneOptions', () => { it('should use defaultConfiguration when no provided', () => { expect( - parseRunOneOptions('root', workspaceJson, [ + parseRunOneOptions('root', workspaceJson, nxJson, [ 'run', 'myproj:build', '--flag=true', @@ -99,20 +101,24 @@ describe('parseRunOneOptions', () => { }); it('should return false when the task is not recognized', () => { - expect(parseRunOneOptions('root', {}, args)).toBe(false); - expect(parseRunOneOptions('root', { projects: {} }, args)).toBe(false); + expect(parseRunOneOptions('root', {}, nxJson, args)).toBe(false); + expect(parseRunOneOptions('root', { projects: {} }, nxJson, args)).toBe( + false + ); expect( - parseRunOneOptions('root', { projects: { architect: {} } }, args) + parseRunOneOptions('root', { projects: { architect: {} } }, nxJson, args) ).toBe(false); }); it('should return false when cannot find the right project', () => { expect( - parseRunOneOptions('root', workspaceJson, ['build', 'wrongproj']) + parseRunOneOptions('root', workspaceJson, nxJson, ['build', 'wrongproj']) ).toBe(false); }); it('should return false when no project specified', () => { - expect(parseRunOneOptions('root', workspaceJson, ['build'])).toBe(false); + expect(parseRunOneOptions('root', workspaceJson, nxJson, ['build'])).toBe( + false + ); }); }); diff --git a/packages/cli/lib/parse-run-one-options.ts b/packages/cli/lib/parse-run-one-options.ts index e1eb9ef126..623b5e7233 100644 --- a/packages/cli/lib/parse-run-one-options.ts +++ b/packages/cli/lib/parse-run-one-options.ts @@ -1,30 +1,33 @@ import yargsParser = require('yargs-parser'); import * as fs from 'fs'; -function calculateDefaultProjectName(cwd: string, root: string, wc: any) { +function calculateDefaultProjectName( + cwd: string, + root: string, + workspaceConfiguration: any, + nxJson +) { let relativeCwd = cwd.replace(/\\/g, '/').split(root.replace(/\\/g, '/'))[1]; if (relativeCwd) { relativeCwd = relativeCwd.startsWith('/') ? relativeCwd.substring(1) : relativeCwd; - const matchingProject = Object.keys(wc.projects).find((p) => { - const projectRoot = wc.projects[p].root; - return ( - relativeCwd == projectRoot || relativeCwd.startsWith(`${projectRoot}/`) - ); - }); + const matchingProject = Object.keys(workspaceConfiguration.projects).find( + (p) => { + const projectRoot = workspaceConfiguration.projects[p].root; + return ( + relativeCwd == projectRoot || + relativeCwd.startsWith(`${projectRoot}/`) + ); + } + ); if (matchingProject) return matchingProject; } - let defaultProjectName = null; - try { - defaultProjectName = wc.cli.defaultProjectName; - } catch (e) {} - try { - if (!defaultProjectName) { - defaultProjectName = wc.defaultProject; - } - } catch (e) {} - return defaultProjectName; + return ( + nxJson.cli?.defaultProjectName || + nxJson.defaultProject || + workspaceConfiguration.defaultProject + ); } const invalidTargetNames = [ @@ -60,13 +63,15 @@ const invalidTargetNames = [ export function parseRunOneOptions( root: string, - workspaceConfigJson: any, + workspaceJsonConfiguration: any, + nxJson: any, args: string[] ): false | { project; target; configuration; parsedArgs } { const defaultProjectName = calculateDefaultProjectName( process.cwd(), root, - workspaceConfigJson + workspaceJsonConfiguration, + nxJson ); const parsedArgs = yargsParser(args, { @@ -105,7 +110,6 @@ export function parseRunOneOptions( if (parsedArgs.project) { project = parsedArgs.project; } - // we need both to be able to run a target, no tasks runner if (!project || !target) { return false; @@ -113,7 +117,8 @@ export function parseRunOneOptions( // we need both to be able to run a target, no tasks runner const p = - workspaceConfigJson.projects && workspaceConfigJson.projects[project]; + workspaceJsonConfiguration.projects && + workspaceJsonConfiguration.projects[project]; if (!p) return false; let targets; diff --git a/packages/cypress/src/generators/cypress-project/cypress-project.spec.ts b/packages/cypress/src/generators/cypress-project/cypress-project.spec.ts index dcc9218058..549d5aad78 100644 --- a/packages/cypress/src/generators/cypress-project/cypress-project.spec.ts +++ b/packages/cypress/src/generators/cypress-project/cypress-project.spec.ts @@ -4,6 +4,7 @@ import { readProjectConfiguration, updateProjectConfiguration, Tree, + WorkspaceJsonConfiguration, } from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { cypressProjectGenerator } from './cypress-project'; @@ -189,7 +190,7 @@ describe('schematic:cypress-project', () => { expect(project.architect.lint).toBeUndefined(); }); - it('should update nx.json', async () => { + it('should update tags and implicit dependencies', async () => { await cypressProjectGenerator(tree, { name: 'my-app-e2e', project: 'my-app', @@ -322,8 +323,13 @@ describe('schematic:cypress-project', () => { name: 'my-app-e2e', }); - const nxJson = readJson(tree, 'nx.json'); - expect(nxJson.projects['my-app-e2e']).toEqual({ tags: [] }); + const workspaceJson = readJson( + tree, + 'workspace.json' + ); + const projectConfig = workspaceJson.projects['my-app-e2e']; + expect(projectConfig.implicitDependencies).not.toBeDefined(); + expect(projectConfig.tags).toEqual([]); }); }); }); diff --git a/packages/cypress/src/generators/cypress-project/cypress-project.ts b/packages/cypress/src/generators/cypress-project/cypress-project.ts index 1c9252a71d..648e0411f7 100644 --- a/packages/cypress/src/generators/cypress-project/cypress-project.ts +++ b/packages/cypress/src/generators/cypress-project/cypress-project.ts @@ -13,7 +13,6 @@ import { Tree, updateJson, ProjectConfiguration, - NxJsonProjectConfiguration, } from '@nrwl/devkit'; import { Linter, lintProjectGenerator } from '@nrwl/linter'; import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial'; @@ -64,7 +63,7 @@ function addProject(tree: Tree, options: CypressProjectSchema) { : devServerTarget; } - const project: ProjectConfiguration & NxJsonProjectConfiguration = { + const project: ProjectConfiguration = { root: options.projectRoot, sourceRoot: joinPathFragments(options.projectRoot, 'src'), projectType: 'application', diff --git a/packages/devkit/src/generators/format-files.ts b/packages/devkit/src/generators/format-files.ts index ddce0d366d..501b8bcd97 100644 --- a/packages/devkit/src/generators/format-files.ts +++ b/packages/devkit/src/generators/format-files.ts @@ -2,8 +2,13 @@ import type { Tree } from '@nrwl/tao/src/shared/tree'; import * as path from 'path'; import type * as Prettier from 'prettier'; import { getWorkspacePath } from '../utils/get-workspace-layout'; -import { readJson, writeJson } from '../utils/json'; +import { readJson, updateJson, writeJson } from '../utils/json'; import { sortObjectByKeys } from '@nrwl/tao/src/utils/object-sort'; +import { + readWorkspaceConfiguration, + updateWorkspaceConfiguration, + WorkspaceConfiguration, +} from './project-configuration'; /** * Formats all the created or updated files using Prettier @@ -15,8 +20,8 @@ export async function formatFiles(tree: Tree): Promise { prettier = await import('prettier'); } catch {} + ensurePropertiesAreInNewLocations(tree); sortWorkspaceJson(tree); - sortNxJson(tree); sortTsConfig(tree); if (!prettier) return; @@ -61,7 +66,7 @@ export async function formatFiles(tree: Tree): Promise { function sortWorkspaceJson(tree: Tree) { const workspaceJsonPath = getWorkspacePath(tree); - if (!path) { + if (!workspaceJsonPath) { return; } @@ -79,17 +84,26 @@ function sortWorkspaceJson(tree: Tree) { } } -function sortNxJson(tree: Tree) { - try { - const nxJson = readJson(tree, 'nx.json'); - const sortedProjects = sortObjectByKeys(nxJson.projects); - writeJson(tree, 'nx.json', { - ...nxJson, - projects: sortedProjects, - }); - } catch (e) { - // catch noop +/** + * `updateWorkspaceConfiguration` already handles + * placing properties in their new locations, so + * reading + updating it ensures that props are placed + * correctly. + */ +function ensurePropertiesAreInNewLocations(tree: Tree) { + const workspacePath = getWorkspacePath(tree); + if (!workspacePath) { + return; } + const wc = readWorkspaceConfiguration(tree); + updateWorkspaceConfiguration(tree, wc); + updateJson(tree, workspacePath, (json) => { + delete json.cli; + delete json.defaultProject; + delete (json as any).schematics; + delete json.generators; + return json; + }); } function sortTsConfig(tree: Tree) { diff --git a/packages/devkit/src/generators/project-configuration.spec.ts b/packages/devkit/src/generators/project-configuration.spec.ts index fe7b04958c..25f3fb61ce 100644 --- a/packages/devkit/src/generators/project-configuration.spec.ts +++ b/packages/devkit/src/generators/project-configuration.spec.ts @@ -60,27 +60,6 @@ describe('project configuration', () => { }); }); - it('should get info from nx.json', () => { - updateJson(tree, getWorkspacePath(tree), (json) => { - json.projects['proj1'] = { - root: 'proj1', - }; - return json; - }); - updateJson(tree, 'nx.json', (json) => { - json.projects['proj1'] = { - tags: ['tag1'], - }; - return json; - }); - - const config = readProjectConfiguration(tree, 'proj1'); - expect(config).toEqual({ - root: 'proj1', - tags: ['tag1'], - }); - }); - it('should should not fail if projects is not defined in nx.json', () => { updateJson(tree, getWorkspacePath(tree), (json) => { json.projects['proj1'] = { @@ -223,27 +202,6 @@ describe('project configuration', () => { }); }); - it('should get info from nx.json', () => { - updateJson(tree, getWorkspacePath(tree), (json) => { - json.projects['proj1'] = { - root: 'proj1', - }; - return json; - }); - updateJson(tree, 'nx.json', (json) => { - json.projects['proj1'] = { - tags: ['tag1'], - }; - return json; - }); - - const config = readProjectConfiguration(tree, 'proj1'); - expect(config).toEqual({ - root: 'proj1', - tags: ['tag1'], - }); - }); - it('should should not fail if projects is not defined in nx.json', () => { updateJson(tree, getWorkspacePath(tree), (json) => { json.projects['proj1'] = { diff --git a/packages/devkit/src/generators/project-configuration.ts b/packages/devkit/src/generators/project-configuration.ts index 9cc7dbf269..e97bf57e0a 100644 --- a/packages/devkit/src/generators/project-configuration.ts +++ b/packages/devkit/src/generators/project-configuration.ts @@ -14,22 +14,19 @@ import { readJson, updateJson, writeJson } from '../utils/json'; import { joinPathFragments } from '../utils/path'; import type { Tree } from '@nrwl/tao/src/shared/tree'; -import type { - NxJsonConfiguration, - NxJsonProjectConfiguration, -} from '@nrwl/tao/src/shared/nx'; +import type { NxJsonConfiguration } from '@nrwl/tao/src/shared/nx'; export type WorkspaceConfiguration = Omit< WorkspaceJsonConfiguration, 'projects' > & - Partial>; + Partial; /** * Adds project configuration to the Nx workspace. * - * The project configuration is stored in workspace.json and nx.json. The utility will update - * both files. + * The project configuration is stored in workspace.json or the associated project.json file. + * The utility will update either files. * * @param tree - the file system tree * @param projectName - unique name. Often directories are part of the name (e.g., mydir-mylib) @@ -39,7 +36,7 @@ export type WorkspaceConfiguration = Omit< export function addProjectConfiguration( tree: Tree, projectName: string, - projectConfiguration: ProjectConfiguration & NxJsonProjectConfiguration, + projectConfiguration: ProjectConfiguration, standalone: boolean = false ): void { standalone = standalone || getWorkspaceLayout(tree).standaloneAsDefault; @@ -55,8 +52,8 @@ export function addProjectConfiguration( /** * Updates the configuration of an existing project. * - * The project configuration is stored in workspace.json and nx.json. The utility will update - * both files. + * The project configuration is stored in workspace.json or the associated project.json file. + * The utility will update either files. * * @param tree - the file system tree * @param projectName - unique name. Often directories are part of the name (e.g., mydir-mylib) @@ -65,7 +62,7 @@ export function addProjectConfiguration( export function updateProjectConfiguration( tree: Tree, projectName: string, - projectConfiguration: ProjectConfiguration & NxJsonProjectConfiguration + projectConfiguration: ProjectConfiguration ): void { setProjectConfiguration(tree, projectName, projectConfiguration, 'update'); } @@ -73,8 +70,8 @@ export function updateProjectConfiguration( /** * Removes the configuration of an existing project. * - * The project configuration is stored in workspace.json and nx.json. - * The utility will update both files. + * The project configuration is stored in workspace.json or the associated project.json file. + * The utility will update either file. */ export function removeProjectConfiguration( tree: Tree, @@ -88,18 +85,12 @@ export function removeProjectConfiguration( * * Use {@link readProjectConfiguration} if only one project is needed. */ -export function getProjects( - tree: Tree -): Map { +export function getProjects(tree: Tree): Map { const workspace = readWorkspace(tree); - const nxJson = readNxJson(tree); return new Map( Object.keys(workspace.projects || {}).map((projectName) => { - return [ - projectName, - getProjectConfiguration(projectName, workspace, nxJson), - ]; + return [projectName, getProjectConfiguration(projectName, workspace)]; }) ); } @@ -110,7 +101,7 @@ export function getProjects( * This does _not_ provide projects configuration, use {@link readProjectConfiguration} instead. */ export function readWorkspaceConfiguration(tree: Tree): WorkspaceConfiguration { - const workspace = readWorkspace(tree); + const workspace = readRawWorkspaceJson(tree); delete workspace.projects; let nxJson = readNxJson(tree); @@ -141,11 +132,11 @@ export function updateWorkspaceConfiguration( const { // Workspace Json Properties version, + + // Nx Json Properties cli, defaultProject, generators, - - // Nx Json Properties implicitDependencies, plugins, npmScope, @@ -156,11 +147,8 @@ export function updateWorkspaceConfiguration( } = workspaceConfig; const workspace: Omit, 'projects'> = { version, - cli, - defaultProject, - generators, }; - const nxJson: Omit, 'projects'> = { + const nxJson: Required = { implicitDependencies, plugins, npmScope, @@ -168,6 +156,9 @@ export function updateWorkspaceConfiguration( workspaceLayout, tasksRunnerOptions, affected, + cli, + generators, + defaultProject, }; updateJson( @@ -220,8 +211,8 @@ function readNxJsonExtends(tree: Tree, nxJson: { extends?: string }) { /** * Reads a project configuration. * - * The project configuration is stored in workspace.json and nx.json. The utility will read - * both files. + * The project configuration is stored in workspace.json or the associated project.json file. + * The utility will read from either file. * * @param tree - the file system tree * @param projectName - unique name. Often directories are part of the name (e.g., mydir-mylib) @@ -230,7 +221,7 @@ function readNxJsonExtends(tree: Tree, nxJson: { extends?: string }) { export function readProjectConfiguration( tree: Tree, projectName: string -): ProjectConfiguration & NxJsonProjectConfiguration { +): ProjectConfiguration { const workspace = readWorkspace(tree); if (!workspace.projects[projectName]) { throw new Error( @@ -242,7 +233,7 @@ export function readProjectConfiguration( const nxJson = readNxJson(tree); - return getProjectConfiguration(projectName, workspace, nxJson); + return getProjectConfiguration(projectName, workspace); } export function readNxJson(tree: Tree): NxJsonConfiguration | null { @@ -275,12 +266,10 @@ export function isStandaloneProject(tree: Tree, project: string): boolean { function getProjectConfiguration( projectName: string, - workspace: WorkspaceJsonConfiguration, - nxJson: NxJsonConfiguration | null -): ProjectConfiguration & NxJsonProjectConfiguration { + workspace: WorkspaceJsonConfiguration +): ProjectConfiguration { return { ...readWorkspaceSection(workspace, projectName), - ...(nxJson === null ? {} : readNxJsonSection(nxJson, projectName)), }; } @@ -291,23 +280,14 @@ function readWorkspaceSection( return workspace.projects[projectName]; } -function readNxJsonSection(nxJson: NxJsonConfiguration, projectName: string) { - return nxJson.projects?.[projectName]; -} - function setProjectConfiguration( tree: Tree, projectName: string, - projectConfiguration: ProjectConfiguration & NxJsonProjectConfiguration, + projectConfiguration: ProjectConfiguration, mode: 'create' | 'update' | 'delete', standalone: boolean = false ): void { - const hasNxJson = tree.exists('nx.json'); - if (mode === 'delete') { - if (hasNxJson) { - addProjectToNxJson(tree, projectName, undefined, mode); - } addProjectToWorkspaceJson(tree, projectName, undefined, mode); return; } @@ -325,25 +305,12 @@ function setProjectConfiguration( mode, standalone ); - - if (hasNxJson) { - const { tags, implicitDependencies } = projectConfiguration; - addProjectToNxJson( - tree, - projectName, - { - tags, - implicitDependencies, - }, - mode - ); - } } function addProjectToWorkspaceJson( tree: Tree, projectName: string, - project: ProjectConfiguration & NxJsonProjectConfiguration, + project: ProjectConfiguration, mode: 'create' | 'update' | 'delete', standalone: boolean = false ) { @@ -370,12 +337,7 @@ function addProjectToWorkspaceJson( } else if (mode === 'delete') { delete workspaceJson.projects[projectName]; } else { - let projectConfiguration: ProjectConfiguration; - if (project) { - const { tags, implicitDependencies, ...c } = project; - projectConfiguration = c; - } - workspaceJson.projects[projectName] = projectConfiguration; + workspaceJson.projects[projectName] = project; } writeJson( tree, @@ -384,31 +346,10 @@ function addProjectToWorkspaceJson( ); } -function addProjectToNxJson( - tree: Tree, - projectName: string, - config: NxJsonProjectConfiguration, - mode: 'create' | 'update' | 'delete' -) { - // distributed project files do not use nx.json, - // so only proceed if the project does not use them. - if (!getProjectFileLocation(tree, projectName)) { - const nxJson = readJson(tree, 'nx.json'); - if (mode === 'delete') { - delete nxJson.projects[projectName]; - } else { - nxJson.projects[projectName] = { - ...{ - tags: [], - }, - ...(config || {}), - }; - } - writeJson(tree, 'nx.json', nxJson); - } -} - -function readWorkspace(tree: Tree): WorkspaceJsonConfiguration { +/** + * Read the workspace configuration, including projects. + */ +export function readWorkspace(tree: Tree): WorkspaceJsonConfiguration { const workspaceJson = inlineProjectConfigurationsWithTree(tree); const originalVersion = workspaceJson.version; return { @@ -426,28 +367,30 @@ function readWorkspace(tree: Tree): WorkspaceJsonConfiguration { function inlineProjectConfigurationsWithTree( tree: Tree ): WorkspaceJsonConfiguration { - const path = getWorkspacePath(tree); - const workspaceJson = readJson(tree, path); + const workspaceJson = readRawWorkspaceJson(tree); Object.entries(workspaceJson.projects || {}).forEach(([project, config]) => { if (typeof config === 'string') { const configFileLocation = joinPathFragments(config, 'project.json'); - workspaceJson.projects[project] = readJson< - ProjectConfiguration & NxJsonProjectConfiguration - >(tree, configFileLocation); + workspaceJson.projects[project] = readJson( + tree, + configFileLocation + ); } }); return workspaceJson as WorkspaceJsonConfiguration; } +function readRawWorkspaceJson(tree: Tree): RawWorkspaceJsonConfiguration { + const path = getWorkspacePath(tree); + return readJson(tree, path); +} + /** * @description Determine where a project's configuration is located. * @returns file path if separate from root config, null otherwise. */ function getProjectFileLocation(tree: Tree, project: string): string | null { - const rawWorkspace = readJson( - tree, - getWorkspacePath(tree) - ); + const rawWorkspace = readRawWorkspaceJson(tree); const projectConfig = rawWorkspace.projects?.[project]; return typeof projectConfig === 'string' ? joinPathFragments(projectConfig, 'project.json') diff --git a/packages/devkit/src/tests/create-tree-with-empty-workspace.ts b/packages/devkit/src/tests/create-tree-with-empty-workspace.ts index 0c89aed0af..f8ee6fb76b 100644 --- a/packages/devkit/src/tests/create-tree-with-empty-workspace.ts +++ b/packages/devkit/src/tests/create-tree-with-empty-workspace.ts @@ -21,7 +21,6 @@ export function createTreeWithEmptyWorkspace(version = 1): Tree { '/nx.json', JSON.stringify({ npmScope: 'proj', - projects: {}, affected: { defaultBase: 'main', }, diff --git a/packages/devkit/src/utils/convert-nx-executor.ts b/packages/devkit/src/utils/convert-nx-executor.ts index f24cc68ddf..e61972252d 100644 --- a/packages/devkit/src/utils/convert-nx-executor.ts +++ b/packages/devkit/src/utils/convert-nx-executor.ts @@ -10,9 +10,8 @@ import { Workspaces } from '@nrwl/tao/src/shared/workspace'; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function convertNxExecutor(executor: Executor) { const builderFunction = (options, builderContext) => { - const workspaceConfig = new Workspaces( - builderContext.workspaceRoot - ).readWorkspaceConfiguration(); + const workspaces = new Workspaces(builderContext.workspaceRoot); + const workspaceConfig = workspaces.readWorkspaceConfiguration(); const context: ExecutorContext = { root: builderContext.workspaceRoot, projectName: builderContext.target.project, diff --git a/packages/express/src/generators/init/init.spec.ts b/packages/express/src/generators/init/init.spec.ts index d8a775ffd1..ca9af10b77 100644 --- a/packages/express/src/generators/init/init.spec.ts +++ b/packages/express/src/generators/init/init.spec.ts @@ -1,4 +1,8 @@ -import { addDependenciesToPackageJson, Tree } from '@nrwl/devkit'; +import { + addDependenciesToPackageJson, + NxJsonConfiguration, + Tree, +} from '@nrwl/devkit'; import { expressVersion } from '../../utils/versions'; import initGenerator from './init'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; @@ -36,8 +40,8 @@ describe('init', () => { describe('defaultCollection', () => { it('should be set if none was set before', async () => { await initGenerator(tree, {}); - const workspaceJson = readJson(tree, 'workspace.json'); - expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/express'); + const { cli } = readJson(tree, 'nx.json'); + expect(cli.defaultCollection).toEqual('@nrwl/express'); }); }); diff --git a/packages/gatsby/src/generators/application/application.spec.ts b/packages/gatsby/src/generators/application/application.spec.ts index fe9309b45c..fbd2baa08f 100644 --- a/packages/gatsby/src/generators/application/application.spec.ts +++ b/packages/gatsby/src/generators/application/application.spec.ts @@ -1,4 +1,4 @@ -import { NxJsonConfiguration } from '@nrwl/devkit'; +import { NxJsonConfiguration, readProjectConfiguration } from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { applicationGenerator } from './application'; import { readJson, Tree } from '@nrwl/devkit'; @@ -19,23 +19,31 @@ describe('app', () => { standaloneConfig: false, }); const workspaceJson = readJson(tree, '/workspace.json'); + const nxJson = readJson(tree, 'nx.json'); expect(workspaceJson.projects['my-app'].root).toEqual('apps/my-app'); expect(workspaceJson.projects['my-app-e2e'].root).toEqual( 'apps/my-app-e2e' ); - expect(workspaceJson.defaultProject).toEqual('my-app'); + expect(nxJson.defaultProject).toEqual('my-app'); }); - it('should update nx.json', async () => { + it('should update tags + implicitDependencies', async () => { await applicationGenerator(tree, { name: 'myApp', style: 'css', tags: 'one,two', standaloneConfig: false, }); - const nxJson = readJson(tree, '/nx.json'); - expect(nxJson.projects).toEqual({ + const myAppConfig = readProjectConfiguration(tree, 'my-app'); + const myAppConfigE2E = readProjectConfiguration(tree, 'my-app-e2e'); + expect({ + 'my-app': { tags: myAppConfig.tags }, + 'my-app-e2e': { + tags: myAppConfigE2E.tags, + implicitDependencies: myAppConfigE2E.implicitDependencies, + }, + }).toEqual({ 'my-app': { tags: ['one', 'two'], }, @@ -77,10 +85,10 @@ describe('app', () => { `import * as styles from './index.module.scss'` ); - const workspaceJson = readJson(tree, '/workspace.json'); - expect( - workspaceJson.schematics['@nrwl/gatsby'].application.style - ).toEqual('scss'); + const nxJson = readJson(tree, 'nx.json'); + expect(nxJson.generators['@nrwl/gatsby'].application.style).toEqual( + 'scss' + ); }); }); @@ -102,10 +110,10 @@ describe('app', () => { `import * as styles from './index.module.less'` ); - const workspaceJson = readJson(tree, '/workspace.json'); - expect( - workspaceJson.schematics['@nrwl/gatsby'].application.style - ).toEqual('less'); + const nxJson = readJson(tree, 'nx.json'); + expect(nxJson.generators['@nrwl/gatsby'].application.style).toEqual( + 'less' + ); }); }); @@ -127,10 +135,10 @@ describe('app', () => { `import * as styles from './index.module.styl'` ); - const workspaceJson = readJson(tree, '/workspace.json'); - expect( - workspaceJson.schematics['@nrwl/gatsby'].application.style - ).toEqual('styl'); + const nxJson = readJson(tree, 'nx.json'); + expect(nxJson.generators['@nrwl/gatsby'].application.style).toEqual( + 'styl' + ); }); }); @@ -153,10 +161,10 @@ describe('app', () => { ); expect(indexContent).toContain(`import styled from 'styled-components'`); - const workspaceJson = readJson(tree, '/workspace.json'); - expect( - workspaceJson.schematics['@nrwl/gatsby'].application.style - ).toEqual('styled-components'); + const nxJson = readJson(tree, 'nx.json'); + expect(nxJson.generators['@nrwl/gatsby'].application.style).toEqual( + 'styled-components' + ); }); }); @@ -179,10 +187,10 @@ describe('app', () => { ); expect(indexContent).toContain(`import styled from '@emotion/styled'`); - const workspaceJson = readJson(tree, '/workspace.json'); - expect( - workspaceJson.schematics['@nrwl/gatsby'].application.style - ).toEqual('@emotion/styled'); + const nxJson = readJson(tree, 'nx.json'); + expect(nxJson.generators['@nrwl/gatsby'].application.style).toEqual( + '@emotion/styled' + ); }); }); @@ -210,10 +218,10 @@ describe('app', () => { `import styled from 'styled-components'` ); - const workspaceJson = readJson(tree, '/workspace.json'); - expect( - workspaceJson.schematics['@nrwl/gatsby'].application.style - ).toEqual('styled-jsx'); + const nxJson = readJson(tree, 'nx.json'); + expect(nxJson.generators['@nrwl/gatsby'].application.style).toEqual( + 'styled-jsx' + ); }); }); diff --git a/packages/gatsby/src/generators/application/lib/add-project.ts b/packages/gatsby/src/generators/application/lib/add-project.ts index 54b9739517..08f5cffad1 100644 --- a/packages/gatsby/src/generators/application/lib/add-project.ts +++ b/packages/gatsby/src/generators/application/lib/add-project.ts @@ -2,16 +2,11 @@ import { NormalizedSchema } from './normalize-options'; import { addProjectConfiguration, joinPathFragments, - NxJsonProjectConfiguration, ProjectConfiguration, Tree, } from '@nrwl/devkit'; export function addProject(host: Tree, options: NormalizedSchema) { - const nxConfig: NxJsonProjectConfiguration = { - tags: options.parsedTags, - }; - const targets: Record = {}; targets.build = { @@ -44,15 +39,13 @@ export function addProject(host: Tree, options: NormalizedSchema) { sourceRoot: joinPathFragments(options.projectRoot, 'src'), projectType: 'application', targets, + tags: options.parsedTags, }; addProjectConfiguration( host, options.projectName, - { - ...project, - ...nxConfig, - }, + project, options.standaloneConfig ); } diff --git a/packages/gatsby/src/generators/init/init.spec.ts b/packages/gatsby/src/generators/init/init.spec.ts index 41070ae169..2c178f444d 100644 --- a/packages/gatsby/src/generators/init/init.spec.ts +++ b/packages/gatsby/src/generators/init/init.spec.ts @@ -1,5 +1,5 @@ import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; -import { readJson, Tree } from '@nrwl/devkit'; +import { NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit'; import { gatsbyInitGenerator } from './init'; @@ -21,8 +21,8 @@ describe('init', () => { describe('defaultCollection', () => { it('should be set if none was set before', async () => { await gatsbyInitGenerator(tree, {}); - const workspaceJson = readJson(tree, 'workspace.json'); - expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/gatsby'); + const { cli } = readJson(tree, 'nx.json'); + expect(cli.defaultCollection).toEqual('@nrwl/gatsby'); }); }); diff --git a/packages/jest/src/executors/jest/jest.impl.spec.ts b/packages/jest/src/executors/jest/jest.impl.spec.ts index d9b644cb7e..6e445dd0de 100644 --- a/packages/jest/src/executors/jest/jest.impl.spec.ts +++ b/packages/jest/src/executors/jest/jest.impl.spec.ts @@ -49,6 +49,7 @@ describe('Jest Executor', () => { }, }, }, + npmScope: 'test', }, target: { executor: '@nrwl/jest:jest', diff --git a/packages/linter/src/executors/eslint/hasher.ts b/packages/linter/src/executors/eslint/hasher.ts index 61a3c058a0..ab1a74b8dd 100644 --- a/packages/linter/src/executors/eslint/hasher.ts +++ b/packages/linter/src/executors/eslint/hasher.ts @@ -3,6 +3,7 @@ import { Hash, Hasher } from '@nrwl/workspace/src/core/hasher/hasher'; import { readJsonFile } from '@nrwl/workspace/src/utilities/fileutils'; import { appRootPath } from '@nrwl/tao/src/utils/app-root'; import { join } from 'path'; +import { Workspaces } from '@nrwl/tao/src/shared/workspace'; export default async function run( task: Task, @@ -15,9 +16,9 @@ export default async function run( const command = hasher.hashCommand(task); const sources = await hasher.hashSource(task); const deps = allDeps(task.id, taskGraph); - const nxJson = readJsonFile(join(appRootPath, 'nx.json')); + const workspace = new Workspaces(appRootPath).readWorkspaceConfiguration(); const tags = hasher.hashArray( - deps.map((d) => (nxJson.projects[d].tags || []).join('|')) + deps.map((d) => (workspace.projects[d].tags || []).join('|')) ); const context = await hasher.hashContext(); return { diff --git a/packages/linter/src/executors/eslint/lint.impl.spec.ts b/packages/linter/src/executors/eslint/lint.impl.spec.ts index 8f7ac75394..a89d51da27 100644 --- a/packages/linter/src/executors/eslint/lint.impl.spec.ts +++ b/packages/linter/src/executors/eslint/lint.impl.spec.ts @@ -89,6 +89,7 @@ describe('Linter Builder', () => { targets: {}, }, }, + npmScope: 'test', }, isVerbose: false, }; diff --git a/packages/linter/src/executors/lint/lint.impl.spec.ts b/packages/linter/src/executors/lint/lint.impl.spec.ts index 7081170427..61c21790d5 100644 --- a/packages/linter/src/executors/lint/lint.impl.spec.ts +++ b/packages/linter/src/executors/lint/lint.impl.spec.ts @@ -72,6 +72,7 @@ describe('Linter Builder', () => { workspace: { version: 2, projects: {}, + npmScope: 'test', }, isVerbose: false, }; diff --git a/packages/linter/src/migrations/update-10-3-0/add-root-eslintrc-json-to-workspace-implicit-deps.spec.ts b/packages/linter/src/migrations/update-10-3-0/add-root-eslintrc-json-to-workspace-implicit-deps.spec.ts index 71365b2363..6cc26d1f93 100644 --- a/packages/linter/src/migrations/update-10-3-0/add-root-eslintrc-json-to-workspace-implicit-deps.spec.ts +++ b/packages/linter/src/migrations/update-10-3-0/add-root-eslintrc-json-to-workspace-implicit-deps.spec.ts @@ -26,7 +26,6 @@ describe('Update implicitDependencies within nx.json to include root .eslintrc.j workspaceLayout: { libsDir: 'packages', }, - projects: {}, affected: { defaultBase: 'main', }, diff --git a/packages/linter/src/utils/convert-tslint-to-eslint/__snapshots__/project-converter.spec.ts.snap b/packages/linter/src/utils/convert-tslint-to-eslint/__snapshots__/project-converter.spec.ts.snap index cc882df1bd..24ee4a7f71 100644 --- a/packages/linter/src/utils/convert-tslint-to-eslint/__snapshots__/project-converter.spec.ts.snap +++ b/packages/linter/src/utils/convert-tslint-to-eslint/__snapshots__/project-converter.spec.ts.snap @@ -56,37 +56,10 @@ Object { exports[`ProjectConverter removeTSLintFromWorkspace() should remove all relevant traces of TSLint from the workspace 2`] = ` Object { - "projects": Object { - "foo": Object { - "architect": Object { - "lint": Object { - "builder": "@angular-devkit/build-angular:tslint", - "options": Object { - "exclude": Array [ - "**/node_modules/**", - "!apps/foo/**/*", - ], - "tsConfig": Array [ - "apps/foo/tsconfig.app.json", - ], - }, - }, - }, - "projectType": "application", - "root": "apps/foo", - "schematics": Object { - "@nrwl/angular:application": Object { - "e2eTestRunner": "cypress", - "linter": "eslint", - "unitTestRunner": "jest", - }, - "@nrwl/angular:library": Object { - "linter": "tslint", - }, - }, - }, + "affected": Object { + "defaultBase": "main", }, - "schematics": Object { + "generators": Object { "@nrwl/angular": Object { "application": Object { "linter": "tslint", @@ -96,11 +69,55 @@ Object { }, }, }, - "version": 1, + "npmScope": "proj", + "tasksRunnerOptions": Object { + "default": Object { + "options": Object { + "cacheableOperations": Array [ + "build", + "lint", + "test", + "e2e", + ], + }, + "runner": "@nrwl/workspace/tasks-runners/default", + }, + }, } `; exports[`ProjectConverter removeTSLintFromWorkspace() should remove all relevant traces of TSLint from the workspace 3`] = ` +Object { + "generators": Object { + "@nrwl/angular:application": Object { + "e2eTestRunner": "cypress", + "linter": "eslint", + "unitTestRunner": "jest", + }, + "@nrwl/angular:library": Object { + "linter": "tslint", + }, + }, + "projectType": "application", + "root": "apps/foo", + "targets": Object { + "lint": Object { + "executor": "@angular-devkit/build-angular:tslint", + "options": Object { + "exclude": Array [ + "**/node_modules/**", + "!apps/foo/**/*", + ], + "tsConfig": Array [ + "apps/foo/tsconfig.app.json", + ], + }, + }, + }, +} +`; + +exports[`ProjectConverter removeTSLintFromWorkspace() should remove all relevant traces of TSLint from the workspace 4`] = ` Object { "dependencies": Object {}, "devDependencies": Object {}, @@ -108,163 +125,112 @@ Object { } `; -exports[`ProjectConverter removeTSLintFromWorkspace() should remove all relevant traces of TSLint from the workspace 4`] = ` +exports[`ProjectConverter removeTSLintFromWorkspace() should remove all relevant traces of TSLint from the workspace 5`] = ` Object { - "projects": Object { - "foo": Object { - "architect": Object { - "lint": Object { - "builder": "@angular-devkit/build-angular:tslint", - "options": Object { - "exclude": Array [ - "**/node_modules/**", - "!apps/foo/**/*", - ], - "tsConfig": Array [ - "apps/foo/tsconfig.app.json", - ], - }, - }, + "affected": Object { + "defaultBase": "main", + }, + "npmScope": "proj", + "tasksRunnerOptions": Object { + "default": Object { + "options": Object { + "cacheableOperations": Array [ + "build", + "lint", + "test", + "e2e", + ], }, - "projectType": "application", - "root": "apps/foo", - "schematics": Object { - "@nrwl/angular:application": Object { - "e2eTestRunner": "cypress", - "unitTestRunner": "jest", - }, + "runner": "@nrwl/workspace/tasks-runners/default", + }, + }, +} +`; + +exports[`ProjectConverter removeTSLintFromWorkspace() should remove all relevant traces of TSLint from the workspace 6`] = ` +Object { + "generators": Object { + "@nrwl/angular:application": Object { + "e2eTestRunner": "cypress", + "unitTestRunner": "jest", + }, + }, + "projectType": "application", + "root": "apps/foo", + "targets": Object { + "lint": Object { + "executor": "@angular-devkit/build-angular:tslint", + "options": Object { + "exclude": Array [ + "**/node_modules/**", + "!apps/foo/**/*", + ], + "tsConfig": Array [ + "apps/foo/tsconfig.app.json", + ], }, }, }, - "schematics": Object { - "@nrwl/angular": Object { - "application": Object { - "linter": "tslint", - }, - "library": Object { - "linter": "tslint", - }, - }, - }, - "version": 1, } `; exports[`ProjectConverter removeTSLintFromWorkspace() should remove the entry in generators for convert-tslint-to-eslint because it is no longer needed 1`] = ` Object { - "projects": Object { - "foo": Object { - "architect": Object { - "lint": Object { - "builder": "@angular-devkit/build-angular:tslint", - "options": Object { - "exclude": Array [ - "**/node_modules/**", - "!apps/foo/**/*", - ], - "tsConfig": Array [ - "apps/foo/tsconfig.app.json", - ], - }, - }, - }, - "projectType": "application", - "root": "apps/foo", - "schematics": Object { - "@nrwl/angular:application": Object { - "e2eTestRunner": "cypress", - "linter": "eslint", - "unitTestRunner": "jest", - }, - "@nrwl/angular:library": Object { - "linter": "tslint", - }, - }, - }, + "affected": Object { + "defaultBase": "main", }, - "schematics": Object { + "generators": Object { "@nrwl/angular": Object { "convert-tslint-to-eslint": Object { "removeTSLintIfNoMoreTSLintTargets": true, }, }, }, - "version": 1, + "npmScope": "proj", + "tasksRunnerOptions": Object { + "default": Object { + "options": Object { + "cacheableOperations": Array [ + "build", + "lint", + "test", + "e2e", + ], + }, + "runner": "@nrwl/workspace/tasks-runners/default", + }, + }, } `; exports[`ProjectConverter removeTSLintFromWorkspace() should remove the entry in generators for convert-tslint-to-eslint because it is no longer needed 2`] = ` Object { - "projects": Object { - "foo": Object { - "architect": Object { - "lint": Object { - "builder": "@angular-devkit/build-angular:tslint", - "options": Object { - "exclude": Array [ - "**/node_modules/**", - "!apps/foo/**/*", - ], - "tsConfig": Array [ - "apps/foo/tsconfig.app.json", - ], - }, - }, - }, - "projectType": "application", - "root": "apps/foo", - "schematics": Object { - "@nrwl/angular:application": Object { - "e2eTestRunner": "cypress", - "unitTestRunner": "jest", - }, + "affected": Object { + "defaultBase": "main", + }, + "npmScope": "proj", + "tasksRunnerOptions": Object { + "default": Object { + "options": Object { + "cacheableOperations": Array [ + "build", + "lint", + "test", + "e2e", + ], }, + "runner": "@nrwl/workspace/tasks-runners/default", }, }, - "schematics": Object { - "@nrwl/angular": Object { - "convert-tslint-to-eslint": Object { - "removeTSLintIfNoMoreTSLintTargets": true, - }, - }, - }, - "version": 1, } `; -exports[`ProjectConverter setDefaults() should save in workspace.json 1`] = ` +exports[`ProjectConverter setDefaults() should save in nx.json 1`] = ` Object { - "projects": Object { - "foo": Object { - "architect": Object { - "lint": Object { - "builder": "@angular-devkit/build-angular:tslint", - "options": Object { - "exclude": Array [ - "**/node_modules/**", - "!apps/foo/**/*", - ], - "tsConfig": Array [ - "apps/foo/tsconfig.app.json", - ], - }, - }, - }, - "projectType": "application", - "root": "apps/foo", - "schematics": Object { - "@nrwl/angular:application": Object { - "e2eTestRunner": "cypress", - "linter": "eslint", - "unitTestRunner": "jest", - }, - "@nrwl/angular:library": Object { - "linter": "tslint", - }, - }, - }, + "affected": Object { + "defaultBase": "main", }, - "schematics": Object { + "generators": Object { "@nrwl/angular": Object { "application": Object { "linter": "tslint", @@ -274,43 +240,29 @@ Object { }, }, }, - "version": 1, + "npmScope": "proj", + "tasksRunnerOptions": Object { + "default": Object { + "options": Object { + "cacheableOperations": Array [ + "build", + "lint", + "test", + "e2e", + ], + }, + "runner": "@nrwl/workspace/tasks-runners/default", + }, + }, } `; -exports[`ProjectConverter setDefaults() should save in workspace.json 2`] = ` +exports[`ProjectConverter setDefaults() should save in nx.json 2`] = ` Object { - "projects": Object { - "foo": Object { - "architect": Object { - "lint": Object { - "builder": "@angular-devkit/build-angular:tslint", - "options": Object { - "exclude": Array [ - "**/node_modules/**", - "!apps/foo/**/*", - ], - "tsConfig": Array [ - "apps/foo/tsconfig.app.json", - ], - }, - }, - }, - "projectType": "application", - "root": "apps/foo", - "schematics": Object { - "@nrwl/angular:application": Object { - "e2eTestRunner": "cypress", - "linter": "eslint", - "unitTestRunner": "jest", - }, - "@nrwl/angular:library": Object { - "linter": "tslint", - }, - }, - }, + "affected": Object { + "defaultBase": "main", }, - "schematics": Object { + "generators": Object { "@nrwl/angular": Object { "application": Object { "linter": "tslint", @@ -324,43 +276,29 @@ Object { }, }, }, - "version": 1, + "npmScope": "proj", + "tasksRunnerOptions": Object { + "default": Object { + "options": Object { + "cacheableOperations": Array [ + "build", + "lint", + "test", + "e2e", + ], + }, + "runner": "@nrwl/workspace/tasks-runners/default", + }, + }, } `; -exports[`ProjectConverter setDefaults() should save in workspace.json 3`] = ` +exports[`ProjectConverter setDefaults() should save in nx.json 3`] = ` Object { - "projects": Object { - "foo": Object { - "architect": Object { - "lint": Object { - "builder": "@angular-devkit/build-angular:tslint", - "options": Object { - "exclude": Array [ - "**/node_modules/**", - "!apps/foo/**/*", - ], - "tsConfig": Array [ - "apps/foo/tsconfig.app.json", - ], - }, - }, - }, - "projectType": "application", - "root": "apps/foo", - "schematics": Object { - "@nrwl/angular:application": Object { - "e2eTestRunner": "cypress", - "linter": "eslint", - "unitTestRunner": "jest", - }, - "@nrwl/angular:library": Object { - "linter": "tslint", - }, - }, - }, + "affected": Object { + "defaultBase": "main", }, - "schematics": Object { + "generators": Object { "@nrwl/angular": Object { "application": Object { "linter": "tslint", @@ -374,7 +312,20 @@ Object { }, }, }, - "version": 1, + "npmScope": "proj", + "tasksRunnerOptions": Object { + "default": Object { + "options": Object { + "cacheableOperations": Array [ + "build", + "lint", + "test", + "e2e", + ], + }, + "runner": "@nrwl/workspace/tasks-runners/default", + }, + }, } `; diff --git a/packages/linter/src/utils/convert-tslint-to-eslint/project-converter.spec.ts b/packages/linter/src/utils/convert-tslint-to-eslint/project-converter.spec.ts index d545da29d5..be910756f1 100644 --- a/packages/linter/src/utils/convert-tslint-to-eslint/project-converter.spec.ts +++ b/packages/linter/src/utils/convert-tslint-to-eslint/project-converter.spec.ts @@ -1,10 +1,10 @@ import { addDependenciesToPackageJson, addProjectConfiguration, + NxJsonConfiguration, readJson, - readWorkspaceConfiguration, + readProjectConfiguration, Tree, - updateWorkspaceConfiguration, writeJson, } from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; @@ -262,7 +262,7 @@ describe('ProjectConverter', () => { }); describe('setDefaults()', () => { - it('should save in workspace.json', async () => { + it('should save in nx.json', async () => { writeJson(host, 'tslint.json', {}); writeJson(host, `${projectRoot}/tslint.json`, {}); @@ -273,8 +273,8 @@ describe('ProjectConverter', () => { eslintInitializer: () => undefined, }); - const workspace = readWorkspaceConfiguration(host); - workspace.generators = { + const nxJson = readJson(host, 'nx.json'); + nxJson.generators = { '@nrwl/angular': { application: { linter: 'tslint', @@ -284,10 +284,10 @@ describe('ProjectConverter', () => { }, }, }; - updateWorkspaceConfiguration(host, workspace); + writeJson(host, 'nx.json', nxJson); // BEFORE - no entry for convert-tslint-to-eslint wthin @nrwl/angular generators - expect(readJson(host, 'workspace.json')).toMatchSnapshot(); + expect(readJson(host, 'nx.json')).toMatchSnapshot(); projectConverter.setDefaults('@nrwl/angular', { ignoreExistingTslintConfig: true, @@ -295,7 +295,7 @@ describe('ProjectConverter', () => { }); // AFTER (1) - convert-tslint-to-eslint wthin @nrwl/angular generators has removeTSLintIfNoMoreTSLintTargets set to true - expect(readJson(host, 'workspace.json')).toMatchSnapshot(); + expect(readJson(host, 'nx.json')).toMatchSnapshot(); projectConverter.setDefaults('@nrwl/angular', { ignoreExistingTslintConfig: false, @@ -303,7 +303,7 @@ describe('ProjectConverter', () => { }); // AFTER (2) - convert-tslint-to-eslint wthin @nrwl/angular generators has removeTSLintIfNoMoreTSLintTargets set to false - expect(readJson(host, 'workspace.json')).toMatchSnapshot(); + expect(readJson(host, 'nx.json')).toMatchSnapshot(); }); }); @@ -328,9 +328,9 @@ describe('ProjectConverter', () => { } )(); - const workspace = readWorkspaceConfiguration(host); + const nxJson = readJson(host, 'nx.json'); // Not using shorthand syntax this time - workspace.generators = { + nxJson.generators = { '@nrwl/angular': { application: { linter: 'tslint', @@ -340,21 +340,26 @@ describe('ProjectConverter', () => { }, }, }; - updateWorkspaceConfiguration(host, workspace); + writeJson(host, 'nx.json', nxJson); // BEFORE - tslint and codelyzer are present expect(readJson(host, 'package.json')).toMatchSnapshot(); - // BEFORE - tslint set as both global and project-level default linter for @nrwl/angular generators - expect(readJson(host, 'workspace.json')).toMatchSnapshot(); + // BEFORE - tslint set as both global linter for @nrwl/angular generators + expect(readJson(host, 'nx.json')).toMatchSnapshot(); + + expect(readProjectConfiguration(host, projectName)).toMatchSnapshot(); await projectConverter.removeTSLintFromWorkspace()(); // AFTER - it should remove tslint and codelyzer expect(readJson(host, 'package.json')).toMatchSnapshot(); - // AFTER - generators config from global and project-level settings removed (because eslint is always default) - expect(readJson(host, 'workspace.json')).toMatchSnapshot(); + // AFTER - generators config from global project-level settings removed (because eslint is always default) + expect(readJson(host, 'nx.json')).toMatchSnapshot(); + + // AFTER - generators config from project-level settings removed (because eslint is always default) + expect(readProjectConfiguration(host, projectName)).toMatchSnapshot(); }); it('should remove the entry in generators for convert-tslint-to-eslint because it is no longer needed', async () => { @@ -368,23 +373,23 @@ describe('ProjectConverter', () => { eslintInitializer: () => undefined, }); - const workspace = readWorkspaceConfiguration(host); - workspace.generators = { + const nxJson = readJson(host, 'nx.json'); + nxJson.generators = { '@nrwl/angular': { 'convert-tslint-to-eslint': { removeTSLintIfNoMoreTSLintTargets: true, }, }, }; - updateWorkspaceConfiguration(host, workspace); + writeJson(host, 'nx.json', nxJson); // BEFORE - convert-tslint-to-eslint wthin @nrwl/angular generators has a value for removeTSLintIfNoMoreTSLintTargets - expect(readJson(host, 'workspace.json')).toMatchSnapshot(); + expect(readJson(host, 'nx.json')).toMatchSnapshot(); await projectConverter.removeTSLintFromWorkspace()(); // AFTER - generators config no longer has a reference to convert-tslint-to-eslint - expect(readJson(host, 'workspace.json')).toMatchSnapshot(); + expect(readJson(host, 'nx.json')).toMatchSnapshot(); }); }); }); diff --git a/packages/linter/src/utils/convert-tslint-to-eslint/project-converter.ts b/packages/linter/src/utils/convert-tslint-to-eslint/project-converter.ts index d71f56d837..231fea1fd9 100644 --- a/packages/linter/src/utils/convert-tslint-to-eslint/project-converter.ts +++ b/packages/linter/src/utils/convert-tslint-to-eslint/project-converter.ts @@ -15,7 +15,6 @@ import { import type { Tree, GeneratorCallback, - NxJsonProjectConfiguration, ProjectConfiguration, } from '@nrwl/devkit'; import type { Linter } from 'eslint'; @@ -56,8 +55,7 @@ export interface ConvertTSLintToESLintSchema { * and it will extend from the root workspace .eslintrc.json file as normal. */ export class ProjectConverter { - private readonly projectConfig: ProjectConfiguration & - NxJsonProjectConfiguration; + private readonly projectConfig: ProjectConfiguration; private readonly rootTSLintJsonPath = 'tslint.json'; private readonly rootTSLintJson: Record; private readonly projectTSLintJsonPath: string; @@ -67,7 +65,7 @@ export class ProjectConverter { private readonly ignoreExistingTslintConfig: boolean; private readonly eslintInitializer: (projectInfo: { projectName: string; - projectConfig: ProjectConfiguration & NxJsonProjectConfiguration; + projectConfig: ProjectConfiguration; }) => Promise; /** @@ -86,7 +84,7 @@ export class ProjectConverter { ignoreExistingTslintConfig: boolean; eslintInitializer: (projectInfo: { projectName: string; - projectConfig: ProjectConfiguration & NxJsonProjectConfiguration; + projectConfig: ProjectConfiguration; }) => Promise; }) { this.host = host; diff --git a/packages/nest/src/generators/init/init.spec.ts b/packages/nest/src/generators/init/init.spec.ts index 8a8478f035..a574abea58 100644 --- a/packages/nest/src/generators/init/init.spec.ts +++ b/packages/nest/src/generators/init/init.spec.ts @@ -39,19 +39,22 @@ describe('init generator', () => { it('should set @nrwl/nest as the default collection when none was set before', async () => { await initGenerator(tree, {}); - const workspaceJson = devkit.readJson(tree, 'workspace.json'); - expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/nest'); + const { cli } = devkit.readJson( + tree, + 'nx.json' + ); + expect(cli.defaultCollection).toEqual('@nrwl/nest'); }); it('should not set @nrwl/nest as the default collection when another one was set before', async () => { - devkit.updateJson(tree, 'workspace.json', (json) => ({ + devkit.updateJson(tree, 'nx.json', (json) => ({ ...json, cli: { defaultCollection: '@nrwl/node' }, })); await initGenerator(tree, {}); - const workspaceJson = devkit.readJson(tree, 'workspace.json'); + const workspaceJson = devkit.readJson(tree, 'nx.json'); expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/node'); }); diff --git a/packages/nest/src/generators/library/library.spec.ts b/packages/nest/src/generators/library/library.spec.ts index 7c26c6836d..a1dbf4a7f6 100644 --- a/packages/nest/src/generators/library/library.spec.ts +++ b/packages/nest/src/generators/library/library.spec.ts @@ -111,14 +111,14 @@ describe('lib', () => { ).toMatchSnapshot(); }); - it('should update nx.json', async () => { + it('should update tags', async () => { await libraryGenerator(tree, { name: libName, tags: 'one,two' }); - const nxJson = readJson(tree, '/nx.json'); - expect(nxJson.projects).toEqual({ - [libFileName]: { + const projects = Object.fromEntries(devkit.getProjects(tree)); + expect(projects).toEqual({ + [libFileName]: expect.objectContaining({ tags: ['one', 'two'], - }, + }), }); }); @@ -177,16 +177,16 @@ describe('lib', () => { const dirFileName = 'my-dir'; const nestedLibFileName = `${dirFileName}-${libFileName}`; - it('should update nx.json', async () => { + it('should update tags', async () => { await libraryGenerator(tree, { name: libName, directory: dirName, tags: 'one,two', }); - const nxJson = readJson(tree, '/nx.json'); - expect(nxJson.projects).toEqual({ - [nestedLibFileName]: { tags: ['one', 'two'] }, + const projects = Object.fromEntries(devkit.getProjects(tree)); + expect(projects).toEqual({ + [nestedLibFileName]: expect.objectContaining({ tags: ['one', 'two'] }), }); }); diff --git a/packages/next/src/generators/application/application.spec.ts b/packages/next/src/generators/application/application.spec.ts index d52e04adb8..c74dcccb29 100644 --- a/packages/next/src/generators/application/application.spec.ts +++ b/packages/next/src/generators/application/application.spec.ts @@ -1,6 +1,6 @@ import { Linter } from '@nrwl/linter'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; -import { readJson, Tree } from '@nrwl/devkit'; +import { getProjects, readJson, NxJsonConfiguration, Tree } from '@nrwl/devkit'; import { applicationGenerator } from './application'; @@ -12,7 +12,7 @@ describe('app', () => { }); describe('not nested', () => { - it('should update workspace.json', async () => { + it('should update workspace.json and set defaultProject', async () => { await applicationGenerator(tree, { name: 'myApp', style: 'css', @@ -20,15 +20,16 @@ describe('app', () => { }); const workspaceJson = readJson(tree, 'workspace.json'); + const nxJson = readJson(tree, 'nx.json'); expect(workspaceJson.projects['my-app'].root).toEqual('apps/my-app'); expect(workspaceJson.projects['my-app-e2e'].root).toEqual( 'apps/my-app-e2e' ); - expect(workspaceJson.defaultProject).toEqual('my-app'); + expect(nxJson.defaultProject).toEqual('my-app'); }); - it('should update nx.json', async () => { + it('should update tags and implicit dependencies', async () => { await applicationGenerator(tree, { name: 'myApp', style: 'css', @@ -36,9 +37,9 @@ describe('app', () => { standaloneConfig: false, }); - const nxJson = readJson(tree, 'nx.json'); + const projects = Object.fromEntries(getProjects(tree)); - expect(nxJson.projects).toMatchObject({ + expect(projects).toMatchObject({ 'my-app': { tags: ['one', 'two'], }, diff --git a/packages/next/src/generators/application/lib/add-project.ts b/packages/next/src/generators/application/lib/add-project.ts index 52440329a8..3821df2501 100644 --- a/packages/next/src/generators/application/lib/add-project.ts +++ b/packages/next/src/generators/application/lib/add-project.ts @@ -2,16 +2,11 @@ import { NormalizedSchema } from './normalize-options'; import { addProjectConfiguration, joinPathFragments, - NxJsonProjectConfiguration, ProjectConfiguration, Tree, } from '@nrwl/devkit'; export function addProject(host: Tree, options: NormalizedSchema) { - const nxConfig: NxJsonProjectConfiguration = { - tags: options.parsedTags, - }; - const targets: Record = {}; targets.build = { @@ -61,6 +56,7 @@ export function addProject(host: Tree, options: NormalizedSchema) { sourceRoot: options.appProjectRoot, projectType: 'application', targets, + tags: options.parsedTags, }; addProjectConfiguration( @@ -68,7 +64,6 @@ export function addProject(host: Tree, options: NormalizedSchema) { options.projectName, { ...project, - ...nxConfig, }, options.standaloneConfig ); diff --git a/packages/next/src/generators/init/init.spec.ts b/packages/next/src/generators/init/init.spec.ts index 529cd072fe..3659375a89 100644 --- a/packages/next/src/generators/init/init.spec.ts +++ b/packages/next/src/generators/init/init.spec.ts @@ -1,5 +1,5 @@ import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; -import { readJson, Tree } from '@nrwl/devkit'; +import { readJson, NxJsonConfiguration, Tree } from '@nrwl/devkit'; import { nextInitGenerator } from './init'; @@ -21,8 +21,8 @@ describe('init', () => { describe('defaultCollection', () => { it('should be set if none was set before', async () => { await nextInitGenerator(tree, {}); - const workspaceJson = readJson(tree, 'workspace.json'); - expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/next'); + const { cli } = readJson(tree, 'nx.json'); + expect(cli.defaultCollection).toEqual('@nrwl/next'); }); }); diff --git a/packages/node/src/executors/build/build.impl.spec.ts b/packages/node/src/executors/build/build.impl.spec.ts index 225b0558c7..c995918aa7 100644 --- a/packages/node/src/executors/build/build.impl.spec.ts +++ b/packages/node/src/executors/build/build.impl.spec.ts @@ -35,6 +35,7 @@ describe('Node Build Executor', () => { sourceRoot: 'apps/wibble', }, }, + npmScope: 'test', }, isVerbose: false, }; diff --git a/packages/node/src/executors/execute/execute.impl.spec.ts b/packages/node/src/executors/execute/execute.impl.spec.ts index 9fbd842c17..85bdefcdcf 100644 --- a/packages/node/src/executors/execute/execute.impl.spec.ts +++ b/packages/node/src/executors/execute/execute.impl.spec.ts @@ -62,6 +62,7 @@ describe('NodeExecuteBuilder', () => { }, }, }, + npmScope: 'test', }, isVerbose: false, }; diff --git a/packages/node/src/executors/package/package.impl.spec.ts b/packages/node/src/executors/package/package.impl.spec.ts index fd50fd5f60..b91f017dc6 100644 --- a/packages/node/src/executors/package/package.impl.spec.ts +++ b/packages/node/src/executors/package/package.impl.spec.ts @@ -71,6 +71,7 @@ describe('NodePackageBuilder', () => { targets: {}, }, }, + npmScope: 'test', }, isVerbose: false, }; diff --git a/packages/node/src/generators/application/application.spec.ts b/packages/node/src/generators/application/application.spec.ts index e96eac2496..9f9b7f8eba 100644 --- a/packages/node/src/generators/application/application.spec.ts +++ b/packages/node/src/generators/application/application.spec.ts @@ -1,4 +1,4 @@ -import { NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit'; +import { NxJsonConfiguration, readJson, Tree, getProjects } from '@nrwl/devkit'; import * as devkit from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; @@ -38,6 +38,7 @@ describe('app', () => { standaloneConfig: false, }); const workspaceJson = readJson(tree, '/workspace.json'); + const nxJson = readJson(tree, 'nx.json'); const project = workspaceJson.projects['my-node-app']; expect(project.root).toEqual('apps/my-node-app'); expect(project.architect).toEqual( @@ -81,17 +82,17 @@ describe('app', () => { }, }); expect(workspaceJson.projects['my-node-app-e2e']).toBeUndefined(); - expect(workspaceJson.defaultProject).toEqual('my-node-app'); + expect(nxJson.defaultProject).toEqual('my-node-app'); }); - it('should update nx.json', async () => { + it('should update tags', async () => { await applicationGenerator(tree, { name: 'myNodeApp', tags: 'one,two', standaloneConfig: false, }); - const nxJson = readJson(tree, '/nx.json'); - expect(nxJson.projects).toEqual({ + const projects = Object.fromEntries(getProjects(tree)); + expect(projects).toMatchObject({ 'my-node-app': { tags: ['one', 'two'], }, @@ -174,6 +175,7 @@ describe('app', () => { standaloneConfig: false, }); const workspaceJson = readJson(tree, '/workspace.json'); + const nxJson = readJson(tree, 'nx.json'); expect(workspaceJson.projects['my-dir-my-node-app'].root).toEqual( 'apps/my-dir/my-node-app' @@ -190,18 +192,18 @@ describe('app', () => { }); expect(workspaceJson.projects['my-dir-my-node-app-e2e']).toBeUndefined(); - expect(workspaceJson.defaultProject).toEqual('my-dir-my-node-app'); + expect(nxJson.defaultProject).toEqual('my-dir-my-node-app'); }); - it('should update nx.json', async () => { + it('should update tags', async () => { await applicationGenerator(tree, { name: 'myNodeApp', directory: 'myDir', tags: 'one,two', standaloneConfig: false, }); - const nxJson = readJson(tree, '/nx.json'); - expect(nxJson.projects).toEqual({ + const projects = Object.fromEntries(getProjects(tree)); + expect(projects).toMatchObject({ 'my-dir-my-node-app': { tags: ['one', 'two'], }, diff --git a/packages/node/src/generators/application/application.ts b/packages/node/src/generators/application/application.ts index e453a6acaa..8421c55b1e 100644 --- a/packages/node/src/generators/application/application.ts +++ b/packages/node/src/generators/application/application.ts @@ -8,7 +8,6 @@ import { joinPathFragments, logger, names, - NxJsonProjectConfiguration, offsetFromRoot, ProjectConfiguration, readProjectConfiguration, @@ -83,7 +82,7 @@ function getServeConfig(options: NormalizedSchema): TargetConfiguration { } function addProject(tree: Tree, options: NormalizedSchema) { - const project: ProjectConfiguration & NxJsonProjectConfiguration = { + const project: ProjectConfiguration = { root: options.appProjectRoot, sourceRoot: joinPathFragments(options.appProjectRoot, 'src'), projectType: 'application', diff --git a/packages/node/src/generators/init/init.spec.ts b/packages/node/src/generators/init/init.spec.ts index 3da335ddca..9076abd5b2 100644 --- a/packages/node/src/generators/init/init.spec.ts +++ b/packages/node/src/generators/init/init.spec.ts @@ -1,4 +1,9 @@ -import { addDependenciesToPackageJson, readJson, Tree } from '@nrwl/devkit'; +import { + addDependenciesToPackageJson, + NxJsonConfiguration, + readJson, + Tree, +} from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { nxVersion } from '../../utils/versions'; @@ -38,8 +43,8 @@ describe('init', () => { describe('defaultCollection', () => { it('should be set if none was set before', async () => { await initGenerator(tree, {}); - const workspaceJson = readJson(tree, 'workspace.json'); - expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/node'); + const nxJson = readJson(tree, 'nx.json'); + expect(nxJson.cli.defaultCollection).toEqual('@nrwl/node'); }); }); diff --git a/packages/node/src/generators/library/library.spec.ts b/packages/node/src/generators/library/library.spec.ts index b69cb28f2b..fded5fb3ba 100644 --- a/packages/node/src/generators/library/library.spec.ts +++ b/packages/node/src/generators/library/library.spec.ts @@ -1,4 +1,4 @@ -import { NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit'; +import { getProjects, NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { Schema } from './schema.d'; @@ -48,14 +48,14 @@ describe('lib', () => { ).toEqual('./src'); }); - it('should update nx.json', async () => { + it('should update tags', async () => { await libraryGenerator(tree, { name: 'myLib', tags: 'one,two', standaloneConfig: false, }); - const nxJson = readJson(tree, '/nx.json'); - expect(nxJson.projects).toEqual({ + const projects = Object.fromEntries(getProjects(tree)); + expect(projects).toMatchObject({ 'my-lib': { tags: ['one', 'two'], }, @@ -148,15 +148,15 @@ describe('lib', () => { }); describe('nested', () => { - it('should update nx.json', async () => { + it('should update tags', async () => { await libraryGenerator(tree, { name: 'myLib', directory: 'myDir', tags: 'one', standaloneConfig: false, }); - const nxJson = readJson(tree, '/nx.json'); - expect(nxJson.projects).toEqual({ + let projects = Object.fromEntries(getProjects(tree)); + expect(projects).toMatchObject({ 'my-dir-my-lib': { tags: ['one'], }, @@ -168,8 +168,8 @@ describe('lib', () => { tags: 'one,two', standaloneConfig: false, }); - const nxJson2 = readJson(tree, '/nx.json'); - expect(nxJson2.projects).toEqual({ + projects = Object.fromEntries(getProjects(tree)); + expect(projects).toMatchObject({ 'my-dir-my-lib': { tags: ['one'], }, diff --git a/packages/nx-plugin/src/generators/e2e-project/e2e.spec.ts b/packages/nx-plugin/src/generators/e2e-project/e2e.spec.ts index 000c7fe33e..558f82dadf 100644 --- a/packages/nx-plugin/src/generators/e2e-project/e2e.spec.ts +++ b/packages/nx-plugin/src/generators/e2e-project/e2e.spec.ts @@ -3,6 +3,7 @@ import { addProjectConfiguration, readProjectConfiguration, readJson, + getProjects, } from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { e2eProjectGenerator } from './e2e'; @@ -66,20 +67,18 @@ describe('NxPlugin e2e-project Generator', () => { expect(project.root).toBe('apps/namespace/my-plugin-e2e'); }); - it('should update the nxJson', async () => { + it('should update the tags and implicit dependencies', async () => { await e2eProjectGenerator(tree, { pluginName: 'my-plugin', pluginOutputPath: `dist/libs/my-plugin`, npmPackageName: '@proj/my-plugin', standaloneConfig: false, }); - - expect(readJson(tree, 'nx.json')).toMatchObject({ - projects: { - 'my-plugin-e2e': { - tags: [], - implicitDependencies: ['my-plugin'], - }, + const projects = Object.fromEntries(getProjects(tree)); + expect(projects).toMatchObject({ + 'my-plugin-e2e': { + tags: [], + implicitDependencies: ['my-plugin'], }, }); }); diff --git a/packages/nx-plugin/src/generators/e2e-project/files/tests/__pluginName__.spec.ts__tmpl__ b/packages/nx-plugin/src/generators/e2e-project/files/tests/__pluginName__.spec.ts__tmpl__ index 14a31d2fe9..46211fc5b5 100644 --- a/packages/nx-plugin/src/generators/e2e-project/files/tests/__pluginName__.spec.ts__tmpl__ +++ b/packages/nx-plugin/src/generators/e2e-project/files/tests/__pluginName__.spec.ts__tmpl__ @@ -27,14 +27,14 @@ describe('<%= pluginName %> e2e', () => { }); describe('--tags', () => { - it('should add tags to nx.json', async () => { + it('should add tags to the project', async () => { const plugin = uniq('<%= pluginName %>'); ensureNxProject('<%= npmPackageName %>', '<%= pluginOutputPath %>'); await runNxCommandAsync( `generate <%=npmPackageName%>:<%= pluginName %> ${plugin} --tags e2etag,e2ePackage` ); - const nxJson = readJson('nx.json'); - expect(nxJson.projects[plugin].tags).toEqual(['e2etag', 'e2ePackage']); + const workspace = readJson('workspace.json'); + expect(workspace.projects[plugin].tags).toEqual(['e2etag', 'e2ePackage']); }, 120000); }); }) diff --git a/packages/react-native/src/generators/application/application.spec.ts b/packages/react-native/src/generators/application/application.spec.ts index 90a192a1bb..6485fe26e7 100644 --- a/packages/react-native/src/generators/application/application.spec.ts +++ b/packages/react-native/src/generators/application/application.spec.ts @@ -39,13 +39,10 @@ describe('app', () => { e2eTestRunner: 'none', }); - const nxJson = readJson(appTree, '/nx.json'); - expect(nxJson).toMatchObject({ - npmScope: 'proj', - projects: { - 'my-app': { - tags: ['one', 'two'], - }, + const { projects } = readJson(appTree, '/workspace.json'); + expect(projects).toMatchObject({ + 'my-app': { + tags: ['one', 'two'], }, }); }); diff --git a/packages/react-native/src/generators/application/lib/add-project.ts b/packages/react-native/src/generators/application/lib/add-project.ts index fe58b60c5f..8b3ef59a31 100644 --- a/packages/react-native/src/generators/application/lib/add-project.ts +++ b/packages/react-native/src/generators/application/lib/add-project.ts @@ -1,6 +1,5 @@ import { addProjectConfiguration, - NxJsonProjectConfiguration, ProjectConfiguration, readWorkspaceConfiguration, TargetConfiguration, @@ -10,20 +9,16 @@ import { import { NormalizedSchema } from './normalize-options'; export function addProject(host: Tree, options: NormalizedSchema) { - const nxConfig: NxJsonProjectConfiguration = { - tags: options.parsedTags, - }; - const project: ProjectConfiguration = { root: options.appProjectRoot, sourceRoot: `${options.appProjectRoot}/src`, projectType: 'application', targets: { ...getTargets(options) }, + tags: options.parsedTags, }; addProjectConfiguration(host, options.projectName, { ...project, - ...nxConfig, }); const workspace = readWorkspaceConfiguration(host); diff --git a/packages/react-native/src/generators/init/init.spec.ts b/packages/react-native/src/generators/init/init.spec.ts index 786aa7bd60..99afc69657 100644 --- a/packages/react-native/src/generators/init/init.spec.ts +++ b/packages/react-native/src/generators/init/init.spec.ts @@ -37,12 +37,12 @@ describe('init', () => { describe('defaultCollection', () => { it('should be set if none was set before', async () => { await reactNativeInitGenerator(tree, { e2eTestRunner: 'none' }); - const workspaceJson = readJson(tree, 'workspace.json'); - expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/react-native'); + const { cli } = readJson(tree, 'nx.json'); + expect(cli.defaultCollection).toEqual('@nrwl/react-native'); }); it('should not be set if something else was set before', async () => { - updateJson(tree, 'workspace.json', (json) => { + updateJson(tree, 'nx.json', (json) => { json.cli = { defaultCollection: '@nrwl/react', }; @@ -52,8 +52,8 @@ describe('init', () => { return json; }); await reactNativeInitGenerator(tree, { e2eTestRunner: 'none' }); - const workspaceJson = readJson(tree, 'workspace.json'); - expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/react'); + const { cli } = readJson(tree, 'nx.json'); + expect(cli.defaultCollection).toEqual('@nrwl/react'); }); }); }); diff --git a/packages/react-native/src/generators/library/library.spec.ts b/packages/react-native/src/generators/library/library.spec.ts index da1ed109b1..8c142a8486 100644 --- a/packages/react-native/src/generators/library/library.spec.ts +++ b/packages/react-native/src/generators/library/library.spec.ts @@ -23,7 +23,7 @@ describe('lib', () => { describe('not nested', () => { it('should update workspace.json', async () => { - await libraryGenerator(appTree, defaultSchema); + await libraryGenerator(appTree, { ...defaultSchema, tags: 'one,two' }); const workspaceJson = readJson(appTree, '/workspace.json'); expect(workspaceJson.projects['my-lib'].root).toEqual('libs/my-lib'); expect(workspaceJson.projects['my-lib'].architect.build).toBeUndefined(); @@ -34,16 +34,7 @@ describe('lib', () => { lintFilePatterns: ['libs/my-lib/**/*.{ts,tsx,js,jsx}'], }, }); - }); - - it('should update nx.json', async () => { - await libraryGenerator(appTree, { ...defaultSchema, tags: 'one,two' }); - const nxJson = readJson(appTree, '/nx.json'); - expect(nxJson.projects).toEqual({ - 'my-lib': { - tags: ['one', 'two'], - }, - }); + expect(workspaceJson.projects['my-lib'].tags).toEqual(['one', 'two']); }); it('should update tsconfig.base.json', async () => { @@ -108,8 +99,8 @@ describe('lib', () => { directory: 'myDir', tags: 'one', }); - const nxJson = readJson(appTree, '/nx.json'); - expect(nxJson.projects).toEqual({ + const workspaceJson = readJson(appTree, '/workspace.json'); + expect(workspaceJson.projects).toMatchObject({ 'my-dir-my-lib': { tags: ['one'], }, @@ -122,8 +113,8 @@ describe('lib', () => { tags: 'one,two', }); - const nxJson2 = readJson(appTree, '/nx.json'); - expect(nxJson2.projects).toEqual({ + const workspaceJson2 = readJson(appTree, '/workspace.json'); + expect(workspaceJson2.projects).toMatchObject({ 'my-dir-my-lib': { tags: ['one'], }, diff --git a/packages/react/src/generators/application/application.spec.ts b/packages/react/src/generators/application/application.spec.ts index a5df042d43..9370c04a04 100644 --- a/packages/react/src/generators/application/application.spec.ts +++ b/packages/react/src/generators/application/application.spec.ts @@ -39,11 +39,11 @@ describe('app', () => { expect(workspaceJson.defaultProject).toEqual('my-app'); }); - it('should update nx.json', async () => { + it('should update tags and implicit dependencies', async () => { await applicationGenerator(appTree, { ...schema, tags: 'one,two' }); - const nxJson = readJson(appTree, './nx.json'); - expect(nxJson.projects).toEqual({ + const projects = Object.fromEntries(getProjects(appTree)); + expect(projects).toMatchObject({ 'my-app': { tags: ['one', 'two'], }, @@ -132,15 +132,15 @@ Object { ); }); - it('should update nx.json', async () => { + it('should update tags and implicit deps', async () => { await applicationGenerator(appTree, { ...schema, directory: 'myDir', tags: 'one,two', }); - const nxJson = readJson(appTree, '/nx.json'); - expect(nxJson.projects).toEqual({ + const projects = Object.fromEntries(getProjects(appTree)); + expect(projects).toMatchObject({ 'my-dir-my-app': { tags: ['one', 'two'], }, diff --git a/packages/react/src/generators/application/lib/add-project.ts b/packages/react/src/generators/application/lib/add-project.ts index 0b42c97e4d..302e3485c3 100644 --- a/packages/react/src/generators/application/lib/add-project.ts +++ b/packages/react/src/generators/application/lib/add-project.ts @@ -2,16 +2,11 @@ import { NormalizedSchema } from '../schema'; import { joinPathFragments, addProjectConfiguration, - NxJsonProjectConfiguration, ProjectConfiguration, TargetConfiguration, } from '@nrwl/devkit'; export function addProject(host, options: NormalizedSchema) { - const nxConfig: NxJsonProjectConfiguration = { - tags: options.parsedTags, - }; - const project: ProjectConfiguration = { root: options.appProjectRoot, sourceRoot: `${options.appProjectRoot}/src`, @@ -20,6 +15,7 @@ export function addProject(host, options: NormalizedSchema) { build: createBuildTarget(options), serve: createServeTarget(options), }, + tags: options.parsedTags, }; addProjectConfiguration( @@ -27,7 +23,6 @@ export function addProject(host, options: NormalizedSchema) { options.projectName, { ...project, - ...nxConfig, }, options.standaloneConfig ); diff --git a/packages/react/src/generators/init/init.spec.ts b/packages/react/src/generators/init/init.spec.ts index de5b42fc07..27785a2fc5 100644 --- a/packages/react/src/generators/init/init.spec.ts +++ b/packages/react/src/generators/init/init.spec.ts @@ -1,4 +1,4 @@ -import { readJson, readWorkspaceConfiguration, Tree } from '@nrwl/devkit'; +import { NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import reactInitGenerator from './init'; import { InitSchema } from './schema'; @@ -28,9 +28,12 @@ describe('init', () => { describe('defaultCollection', () => { it('should be set if none was set before', async () => { await reactInitGenerator(tree, schema); - const workspace = readWorkspaceConfiguration(tree); - expect(workspace.cli.defaultCollection).toEqual('@nrwl/react'); - expect(workspace.generators['@nrwl/react'].application.babel).toBe(true); + const { cli, generators } = readJson( + tree, + 'nx.json' + ); + expect(cli.defaultCollection).toEqual('@nrwl/react'); + expect(generators['@nrwl/react'].application.babel).toBe(true); }); }); diff --git a/packages/react/src/generators/library/library.spec.ts b/packages/react/src/generators/library/library.spec.ts index 95bb0ee72d..351b09981c 100644 --- a/packages/react/src/generators/library/library.spec.ts +++ b/packages/react/src/generators/library/library.spec.ts @@ -1,4 +1,10 @@ -import { getProjects, readJson, Tree, updateJson } from '@nrwl/devkit'; +import { + getProjects, + readJson, + readProjectConfiguration, + Tree, + updateJson, +} from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import libraryGenerator from './library'; import { Linter } from '@nrwl/linter'; @@ -39,14 +45,14 @@ describe('lib', () => { }); }); - it('should update nx.json', async () => { + it('should update tags', async () => { await libraryGenerator(appTree, { ...defaultSchema, tags: 'one,two' }); - const nxJson = readJson(appTree, '/nx.json'); - expect(nxJson.projects).toEqual({ - 'my-lib': { + const project = readProjectConfiguration(appTree, 'my-lib'); + expect(project).toEqual( + expect.objectContaining({ tags: ['one', 'two'], - }, - }); + }) + ); }); it('should add react and react-dom packages to package.json if not already present', async () => { @@ -170,18 +176,18 @@ describe('lib', () => { }); describe('nested', () => { - it('should update nx.json', async () => { + it('should update tags and implicitDependencies', async () => { await libraryGenerator(appTree, { ...defaultSchema, directory: 'myDir', tags: 'one', }); - const nxJson = readJson(appTree, '/nx.json'); - expect(nxJson.projects).toEqual({ - 'my-dir-my-lib': { + const myLib = readProjectConfiguration(appTree, 'my-dir-my-lib'); + expect(myLib).toEqual( + expect.objectContaining({ tags: ['one'], - }, - }); + }) + ); await libraryGenerator(appTree, { ...defaultSchema, @@ -190,15 +196,12 @@ describe('lib', () => { tags: 'one,two', }); - const nxJson2 = readJson(appTree, '/nx.json'); - expect(nxJson2.projects).toEqual({ - 'my-dir-my-lib': { - tags: ['one'], - }, - 'my-dir-my-lib2': { + const myLib2 = readProjectConfiguration(appTree, 'my-dir-my-lib2'); + expect(myLib2).toEqual( + expect.objectContaining({ tags: ['one', 'two'], - }, - }); + }) + ); }); it('should generate files', async () => { diff --git a/packages/storybook/src/executors/build-storybook/build-storybook.impl.spec.ts b/packages/storybook/src/executors/build-storybook/build-storybook.impl.spec.ts index 7820361752..484fe716ea 100644 --- a/packages/storybook/src/executors/build-storybook/build-storybook.impl.spec.ts +++ b/packages/storybook/src/executors/build-storybook/build-storybook.impl.spec.ts @@ -33,6 +33,7 @@ describe('Build storybook', () => { targets: {}, }, }, + npmScope: 'test', }, isVerbose: false, }; diff --git a/packages/storybook/src/executors/storybook/storybook.impl.spec.ts b/packages/storybook/src/executors/storybook/storybook.impl.spec.ts index df726235cb..61404c3a62 100644 --- a/packages/storybook/src/executors/storybook/storybook.impl.spec.ts +++ b/packages/storybook/src/executors/storybook/storybook.impl.spec.ts @@ -59,6 +59,7 @@ describe('@nrwl/storybook:storybook', () => { targets: {}, }, }, + npmScope: 'test', }, isVerbose: false, }; diff --git a/packages/storybook/src/generators/init/init.spec.ts b/packages/storybook/src/generators/init/init.spec.ts index e897a8b8a4..630f3536ea 100644 --- a/packages/storybook/src/generators/init/init.spec.ts +++ b/packages/storybook/src/generators/init/init.spec.ts @@ -1,4 +1,9 @@ -import { addDependenciesToPackageJson, readJson, Tree } from '@nrwl/devkit'; +import { + addDependenciesToPackageJson, + NxJsonConfiguration, + readJson, + Tree, +} from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { storybookVersion } from '../../utils/versions'; @@ -258,7 +263,7 @@ describe('@nrwl/storybook:init', () => { await initGenerator(tree, { uiFramework: '@storybook/html', }); - const nxJson = readJson(tree, 'nx.json'); + const nxJson = readJson(tree, 'nx.json'); expect( nxJson.tasksRunnerOptions.default.options.cacheableOperations ).toContain('build-storybook'); @@ -268,7 +273,7 @@ describe('@nrwl/storybook:init', () => { await initGenerator(tree, { uiFramework: '@storybook/web-components', }); - const nxJson = readJson(tree, 'nx.json'); + const nxJson = readJson(tree, 'nx.json'); expect( nxJson.tasksRunnerOptions.default.options.cacheableOperations ).toContain('build-storybook'); @@ -278,7 +283,7 @@ describe('@nrwl/storybook:init', () => { await initGenerator(tree, { uiFramework: '@storybook/vue', }); - const nxJson = readJson(tree, 'nx.json'); + const nxJson = readJson(tree, 'nx.json'); expect( nxJson.tasksRunnerOptions.default.options.cacheableOperations ).toContain('build-storybook'); diff --git a/packages/tao/src/commands/generate.ts b/packages/tao/src/commands/generate.ts index 2c1cd89628..d422528b92 100644 --- a/packages/tao/src/commands/generate.ts +++ b/packages/tao/src/commands/generate.ts @@ -7,10 +7,11 @@ import { Schema, } from '../shared/params'; import { printHelp } from '../shared/print-help'; -import { WorkspaceJsonConfiguration, Workspaces } from '../shared/workspace'; +import { Workspaces } from '../shared/workspace'; import { FileChange, flushChanges, FsTree } from '../shared/tree'; import { logger } from '../shared/logger'; import * as chalk from 'chalk'; +import { NxJsonConfiguration } from '../shared/nx'; export interface GenerateOptions { collectionName: string; @@ -125,8 +126,8 @@ export function printGenHelp(opts: GenerateOptions, schema: Schema) { }); } -function readDefaultCollection(workspace: WorkspaceJsonConfiguration) { - return workspace.cli ? workspace.cli.defaultCollection : null; +function readDefaultCollection(nxConfig: NxJsonConfiguration) { + return nxConfig.cli ? nxConfig.cli.defaultCollection : null; } function printChanges(fileChanges: FileChange[]) { diff --git a/packages/tao/src/commands/migrate.ts b/packages/tao/src/commands/migrate.ts index d0818120af..f38d060188 100644 --- a/packages/tao/src/commands/migrate.ts +++ b/packages/tao/src/commands/migrate.ts @@ -14,6 +14,7 @@ import { writeJsonFile, } from '../utils/fileutils'; import { appRootPath } from '../utils/app-root'; +import { NxJsonConfiguration } from '../shared/nx'; type Dependencies = 'dependencies' | 'devDependencies'; @@ -618,7 +619,7 @@ async function generateMigrationsJsonAndUpdatePackageJson( function showConnectToCloudMessage() { try { - const nxJson = readJsonFile('nx.json'); + const nxJson = readJsonFile('nx.json'); const defaultRunnerIsUsed = Object.values(nxJson.tasksRunnerOptions).find( (r: any) => r.runner == '@nrwl/workspace/tasks-runners/default' ); diff --git a/packages/tao/src/commands/ngcli-adapter.ts b/packages/tao/src/commands/ngcli-adapter.ts index 24947e3aa2..479a715565 100644 --- a/packages/tao/src/commands/ngcli-adapter.ts +++ b/packages/tao/src/commands/ngcli-adapter.ts @@ -15,21 +15,24 @@ import { createConsoleLogger, NodeJsSyncHost } from '@angular-devkit/core/node'; import { Stats } from 'fs'; import { detectPackageManager } from '../shared/package-manager'; import { GenerateOptions } from './generate'; -import { Tree } from '../shared/tree'; +import { FileChange, Tree } from '../shared/tree'; import { - inlineProjectConfigurations, + ProjectConfiguration, + RawWorkspaceJsonConfiguration, toNewFormat, toNewFormatOrNull, toOldFormatOrNull, workspaceConfigName, + WorkspaceJsonConfiguration, } from '../shared/workspace'; import { dirname, extname, resolve, join, basename } from 'path'; import { FileBuffer } from '@angular-devkit/core/src/virtual-fs/host/interface'; -import { EMPTY, Observable, of, concat } from 'rxjs'; +import { EMPTY, Observable, of, concat, combineLatest } from 'rxjs'; import { catchError, map, switchMap, tap, toArray } from 'rxjs/operators'; import { NX_ERROR, NX_PREFIX } from '../shared/logger'; import { readJsonFile } from '../utils/fileutils'; import { parseJson, serializeJson } from '../utils/json'; +import { NxJsonConfiguration } from '../shared/nx'; export async function scheduleTarget( root: string, @@ -191,43 +194,77 @@ async function runSchematic( return { status: 0, loggingQueue: record.loggingQueue }; } +type AngularJsonConfiguration = WorkspaceJsonConfiguration & + Pick & { + schematics?: NxJsonConfiguration['generators']; + }; export class NxScopedHost extends virtualFs.ScopedHost { constructor(root: Path) { super(new NodeJsSyncHost(), root); } + protected __readWorkspaceConfiguration = ( + configFileName: ('workspace.json' | 'angular.json') & Path, + overrides?: { + workspace?: Observable; + nx?: Observable; + } + ): Observable => { + return super.exists('nx.json' as Path).pipe( + switchMap((nxJsonExists) => + (!nxJsonExists // if no nxJson, let it be undefined + ? (overrides?.workspace || super.read(configFileName)).pipe( + map((x) => [x]) + ) + : combineLatest([ + // read both values + overrides?.workspace || super.read(configFileName), + overrides?.nx || super.read('nx.json' as Path), + ]) + ).pipe( + switchMap(([w, n]) => { + try { + // parse both from json, nxJson may be null + const workspaceJson: AngularJsonConfiguration = parseJson( + Buffer.from(w).toString() + ); + const nxJson: NxJsonConfiguration | null = n + ? parseJson(Buffer.from(n).toString()) + : null; + + // assign props ng cli expects from nx json, if it exists + workspaceJson.cli ??= nxJson?.cli; + workspaceJson.generators ??= nxJson?.generators; + workspaceJson.defaultProject ??= nxJson?.defaultProject; + + // resolve inline configurations and downlevel format + return this.resolveInlineProjectConfigurations( + workspaceJson + ).pipe( + map((x) => { + if (workspaceJson.version === 2) { + const formatted = toOldFormatOrNull(workspaceJson); + return formatted + ? Buffer.from(serializeJson(formatted)) + : Buffer.from(serializeJson(x)); + } + return Buffer.from(serializeJson(x)); + }) + ); + } catch { + return of(w); + } + }) + ) + ) + ); + }; + read(path: Path): Observable { return this.context(path).pipe( switchMap((r) => { if (r.isWorkspaceConfig) { - if (r.isNewFormat) { - return super.read(r.actualConfigFileName).pipe( - switchMap((r) => { - try { - const w = parseJson(Buffer.from(r).toString()); - return this.resolveInlineProjectConfigurations(w).pipe( - map((w) => { - const formatted = toOldFormatOrNull(w); - return formatted - ? Buffer.from(serializeJson(formatted)) - : Buffer.from(serializeJson(w)); - }) - ); - } catch (ex) { - return of(r); - } - }) - ); - } else { - return super.read(r.actualConfigFileName).pipe( - map((r) => { - const w = parseJson(Buffer.from(r).toString()); - return Buffer.from( - serializeJson(inlineProjectConfigurations(w)) - ); - }) - ); - } + return this.__readWorkspaceConfiguration(r.actualConfigFileName); } else { return super.read(path); } @@ -326,18 +363,63 @@ export class NxScopedHost extends virtualFs.ScopedHost { if (context.isNewFormat) { try { const w = parseJson(Buffer.from(content).toString()); - const formatted = toNewFormatOrNull(w); + const formatted: AngularJsonConfiguration = toNewFormatOrNull(w); if (formatted) { - return this.writeWorkspaceConfigFiles(context, formatted); + const { cli, generators, defaultProject, ...workspaceJson } = + formatted; + return concat( + this.writeWorkspaceConfigFiles(context, workspaceJson), + cli || generators || defaultProject + ? this.__saveNxJsonProps({ cli, generators, defaultProject }) + : of(null) + ); } else { - return this.writeWorkspaceConfigFiles(context, config); + const { + cli, + schematics, + generators, + defaultProject, + ...angularJson + } = w; + return concat( + this.writeWorkspaceConfigFiles( + context.actualConfigFileName, + angularJson + ), + cli || schematics + ? this.__saveNxJsonProps({ + cli, + defaultProject, + generators: schematics || generators, + }) + : of(null) + ); } - } catch (e) { - return this.writeWorkspaceConfigFiles(context, config); - } - } else { - return this.writeWorkspaceConfigFiles(context, config); + } catch (e) {} } + const { cli, schematics, generators, defaultProject, ...angularJson } = + config; + return concat( + this.writeWorkspaceConfigFiles(context, angularJson), + this.__saveNxJsonProps({ + cli, + defaultProject, + generators: schematics || generators, + }) + ); + } + + private __saveNxJsonProps( + props: Partial + ): Observable { + const nxJsonPath = 'nx.json' as Path; + return super.read(nxJsonPath).pipe( + switchMap((buf) => { + const nxJson = parseJson(Buffer.from(buf).toString()); + Object.assign(nxJson, props); + return super.write(nxJsonPath, Buffer.from(serializeJson(nxJson))); + }) + ); } private writeWorkspaceConfigFiles( @@ -381,9 +463,9 @@ export class NxScopedHost extends virtualFs.ScopedHost { : workspaceJsonWrite; } - protected resolveInlineProjectConfigurations(config: { - projects: Record; - }): Observable { + protected resolveInlineProjectConfigurations( + config: RawWorkspaceJsonConfiguration + ): Observable { // Creates an observable where each emission is a project configuration // that is not listed inside workspace.json. Each time it encounters a // standalone config, observable is updated by concatenating the new @@ -419,7 +501,7 @@ export class NxScopedHost extends virtualFs.ScopedHost { x.forEach(({ project, projectConfig }) => { config.projects[project] = projectConfig; }); - return config; + return config as WorkspaceJsonConfiguration; }) ); } @@ -464,6 +546,7 @@ export class NxScopeHostUsedForWrappedSchematics extends NxScopedHost { read(path: Path): Observable { if (isWorkspaceConfigPath(path)) { const match = findWorkspaceConfigFileChange(this.host); + const nxJsonChange = findMatchingFileChange(this.host, 'nx.json' as Path); // no match, default to existing behavior if (!match) { return super.read(path); @@ -471,15 +554,10 @@ export class NxScopeHostUsedForWrappedSchematics extends NxScopedHost { // we try to format it, if it changes, return it, otherwise return the original change try { - const w = parseJson(Buffer.from(match.content).toString()); - return this.resolveInlineProjectConfigurations(w).pipe( - map((x) => { - const formatted = toOldFormatOrNull(w); - return formatted - ? Buffer.from(serializeJson(formatted)) - : Buffer.from(serializeJson(x)); - }) - ); + return this.__readWorkspaceConfiguration(match.path, { + workspace: of(match.content), + nx: nxJsonChange ? of(nxJsonChange.content) : null, + }); } catch (e) { return super.read(path); } @@ -542,10 +620,15 @@ export class NxScopeHostUsedForWrappedSchematics extends NxScopedHost { } } -function findWorkspaceConfigFileChange(host: Tree) { +type WorkspaceConfigFileChange = FileChange & { + path: ('workspace.json' | 'angular.json') & Path; +}; +function findWorkspaceConfigFileChange(host: Tree): WorkspaceConfigFileChange { return host .listChanges() - .find((f) => f.path == 'workspace.json' || f.path == 'angular.json'); + .find( + (f) => f.path == 'workspace.json' || f.path == 'angular.json' + ) as WorkspaceConfigFileChange; } function findMatchingFileChange(host: Tree, path: Path) { @@ -897,7 +980,7 @@ export function wrapAngularDevkitSchematic( r.eventPath === 'angular.json' || r.eventPath === 'workspace.json' ) { - splitProjectFileUpdatesFromWorkspaceUpdate(host, r); + saveWorkspaceConfigurationInWrappedSchematic(host, r); } host.write(r.eventPath, r.content); } else if (event.kind === 'create') { @@ -1045,11 +1128,11 @@ const getTargetLogger = ( return tslintExecutorLogger; }; -function splitProjectFileUpdatesFromWorkspaceUpdate( +function saveWorkspaceConfigurationInWrappedSchematic( host: Tree, r: { eventPath: string; content: Buffer } ) { - const workspace: { + const workspace: Omit & { projects: { [key: string]: string | { configFilePath?: string } }; } = parseJson(r.content.toString()); for (const [project, config] of Object.entries(workspace.projects)) { @@ -1058,7 +1141,16 @@ function splitProjectFileUpdatesFromWorkspaceUpdate( workspace.projects[project] = normalize(dirname(path)); delete config.configFilePath; host.write(path, serializeJson(config)); - r.content = Buffer.from(serializeJson(workspace)); } } + const nxJson: NxJsonConfiguration = parseJson( + host.read('nx.json').toString() + ); + nxJson.generators = workspace.generators || workspace.schematics; + nxJson.cli = workspace.cli || nxJson.cli; + nxJson.defaultProject = workspace.defaultProject; + delete workspace.cli; + delete workspace.generators; + delete workspace.schematics; + r.content = Buffer.from(serializeJson(workspace)); } diff --git a/packages/tao/src/commands/run.ts b/packages/tao/src/commands/run.ts index 790f17e8d6..6651769ed6 100644 --- a/packages/tao/src/commands/run.ts +++ b/packages/tao/src/commands/run.ts @@ -18,6 +18,7 @@ import { import * as chalk from 'chalk'; import { logger } from '../shared/logger'; +import { NxJsonConfiguration } from '../shared/nx'; export interface Target { project: string; @@ -179,7 +180,7 @@ async function runExecutorInternal( options: { [k: string]: any }, root: string, cwd: string, - workspace: WorkspaceJsonConfiguration, + workspace: WorkspaceJsonConfiguration & NxJsonConfiguration, isVerbose: boolean, printHelp: boolean ): Promise> { diff --git a/packages/tao/src/shared/nx.ts b/packages/tao/src/shared/nx.ts index 6dc3a84735..4ee5be5ecd 100644 --- a/packages/tao/src/shared/nx.ts +++ b/packages/tao/src/shared/nx.ts @@ -1,3 +1,4 @@ +import { PackageManager } from './package-manager'; import { TargetDependencyConfig } from './workspace'; export type ImplicitDependencyEntry = { @@ -36,11 +37,8 @@ export interface NxJsonConfiguration { */ affected?: NxAffectedConfig; /** - * Configuration for projects + * Where new apps + libs should be placed */ - projects: { - [projectName: string]: NxJsonProjectConfiguration; - }; workspaceLayout?: { libsDir: string; appsDir: string; @@ -60,12 +58,46 @@ export interface NxJsonConfiguration { options?: any; }; }; + /** + * List of default values used by generators. + * + * These defaults are global. They are used when no other defaults are configured. + * + * Example: + * + * ``` + * { + * "@nrwl/react": { + * "library": { + * "style": "scss" + * } + * } + * } + * ``` + */ + generators?: { [collectionName: string]: { [generatorName: string]: any } }; + + /** + * Default generator collection. It is used when no collection is provided. + */ + cli?: { + packageManager?: PackageManager; + defaultCollection?: string; + }; /** * Plugins for extending the project graph */ plugins?: string[]; + /** + * Default project. When project isn't provided, the default project + * will be used. Convenient for small workspaces with one main application. + */ + defaultProject?: string; } +/** + * @deprecated(v14): nx.json no longer contains projects + */ export interface NxJsonProjectConfiguration { implicitDependencies?: string[]; tags?: string[]; diff --git a/packages/tao/src/shared/params.ts b/packages/tao/src/shared/params.ts index 793d2bb6c1..eec9ffd13c 100644 --- a/packages/tao/src/shared/params.ts +++ b/packages/tao/src/shared/params.ts @@ -1,6 +1,7 @@ import type { Arguments } from 'yargs-parser'; import { TargetConfiguration, WorkspaceJsonConfiguration } from './workspace'; import { logger } from './logger'; +import { NxJsonConfiguration } from './nx'; type PropertyDescription = { type?: string; @@ -518,7 +519,7 @@ export async function combineOptionsForGenerator( commandLineOpts: Options, collectionName: string, generatorName: string, - wc: WorkspaceJsonConfiguration | null, + wc: (WorkspaceJsonConfiguration & NxJsonConfiguration) | null, schema: Schema, isInteractive: boolean, defaultProjectName: string | null, @@ -610,12 +611,12 @@ export function convertSmartDefaultsIntoNamedParams( function getGeneratorDefaults( projectName: string | null, - wc: WorkspaceJsonConfiguration, + wc: (WorkspaceJsonConfiguration & NxJsonConfiguration) | null, collectionName: string, generatorName: string ) { let defaults = {}; - if (wc.generators) { + if (wc?.generators) { if ( wc.generators[collectionName] && wc.generators[collectionName][generatorName] @@ -634,6 +635,7 @@ function getGeneratorDefaults( } if ( projectName && + wc && wc.projects[projectName] && wc.projects[projectName].generators ) { diff --git a/packages/tao/src/shared/workspace.ts b/packages/tao/src/shared/workspace.ts index 5c30b48313..f4038d7e2d 100644 --- a/packages/tao/src/shared/workspace.ts +++ b/packages/tao/src/shared/workspace.ts @@ -2,14 +2,13 @@ import { existsSync } from 'fs'; import * as path from 'path'; import { appRootPath } from '../utils/app-root'; import { readJsonFile } from '../utils/fileutils'; -import type { NxJsonConfiguration, NxJsonProjectConfiguration } from './nx'; -import type { PackageManager } from './package-manager'; +import type { NxJsonConfiguration } from './nx'; import { TaskGraph } from './tasks'; export interface Workspace extends WorkspaceJsonConfiguration, NxJsonConfiguration { - projects: Record; + projects: Record; } /** @@ -23,39 +22,8 @@ export interface WorkspaceJsonConfiguration { /** * Projects' configurations */ - projects: { [projectName: string]: ProjectConfiguration }; - - /** - * Default project. When project isn't provided, the default project - * will be used. Convenient for small workspaces with one main application. - */ - defaultProject?: string; - - /** - * List of default values used by generators. - * - * These defaults are global. They are used when no other defaults are configured. - * - * Example: - * - * ``` - * { - * "@nrwl/react": { - * "library": { - * "style": "scss" - * } - * } - * } - * ``` - */ - generators?: { [collectionName: string]: { [generatorName: string]: any } }; - - /** - * Default generator collection. It is used when no collection is provided. - */ - cli?: { - packageManager?: PackageManager; - defaultCollection?: string; + projects: { + [projectName: string]: ProjectConfiguration; }; } @@ -111,6 +79,16 @@ export interface ProjectConfiguration { * ``` */ generators?: { [collectionName: string]: { [generatorName: string]: any } }; + + /** + * List of projects which are added as a dependency + */ + implicitDependencies?: string[]; + + /** + * List of tags used by nx-enforce-module-boundaries / dep-graph + */ + tags?: string[]; } export interface TargetDependencyConfig { @@ -258,7 +236,7 @@ export interface ExecutorContext { /** * The full workspace configuration */ - workspace: WorkspaceJsonConfiguration; + workspace: WorkspaceJsonConfiguration & NxJsonConfiguration; /** * The current working directory @@ -278,7 +256,10 @@ export class Workspaces { return path.relative(this.root, cwd) || null; } - calculateDefaultProjectName(cwd: string, wc: WorkspaceJsonConfiguration) { + calculateDefaultProjectName( + cwd: string, + wc: WorkspaceJsonConfiguration & NxJsonConfiguration + ) { const relativeCwd = this.relativeCwd(cwd); if (relativeCwd) { const matchingProject = Object.keys(wc.projects).find((p) => { @@ -293,11 +274,19 @@ export class Workspaces { return wc.defaultProject; } - readWorkspaceConfiguration(): WorkspaceJsonConfiguration { - const w = readJsonFile( + readWorkspaceConfiguration(): WorkspaceJsonConfiguration & + NxJsonConfiguration { + const rawWorkspace = readJsonFile( path.join(this.root, workspaceConfigName(this.root)) ); - return resolveNewFormatWithInlineProjects(w, this.root); + const parsedWorkspace = resolveNewFormatWithInlineProjects( + rawWorkspace, + this.root + ); + const nxJson = readJsonFile( + path.join(this.root, 'nx.json') + ); + return { ...parsedWorkspace, ...nxJson }; } isNxExecutor(nodeModule: string, executor: string) { diff --git a/packages/web/src/executors/package/package.impl.spec.ts b/packages/web/src/executors/package/package.impl.spec.ts index f431b3920e..9fceb10f6a 100644 --- a/packages/web/src/executors/package/package.impl.spec.ts +++ b/packages/web/src/executors/package/package.impl.spec.ts @@ -18,6 +18,7 @@ describe('packageExecutor', () => { workspace: { version: 2, projects: {}, + npmScope: 'test', }, isVerbose: false, projectName: 'example', diff --git a/packages/web/src/generators/application/application.spec.ts b/packages/web/src/generators/application/application.spec.ts index a64191b3d9..ea40c974d5 100644 --- a/packages/web/src/generators/application/application.spec.ts +++ b/packages/web/src/generators/application/application.spec.ts @@ -1,4 +1,4 @@ -import { readJson } from '@nrwl/devkit'; +import { getProjects, readJson } from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import type { Tree, NxJsonConfiguration } from '@nrwl/devkit'; @@ -19,22 +19,23 @@ describe('app', () => { standaloneConfig: false, }); const workspaceJson = readJson(tree, '/workspace.json'); + const nxJson = readJson(tree, 'nx.json'); expect(workspaceJson.projects['my-app'].root).toEqual('apps/my-app'); expect(workspaceJson.projects['my-app-e2e'].root).toEqual( 'apps/my-app-e2e' ); - expect(workspaceJson.defaultProject).toEqual('my-app'); + expect(nxJson.defaultProject).toEqual('my-app'); }); - it('should update nx.json', async () => { + it('should update tags and implicit dependencies', async () => { await applicationGenerator(tree, { name: 'myApp', tags: 'one,two', standaloneConfig: false, }); - const nxJson = readJson(tree, '/nx.json'); - expect(nxJson.projects).toEqual({ + const projects = Object.fromEntries(getProjects(tree)); + expect(projects).toMatchObject({ 'my-app': { tags: ['one', 'two'], }, @@ -148,15 +149,15 @@ describe('app', () => { ); }); - it('should update nx.json', async () => { + it('should update tags and implicit dependencies', async () => { await applicationGenerator(tree, { name: 'myApp', directory: 'myDir', tags: 'one,two', standaloneConfig: false, }); - const nxJson = readJson(tree, '/nx.json'); - expect(nxJson.projects).toEqual({ + const projects = Object.fromEntries(getProjects(tree)); + expect(projects).toMatchObject({ 'my-dir-my-app': { tags: ['one', 'two'], }, diff --git a/packages/web/src/generators/application/application.ts b/packages/web/src/generators/application/application.ts index 2f0365b75a..63cd76729b 100644 --- a/packages/web/src/generators/application/application.ts +++ b/packages/web/src/generators/application/application.ts @@ -7,7 +7,6 @@ import { getWorkspaceLayout, joinPathFragments, names, - NxJsonProjectConfiguration, offsetFromRoot, ProjectConfiguration, readWorkspaceConfiguration, @@ -132,7 +131,7 @@ function addServeTarget( function addProject(tree: Tree, options: NormalizedSchema) { const targets: Record = {}; - let project: ProjectConfiguration & NxJsonProjectConfiguration = { + let project: ProjectConfiguration = { projectType: 'application', root: options.appProjectRoot, sourceRoot: joinPathFragments(options.appProjectRoot, 'src'), diff --git a/packages/web/src/generators/init/init.spec.ts b/packages/web/src/generators/init/init.spec.ts index 2821cdfa9b..21c6dbf9bd 100644 --- a/packages/web/src/generators/init/init.spec.ts +++ b/packages/web/src/generators/init/init.spec.ts @@ -1,4 +1,9 @@ -import { addDependenciesToPackageJson, readJson, Tree } from '@nrwl/devkit'; +import { + addDependenciesToPackageJson, + NxJsonConfiguration, + readJson, + Tree, +} from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { nxVersion } from '../../utils/versions'; @@ -36,8 +41,8 @@ describe('init', () => { describe('defaultCollection', () => { it('should be set if none was set before', async () => { await webInitGenerator(tree, {}); - const workspaceJson = readJson(tree, 'workspace.json'); - expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/web'); + const { cli } = readJson(tree, 'nx.json'); + expect(cli.defaultCollection).toEqual('@nrwl/web'); }); }); diff --git a/packages/workspace/migrations.json b/packages/workspace/migrations.json index 36da3663c1..0ea0cdd17e 100644 --- a/packages/workspace/migrations.json +++ b/packages/workspace/migrations.json @@ -181,6 +181,12 @@ "description": "Add default base to nx.json if its not currently set", "factory": "./src/migrations/update-13-0-0/set-default-base-if-not-set", "cli": "nx" + }, + "13-0-0-config-locations": { + "version": "13.0.0-beta.4", + "description": "Move global settings into nx.json, and project specific settings into workspace.json", + "cli": "nx", + "implementation": "./src/migrations/update-13-0-0/config-locations/config-locations" } }, "packageJsonUpdates": { diff --git a/packages/workspace/package.json b/packages/workspace/package.json index 958c246f2f..2f8a55fae9 100644 --- a/packages/workspace/package.json +++ b/packages/workspace/package.json @@ -81,5 +81,8 @@ "minimatch": "3.0.4", "enquirer": "~2.3.6", "tslib": "^2.0.0" + }, + "nx-migrations": { + "migrations": "./migrations.json" } } diff --git a/packages/workspace/project.json b/packages/workspace/project.json index e1d9012651..830131a5c3 100644 --- a/packages/workspace/project.json +++ b/packages/workspace/project.json @@ -1,6 +1,6 @@ { "root": "packages/workspace", - "sourceRoot": "packages/workspace", + "sourceRoot": "packages/workspace/src", "projectType": "library", "implicitDependencies": ["dep-graph-dep-graph"], "targets": { diff --git a/packages/workspace/src/command-line/format.ts b/packages/workspace/src/command-line/format.ts index f8a18ced46..b7378e55e1 100644 --- a/packages/workspace/src/command-line/format.ts +++ b/packages/workspace/src/command-line/format.ts @@ -13,10 +13,16 @@ import { NxArgs, splitArgsIntoNxArgsAndOverrides } from './utils'; import { reformattedWorkspaceJsonOrNull, workspaceConfigName, + WorkspaceJsonConfiguration, } from '@nrwl/tao/src/shared/workspace'; import { appRootPath } from '@nrwl/tao/src/utils/app-root'; import * as prettier from 'prettier'; -import { readJsonFile, writeJsonFile } from '@nrwl/devkit'; +import { + NxJsonConfiguration, + ProjectConfiguration, + readJsonFile, + writeJsonFile, +} from '@nrwl/devkit'; import { sortObjectByKeys } from '@nrwl/tao/src/utils/object-sort'; const PRETTIER_PATH = require.resolve('prettier/bin-prettier'); @@ -38,8 +44,8 @@ export async function format( case 'write': updateWorkspaceJsonToMatchFormatVersion(); sortWorkspaceJson(); - sortNxJson(); sortTsConfig(); + movePropertiesToNewLocations(); chunkList.push([workspaceJsonPath, 'nx.json', 'tsconfig.base.json']); chunkList.forEach((chunk) => write(chunk)); break; @@ -163,18 +169,6 @@ function sortWorkspaceJson() { } } -function sortNxJson() { - try { - const nxJsonPath = path.join(appRootPath, 'nx.json'); - const nxJson = readJsonFile(nxJsonPath); - const sortedProjects = sortObjectByKeys(nxJson.projects); - nxJson.projects = sortedProjects; - writeJsonFile(nxJsonPath, nxJson); - } catch (e) { - // catch noop - } -} - function sortTsConfig() { try { const tsconfigPath = path.join(appRootPath, 'tsconfig.base.json'); @@ -186,3 +180,57 @@ function sortTsConfig() { // catch noop } } + +function movePropertiesToNewLocations() { + const workspaceConfig = workspaceConfigName(appRootPath); + try { + const workspaceJson = readJsonFile< + NxJsonConfiguration & WorkspaceJsonConfiguration + >(workspaceConfig); + const nxJson = readJsonFile< + NxJsonConfiguration & WorkspaceJsonConfiguration + >('nx.json'); + if ( + workspaceJson.cli || + workspaceJson.generators || + nxJson.projects || + nxJson.defaultProject + ) { + nxJson.cli ??= workspaceJson.cli; + nxJson.generators ??= workspaceJson.generators; + nxJson.defaultProject ??= workspaceJson.defaultProject; + delete workspaceJson['cli']; + delete workspaceJson['generators']; + delete workspaceJson['defaultProject']; + moveTagsAndImplicitDepsFromNxJsonToWorkspaceJson(workspaceJson, nxJson); + writeJsonFile(workspaceConfig, workspaceJson); + writeJsonFile('nx.json', nxJson); + } + } catch (e) { + console.error( + `Error moving properties between Nx.Json + ${workspaceConfig}` + ); + console.error(e); + } +} + +export function moveTagsAndImplicitDepsFromNxJsonToWorkspaceJson( + workspaceJson: WorkspaceJsonConfiguration, + nxJson: NxJsonConfiguration & { + projects: Record< + string, + Pick + >; + } +) { + if (!nxJson.projects) { + return; + } + Object.entries(nxJson.projects).forEach(([project, config]) => { + workspaceJson.projects[project] = { + ...workspaceJson.projects[project], + ...config, + }; + }); + delete nxJson.projects; +} diff --git a/packages/workspace/src/command-line/utils.spec.ts b/packages/workspace/src/command-line/utils.spec.ts index bcebd511ea..59485453b1 100644 --- a/packages/workspace/src/command-line/utils.spec.ts +++ b/packages/workspace/src/command-line/utils.spec.ts @@ -62,7 +62,6 @@ describe('splitArgs', () => { affected: { defaultBase: 'develop', }, - projects: {}, }); expect( splitArgsIntoNxArgsAndOverrides( @@ -82,7 +81,6 @@ describe('splitArgs', () => { it('should return a default base branch if not configured in nx.json', () => { jest.spyOn(fileUtils, 'readNxJson').mockReturnValue({ npmScope: 'testing', - projects: {}, }); expect( splitArgsIntoNxArgsAndOverrides( @@ -229,7 +227,6 @@ describe('getAffectedConfig', () => { affected: { defaultBase: 'testing', }, - projects: {}, }); expect(getAffectedConfig().defaultBase).toEqual('testing'); diff --git a/packages/workspace/src/core/affected-project-graph/affected-project-graph.spec.ts b/packages/workspace/src/core/affected-project-graph/affected-project-graph.spec.ts index b5c6daa0da..4cad74d388 100644 --- a/packages/workspace/src/core/affected-project-graph/affected-project-graph.spec.ts +++ b/packages/workspace/src/core/affected-project-graph/affected-project-graph.spec.ts @@ -3,8 +3,11 @@ import { vol } from 'memfs'; import { stripIndents } from '@angular-devkit/core/src/utils/literals'; import { filterAffected } from './affected-project-graph'; import { WholeFileChange } from '../file-utils'; -import type { NxJsonConfiguration } from '@nrwl/devkit'; import { buildProjectGraph } from '../project-graph/build-project-graph'; +import type { + NxJsonConfiguration, + WorkspaceJsonConfiguration, +} from '@nrwl/devkit'; jest.mock('fs', () => require('memfs').fs); jest.mock('@nrwl/tao/src/utils/app-root', () => ({ @@ -13,7 +16,7 @@ jest.mock('@nrwl/tao/src/utils/app-root', () => ({ describe('project graph', () => { let packageJson: any; - let workspaceJson: any; + let workspaceJson: WorkspaceJsonConfiguration; let tsConfigJson: any; let nxJson: NxJsonConfiguration; let filesJson: any; @@ -33,31 +36,38 @@ describe('project graph', () => { }, }; workspaceJson = { + version: 2, projects: { demo: { root: 'apps/demo/', sourceRoot: 'apps/demo/src', projectType: 'application', + implicitDependencies: ['api'], + targets: {}, }, 'demo-e2e': { root: 'apps/demo-e2e/', sourceRoot: 'apps/demo-e2e/src', projectType: 'application', + targets: {}, }, ui: { root: 'libs/ui/', sourceRoot: 'libs/ui/src', projectType: 'library', + targets: {}, }, util: { root: 'libs/util/', sourceRoot: 'libs/util/src', projectType: 'library', + targets: {}, }, api: { root: 'apps/api/', sourceRoot: 'apps/api/src', projectType: 'application', + targets: {}, }, }, }; @@ -74,13 +84,6 @@ describe('project graph', () => { }, 'something-for-api.txt': ['api'], }, - projects: { - api: { tags: [] }, - demo: { tags: [], implicitDependencies: ['api'] }, - 'demo-e2e': { tags: [] }, - ui: { tags: [] }, - util: { tags: [] }, - }, }; tsConfigJson = { compilerOptions: { @@ -262,11 +265,11 @@ describe('project graph', () => { expect(Object.keys(affected.nodes)).toEqual([ 'npm:@nrwl/workspace', - 'api', 'demo', 'demo-e2e', 'ui', 'util', + 'api', ]); }); }); diff --git a/packages/workspace/src/core/affected-project-graph/affected-project-graph.ts b/packages/workspace/src/core/affected-project-graph/affected-project-graph.ts index 641af3231a..94873980b4 100644 --- a/packages/workspace/src/core/affected-project-graph/affected-project-graph.ts +++ b/packages/workspace/src/core/affected-project-graph/affected-project-graph.ts @@ -5,7 +5,11 @@ import { readPackageJson, readWorkspaceJson, } from '../file-utils'; -import type { NxJsonConfiguration, ProjectGraph } from '@nrwl/devkit'; +import type { + NxJsonConfiguration, + ProjectGraph, + WorkspaceJsonConfiguration, +} from '@nrwl/devkit'; import { getImplicitlyTouchedProjects, getTouchedProjects, @@ -17,25 +21,26 @@ import { TouchedProjectLocator, } from './affected-project-graph-models'; import { normalizeNxJson } from '../normalize-nx-json'; -import { getTouchedProjectsInNxJson } from './locators/nx-json-changes'; import { getTouchedProjectsInWorkspaceJson } from './locators/workspace-json-changes'; import { getTouchedProjectsFromTsConfig } from './locators/tsconfig-json-changes'; export function filterAffected( graph: ProjectGraph, touchedFiles: FileChange[], - workspaceJson: any = readWorkspaceJson(), + workspaceJson: WorkspaceJsonConfiguration = readWorkspaceJson(), nxJson: NxJsonConfiguration = readNxJson(), packageJson: any = readPackageJson() ): ProjectGraph { - const normalizedNxJson = normalizeNxJson(nxJson); + const normalizedNxJson = normalizeNxJson( + nxJson, + Object.keys(workspaceJson.projects) + ); // Additional affected logic should be in this array. const touchedProjectLocators: TouchedProjectLocator[] = [ getTouchedProjects, getImplicitlyTouchedProjects, getTouchedNpmPackages, getImplicitlyTouchedProjectsByJsonChanges, - getTouchedProjectsInNxJson, getTouchedProjectsInWorkspaceJson, getTouchedProjectsFromTsConfig, ]; diff --git a/packages/workspace/src/core/affected-project-graph/locators/implicit-json-changes.spec.ts b/packages/workspace/src/core/affected-project-graph/locators/implicit-json-changes.spec.ts index 4536fc2237..e00e095dbd 100644 --- a/packages/workspace/src/core/affected-project-graph/locators/implicit-json-changes.spec.ts +++ b/packages/workspace/src/core/affected-project-graph/locators/implicit-json-changes.spec.ts @@ -31,7 +31,6 @@ describe('getImplicitlyTouchedProjectsByJsonChanges', () => { }, }, npmScope: 'scope', - projects: {}, }; }); diff --git a/packages/workspace/src/core/affected-project-graph/locators/npm-packages.spec.ts b/packages/workspace/src/core/affected-project-graph/locators/npm-packages.spec.ts index 4401d8c36f..50324b29c4 100644 --- a/packages/workspace/src/core/affected-project-graph/locators/npm-packages.spec.ts +++ b/packages/workspace/src/core/affected-project-graph/locators/npm-packages.spec.ts @@ -24,10 +24,6 @@ describe('getTouchedNpmPackages', () => { }, }, npmScope: 'scope', - projects: { - proj1: {}, - proj2: {}, - }, }; projectGraph = { nodes: { diff --git a/packages/workspace/src/core/affected-project-graph/locators/nx-json-changes.spec.ts b/packages/workspace/src/core/affected-project-graph/locators/nx-json-changes.spec.ts deleted file mode 100644 index 67d6b6cc40..0000000000 --- a/packages/workspace/src/core/affected-project-graph/locators/nx-json-changes.spec.ts +++ /dev/null @@ -1,218 +0,0 @@ -import { getTouchedProjectsInNxJson } from './nx-json-changes'; -import { WholeFileChange } from '../../file-utils'; -import { DiffType } from '../../../utilities/json-diff'; - -describe('getTouchedProjectsInNxJson', () => { - it('should not return changes when nx.json is not touched', () => { - const result = getTouchedProjectsInNxJson( - [ - { - file: 'source.ts', - hash: 'some-hash', - getChanges: () => [new WholeFileChange()], - }, - ], - {}, - { - npmScope: 'proj', - projects: { - proj1: { - tags: [], - }, - }, - } - ); - expect(result).toEqual([]); - }); - - it('should return all projects for a whole file change', () => { - const result = getTouchedProjectsInNxJson( - [ - { - file: 'nx.json', - hash: 'some-hash', - getChanges: () => [new WholeFileChange()], - }, - ], - {}, - { - npmScope: 'proj', - projects: { - proj1: { - tags: [], - }, - proj2: { - tags: [], - }, - }, - } - ); - expect(result).toEqual(['proj1', 'proj2']); - }); - - it('should return all projects for changes to npmScope', () => { - const result = getTouchedProjectsInNxJson( - [ - { - file: 'nx.json', - hash: 'some-hash', - getChanges: () => [ - { - type: DiffType.Modified, - path: ['npmScope'], - value: { - lhs: 'proj', - rhs: 'awesome-proj', - }, - }, - ], - }, - ], - {}, - { - npmScope: 'proj', - projects: { - proj1: { - tags: [], - }, - proj2: { - tags: [], - }, - }, - } - ); - expect(result).toEqual(['proj1', 'proj2']); - }); - - it('should return projects added in nx.json', () => { - const result = getTouchedProjectsInNxJson( - [ - { - file: 'nx.json', - hash: 'some-hash', - getChanges: () => [ - { - type: DiffType.Added, - path: ['projects', 'proj1'], - value: { - lhs: undefined, - rhs: { - tags: [], - }, - }, - }, - { - type: DiffType.Added, - path: ['projects', 'proj1', 'tags'], - value: { - lhs: undefined, - rhs: [], - }, - }, - ], - }, - ], - {}, - { - npmScope: 'proj', - projects: { - proj1: { - tags: [], - }, - proj2: { - tags: [], - }, - }, - } - ); - expect(result).toEqual(['proj1']); - }); - - it('should return all projects when a project is removed', () => { - const result = getTouchedProjectsInNxJson( - [ - { - file: 'nx.json', - hash: 'some-hash', - getChanges: () => [ - { - type: DiffType.Deleted, - path: ['projects', 'proj3'], - value: { - lhs: { - tags: [], - }, - rhs: undefined, - }, - }, - ], - }, - ], - {}, - { - npmScope: 'proj', - projects: { - proj1: { - tags: [], - }, - proj2: { - tags: [], - }, - }, - } - ); - expect(result).toEqual(['proj1', 'proj2']); - }); - - it('should return projects modified in nx.json', () => { - const result = getTouchedProjectsInNxJson( - [ - { - file: 'nx.json', - hash: 'some-hash', - getChanges: () => [ - { - type: DiffType.Modified, - path: ['projects', 'proj1'], - value: { - lhs: { tags: ['scope:feat'] }, - rhs: { - tags: ['scope:shared'], - }, - }, - }, - { - type: DiffType.Modified, - path: ['projects', 'proj1', 'tags'], - value: { - lhs: ['scope:feat'], - rhs: ['scope:shared'], - }, - }, - { - type: DiffType.Modified, - path: ['projects', 'proj1', 'tags', '0'], - value: { - lhs: 'scope:feat', - rhs: 'scope:shared', - }, - }, - ], - }, - ], - {}, - { - npmScope: 'proj', - projects: { - proj1: { - tags: [], - }, - proj2: { - tags: [], - }, - }, - } - ); - expect(result).toEqual(['proj1']); - }); -}); diff --git a/packages/workspace/src/core/affected-project-graph/locators/nx-json-changes.ts b/packages/workspace/src/core/affected-project-graph/locators/nx-json-changes.ts deleted file mode 100644 index 4ab7074a30..0000000000 --- a/packages/workspace/src/core/affected-project-graph/locators/nx-json-changes.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { isWholeFileChange, WholeFileChange } from '../../file-utils'; -import { - DiffType, - isJsonChange, - JsonChange, -} from '../../../utilities/json-diff'; -import { TouchedProjectLocator } from '../affected-project-graph-models'; - -export const getTouchedProjectsInNxJson: TouchedProjectLocator< - WholeFileChange | JsonChange -> = (touchedFiles, workspaceJson, nxJson): string[] => { - const nxJsonChange = touchedFiles.find((change) => change.file === 'nx.json'); - if (!nxJsonChange) { - return []; - } - - const changes = nxJsonChange.getChanges(); - - if ( - changes.some((change) => { - if (isJsonChange(change)) { - return change.path[0] !== 'projects'; - } - if (isWholeFileChange(change)) { - return true; - } - return false; - }) - ) { - return Object.keys(nxJson.projects); - } - - const touched = []; - for (let i = 0; i < changes.length; i++) { - const change = changes[i]; - if (!isJsonChange(change) || change.path[0] !== 'projects') { - continue; - } - - // Only look for changes that are changes to the whole project definition - if (change.path.length !== 2) { - continue; - } - - switch (change.type) { - case DiffType.Deleted: { - // We are not sure which projects used to depend on a deleted project - // so return all projects to be safe - return Object.keys(nxJson.projects); - } - default: { - // Add the project name - touched.push(change.path[1]); - } - } - } - return touched; -}; diff --git a/packages/workspace/src/core/affected-project-graph/locators/tsconfig-json-changes.spec.ts b/packages/workspace/src/core/affected-project-graph/locators/tsconfig-json-changes.spec.ts index 225cd56be0..79c710521c 100644 --- a/packages/workspace/src/core/affected-project-graph/locators/tsconfig-json-changes.spec.ts +++ b/packages/workspace/src/core/affected-project-graph/locators/tsconfig-json-changes.spec.ts @@ -52,11 +52,6 @@ describe('getTouchedProjectsFromTsConfig', () => { {}, { npmScope: 'proj', - projects: { - proj1: { - tags: [], - }, - }, } ); expect(result).toEqual([]); diff --git a/packages/workspace/src/core/affected-project-graph/locators/workspace-json-changes.spec.ts b/packages/workspace/src/core/affected-project-graph/locators/workspace-json-changes.spec.ts index 81349e6180..de4972807e 100644 --- a/packages/workspace/src/core/affected-project-graph/locators/workspace-json-changes.spec.ts +++ b/packages/workspace/src/core/affected-project-graph/locators/workspace-json-changes.spec.ts @@ -15,11 +15,6 @@ describe('getTouchedProjectsInWorkspaceJson', () => { {}, { npmScope: 'proj', - projects: { - proj1: { - tags: [], - }, - }, } ); expect(result).toEqual([]); diff --git a/packages/workspace/src/core/assert-workspace-validity.spec.ts b/packages/workspace/src/core/assert-workspace-validity.spec.ts index 9e0c50ab65..d869559c83 100644 --- a/packages/workspace/src/core/assert-workspace-validity.spec.ts +++ b/packages/workspace/src/core/assert-workspace-validity.spec.ts @@ -10,26 +10,6 @@ describe('assertWorkspaceValidity', () => { implicitDependencies: { 'nx.json': '*', }, - projects: { - app1: { - tags: [], - }, - 'app1-e2e': { - tags: [], - }, - app2: { - tags: [], - }, - 'app2-e2e': { - tags: [], - }, - lib1: { - tags: [], - }, - lib2: { - tags: [], - }, - }, }; mockWorkspaceJson = { projects: { @@ -47,45 +27,6 @@ describe('assertWorkspaceValidity', () => { assertWorkspaceValidity(mockWorkspaceJson, mockNxJson); }); - it('should throw for a missing project in workspace.json', () => { - jest.spyOn(output, 'error'); - delete mockWorkspaceJson.projects.app1; - - const mockExit = jest - .spyOn(process, 'exit') - .mockImplementation(((code?: number) => {}) as any); - assertWorkspaceValidity(mockWorkspaceJson, mockNxJson); - - expect(output.error).toHaveBeenCalledWith({ - title: 'Configuration Error', - bodyLines: [ - `workspace.json and nx.json are out of sync. The following projects are missing in workspace.json: app1`, - ], - }); - expect(mockExit).toHaveBeenCalledWith(1); - mockExit.mockRestore(); - }); - - // it('should throw for a missing project in nx.json', () => { - // jest.spyOn(output, 'error'); - - // delete mockNxJson.projects.app1; - - // const mockExit = jest - // .spyOn(process, 'exit') - // .mockImplementation(((code?: number) => {}) as any); - // assertWorkspaceValidity(mockWorkspaceJson, mockNxJson); - - // expect(mockExit).toHaveBeenCalledWith(1); - // expect(output.error).toHaveBeenCalledWith({ - // title: 'Configuration Error', - // bodyLines: [ - // `workspace.json and nx.json are out of sync. The following projects are missing in nx.json: app1`, - // ], - // }); - // mockExit.mockRestore(); - // }); - it('should throw for an invalid top-level implicit dependency', () => { jest.spyOn(output, 'error'); mockNxJson.implicitDependencies = { @@ -101,7 +42,7 @@ describe('assertWorkspaceValidity', () => { expect(output.error).toHaveBeenCalledWith({ title: 'Configuration Error', bodyLines: [ - `The following implicitDependencies specified in nx.json are invalid: + `The following implicitDependencies specified in project configurations are invalid: README.md invalidproj`, ], @@ -111,7 +52,7 @@ describe('assertWorkspaceValidity', () => { it('should throw for an invalid project-level implicit dependency', () => { jest.spyOn(output, 'error'); - mockNxJson.projects.app2.implicitDependencies = ['invalidproj']; + mockWorkspaceJson.projects.app2.implicitDependencies = ['invalidproj']; const mockExit = jest .spyOn(process, 'exit') @@ -122,7 +63,7 @@ describe('assertWorkspaceValidity', () => { expect(output.error).toHaveBeenCalledWith({ title: 'Configuration Error', bodyLines: [ - `The following implicitDependencies specified in nx.json are invalid: + `The following implicitDependencies specified in project configurations are invalid: app2 invalidproj`, ], diff --git a/packages/workspace/src/core/assert-workspace-validity.ts b/packages/workspace/src/core/assert-workspace-validity.ts index 4043485ad8..02df171884 100644 --- a/packages/workspace/src/core/assert-workspace-validity.ts +++ b/packages/workspace/src/core/assert-workspace-validity.ts @@ -10,25 +10,9 @@ export function assertWorkspaceValidity( nxJson: NxJsonConfiguration ) { const workspaceJsonProjects = Object.keys(workspaceJson.projects); - const nxJsonProjects = Object.keys(nxJson.projects); - - if (minus(nxJsonProjects, workspaceJsonProjects).length > 0) { - output.error({ - title: 'Configuration Error', - bodyLines: [ - `${workspaceFileName()} and nx.json are out of sync. The following projects are missing in ${workspaceFileName()}: ${minus( - nxJsonProjects, - workspaceJsonProjects - ).join(', ')}`, - ], - }); - - process.exit(1); - } const projects = { ...workspaceJson.projects, - ...nxJson.projects, }; const invalidImplicitDependencies = new Map(); @@ -68,16 +52,16 @@ export function assertWorkspaceValidity( return map; }, invalidImplicitDependencies); - nxJsonProjects - .filter((nxJsonProjectName) => { - const project = nxJson.projects[nxJsonProjectName]; + workspaceJsonProjects + .filter((projectName) => { + const project = projects[projectName]; return !!project.implicitDependencies; }) - .reduce((map, nxJsonProjectName) => { - const project = nxJson.projects[nxJsonProjectName]; + .reduce((map, projectName) => { + const project = projects[projectName]; detectAndSetInvalidProjectValues( map, - nxJsonProjectName, + projectName, project.implicitDependencies, projects ); @@ -88,7 +72,7 @@ export function assertWorkspaceValidity( return; } - let message = `The following implicitDependencies specified in nx.json are invalid: + let message = `The following implicitDependencies specified in project configurations are invalid: `; invalidImplicitDependencies.forEach((projectNames, key) => { const str = ` ${key} diff --git a/packages/workspace/src/core/file-utils.ts b/packages/workspace/src/core/file-utils.ts index 7c1fbbaa80..bc7bc4a05c 100644 --- a/packages/workspace/src/core/file-utils.ts +++ b/packages/workspace/src/core/file-utils.ts @@ -6,7 +6,6 @@ import { import type { FileData, NxJsonConfiguration, - NxJsonProjectConfiguration, ProjectGraphNode, } from '@nrwl/devkit'; import { ProjectFileMap } from '@nrwl/devkit'; @@ -209,20 +208,6 @@ export function readNxJson( throw new Error(`nx.json must define the npmScope property.`); } - // NOTE: As we work towards removing nx.json, some settings are now found in - // the workspace.json file. Currently this is only supported for projects - // with separated configs, as they list tags / implicit deps inside the project.json file. - const workspace = readWorkspaceConfig({ format: 'nx', path: appRootPath }); - Object.entries(workspace.projects).forEach( - ([project, projectConfig]: [string, NxJsonProjectConfiguration]) => { - config.projects ??= {}; - if (!config.projects[project]) { - const { tags, implicitDependencies } = projectConfig; - config.projects[project] = { tags, implicitDependencies }; - } - } - ); - const nxJsonExtends = readNxJsonExtends(config as any); if (nxJsonExtends) { return { ...nxJsonExtends, ...config }; diff --git a/packages/workspace/src/core/hasher/hasher.spec.ts b/packages/workspace/src/core/hasher/hasher.spec.ts index d9ac60a05d..bad9b6fe8f 100644 --- a/packages/workspace/src/core/hasher/hasher.spec.ts +++ b/packages/workspace/src/core/hasher/hasher.spec.ts @@ -16,10 +16,6 @@ fs.existsSync = () => true; describe('Hasher', () => { const nxJson = { npmScope: 'nrwl', - projects: { - parent: { implicitDependencies: [], tags: [] }, - child: { implicitDependencies: [], tags: [] }, - }, }; const workSpaceJson = { @@ -113,7 +109,7 @@ describe('Hasher', () => { expect(hash.details.command).toEqual('parent|build||{"prop":"prop-value"}'); expect(hash.details.nodes).toEqual({ parent: - '/file|file.hash|{"root":"libs/parent"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', + '/file|file.hash|{"root":"libs/parent"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', }); expect(hash.details.implicitDeps).toEqual({ 'nx.json': '{"npmScope":"nrwl"}', @@ -170,7 +166,7 @@ describe('Hasher', () => { expect(hash.details.command).toEqual('parent|build||{"prop":"prop-value"}'); expect(hash.details.nodes).toEqual({ parent: - '/file.ts|file.hash|{"root":"libs/parent"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"]}}}', + '/file.ts|file.hash|{"root":"libs/parent"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"]}}}', }); expect(hash.details.implicitDeps).toEqual({ 'nx.json': '{"npmScope":"nrwl"}', @@ -267,9 +263,9 @@ describe('Hasher', () => { // note that the parent hash is based on parent source files only! expect(hash.details.nodes).toEqual({ child: - '/fileb.ts|b.hash|{"root":"libs/child"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', + '/fileb.ts|b.hash|{"root":"libs/child"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', parent: - '/filea.ts|a.hash|{"root":"libs/parent"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', + '/filea.ts|a.hash|{"root":"libs/parent"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', }); }); @@ -315,7 +311,7 @@ describe('Hasher', () => { // note that the parent hash is based on parent source files only! expect(hash.details.nodes).toEqual({ - app: '/filea.ts|a.hash|""|""|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', + app: '/filea.ts|a.hash|""|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', 'npm:react': '17.0.0', }); }); @@ -367,9 +363,9 @@ describe('Hasher', () => { expect(tasksHash.value).toContain('build'); //target expect(tasksHash.details.nodes).toEqual({ child: - '/fileb.ts|b.hash|{"root":"libs/child"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', + '/fileb.ts|b.hash|{"root":"libs/child"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', parent: - '/filea.ts|a.hash|{"root":"libs/parent"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', + '/filea.ts|a.hash|{"root":"libs/parent"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', }); const hashb = await hasher.hashTaskWithDepsAndContext({ @@ -386,9 +382,9 @@ describe('Hasher', () => { expect(hashb.value).toContain('build'); //target expect(hashb.details.nodes).toEqual({ child: - '/fileb.ts|b.hash|{"root":"libs/child"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', + '/fileb.ts|b.hash|{"root":"libs/child"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', parent: - '/filea.ts|a.hash|{"root":"libs/parent"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', + '/filea.ts|a.hash|{"root":"libs/parent"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}', }); }); diff --git a/packages/workspace/src/core/hasher/hasher.ts b/packages/workspace/src/core/hasher/hasher.ts index 36b3900a5f..9f9fdcc9cb 100644 --- a/packages/workspace/src/core/hasher/hasher.ts +++ b/packages/workspace/src/core/hasher/hasher.ts @@ -354,7 +354,6 @@ class ProjectHasher { const workspaceJson = JSON.stringify( this.workspaceJson.projects[projectName] ?? '' ); - const nxJson = JSON.stringify(this.nxJson.projects[projectName] ?? ''); let tsConfig: string; @@ -369,7 +368,6 @@ class ProjectHasher { ...fileNames, ...values, workspaceJson, - nxJson, tsConfig, ]) ); @@ -423,7 +421,7 @@ class ProjectHasher { res.projects ??= {}; return res; } catch { - return { projects: {}, npmScope: '' }; + return { npmScope: '' }; } } } diff --git a/packages/workspace/src/core/normalize-nx-json.spec.ts b/packages/workspace/src/core/normalize-nx-json.spec.ts index 0ce045589b..ad5512d09d 100644 --- a/packages/workspace/src/core/normalize-nx-json.spec.ts +++ b/packages/workspace/src/core/normalize-nx-json.spec.ts @@ -1,28 +1,27 @@ +import { ProjectConfiguration } from '@nrwl/devkit'; import { normalizeNxJson } from './normalize-nx-json'; describe('normalizeNxJson', () => { it('should expand projects array', () => { - const result = normalizeNxJson({ - npmScope: 'nrwl', - projects: { - demo: { tags: [] }, - ui: { tags: [] }, - util: { tags: [] }, - }, - implicitDependencies: { - 'package.json': '*', - 'whatever.json': { - a: { - b: { - c: ['demo'], - d: { - e: '*', + const result = normalizeNxJson( + { + npmScope: 'nrwl', + implicitDependencies: { + 'package.json': '*', + 'whatever.json': { + a: { + b: { + c: ['demo'], + d: { + e: '*', + }, }, }, }, }, }, - }); + ['demo', 'ui', 'util'] + ); expect(result.implicitDependencies).toEqual({ 'package.json': ['demo', 'ui', 'util'], diff --git a/packages/workspace/src/core/normalize-nx-json.ts b/packages/workspace/src/core/normalize-nx-json.ts index 06812f1423..1064f5cf86 100644 --- a/packages/workspace/src/core/normalize-nx-json.ts +++ b/packages/workspace/src/core/normalize-nx-json.ts @@ -1,4 +1,4 @@ -import { NxJsonConfiguration } from '@nrwl/devkit'; +import { NxJsonConfiguration, WorkspaceJsonConfiguration } from '@nrwl/devkit'; /** * Normalize nx json by replacing wildcard `*` implicit dependencies @@ -7,7 +7,8 @@ import { NxJsonConfiguration } from '@nrwl/devkit'; * @returns {NxJsonConfiguration} */ export function normalizeNxJson( - nxJson: NxJsonConfiguration + nxJson: NxJsonConfiguration, + projects: string[] ): NxJsonConfiguration { return nxJson.implicitDependencies ? { @@ -15,7 +16,7 @@ export function normalizeNxJson( implicitDependencies: Object.entries( nxJson.implicitDependencies ).reduce((acc, [key, val]) => { - acc[key] = recur(nxJson, val); + acc[key] = recur(projects, val); return acc; }, {}), } @@ -28,17 +29,14 @@ export function normalizeNxJson( * @param {'*' | string[] | {}} v * @returns {string[] | {}} */ -function recur( - nxJson: NxJsonConfiguration, - v: '*' | string[] | {} -): string[] | {} { +function recur(projects: string[], v: '*' | string[] | {}): string[] | {} { if (v === '*') { - return Object.keys(nxJson.projects); + return projects; } else if (Array.isArray(v)) { return v; } else { return Object.keys(v).reduce((acc, key) => { - acc[key] = recur(nxJson, v[key]); + acc[key] = recur(projects, v[key]); return acc; }, {}); } diff --git a/packages/workspace/src/core/nx-deps/nx-deps-cache.spec.ts b/packages/workspace/src/core/nx-deps/nx-deps-cache.spec.ts index 65ed671e13..f86fe6a97a 100644 --- a/packages/workspace/src/core/nx-deps/nx-deps-cache.spec.ts +++ b/packages/workspace/src/core/nx-deps/nx-deps-cache.spec.ts @@ -304,7 +304,6 @@ describe('nx deps utils', () => { function createNxJson(p: Partial): NxJsonConfiguration { const defaults: NxJsonConfiguration = { npmScope: '', - projects: { mylib: {} }, workspaceLayout: {} as any, targetDependencies: {}, plugins: ['plugin'], diff --git a/packages/workspace/src/core/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts b/packages/workspace/src/core/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts index c35ac52969..0bc2b2e463 100644 --- a/packages/workspace/src/core/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts +++ b/packages/workspace/src/core/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts @@ -36,9 +36,6 @@ describe('explicit package json dependencies', () => { const nxJson = { npmScope: 'proj', - projects: { - proj1: {}, - }, }; fsJson = { diff --git a/packages/workspace/src/core/project-graph/build-dependencies/explicit-project-dependencies.spec.ts b/packages/workspace/src/core/project-graph/build-dependencies/explicit-project-dependencies.spec.ts index 2dd5265c33..bb5f43e760 100644 --- a/packages/workspace/src/core/project-graph/build-dependencies/explicit-project-dependencies.spec.ts +++ b/packages/workspace/src/core/project-graph/build-dependencies/explicit-project-dependencies.spec.ts @@ -42,9 +42,6 @@ describe('explicit project dependencies', () => { }; const nxJson = { npmScope: 'proj', - projects: { - proj1: {}, - }, }; const tsConfig = { compilerOptions: { diff --git a/packages/workspace/src/core/project-graph/build-project-graph.spec.ts b/packages/workspace/src/core/project-graph/build-project-graph.spec.ts index 7b570abde6..eafe115b8c 100644 --- a/packages/workspace/src/core/project-graph/build-project-graph.spec.ts +++ b/packages/workspace/src/core/project-graph/build-project-graph.spec.ts @@ -9,12 +9,13 @@ import { NxJsonConfiguration, stripIndents, DependencyType, + WorkspaceJsonConfiguration, } from '@nrwl/devkit'; import { defaultFileHasher } from '../hasher/file-hasher'; describe('project graph', () => { let packageJson: any; - let workspaceJson: any; + let workspaceJson: WorkspaceJsonConfiguration; let nxJson: NxJsonConfiguration; let tsConfigJson: any; let filesJson: any; @@ -31,41 +32,50 @@ describe('project graph', () => { }, }; workspaceJson = { + version: 2, projects: { demo: { root: 'apps/demo/', sourceRoot: 'apps/demo/src', projectType: 'application', + implicitDependencies: ['api'], + targets: {}, }, 'demo-e2e': { root: 'apps/demo-e2e/', sourceRoot: 'apps/demo-e2e/src', projectType: 'application', + targets: {}, }, ui: { root: 'libs/ui/', sourceRoot: 'libs/ui/src', projectType: 'library', + targets: {}, }, 'shared-util': { root: 'libs/shared/util/', sourceRoot: 'libs/shared/util/src', projectType: 'library', + targets: {}, }, 'shared-util-data': { root: 'libs/shared/util/data', sourceRoot: 'libs/shared/util/data/src', projectType: 'library', + targets: {}, }, 'lazy-lib': { root: 'libs/lazy-lib', sourceRoot: 'libs/lazy-lib', projectType: 'library', + targets: {}, }, api: { root: 'apps/api/', sourceRoot: 'apps/api/src', projectType: 'application', + targets: {}, }, }, }; @@ -78,15 +88,6 @@ describe('project graph', () => { }, }, }, - projects: { - api: { tags: [] }, - demo: { tags: [], implicitDependencies: ['api'] }, - 'demo-e2e': { tags: [] }, - ui: { tags: [] }, - 'shared-util': { tags: [] }, - 'shared-util-data': { tags: [] }, - 'lazy-lib': { tags: [] }, - }, }; tsConfigJson = { compilerOptions: { diff --git a/packages/workspace/src/core/project-graph/build-project-graph.ts b/packages/workspace/src/core/project-graph/build-project-graph.ts index 0901e57e71..c5d30505ea 100644 --- a/packages/workspace/src/core/project-graph/build-project-graph.ts +++ b/packages/workspace/src/core/project-graph/build-project-graph.ts @@ -73,7 +73,10 @@ export async function buildProjectGraphUsingProjectFileMap( }> { const nxJson = readNxJson(); assertWorkspaceValidity(workspaceJson, nxJson); - const normalizedNxJson = normalizeNxJson(nxJson); + const normalizedNxJson = normalizeNxJson( + nxJson, + Object.keys(workspaceJson.projects) + ); const packageJsonDeps = readCombinedDeps(); const rootTsConfig = readRootTsConfig(); @@ -315,7 +318,6 @@ function createContext( > = Object.keys(workspaceJson.projects).reduce((map, projectName) => { map[projectName] = { ...workspaceJson.projects[projectName], - ...nxJson.projects[projectName], }; return map; }, {}); diff --git a/packages/workspace/src/core/target-project-locator.spec.ts b/packages/workspace/src/core/target-project-locator.spec.ts index d98b16e9ad..a307faf288 100644 --- a/packages/workspace/src/core/target-project-locator.spec.ts +++ b/packages/workspace/src/core/target-project-locator.spec.ts @@ -23,9 +23,6 @@ describe('findTargetProjectWithImport', () => { }; const nxJson = { npmScope: 'proj', - projects: { - proj1: {}, - }, }; const tsConfig = { compilerOptions: { diff --git a/packages/workspace/src/executors/tsc/tsc.impl.spec.ts b/packages/workspace/src/executors/tsc/tsc.impl.spec.ts index 0b97a43d1d..6dd7acd14e 100644 --- a/packages/workspace/src/executors/tsc/tsc.impl.spec.ts +++ b/packages/workspace/src/executors/tsc/tsc.impl.spec.ts @@ -53,6 +53,7 @@ describe('executor: tsc', () => { targets: {}, }, }, + npmScope: 'test', }, isVerbose: false, }; diff --git a/packages/workspace/src/generators/convert-to-nx-project/convert-to-nx-project.spec.ts b/packages/workspace/src/generators/convert-to-nx-project/convert-to-nx-project.spec.ts index 1c9b5d7d6c..d7f280a262 100644 --- a/packages/workspace/src/generators/convert-to-nx-project/convert-to-nx-project.spec.ts +++ b/packages/workspace/src/generators/convert-to-nx-project/convert-to-nx-project.spec.ts @@ -1,5 +1,5 @@ import { - NxJsonProjectConfiguration, + ProjectConfiguration, readJson, readProjectConfiguration, } from '@nrwl/devkit'; @@ -115,7 +115,7 @@ describe('convert-to-nx-project', () => { } }); - it('should extract tags from nx.json into project.json', async () => { + it('should include tags in project.json', async () => { const tree = createTreeWithEmptyWorkspace(2); await libraryGenerator(tree, { @@ -128,7 +128,7 @@ describe('convert-to-nx-project', () => { await convertToNxProject(tree, { all: true }); - const newConfigFile = await readJson( + const newConfigFile = await readJson( tree, getProjectConfigurationPath(config) ); diff --git a/packages/workspace/src/generators/convert-to-nx-project/convert-to-nx-project.ts b/packages/workspace/src/generators/convert-to-nx-project/convert-to-nx-project.ts index fe3db175fd..39400c8c55 100644 --- a/packages/workspace/src/generators/convert-to-nx-project/convert-to-nx-project.ts +++ b/packages/workspace/src/generators/convert-to-nx-project/convert-to-nx-project.ts @@ -8,8 +8,6 @@ import { getWorkspacePath, logger, normalizePath, - NxJsonConfiguration, - NxJsonProjectConfiguration, ProjectConfiguration, readProjectConfiguration, readWorkspaceConfiguration, @@ -60,7 +58,7 @@ To upgrade change the version number at the top of ${getWorkspacePath( ? getProjects(host).entries() : ([[schema.project, readProjectConfiguration(host, schema.project)]] as [ string, - ProjectConfiguration & NxJsonProjectConfiguration + ProjectConfiguration ][]); for (const [project, configuration] of projects) { @@ -76,11 +74,6 @@ To upgrade change the version number at the top of ${getWorkspacePath( value.projects[project] = normalizePath(dirname(configPath)); return value; }); - - updateJson(host, 'nx.json', (value: NxJsonConfiguration) => { - delete value.projects[project]; - return value; - }); } await formatFiles(host); diff --git a/packages/workspace/src/generators/init/__snapshots__/init.spec.ts.snap b/packages/workspace/src/generators/init/__snapshots__/init.spec.ts.snap index 95e9d91849..a98dbe5dfd 100644 --- a/packages/workspace/src/generators/init/__snapshots__/init.spec.ts.snap +++ b/packages/workspace/src/generators/init/__snapshots__/init.spec.ts.snap @@ -5,6 +5,10 @@ Object { "affected": Object { "defaultBase": "main", }, + "cli": Object { + "defaultCollection": "@nrwl/angular", + }, + "defaultProject": "myApp", "implicitDependencies": Object { ".eslintrc.json": "*", "angular.json": "*", @@ -14,17 +18,6 @@ Object { "tslint.json": "*", }, "npmScope": "my-app", - "projects": Object { - "myApp": Object { - "tags": Array [], - }, - "myApp-e2e": Object { - "implicitDependencies": Array [ - "myApp", - ], - "tags": Array [], - }, - }, } `; diff --git a/packages/workspace/src/generators/init/init.spec.ts b/packages/workspace/src/generators/init/init.spec.ts index a059a88a98..69fbe58b4e 100644 --- a/packages/workspace/src/generators/init/init.spec.ts +++ b/packages/workspace/src/generators/init/init.spec.ts @@ -1,5 +1,6 @@ import { readJson, Tree } from '@nrwl/devkit'; import { createTree } from '@nrwl/devkit/testing'; + import { initGenerator } from './init'; describe('workspace', () => { @@ -138,7 +139,7 @@ describe('workspace', () => { it('should set the default collection to @nrwl/angular', async () => { await initGenerator(tree, { name: 'myApp' }); - expect(readJson(tree, 'angular.json').cli.defaultCollection).toBe( + expect(readJson(tree, 'nx.json').cli.defaultCollection).toBe( '@nrwl/angular' ); }); @@ -350,7 +351,6 @@ describe('workspace', () => { }); const nxJson = readJson(tree, '/nx.json'); - expect(nxJson.projects).toEqual({ myproj: { tags: [] } }); expect(nxJson.npmScope).toEqual('myproj'); }); diff --git a/packages/workspace/src/generators/init/init.ts b/packages/workspace/src/generators/init/init.ts index edde6d1214..465e6a0245 100755 --- a/packages/workspace/src/generators/init/init.ts +++ b/packages/workspace/src/generators/init/init.ts @@ -10,6 +10,7 @@ import { joinPathFragments, names, normalizePath, + NxJsonConfiguration, offsetFromRoot, readJson, readProjectConfiguration, @@ -421,30 +422,20 @@ function moveExistingFiles(host: Tree, options: Schema) { } async function createAdditionalFiles(host: Tree, options: Schema) { - host.write( - 'nx.json', - serializeJson({ - npmScope: options.npmScope, - affected: { - defaultBase: `${options.defaultBase}` || deduceDefaultBase(), - }, - implicitDependencies: { - 'angular.json': '*', - 'package.json': '*', - 'tslint.json': '*', - '.eslintrc.json': '*', - 'nx.json': '*', - }, - projects: { - [options.name]: { - tags: [], - }, - [`${getE2eKey(host)}-e2e`]: { - tags: [], - }, - }, - }) - ); + const nxJson: NxJsonConfiguration = { + npmScope: options.npmScope, + affected: { + defaultBase: `${options.defaultBase}` || deduceDefaultBase(), + }, + implicitDependencies: { + 'angular.json': '*', + 'package.json': '*', + 'tslint.json': '*', + '.eslintrc.json': '*', + 'nx.json': '*', + }, + }; + host.write('nx.json', serializeJson(nxJson)); host.write('libs/.gitkeep', ''); const recommendations = [ @@ -542,7 +533,7 @@ function createNxJson(host: Tree) { const tsConfigPath = getRootTsConfigPath(host); host.write( 'nx.json', - serializeJson({ + serializeJson({ npmScope: name, implicitDependencies: { 'angular.json': '*', @@ -552,11 +543,6 @@ function createNxJson(host: Tree) { '.eslintrc.json': '*', 'nx.json': '*', }, - projects: { - [name]: { - tags: [], - }, - }, tasksRunnerOptions: { default: { runner: '@nrwl/workspace/tasks-runners/default', diff --git a/packages/workspace/src/generators/library/library.spec.ts b/packages/workspace/src/generators/library/library.spec.ts index 246593de60..1affa974c2 100644 --- a/packages/workspace/src/generators/library/library.spec.ts +++ b/packages/workspace/src/generators/library/library.spec.ts @@ -1,4 +1,4 @@ -import { readJson, Tree, updateJson } from '@nrwl/devkit'; +import { getProjects, readJson, Tree, updateJson } from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { NxJsonConfiguration } from '@nrwl/devkit'; @@ -36,14 +36,14 @@ describe('lib', () => { expect(workspaceJson.projects['my-lib'].architect.build).toBeUndefined(); }); - it('should update nx.json', async () => { + it('should update tags', async () => { await libraryGenerator(tree, { ...defaultOptions, name: 'myLib', tags: 'one,two', }); - const nxJson = readJson(tree, '/nx.json'); - expect(nxJson.projects).toEqual({ + const projects = Object.fromEntries(getProjects(tree)); + expect(projects).toMatchObject({ 'my-lib': { tags: ['one', 'two'], }, @@ -166,15 +166,15 @@ describe('lib', () => { }); describe('nested', () => { - it('should update nx.json', async () => { + it('should update tags', async () => { await libraryGenerator(tree, { ...defaultOptions, name: 'myLib', directory: 'myDir', tags: 'one', }); - const nxJson = readJson(tree, '/nx.json'); - expect(nxJson.projects).toEqual({ + let projects = Object.fromEntries(getProjects(tree)); + expect(projects).toMatchObject({ 'my-dir-my-lib': { tags: ['one'], }, @@ -187,8 +187,8 @@ describe('lib', () => { tags: 'one,two', simpleModuleName: true, }); - const nxJson2 = readJson(tree, '/nx.json'); - expect(nxJson2.projects).toEqual({ + projects = Object.fromEntries(getProjects(tree)); + expect(projects).toMatchObject({ 'my-dir-my-lib': { tags: ['one'], }, diff --git a/packages/workspace/src/generators/library/library.ts b/packages/workspace/src/generators/library/library.ts index 28aca78241..4727b7a523 100644 --- a/packages/workspace/src/generators/library/library.ts +++ b/packages/workspace/src/generators/library/library.ts @@ -12,7 +12,6 @@ import { GeneratorCallback, joinPathFragments, ProjectConfiguration, - NxJsonProjectConfiguration, } from '@nrwl/devkit'; import { join } from 'path'; import { runTasksInSerial } from '../../utilities/run-tasks-in-serial'; @@ -33,8 +32,7 @@ export interface NormalizedSchema extends Schema { } function addProject(tree: Tree, options: NormalizedSchema) { - const projectConfiguration: ProjectConfiguration & - NxJsonProjectConfiguration = { + const projectConfiguration: ProjectConfiguration = { root: options.projectRoot, sourceRoot: joinPathFragments(options.projectRoot, 'src'), projectType: 'library', diff --git a/packages/workspace/src/generators/move/lib/move-project-configuration.spec.ts b/packages/workspace/src/generators/move/lib/move-project-configuration.spec.ts index bdfd91fc97..84e8cd0004 100644 --- a/packages/workspace/src/generators/move/lib/move-project-configuration.spec.ts +++ b/packages/workspace/src/generators/move/lib/move-project-configuration.spec.ts @@ -1,4 +1,4 @@ -import type { Tree } from '@nrwl/devkit'; +import { getProjects, Tree } from '@nrwl/devkit'; import { addProjectConfiguration, ProjectConfiguration, @@ -181,9 +181,8 @@ describe('moveProjectConfiguration', () => { expect(similarProject.root).toBe('apps/my-source-e2e'); }); - it('should update nx.json', () => { + it('should update tags and implicitDependencies', () => { setupWorkspace(); - moveProjectConfiguration(tree, schema, projectConfig); const actualProject = readProjectConfiguration( @@ -192,7 +191,8 @@ describe('moveProjectConfiguration', () => { ); expect(actualProject.tags).toEqual(['type:ui']); expect(actualProject.implicitDependencies).toEqual(['my-other-lib']); - expect(readJson(tree, 'nx.json').projects['my-source']).not.toBeDefined(); + const projects = Object.fromEntries(getProjects(tree)); + expect(projects['my-source']).not.toBeDefined(); }); it('should support moving a standalone project', () => { diff --git a/packages/workspace/src/generators/move/lib/move-project-configuration.ts b/packages/workspace/src/generators/move/lib/move-project-configuration.ts index cbd60bae1b..69573f8b26 100644 --- a/packages/workspace/src/generators/move/lib/move-project-configuration.ts +++ b/packages/workspace/src/generators/move/lib/move-project-configuration.ts @@ -1,7 +1,6 @@ import { addProjectConfiguration, isStandaloneProject, - NxJsonProjectConfiguration, ProjectConfiguration, removeProjectConfiguration, Tree, @@ -11,7 +10,7 @@ import { NormalizedSchema } from '../schema'; export function moveProjectConfiguration( tree: Tree, schema: NormalizedSchema, - projectConfig: ProjectConfiguration & NxJsonProjectConfiguration + projectConfig: ProjectConfiguration ) { const isStandalone = isStandaloneProject(tree, schema.projectName); const projectString = JSON.stringify(projectConfig); diff --git a/packages/workspace/src/generators/move/lib/update-implicit-dependencies.ts b/packages/workspace/src/generators/move/lib/update-implicit-dependencies.ts index 408aa9eae6..a9f3603ba6 100644 --- a/packages/workspace/src/generators/move/lib/update-implicit-dependencies.ts +++ b/packages/workspace/src/generators/move/lib/update-implicit-dependencies.ts @@ -1,9 +1,9 @@ -import type { NxJsonConfiguration, Tree } from '@nrwl/devkit'; -import { updateJson } from '@nrwl/devkit'; +import type { Tree } from '@nrwl/devkit'; +import { getProjects, updateProjectConfiguration } from '@nrwl/devkit'; import type { NormalizedSchema } from '../schema'; /** - * Updates the nx.json file by renaming the project + * Updates the workspace.json file by renaming the project * * @param schema The options provided to the schematic */ @@ -11,15 +11,13 @@ export function updateImplicitDependencies( tree: Tree, schema: NormalizedSchema ) { - updateJson(tree, 'nx.json', (json) => { - Object.values(json.projects).forEach((project) => { - if (project.implicitDependencies) { - const index = project.implicitDependencies.indexOf(schema.projectName); - if (index !== -1) { - project.implicitDependencies[index] = schema.newProjectName; - } + for (const [projectName, project] of getProjects(tree)) { + if (project.implicitDependencies) { + const index = project.implicitDependencies.indexOf(schema.projectName); + if (index !== -1) { + project.implicitDependencies[index] = schema.newProjectName; + updateProjectConfiguration(tree, projectName, project); } - }); - return json; - }); + } + } } diff --git a/packages/workspace/src/generators/new/__snapshots__/new.spec.ts.snap b/packages/workspace/src/generators/new/__snapshots__/new.spec.ts.snap index e761b60aa1..5c8f69ab5e 100644 --- a/packages/workspace/src/generators/new/__snapshots__/new.spec.ts.snap +++ b/packages/workspace/src/generators/new/__snapshots__/new.spec.ts.snap @@ -77,6 +77,9 @@ Object { "affected": Object { "defaultBase": "main", }, + "cli": Object { + "defaultCollection": "@nrwl/workspace", + }, "implicitDependencies": Object { ".eslintrc.json": "*", "package.json": Object { @@ -85,7 +88,6 @@ Object { }, }, "npmScope": "npmScope", - "projects": Object {}, "targetDependencies": Object { "build": Array [ Object { @@ -112,9 +114,6 @@ Object { exports[`new should generate an empty workspace.json 1`] = ` Object { - "cli": Object { - "defaultCollection": "@nrwl/workspace", - }, "projects": Object {}, "version": 2, } diff --git a/packages/workspace/src/generators/new/new.spec.ts b/packages/workspace/src/generators/new/new.spec.ts index 83bafb7cfe..7364b07e95 100644 --- a/packages/workspace/src/generators/new/new.spec.ts +++ b/packages/workspace/src/generators/new/new.spec.ts @@ -66,7 +66,7 @@ describe('new', () => { describe.each([['npm'], ['yarn'], ['pnpm']])( '%s', (packageManager: PackageManager) => { - it('should set the packageManager in workspace.json', async () => { + it('should set the packageManager in nx.json', async () => { await newGenerator(tree, { ...defaultOptions, name: 'my-workspace', @@ -77,8 +77,8 @@ describe('new', () => { packageManager, }); - const workspaceJson = readJson(tree, 'my-workspace/angular.json'); - expect(workspaceJson.cli.packageManager).toEqual(packageManager); + const nxJson = readJson(tree, 'my-workspace/nx.json'); + expect(nxJson.cli.packageManager).toEqual(packageManager); }); } ); diff --git a/packages/workspace/src/generators/new/new.ts b/packages/workspace/src/generators/new/new.ts index 77441093fc..6b05c4a362 100644 --- a/packages/workspace/src/generators/new/new.ts +++ b/packages/workspace/src/generators/new/new.ts @@ -10,6 +10,7 @@ import { getPackageManagerCommand, WorkspaceJsonConfiguration, PackageManager, + NxJsonConfiguration, } from '@nrwl/devkit'; import { join } from 'path'; @@ -180,9 +181,6 @@ export async function newGenerator(host: Tree, options: Schema) { await workspaceGenerator(host, { ...options, nxCloud: undefined } as any); - if (options.cli === 'angular') { - setDefaultPackageManager(host, options); - } setDefaultLinter(host, options); addPresetDependencies(host, options); addCloudDependencies(host, options); @@ -351,24 +349,6 @@ function getWorkspacePath(host: Tree, { directory, cli }: Schema) { return join(directory, cli === 'angular' ? 'angular.json' : 'workspace.json'); } -function setDefaultPackageManager(host: Tree, options: Schema) { - if (!options.packageManager) { - return; - } - - updateJson( - host, - getWorkspacePath(host, options), - (json) => { - if (!json.cli) { - json.cli = {}; - } - json.cli.packageManager = options.packageManager; - return json; - } - ); -} - function setDefault( json: any, collectionName: string, diff --git a/packages/workspace/src/generators/preset/preset.spec.ts b/packages/workspace/src/generators/preset/preset.spec.ts index b67d754b2f..15b8c61587 100644 --- a/packages/workspace/src/generators/preset/preset.spec.ts +++ b/packages/workspace/src/generators/preset/preset.spec.ts @@ -1,4 +1,4 @@ -import { readJson, Tree } from '@nrwl/devkit'; +import { Tree, readJson, NxJsonConfiguration } from '@nrwl/devkit'; import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { overrideCollectionResolutionForTesting } from '@nrwl/devkit/ngcli-adapter'; import { presetGenerator } from './preset'; @@ -55,7 +55,7 @@ describe('preset', () => { expect(tree.children('apps/proj/src/app')).toMatchSnapshot(); expect( - JSON.parse(tree.read('/workspace.json').toString()).cli.defaultCollection + readJson(tree, 'nx.json').cli.defaultCollection ).toBe('@nrwl/angular'); }); @@ -67,9 +67,9 @@ describe('preset', () => { standaloneConfig: false, }); expect(tree.exists('/apps/proj/src/main.ts')).toBe(true); - expect(readJson(tree, '/workspace.json').cli.defaultCollection).toBe( - '@nrwl/web' - ); + expect( + readJson(tree, 'nx.json').cli.defaultCollection + ).toBe('@nrwl/web'); }); it(`should create files (preset = ${Preset.React})`, async () => { @@ -82,9 +82,9 @@ describe('preset', () => { standaloneConfig: false, }); expect(tree.exists('/apps/proj/src/main.tsx')).toBe(true); - expect(readJson(tree, '/workspace.json').cli.defaultCollection).toBe( - '@nrwl/react' - ); + expect( + readJson(tree, 'nx.json').cli.defaultCollection + ).toBe('@nrwl/react'); }); it(`should create files (preset = ${Preset.NextJs})`, async () => { @@ -97,9 +97,9 @@ describe('preset', () => { standaloneConfig: false, }); expect(tree.exists('/apps/proj/pages/index.tsx')).toBe(true); - expect(readJson(tree, '/workspace.json').cli.defaultCollection).toBe( - '@nrwl/next' - ); + expect( + readJson(tree, 'nx.json').cli.defaultCollection + ).toBe('@nrwl/next'); }); it(`should create files (preset = ${Preset.AngularWithNest})`, async () => { @@ -162,9 +162,9 @@ describe('preset', () => { }); expect(tree.exists('/apps/proj/src/pages/index.tsx')).toBe(true); - expect(readJson(tree, '/workspace.json').cli.defaultCollection).toBe( - '@nrwl/gatsby' - ); + expect( + readJson(tree, 'nx.json').cli.defaultCollection + ).toBe('@nrwl/gatsby'); }); it('should create files (preset = react-native)', async () => { @@ -177,8 +177,8 @@ describe('preset', () => { }); expect(tree.exists('/apps/proj/src/app/App.tsx')).toBe(true); - expect(readJson(tree, '/workspace.json').cli.defaultCollection).toBe( - '@nrwl/react-native' - ); + expect( + readJson(tree, 'nx.json').cli.defaultCollection + ).toBe('@nrwl/react-native'); }); }); diff --git a/packages/workspace/src/generators/workspace/files/__workspaceFile__.json b/packages/workspace/src/generators/workspace/files/__workspaceFile__.json__tmpl__ similarity index 60% rename from packages/workspace/src/generators/workspace/files/__workspaceFile__.json rename to packages/workspace/src/generators/workspace/files/__workspaceFile__.json__tmpl__ index 566bd7faec..64ca5a2862 100644 --- a/packages/workspace/src/generators/workspace/files/__workspaceFile__.json +++ b/packages/workspace/src/generators/workspace/files/__workspaceFile__.json__tmpl__ @@ -5,8 +5,5 @@ <% if(cli === 'nx') { %> "version": 2, <% } %> - "projects": {}, - "cli": { - "defaultCollection": "@nrwl/workspace" - } + "projects": {} } diff --git a/packages/workspace/src/generators/workspace/files/nx.json__tmpl__ b/packages/workspace/src/generators/workspace/files/nx.json__tmpl__ index d5bcfc0e7f..6f6a8bab90 100644 --- a/packages/workspace/src/generators/workspace/files/nx.json__tmpl__ +++ b/packages/workspace/src/generators/workspace/files/nx.json__tmpl__ @@ -3,6 +3,10 @@ "affected": { "defaultBase": "<%= defaultBase %>" }, + "cli": { + "defaultCollection": "@nrwl/workspace"<% if (packageManager && cli === 'angular') { %>, + "packageManager": "<%=packageManager%>" <% } %> + }, "implicitDependencies": { "package.json": { "dependencies": "*", @@ -30,6 +34,5 @@ "projects": "dependencies" } ] - }, - "projects": {} + } } \ No newline at end of file diff --git a/packages/workspace/src/generators/workspace/schema.d.ts b/packages/workspace/src/generators/workspace/schema.d.ts index 01ff0a9012..10398c15a7 100644 --- a/packages/workspace/src/generators/workspace/schema.d.ts +++ b/packages/workspace/src/generators/workspace/schema.d.ts @@ -9,4 +9,5 @@ export interface Schema { cli: 'nx' | 'angular'; preset: string; defaultBase: string; + packageManager?: string; } diff --git a/packages/workspace/src/generators/workspace/schema.json b/packages/workspace/src/generators/workspace/schema.json index f31c96f435..25a2c4624d 100644 --- a/packages/workspace/src/generators/workspace/schema.json +++ b/packages/workspace/src/generators/workspace/schema.json @@ -90,6 +90,11 @@ ], "default": true }, + "packageManager": { + "description": "The package manager used to install dependencies.", + "type": "string", + "enum": ["npm", "yarn", "pnpm"] + }, "cli": { "description": "CLI used for generating code and running tasks", "type": "string", diff --git a/packages/workspace/src/generators/workspace/workspace.spec.ts b/packages/workspace/src/generators/workspace/workspace.spec.ts index 1f57b335a5..ec5692a950 100644 --- a/packages/workspace/src/generators/workspace/workspace.spec.ts +++ b/packages/workspace/src/generators/workspace/workspace.spec.ts @@ -39,6 +39,9 @@ describe('@nrwl/workspace:workspace', () => { affected: { defaultBase: 'main', }, + cli: { + defaultCollection: '@nrwl/workspace', + }, implicitDependencies: { 'package.json': { dependencies: '*', @@ -62,7 +65,6 @@ describe('@nrwl/workspace:workspace', () => { }, ], }, - projects: {}, }); }); diff --git a/packages/workspace/src/generators/workspace/workspace.ts b/packages/workspace/src/generators/workspace/workspace.ts index 7c567d74b7..4b91494592 100644 --- a/packages/workspace/src/generators/workspace/workspace.ts +++ b/packages/workspace/src/generators/workspace/workspace.ts @@ -73,6 +73,7 @@ function createFiles(host: Tree, options: Schema) { ...(options as object), nxVersion, npmScope, + packageManager: options.packageManager, }); } diff --git a/packages/workspace/src/migrations/update-13-0-0/config-locations/config-locations.spec.ts b/packages/workspace/src/migrations/update-13-0-0/config-locations/config-locations.spec.ts new file mode 100644 index 0000000000..0e8b2a7696 --- /dev/null +++ b/packages/workspace/src/migrations/update-13-0-0/config-locations/config-locations.spec.ts @@ -0,0 +1,50 @@ +import { + Tree, + writeJson, + updateJson, + readWorkspaceConfiguration, + readJson, +} from '@nrwl/devkit'; +import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; +import update from './config-locations'; + +describe('update to v13 config locations', () => { + let tree: Tree; + + beforeEach(async () => { + tree = createTreeWithEmptyWorkspace(2); + updateJson(tree, 'workspace.json', (json) => ({ + ...json, + cli: { + defaultCollection: '@nrwl/workspace', + packageManager: 'npm', + }, + generators: {}, + defaultProject: 'a', + projects: { + a: {}, + }, + })); + writeJson(tree, 'nx.json', { + npmScope: 'test', + projects: { + a: { + tags: ['test'], + }, + }, + }); + }); + + it('should move properties to correct place', async () => { + await update(tree); + const workspaceJson = readJson(tree, 'workspace.json'); + const nxJson = readJson(tree, 'nx.json'); + expect(nxJson.projects).not.toBeDefined(); + expect(nxJson.cli?.defaultCollection).toEqual('@nrwl/workspace'); + expect(nxJson.cli?.packageManager).toEqual('npm'); + expect(nxJson.generators).toEqual({}); + expect(workspaceJson.projects.a.tags).toEqual(['test']); + expect(workspaceJson.cli).not.toBeDefined(); + expect(workspaceJson.defaultProject).not.toBeDefined(); + }); +}); diff --git a/packages/workspace/src/migrations/update-13-0-0/config-locations/config-locations.ts b/packages/workspace/src/migrations/update-13-0-0/config-locations/config-locations.ts new file mode 100644 index 0000000000..830cfc2012 --- /dev/null +++ b/packages/workspace/src/migrations/update-13-0-0/config-locations/config-locations.ts @@ -0,0 +1,31 @@ +import { + NxJsonConfiguration, + ProjectConfiguration, + readJson, + writeJson, + readProjectConfiguration, + Tree, + updateProjectConfiguration, + formatFiles, +} from '@nrwl/devkit'; + +export default async function update(host: Tree) { + const nxJson = readJson(host, 'nx.json') as NxJsonConfiguration & { + projects: Record< + string, + Pick + >; + }; + // updateProjectConfiguration automatically saves the project opts into workspace/project.json + Object.entries(nxJson.projects).forEach(([p, nxJsonConfig]) => { + const configuration = readProjectConfiguration(host, p); + configuration.tags ??= nxJsonConfig.tags; + configuration.implicitDependencies ??= nxJsonConfig.implicitDependencies; + updateProjectConfiguration(host, p, configuration); + }); + + delete nxJson.projects; + + writeJson(host, 'nx.json', nxJson); + await formatFiles(host); // format files handles moving config options to new spots. +} diff --git a/packages/workspace/src/migrations/update-8-12-0/add-implicit-e2e-deps.spec.ts b/packages/workspace/src/migrations/update-8-12-0/add-implicit-e2e-deps.spec.ts index cf55d43c9f..c5e54046d0 100644 --- a/packages/workspace/src/migrations/update-8-12-0/add-implicit-e2e-deps.spec.ts +++ b/packages/workspace/src/migrations/update-8-12-0/add-implicit-e2e-deps.spec.ts @@ -11,7 +11,7 @@ describe('Update 8.12.0', () => { tree = Tree.empty(); tree = createEmptyWorkspace(tree); tree = await callRule( - updateJsonInTree('nx.json', (json) => { + updateJsonInTree('workspace.json', (json) => { json.projects['my-app'] = { tags: [], }; @@ -30,21 +30,22 @@ describe('Update 8.12.0', () => { it('should add implicit dependencies for e2e projects', async () => { const result = await runMigration('add-implicit-e2e-deps', {}, tree); - const nxJson = readJsonInTree(result, 'nx.json'); + const workspaceJson = readJsonInTree(result, 'workspace.json'); + console.log(workspaceJson); - expect(nxJson.projects['my-app-e2e']).toEqual({ + expect(workspaceJson.projects['my-app-e2e']).toEqual({ tags: [], implicitDependencies: ['my-app'], }); - expect(nxJson.projects['my-non-existent-app-e2e']).toEqual({ + expect(workspaceJson.projects['my-non-existent-app-e2e']).toEqual({ tags: [], }); }); it('should not add duplicate implicit dependencies for e2e projects', async () => { tree = await callRule( - updateJsonInTree('nx.json', (json) => { + updateJsonInTree('workspace.json', (json) => { json.projects['my-app-e2e'].implicitDependencies = ['my-app']; return json; }), @@ -52,14 +53,14 @@ describe('Update 8.12.0', () => { ); const result = await runMigration('add-implicit-e2e-deps', {}, tree); - const nxJson = readJsonInTree(result, 'nx.json'); + const workspaceJson = readJsonInTree(result, 'workspace.json'); - expect(nxJson.projects['my-app-e2e']).toEqual({ + expect(workspaceJson.projects['my-app-e2e']).toMatchObject({ tags: [], implicitDependencies: ['my-app'], }); - expect(nxJson.projects['my-non-existent-app-e2e']).toEqual({ + expect(workspaceJson.projects['my-non-existent-app-e2e']).toMatchObject({ tags: [], }); }); diff --git a/packages/workspace/src/migrations/update-8-12-0/add-implicit-e2e-deps.ts b/packages/workspace/src/migrations/update-8-12-0/add-implicit-e2e-deps.ts index 61500cc86d..ff0422c9ad 100644 --- a/packages/workspace/src/migrations/update-8-12-0/add-implicit-e2e-deps.ts +++ b/packages/workspace/src/migrations/update-8-12-0/add-implicit-e2e-deps.ts @@ -7,27 +7,29 @@ import { import { stripIndents } from '@angular-devkit/core/src/utils/literals'; import { updateJsonInTree } from '../../utils/ast-utils'; -import type { NxJsonConfiguration } from '@nrwl/devkit'; +import type { WorkspaceJsonConfiguration } from '@nrwl/devkit'; import { formatFiles } from '@nrwl/workspace/src/utils/rules/format-files'; +import { workspaceConfigName } from '@nrwl/tao/src/shared/workspace'; -const addE2eImplicitDependencies = updateJsonInTree( - 'nx.json', - (json) => { - Object.keys(json.projects).forEach((proj) => { - const implicitE2eName = proj.replace(/-e2e$/, ''); - if (proj.endsWith('-e2e') && json.projects[implicitE2eName]) { - json.projects[proj].implicitDependencies = - json.projects[proj].implicitDependencies || []; - if ( - !json.projects[proj].implicitDependencies.includes(implicitE2eName) - ) { - json.projects[proj].implicitDependencies.push(implicitE2eName); +const addE2eImplicitDependencies: Rule = (tree: Tree) => + updateJsonInTree( + workspaceConfigName(tree.root.path), + (json) => { + Object.keys(json.projects).forEach((proj) => { + const implicitE2eName = proj.replace(/-e2e$/, ''); + if (proj.endsWith('-e2e') && json.projects[implicitE2eName]) { + json.projects[proj].implicitDependencies = + json.projects[proj].implicitDependencies || []; + if ( + !json.projects[proj].implicitDependencies.includes(implicitE2eName) + ) { + json.projects[proj].implicitDependencies.push(implicitE2eName); + } } - } - }); - return json; - } -); + }); + return json; + } + ); function showInfo(host: Tree, context: SchematicContext) { context.logger.info(stripIndents` diff --git a/packages/workspace/src/migrations/update-8-12-0/update-enforce-boundary-lint-rule.spec.ts b/packages/workspace/src/migrations/update-8-12-0/update-enforce-boundary-lint-rule.spec.ts index 50bc352476..8f09e5a7b5 100644 --- a/packages/workspace/src/migrations/update-8-12-0/update-enforce-boundary-lint-rule.spec.ts +++ b/packages/workspace/src/migrations/update-8-12-0/update-enforce-boundary-lint-rule.spec.ts @@ -31,7 +31,7 @@ describe('Add update-enforce-boundary-lint rule', () => { ); tree.create( '/nx.json', - JSON.stringify({ npmScope: 'proj', projects: {} }) + JSON.stringify({ npmScope: 'proj' }) ); tree.create( '/tsconfig.json', diff --git a/packages/workspace/src/tasks-runner/run-command.spec.ts b/packages/workspace/src/tasks-runner/run-command.spec.ts index 9c4e23f8f4..fbd271b61a 100644 --- a/packages/workspace/src/tasks-runner/run-command.spec.ts +++ b/packages/workspace/src/tasks-runner/run-command.spec.ts @@ -758,7 +758,6 @@ describe('getRunner', () => { beforeEach(() => { nxJson = { npmScope: 'proj', - projects: {}, }; mockRunner = jest.fn(); }); diff --git a/packages/workspace/src/tasks-runner/tasks-schedule.spec.ts b/packages/workspace/src/tasks-runner/tasks-schedule.spec.ts index a9656e53b0..95830657e0 100644 --- a/packages/workspace/src/tasks-runner/tasks-schedule.spec.ts +++ b/packages/workspace/src/tasks-runner/tasks-schedule.spec.ts @@ -51,6 +51,7 @@ describe('TasksSchedule', () => { readWorkspaceConfiguration() { return { version: 2, + npmScope: '', projects: { app1: { root: 'app1', diff --git a/packages/workspace/src/utilities/cache-directory.ts b/packages/workspace/src/utilities/cache-directory.ts index fb7438aec9..d092116ead 100644 --- a/packages/workspace/src/utilities/cache-directory.ts +++ b/packages/workspace/src/utilities/cache-directory.ts @@ -1,9 +1,10 @@ +import { NxJsonConfiguration } from '@nrwl/devkit'; import { join } from 'path'; import { readJsonFile } from './fileutils'; export function readCacheDirectoryProperty(root: string) { try { - const nxJson = readJsonFile(join(root, 'nx.json')); + const nxJson = readJsonFile(join(root, 'nx.json')); return nxJson.tasksRunnerOptions.default.options.cacheDirectory; } catch (e) { return undefined; diff --git a/packages/workspace/src/utilities/set-default-collection.ts b/packages/workspace/src/utilities/set-default-collection.ts index f97e9fa66e..0f18c54ee7 100644 --- a/packages/workspace/src/utilities/set-default-collection.ts +++ b/packages/workspace/src/utilities/set-default-collection.ts @@ -1,7 +1,7 @@ import { + Tree, readWorkspaceConfiguration, updateWorkspaceConfiguration, - Tree, } from '@nrwl/devkit'; /** diff --git a/packages/workspace/src/utils/ast-utils.ts b/packages/workspace/src/utils/ast-utils.ts index 1882512585..8a666572b7 100644 --- a/packages/workspace/src/utils/ast-utils.ts +++ b/packages/workspace/src/utils/ast-utils.ts @@ -18,14 +18,14 @@ import { Tree, } from '@angular-devkit/schematics'; import * as ts from 'typescript'; -import { parseJson, serializeJson } from '@nrwl/devkit'; +import { parseJson, ProjectConfiguration, serializeJson } from '@nrwl/devkit'; import { getWorkspacePath } from './cli-config-utils'; import { FileData } from '../core/file-utils'; import { extname, join, normalize, Path } from '@angular-devkit/core'; import type { NxJsonConfiguration, - NxJsonProjectConfiguration, ProjectGraph, + WorkspaceJsonConfiguration, } from '@nrwl/devkit'; import { addInstallTask } from './rules/add-install-task'; import { findNodes } from '../utilities/typescript/find-nodes'; @@ -458,15 +458,21 @@ export function updateNxJsonInTree( }; } +/** + * Sets former nx.json options on projects which are already in workspace.json + * @deprecated(v14) project options are no longer stored in nx.json, this should not be used. + */ export function addProjectToNxJsonInTree( projectName: string, - options: NxJsonProjectConfiguration + options: Pick ): Rule { - const defaultOptions = { - tags: [], - }; - return updateNxJsonInTree((json) => { - json.projects[projectName] = { ...defaultOptions, ...options }; + return updateWorkspaceInTree((json: WorkspaceJsonConfiguration) => { + const project = + json.projects[projectName] ?? ({} as Partial); + project.tags = options.tags ?? project.tags ?? []; + project.implicitDependencies = + options.implicitDependencies ?? project.implicitDependencies; + json.projects[projectName] = project as ProjectConfiguration; return json; }); } diff --git a/packages/workspace/src/utils/rules/workspace.spec.ts b/packages/workspace/src/utils/rules/workspace.spec.ts index 66b3547554..c27fcf072e 100644 --- a/packages/workspace/src/utils/rules/workspace.spec.ts +++ b/packages/workspace/src/utils/rules/workspace.spec.ts @@ -8,6 +8,14 @@ import { WorkspaceFormat, } from '@angular-devkit/core/src/workspace/core'; +/** + * This test suite is ran with utils from @angular-devkit. + * The rules are being tested as though they were used + * in a non-nx angular workspace. This means changes from + * ngcli-adapter or wrapAngularDevkitSchematic are not applied + * to the rules during the unit tests, as they would not be applied + * when being ran in a non-nx workspace. + */ describe('Workspace', () => { const defaultCollectionName = '@nrwl/node'; const workspaceJsonFileName = 'workspace.json';