From e491c6f7382064fb1f17c0dcd2e642428ca822e4 Mon Sep 17 00:00:00 2001 From: Victor Savkin Date: Tue, 31 May 2022 11:01:57 -0400 Subject: [PATCH] feat(core): make nx.json optional --- dep-graph/client/project.json | 4 +- docs/generated/cli/init.md | 16 + docs/generated/devkit/index.md | 50 +- docs/generated/packages/cli.json | 6 + docs/generated/packages/devkit.json | 2 +- docs/map.json | 1 + docs/shared/nx-core.md | 1 - e2e/add-nx-to-monorepo/project.json | 2 +- .../src/add-nx-to-monorepo.test.ts | 15 + e2e/angular-core/project.json | 2 +- e2e/angular-extensions/project.json | 2 +- e2e/cli/project.json | 2 +- e2e/cypress/project.json | 2 +- e2e/detox/project.json | 2 +- e2e/jest/project.json | 2 +- e2e/js/project.json | 2 +- e2e/linter/project.json | 2 +- e2e/next/project.json | 2 +- e2e/node/project.json | 2 +- e2e/nx-init/jest.config.ts | 10 + e2e/nx-init/project.json | 34 ++ e2e/nx-init/src/nx-init.test.ts | 37 ++ e2e/nx-init/tsconfig.json | 13 + e2e/nx-init/tsconfig.spec.json | 20 + e2e/nx-plugin/project.json | 2 +- e2e/react-native/project.json | 2 +- e2e/react/project.json | 2 +- e2e/storybook/project.json | 2 +- e2e/utils/index.ts | 4 +- e2e/web/project.json | 2 +- e2e/workspace-core/project.json | 2 +- e2e/workspace-create/project.json | 2 +- e2e/workspace-integrations/project.json | 2 +- lerna.json | 2 +- nx-dev/nx-dev/project.json | 10 +- packages/add-nx-to-monorepo/project.json | 4 +- .../src/add-nx-to-monorepo.ts | 50 +- packages/angular/project.json | 2 +- .../module-federation-dev-server.impl.ts | 9 +- .../webpack-server/webpack-server.impl.ts | 11 +- .../with-module-federation.spec.ts.snap | 257 ---------- .../utils/mfe/with-module-federation.spec.ts | 475 ------------------ .../src/utils/mfe/with-module-federation.ts | 10 +- packages/cli/project.json | 2 +- packages/cra-to-nx/project.json | 4 +- packages/create-nx-plugin/project.json | 2 +- packages/create-nx-workspace/project.json | 2 +- packages/cypress/project.json | 2 +- .../cypress/src/executors/cypress/hasher.ts | 4 +- packages/detox/project.json | 2 +- packages/devkit/index.ts | 14 +- packages/devkit/project.json | 2 +- packages/eslint-plugin-nx/project.json | 2 +- .../rules/enforce-module-boundaries.spec.ts | 2 +- packages/express/project.json | 2 +- packages/jest/project.json | 2 +- .../src/utils/config/get-jest-projects.ts | 4 +- packages/js/project.json | 2 +- packages/linter/project.json | 2 +- .../linter/src/executors/eslint/hasher.ts | 4 +- packages/make-angular-cli-faster/project.json | 2 +- packages/nest/project.json | 2 +- packages/next/project.json | 2 +- packages/node/project.json | 2 +- packages/nx-plugin/project.json | 2 +- .../bin/{init.ts => compute-project-graph.ts} | 0 packages/nx/bin/nx.ts | 12 +- packages/nx/package.json | 2 +- packages/nx/presets/core.json | 21 +- packages/nx/presets/npm.json | 20 +- packages/nx/project.json | 2 +- packages/nx/src/adapter/compat.ts | 2 +- packages/nx/src/adapter/ngcli-adapter.ts | 22 +- packages/nx/src/command-line/affected.ts | 5 +- .../src/command-line/connect-to-nx-cloud.ts | 2 +- packages/nx/src/command-line/dep-graph.ts | 4 +- packages/nx/src/command-line/format.ts | 22 +- packages/nx/src/command-line/generate.ts | 2 +- packages/nx/src/command-line/init.ts | 40 ++ packages/nx/src/command-line/lint.ts | 3 +- packages/nx/src/command-line/list.ts | 2 +- packages/nx/src/command-line/nx-commands.ts | 7 +- .../nx/src/command-line/read-environment.ts | 7 +- packages/nx/src/command-line/report.spec.ts | 2 +- packages/nx/src/command-line/report.ts | 2 +- packages/nx/src/command-line/run-many.ts | 6 +- packages/nx/src/command-line/run-one.ts | 12 +- packages/nx/src/command-line/run.ts | 6 +- .../src/command-line/workspace-generators.ts | 2 +- packages/nx/src/config/configuration.ts | 24 + packages/nx/src/config/misc-interfaces.ts | 6 +- .../src/config/workspace-json-project-json.ts | 17 +- packages/nx/src/config/workspaces.ts | 59 ++- packages/nx/src/daemon/client/client.ts | 2 +- ...project-graph-incremental-recomputation.ts | 6 +- packages/nx/src/daemon/server/server.ts | 2 +- .../nx/src/daemon/server/shutdown-utils.ts | 2 +- packages/nx/src/daemon/server/watcher.ts | 2 +- .../generators/utils/project-configuration.ts | 36 +- packages/nx/src/hasher/file-hasher-base.ts | 2 +- packages/nx/src/hasher/file-hasher.ts | 2 +- .../nx/src/hasher/git-based-file-hasher.ts | 2 +- packages/nx/src/hasher/hasher.spec.ts | 2 +- packages/nx/src/hasher/hasher.ts | 8 +- .../nx/src/hasher/node-based-file-hasher.ts | 2 +- .../affected/affected-project-graph.spec.ts | 2 +- .../affected/affected-project-graph.ts | 15 +- ...explicit-package-json-dependencies.spec.ts | 2 +- .../explicit-project-dependencies.spec.ts | 2 +- .../implict-project-dependencies.spec.ts | 2 +- .../project-graph/build-nodes/npm-packages.ts | 2 +- .../build-nodes/workspace-projects.ts | 2 +- .../project-graph/build-project-graph.spec.ts | 2 +- .../src/project-graph/build-project-graph.ts | 16 +- packages/nx/src/project-graph/file-utils.ts | 51 +- .../nx/src/project-graph/nx-deps-cache.ts | 4 +- .../nx/src/project-graph/project-graph.ts | 3 +- .../nx/src/tasks-runner/batch/run-batch.ts | 9 +- packages/nx/src/tasks-runner/cache.ts | 2 +- .../forked-process-task-runner.ts | 2 +- packages/nx/src/tasks-runner/run-command.ts | 2 +- .../nx/src/tasks-runner/task-orchestrator.ts | 2 +- packages/nx/src/tasks-runner/utils.ts | 2 +- packages/nx/src/utils/app-root.ts | 37 -- packages/nx/src/utils/cache-directory.ts | 2 +- .../nx/src/utils/command-line-utils.spec.ts | 105 ++-- packages/nx/src/utils/command-line-utils.ts | 28 +- packages/nx/src/utils/find-workspace-root.ts | 17 +- packages/nx/src/utils/nx-plugin.ts | 6 +- packages/nx/src/utils/params.ts | 6 +- .../src/utils/plugins/plugin-capabilities.ts | 2 +- .../src/utils/target-project-locator.spec.ts | 2 +- .../nx/src/utils/target-project-locator.ts | 2 +- packages/nx/src/utils/typescript.ts | 2 +- packages/nx/src/utils/workspace-root.ts | 38 ++ packages/react-native/project.json | 2 +- packages/react/project.json | 2 +- .../with-module-federation.ts | 12 +- packages/storybook/migrations.json | 11 - packages/storybook/project.json | 2 +- .../update-8-8-2/update-builder-8-8-2.spec.ts | 157 ------ .../update-8-8-2/update-builder-8-8-2.ts | 66 --- .../migrations/update-9-0-0/update-9-0-0.ts | 12 - .../migrations/update-9-2-0/update-9-2-0.ts | 7 - packages/tao/project.json | 2 +- packages/tao/src/utils/app-root.ts | 2 +- packages/web/project.json | 2 +- packages/workspace/index.ts | 2 - packages/workspace/project.json | 2 +- .../nxEnforceModuleBoundariesRule.spec.ts | 2 +- packages/workspace/src/utilities/app-root.ts | 2 +- .../workspace/src/utilities/generate-globs.ts | 2 +- packages/workspace/src/utils/app-root.ts | 2 +- packages/workspace/src/utils/ast-utils.ts | 5 +- typedoc-theme/project.json | 2 +- workspace.json | 1 + 156 files changed, 711 insertions(+), 1479 deletions(-) create mode 100644 docs/generated/cli/init.md create mode 100644 e2e/nx-init/jest.config.ts create mode 100644 e2e/nx-init/project.json create mode 100644 e2e/nx-init/src/nx-init.test.ts create mode 100644 e2e/nx-init/tsconfig.json create mode 100644 e2e/nx-init/tsconfig.spec.json delete mode 100644 packages/angular/src/utils/mfe/__snapshots__/with-module-federation.spec.ts.snap delete mode 100644 packages/angular/src/utils/mfe/with-module-federation.spec.ts rename packages/nx/bin/{init.ts => compute-project-graph.ts} (100%) create mode 100644 packages/nx/src/command-line/init.ts create mode 100644 packages/nx/src/config/configuration.ts delete mode 100644 packages/nx/src/utils/app-root.ts create mode 100644 packages/nx/src/utils/workspace-root.ts delete mode 100644 packages/storybook/src/migrations/update-8-8-2/update-builder-8-8-2.spec.ts delete mode 100644 packages/storybook/src/migrations/update-8-8-2/update-builder-8-8-2.ts delete mode 100644 packages/storybook/src/migrations/update-9-0-0/update-9-0-0.ts delete mode 100644 packages/storybook/src/migrations/update-9-2-0/update-9-2-0.ts diff --git a/dep-graph/client/project.json b/dep-graph/client/project.json index aa14c2d7d201e..f9664e86f951a 100644 --- a/dep-graph/client/project.json +++ b/dep-graph/client/project.json @@ -89,7 +89,7 @@ } }, "serve": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": [], "options": { "commands": [ @@ -113,7 +113,7 @@ } }, "serve-for-e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": [], "options": { "commands": [ diff --git a/docs/generated/cli/init.md b/docs/generated/cli/init.md new file mode 100644 index 0000000000000..89af4411b3d4d --- /dev/null +++ b/docs/generated/cli/init.md @@ -0,0 +1,16 @@ +--- +title: 'init - CLI command' +description: 'Adds nx.json file and installs nx if not installed already' +--- + +# init + +Adds nx.json file and installs nx if not installed already + +## Usage + +```bash +nx init +``` + +[Install `nx` globally](/getting-started/nx-setup#install-nx) to invoke the command directly using `nx`, or use `npx nx`, `yarn nx`, or `pnpx nx`. diff --git a/docs/generated/devkit/index.md b/docs/generated/devkit/index.md index ea76551b828fa..584a32d423e01 100644 --- a/docs/generated/devkit/index.md +++ b/docs/generated/devkit/index.md @@ -76,12 +76,12 @@ It only uses language primitives and immutable objects - [NxAffectedConfig](../../devkit/index#nxaffectedconfig) - [NxJsonConfiguration](../../devkit/index#nxjsonconfiguration) - [ProjectConfiguration](../../devkit/index#projectconfiguration) +- [ProjectsConfigurations](../../devkit/index#projectsconfigurations) - [TargetConfiguration](../../devkit/index#targetconfiguration) - [TargetDependencyConfig](../../devkit/index#targetdependencyconfig) - [Task](../../devkit/index#task) - [TaskGraph](../../devkit/index#taskgraph) - [Workspace](../../devkit/index#workspace) -- [WorkspaceJsonConfiguration](../../devkit/index#workspacejsonconfiguration) ### Generators Type aliases @@ -112,6 +112,7 @@ It only uses language primitives and immutable objects - [ImplicitDependencyEntry](../../devkit/index#implicitdependencyentry) - [ProjectType](../../devkit/index#projecttype) - [TaskGraphExecutor](../../devkit/index#taskgraphexecutor) +- [WorkspaceJsonConfiguration](../../devkit/index#workspacejsonconfiguration) ### Logger Variables @@ -151,6 +152,7 @@ It only uses language primitives and immutable objects - [offsetFromRoot](../../devkit/index#offsetfromroot) - [parseJson](../../devkit/index#parsejson) - [parseTargetString](../../devkit/index#parsetargetstring) +- [readAllWorkspaceConfiguration](../../devkit/index#readallworkspaceconfiguration) - [readCachedProjectGraph](../../devkit/index#readcachedprojectgraph) - [readJson](../../devkit/index#readjson) - [readJsonFile](../../devkit/index#readjsonfile) @@ -424,6 +426,12 @@ A plugin for Nx --- +### ProjectsConfigurations + +• **ProjectsConfigurations**: `Object` + +--- + ### TargetConfiguration • **TargetConfiguration**: `Object` @@ -452,17 +460,11 @@ A plugin for Nx • **Workspace**: `Object` ---- - -### WorkspaceJsonConfiguration - -• **WorkspaceJsonConfiguration**: `Object` - ## Generators Type aliases ### WorkspaceConfiguration -Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<[`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)\> +Ƭ **WorkspaceConfiguration**: `Omit`<[`ProjectsConfigurations`](../../devkit/index#projectsconfigurations), `"projects"`\> & `Partial`<[`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)\> --- @@ -666,6 +668,12 @@ Implementation of a target of a project that handles multiple projects to be bat `Promise`<`Record`<`string`, `Object`\>\> +--- + +### WorkspaceJsonConfiguration + +Ƭ **WorkspaceJsonConfiguration**: [`ProjectsConfigurations`](../../devkit/index#projectsconfigurations) + ## Logger Variables ### logger @@ -689,7 +697,7 @@ Implementation of a target of a project that handles multiple projects to be bat ### appRootPath -• **appRootPath**: `string` +• **appRootPath**: `string` = `workspaceRoot` --- @@ -707,7 +715,7 @@ Implementation of a target of a project that handles multiple projects to be bat ### workspaceRoot -• **workspaceRoot**: `string` = `appRootPath` +• **workspaceRoot**: `string` ## Functions @@ -1357,6 +1365,16 @@ parseTargetString('proj:test:production'); // returns { project: "proj", target: --- +### readAllWorkspaceConfiguration + +▸ **readAllWorkspaceConfiguration**(): [`ProjectsConfigurations`](../../devkit/index#projectsconfigurations) & [`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration) + +#### Returns + +[`ProjectsConfigurations`](../../devkit/index#projectsconfigurations) & [`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration) + +--- + ### readCachedProjectGraph ▸ **readCachedProjectGraph**(): [`ProjectGraph`](../../devkit/index#projectgraph) @@ -1426,17 +1444,7 @@ Object the JSON content of the file represents ### readNxJson -▸ **readNxJson**(`path?`): [`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration) - -Returns the contents of nx.json. - -If nx.json extends another config file, it will be inlined here. - -#### Parameters - -| Name | Type | -| :----- | :------- | -| `path` | `string` | +▸ **readNxJson**(): [`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration) #### Returns diff --git a/docs/generated/packages/cli.json b/docs/generated/packages/cli.json index 48e7ffcb9e691..4c31cfb2d0b2c 100644 --- a/docs/generated/packages/cli.json +++ b/docs/generated/packages/cli.json @@ -11,6 +11,12 @@ "file": "generated/cli/create-nx-workspace", "content": "---\ntitle: 'create-nx-workspace - CLI command'\ndescription: 'Create a new Nx workspace'\n---\n\n# create-nx-workspace\n\nCreate a new Nx workspace\n\n## Usage\n\n```bash\ncreate-nx-workspace [name] [options]\n```\n\nInstall `create-nx-workspace` globally to invoke the command directly, or use `npx create-nx-workspace`, `yarn create nx-workspace`, or `pnpx create-nx-workspace`.\n\n## Options\n\n### allPrompts\n\nType: boolean\n\nDefault: false\n\nShow all prompts\n\n### appName\n\nType: string\n\nThe name of the application when a preset with pregenerated app is selected\n\n### ci\n\nType: string\n\nChoices: [github, circleci, azure]\n\nGenerate a CI workflow file\n\n### cli\n\nType: string\n\nChoices: [nx, angular]\n\nCLI to power the Nx workspace\n\n### defaultBase\n\nType: string\n\nDefault: main\n\nDefault base to use for new projects\n\n### help\n\nType: boolean\n\nShow help\n\n### interactive\n\nType: boolean\n\nEnable interactive mode with presets\n\n### name\n\nType: string\n\nWorkspace name (e.g. org name)\n\n### nxCloud\n\nType: boolean\n\nUse Nx Cloud\n\n### packageManager\n\nType: string\n\nChoices: [npm, pnpm, yarn]\n\nDefault: npm\n\nPackage manager to use\n\n### preset\n\nType: string\n\nCustomizes the initial content of your workspace. Default presets include: [\"apps\", \"empty\", \"core\", \"npm\", \"ts\", \"web-components\", \"angular\", \"angular-nest\", \"react\", \"react-express\", \"react-native\", \"next\", \"nest\", \"express\"]. To build your own see https://nx.dev/packages/nx-plugin#preset\n\n### style\n\nType: string\n\nStyle option to be used when a preset with pregenerated app is selected\n\n### version\n\nType: boolean\n\nShow version number\n" }, + { + "name": "init", + "id": "init", + "file": "generated/cli/init", + "content": "---\ntitle: 'init - CLI command'\ndescription: 'Adds nx.json file and installs nx if not installed already'\n---\n\n# init\n\nAdds nx.json file and installs nx if not installed already\n\n## Usage\n\n```bash\nnx init\n```\n\n[Install `nx` globally](/getting-started/nx-setup#install-nx) to invoke the command directly using `nx`, or use `npx nx`, `yarn nx`, or `pnpx nx`.\n" + }, { "name": "generate", "id": "generate", diff --git a/docs/generated/packages/devkit.json b/docs/generated/packages/devkit.json index ef68086734c14..a4b5b9da2a79f 100644 --- a/docs/generated/packages/devkit.json +++ b/docs/generated/packages/devkit.json @@ -9,7 +9,7 @@ "id": "index", "name": "Overview", "file": "generated/devkit/index", - "content": "# Module: index\n\nThe Nx Devkit is the underlying technology used to customize Nx to support\ndifferent technologies and custom use-cases. It contains many utility\nfunctions for reading and writing files, updating configuration,\nworking with Abstract Syntax Trees(ASTs), and more.\n\nAs with most things in Nx, the core of Nx Devkit is very simple.\nIt only uses language primitives and immutable objects\n(the tree being the only exception).\n\n## Table of contents\n\n### Project Graph Enumerations\n\n- [DependencyType](../../devkit/index#dependencytype)\n\n### Utils Enumerations\n\n- [ChangeType](../../devkit/index#changetype)\n\n### Project Graph Classes\n\n- [ProjectGraphBuilder](../../devkit/index#projectgraphbuilder)\n\n### Utils Classes\n\n- [Hasher](../../devkit/index#hasher)\n\n### Workspace Classes\n\n- [Workspaces](../../devkit/index#workspaces)\n\n### Commands Interfaces\n\n- [Target](../../devkit/index#target)\n\n### Other Interfaces\n\n- [NxPlugin](../../devkit/index#nxplugin)\n\n### Project Graph Interfaces\n\n- [FileData](../../devkit/index#filedata)\n- [ProjectFileMap](../../devkit/index#projectfilemap)\n- [ProjectGraph](../../devkit/index#projectgraph)\n- [ProjectGraphDependency](../../devkit/index#projectgraphdependency)\n- [ProjectGraphExternalNode](../../devkit/index#projectgraphexternalnode)\n- [ProjectGraphProcessorContext](../../devkit/index#projectgraphprocessorcontext)\n- [ProjectGraphProjectNode](../../devkit/index#projectgraphprojectnode)\n- [ProjectGraphV4](../../devkit/index#projectgraphv4)\n\n### Tree Interfaces\n\n- [FileChange](../../devkit/index#filechange)\n- [Tree](../../devkit/index#tree)\n\n### Utils Interfaces\n\n- [DefaultTasksRunnerOptions](../../devkit/index#defaulttasksrunneroptions)\n- [Hash](../../devkit/index#hash)\n- [JsonParseOptions](../../devkit/index#jsonparseoptions)\n- [JsonSerializeOptions](../../devkit/index#jsonserializeoptions)\n- [RemoteCache](../../devkit/index#remotecache)\n- [StringDeletion](../../devkit/index#stringdeletion)\n- [StringInsertion](../../devkit/index#stringinsertion)\n\n### Workspace Interfaces\n\n- [ExecutorContext](../../devkit/index#executorcontext)\n- [ExecutorsJson](../../devkit/index#executorsjson)\n- [GeneratorsJson](../../devkit/index#generatorsjson)\n- [HasherContext](../../devkit/index#hashercontext)\n- [ImplicitJsonSubsetDependency](../../devkit/index#implicitjsonsubsetdependency)\n- [MigrationsJson](../../devkit/index#migrationsjson)\n- [NxAffectedConfig](../../devkit/index#nxaffectedconfig)\n- [NxJsonConfiguration](../../devkit/index#nxjsonconfiguration)\n- [ProjectConfiguration](../../devkit/index#projectconfiguration)\n- [TargetConfiguration](../../devkit/index#targetconfiguration)\n- [TargetDependencyConfig](../../devkit/index#targetdependencyconfig)\n- [Task](../../devkit/index#task)\n- [TaskGraph](../../devkit/index#taskgraph)\n- [Workspace](../../devkit/index#workspace)\n- [WorkspaceJsonConfiguration](../../devkit/index#workspacejsonconfiguration)\n\n### Generators Type aliases\n\n- [WorkspaceConfiguration](../../devkit/index#workspaceconfiguration)\n\n### Other Type aliases\n\n- [ProjectTargetConfigurator](../../devkit/index#projecttargetconfigurator)\n\n### Package Manager Type aliases\n\n- [PackageManager](../../devkit/index#packagemanager)\n\n### Project Graph Type aliases\n\n- [ProjectGraphNode](../../devkit/index#projectgraphnode)\n\n### Utils Type aliases\n\n- [StringChange](../../devkit/index#stringchange)\n\n### Workspace Type aliases\n\n- [CustomHasher](../../devkit/index#customhasher)\n- [Executor](../../devkit/index#executor)\n- [Generator](../../devkit/index#generator)\n- [GeneratorCallback](../../devkit/index#generatorcallback)\n- [ImplicitDependencyEntry](../../devkit/index#implicitdependencyentry)\n- [ProjectType](../../devkit/index#projecttype)\n- [TaskGraphExecutor](../../devkit/index#taskgraphexecutor)\n\n### Logger Variables\n\n- [logger](../../devkit/index#logger)\n\n### Utils Variables\n\n- [appRootPath](../../devkit/index#approotpath)\n- [cacheDir](../../devkit/index#cachedir)\n- [output](../../devkit/index#output)\n- [workspaceRoot](../../devkit/index#workspaceroot)\n\n### Functions\n\n- [addDependenciesToPackageJson](../../devkit/index#adddependenciestopackagejson)\n- [addProjectConfiguration](../../devkit/index#addprojectconfiguration)\n- [applyChangesToString](../../devkit/index#applychangestostring)\n- [convertNxExecutor](../../devkit/index#convertnxexecutor)\n- [convertNxGenerator](../../devkit/index#convertnxgenerator)\n- [createProjectGraphAsync](../../devkit/index#createprojectgraphasync)\n- [defaultTasksRunner](../../devkit/index#defaulttasksrunner)\n- [detectPackageManager](../../devkit/index#detectpackagemanager)\n- [formatFiles](../../devkit/index#formatfiles)\n- [generateFiles](../../devkit/index#generatefiles)\n- [getOutputsForTargetAndConfiguration](../../devkit/index#getoutputsfortargetandconfiguration)\n- [getPackageManagerCommand](../../devkit/index#getpackagemanagercommand)\n- [getPackageManagerVersion](../../devkit/index#getpackagemanagerversion)\n- [getProjects](../../devkit/index#getprojects)\n- [getWorkspaceLayout](../../devkit/index#getworkspacelayout)\n- [getWorkspacePath](../../devkit/index#getworkspacepath)\n- [installPackagesTask](../../devkit/index#installpackagestask)\n- [isStandaloneProject](../../devkit/index#isstandaloneproject)\n- [joinPathFragments](../../devkit/index#joinpathfragments)\n- [moveFilesToNewDirectory](../../devkit/index#movefilestonewdirectory)\n- [names](../../devkit/index#names)\n- [normalizePath](../../devkit/index#normalizepath)\n- [offsetFromRoot](../../devkit/index#offsetfromroot)\n- [parseJson](../../devkit/index#parsejson)\n- [parseTargetString](../../devkit/index#parsetargetstring)\n- [readCachedProjectGraph](../../devkit/index#readcachedprojectgraph)\n- [readJson](../../devkit/index#readjson)\n- [readJsonFile](../../devkit/index#readjsonfile)\n- [readNxJson](../../devkit/index#readnxjson)\n- [readProjectConfiguration](../../devkit/index#readprojectconfiguration)\n- [readTargetOptions](../../devkit/index#readtargetoptions)\n- [readWorkspaceConfiguration](../../devkit/index#readworkspaceconfiguration)\n- [removeDependenciesFromPackageJson](../../devkit/index#removedependenciesfrompackagejson)\n- [removeProjectConfiguration](../../devkit/index#removeprojectconfiguration)\n- [reverse](../../devkit/index#reverse)\n- [runExecutor](../../devkit/index#runexecutor)\n- [serializeJson](../../devkit/index#serializejson)\n- [stripIndents](../../devkit/index#stripindents)\n- [stripJsonComments](../../devkit/index#stripjsoncomments)\n- [targetToTargetString](../../devkit/index#targettotargetstring)\n- [toJS](../../devkit/index#tojs)\n- [updateJson](../../devkit/index#updatejson)\n- [updateProjectConfiguration](../../devkit/index#updateprojectconfiguration)\n- [updateTsConfigsToJs](../../devkit/index#updatetsconfigstojs)\n- [updateWorkspaceConfiguration](../../devkit/index#updateworkspaceconfiguration)\n- [visitNotIgnoredFiles](../../devkit/index#visitnotignoredfiles)\n- [workspaceLayout](../../devkit/index#workspacelayout)\n- [writeJson](../../devkit/index#writejson)\n- [writeJsonFile](../../devkit/index#writejsonfile)\n\n## Project Graph Enumerations\n\n### DependencyType\n\n• **DependencyType**: `Object`\n\n---\n\n## Utils Enumerations\n\n### ChangeType\n\n• **ChangeType**: `Object`\n\n## Project Graph Classes\n\n### ProjectGraphBuilder\n\n• **ProjectGraphBuilder**: `Object`\n\n---\n\n## Utils Classes\n\n### Hasher\n\n• **Hasher**: `Object`\n\n---\n\n## Workspace Classes\n\n### Workspaces\n\n• **Workspaces**: `Object`\n\n## Commands Interfaces\n\n### Target\n\n• **Target**: `Object`\n\n---\n\n## Other Interfaces\n\n### NxPlugin\n\n• **NxPlugin**: `Object`\n\nA plugin for Nx\n\n---\n\n## Project Graph Interfaces\n\n### FileData\n\n• **FileData**: `Object`\n\n---\n\n### ProjectFileMap\n\n• **ProjectFileMap**: `Object`\n\n---\n\n### ProjectGraph\n\n• **ProjectGraph**<`T`\\>: `Object`\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n---\n\n### ProjectGraphDependency\n\n• **ProjectGraphDependency**: `Object`\n\n---\n\n### ProjectGraphExternalNode\n\n• **ProjectGraphExternalNode**: `Object`\n\n---\n\n### ProjectGraphProcessorContext\n\n• **ProjectGraphProcessorContext**: `Object`\n\n---\n\n### ProjectGraphProjectNode\n\n• **ProjectGraphProjectNode**<`T`\\>: `Object`\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n---\n\n### ProjectGraphV4\n\n• **ProjectGraphV4**<`T`\\>: `Object`\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n---\n\n## Tree Interfaces\n\n### FileChange\n\n• **FileChange**: `Object`\n\n---\n\n### Tree\n\n• **Tree**: `Object`\n\n---\n\n## Utils Interfaces\n\n### DefaultTasksRunnerOptions\n\n• **DefaultTasksRunnerOptions**: `Object`\n\n---\n\n### Hash\n\n• **Hash**: `Object`\n\n---\n\n### JsonParseOptions\n\n• **JsonParseOptions**: `Object`\n\n---\n\n### JsonSerializeOptions\n\n• **JsonSerializeOptions**: `Object`\n\n---\n\n### RemoteCache\n\n• **RemoteCache**: `Object`\n\n---\n\n### StringDeletion\n\n• **StringDeletion**: `Object`\n\n---\n\n### StringInsertion\n\n• **StringInsertion**: `Object`\n\n---\n\n## Workspace Interfaces\n\n### ExecutorContext\n\n• **ExecutorContext**: `Object`\n\n---\n\n### ExecutorsJson\n\n• **ExecutorsJson**: `Object`\n\n---\n\n### GeneratorsJson\n\n• **GeneratorsJson**: `Object`\n\n---\n\n### HasherContext\n\n• **HasherContext**: `Object`\n\n---\n\n### ImplicitJsonSubsetDependency\n\n• **ImplicitJsonSubsetDependency**<`T`\\>: `Object`\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :------------------ |\n| `T` | `\"*\"` \\| `string`[] |\n\n---\n\n### MigrationsJson\n\n• **MigrationsJson**: `Object`\n\n---\n\n### NxAffectedConfig\n\n• **NxAffectedConfig**: `Object`\n\n---\n\n### NxJsonConfiguration\n\n• **NxJsonConfiguration**<`T`\\>: `Object`\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :------------------ |\n| `T` | `\"*\"` \\| `string`[] |\n\n---\n\n### ProjectConfiguration\n\n• **ProjectConfiguration**: `Object`\n\n---\n\n### TargetConfiguration\n\n• **TargetConfiguration**: `Object`\n\n---\n\n### TargetDependencyConfig\n\n• **TargetDependencyConfig**: `Object`\n\n---\n\n### Task\n\n• **Task**: `Object`\n\n---\n\n### TaskGraph\n\n• **TaskGraph**: `Object`\n\n---\n\n### Workspace\n\n• **Workspace**: `Object`\n\n---\n\n### WorkspaceJsonConfiguration\n\n• **WorkspaceJsonConfiguration**: `Object`\n\n## Generators Type aliases\n\n### WorkspaceConfiguration\n\nƬ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../devkit/index#workspacejsonconfiguration), `\"projects\"`\\> & `Partial`<[`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)\\>\n\n---\n\n## Other Type aliases\n\n### ProjectTargetConfigurator\n\nƬ **ProjectTargetConfigurator**: (`file`: `string`) => `Record`<`string`, [`TargetConfiguration`](../../devkit/index#targetconfiguration)\\>\n\n#### Type declaration\n\n▸ (`file`): `Record`<`string`, [`TargetConfiguration`](../../devkit/index#targetconfiguration)\\>\n\n##### Parameters\n\n| Name | Type |\n| :----- | :------- |\n| `file` | `string` |\n\n##### Returns\n\n`Record`<`string`, [`TargetConfiguration`](../../devkit/index#targetconfiguration)\\>\n\n---\n\n## Package Manager Type aliases\n\n### PackageManager\n\nƬ **PackageManager**: `\"yarn\"` \\| `\"pnpm\"` \\| `\"npm\"`\n\n---\n\n## Project Graph Type aliases\n\n### ProjectGraphNode\n\nƬ **ProjectGraphNode**<`T`\\>: [`ProjectGraphProjectNode`](../../devkit/index#projectgraphprojectnode)<`T`\\> \\| [`ProjectGraphExternalNode`](../../devkit/index#projectgraphexternalnode)\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n---\n\n## Utils Type aliases\n\n### StringChange\n\nƬ **StringChange**: [`StringInsertion`](../../devkit/index#stringinsertion) \\| [`StringDeletion`](../../devkit/index#stringdeletion)\n\n---\n\n## Workspace Type aliases\n\n### CustomHasher\n\nƬ **CustomHasher**: (`task`: [`Task`](../../devkit/index#task), `context`: [`HasherContext`](../../devkit/index#hashercontext)) => `Promise`<[`Hash`](../../devkit/index#hash)\\>\n\n#### Type declaration\n\n▸ (`task`, `context`): `Promise`<[`Hash`](../../devkit/index#hash)\\>\n\n##### Parameters\n\n| Name | Type |\n| :-------- | :-------------------------------------------------- |\n| `task` | [`Task`](../../devkit/index#task) |\n| `context` | [`HasherContext`](../../devkit/index#hashercontext) |\n\n##### Returns\n\n`Promise`<[`Hash`](../../devkit/index#hash)\\>\n\n---\n\n### Executor\n\nƬ **Executor**<`T`\\>: (`options`: `T`, `context`: [`ExecutorContext`](../../devkit/index#executorcontext)) => `Promise`<`Object`\\> \\| `AsyncIterableIterator`<`Object`\\>\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n#### Type declaration\n\n▸ (`options`, `context`): `Promise`<`Object`\\> \\| `AsyncIterableIterator`<`Object`\\>\n\nImplementation of a target of a project\n\n##### Parameters\n\n| Name | Type |\n| :-------- | :------------------------------------------------------ |\n| `options` | `T` |\n| `context` | [`ExecutorContext`](../../devkit/index#executorcontext) |\n\n##### Returns\n\n`Promise`<`Object`\\> \\| `AsyncIterableIterator`<`Object`\\>\n\n---\n\n### Generator\n\nƬ **Generator**<`T`\\>: (`tree`: `any`, `schema`: `T`) => `void` \\| [`GeneratorCallback`](../../devkit/index#generatorcallback) \\| `Promise`<`void` \\| [`GeneratorCallback`](../../devkit/index#generatorcallback)\\>\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :-------- |\n| `T` | `unknown` |\n\n#### Type declaration\n\n▸ (`tree`, `schema`): `void` \\| [`GeneratorCallback`](../../devkit/index#generatorcallback) \\| `Promise`<`void` \\| [`GeneratorCallback`](../../devkit/index#generatorcallback)\\>\n\nA function that schedules updates to the filesystem to be done atomically\n\n##### Parameters\n\n| Name | Type |\n| :------- | :---- |\n| `tree` | `any` |\n| `schema` | `T` |\n\n##### Returns\n\n`void` \\| [`GeneratorCallback`](../../devkit/index#generatorcallback) \\| `Promise`<`void` \\| [`GeneratorCallback`](../../devkit/index#generatorcallback)\\>\n\n---\n\n### GeneratorCallback\n\nƬ **GeneratorCallback**: () => `void` \\| `Promise`<`void`\\>\n\n#### Type declaration\n\n▸ (): `void` \\| `Promise`<`void`\\>\n\nA callback function that is executed after changes are made to the file system\n\n##### Returns\n\n`void` \\| `Promise`<`void`\\>\n\n---\n\n### ImplicitDependencyEntry\n\nƬ **ImplicitDependencyEntry**<`T`\\>: `Object`\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :------------------ |\n| `T` | `\"*\"` \\| `string`[] |\n\n#### Index signature\n\n▪ [key: `string`]: `T` \\| [`ImplicitJsonSubsetDependency`](../../devkit/index#implicitjsonsubsetdependency)<`T`\\>\n\n---\n\n### ProjectType\n\nƬ **ProjectType**: `\"library\"` \\| `\"application\"`\n\n---\n\n### TaskGraphExecutor\n\nƬ **TaskGraphExecutor**<`T`\\>: (`taskGraph`: [`TaskGraph`](../../devkit/index#taskgraph), `options`: `Record`<`string`, `T`\\>, `overrides`: `T`, `context`: [`ExecutorContext`](../../devkit/index#executorcontext)) => `Promise`<`Record`<`string`, `Object`\\>\\>\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n#### Type declaration\n\n▸ (`taskGraph`, `options`, `overrides`, `context`): `Promise`<`Record`<`string`, `Object`\\>\\>\n\nImplementation of a target of a project that handles multiple projects to be batched\n\n##### Parameters\n\n| Name | Type |\n| :---------- | :------------------------------------------------------ |\n| `taskGraph` | [`TaskGraph`](../../devkit/index#taskgraph) |\n| `options` | `Record`<`string`, `T`\\> |\n| `overrides` | `T` |\n| `context` | [`ExecutorContext`](../../devkit/index#executorcontext) |\n\n##### Returns\n\n`Promise`<`Record`<`string`, `Object`\\>\\>\n\n## Logger Variables\n\n### logger\n\n• **logger**: `Object`\n\n#### Type declaration\n\n| Name | Type |\n| :------ | :-------------------------- |\n| `debug` | (...`s`: `any`[]) => `void` |\n| `error` | (`s`: `any`) => `void` |\n| `fatal` | (...`s`: `any`[]) => `void` |\n| `info` | (`s`: `any`) => `void` |\n| `log` | (...`s`: `any`[]) => `void` |\n| `warn` | (`s`: `any`) => `void` |\n\n---\n\n## Utils Variables\n\n### appRootPath\n\n• **appRootPath**: `string`\n\n---\n\n### cacheDir\n\n• **cacheDir**: `string`\n\n---\n\n### output\n\n• **output**: `CLIOutput`\n\n---\n\n### workspaceRoot\n\n• **workspaceRoot**: `string` = `appRootPath`\n\n## Functions\n\n### addDependenciesToPackageJson\n\n▸ **addDependenciesToPackageJson**(`tree`, `dependencies`, `devDependencies`, `packageJsonPath?`): [`GeneratorCallback`](../../devkit/index#generatorcallback)\n\nAdd Dependencies and Dev Dependencies to package.json\n\nFor example:\n\n```typescript\naddDependenciesToPackageJson(tree, { react: 'latest' }, { jest: 'latest' });\n```\n\nThis will **add** `react` and `jest` to the dependencies and devDependencies sections of package.json respectively.\n\n#### Parameters\n\n| Name | Type | Default value | Description |\n| :---------------- | :-------------------------------- | :--------------- | :---------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | `undefined` | Tree representing file system to modify |\n| `dependencies` | `Record`<`string`, `string`\\> | `undefined` | Dependencies to be added to the dependencies section of package.json |\n| `devDependencies` | `Record`<`string`, `string`\\> | `undefined` | Dependencies to be added to the devDependencies section of package.json |\n| `packageJsonPath` | `string` | `'package.json'` | Path to package.json |\n\n#### Returns\n\n[`GeneratorCallback`](../../devkit/index#generatorcallback)\n\nCallback to install dependencies only if necessary. undefined is returned if changes are not necessary.\n\n---\n\n### addProjectConfiguration\n\n▸ **addProjectConfiguration**(`tree`, `projectName`, `projectConfiguration`, `standalone?`): `void`\n\nAdds project configuration to the Nx workspace.\n\nThe project configuration is stored in workspace.json or the associated project.json file.\nThe utility will update either files.\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------------------- | :---------------------------------------------------------------- | :----------------------------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |\n| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) |\n| `projectConfiguration` | [`ProjectConfiguration`](../../devkit/index#projectconfiguration) | project configuration |\n| `standalone?` | `boolean` | should the project use package.json? If false, the project config is inside workspace.json |\n\n#### Returns\n\n`void`\n\n---\n\n### applyChangesToString\n\n▸ **applyChangesToString**(`text`, `changes`): `string`\n\nApplies a list of changes to a string's original value.\n\nThis is useful when working with ASTs.\n\nFor Example, to rename a property in a method's options:\n\n```typescript\nconst code = `bootstrap({\n target: document.querySelector('#app')\n})`;\n\nconst indexOfPropertyName = 13; // Usually determined by analyzing an AST.\nconst updatedCode = applyChangesToString(code, [\n {\n type: ChangeType.Insert,\n index: indexOfPropertyName,\n text: 'element',\n },\n {\n type: ChangeType.Delete,\n start: indexOfPropertyName,\n length: 6,\n },\n]);\n\nbootstrap({\n element: document.querySelector('#app'),\n});\n```\n\n#### Parameters\n\n| Name | Type |\n| :-------- | :-------------------------------------------------- |\n| `text` | `string` |\n| `changes` | [`StringChange`](../../devkit/index#stringchange)[] |\n\n#### Returns\n\n`string`\n\n---\n\n### convertNxExecutor\n\n▸ **convertNxExecutor**(`executor`): `any`\n\nConvert an Nx Executor into an Angular Devkit Builder\n\nUse this to expose a compatible Angular Builder\n\n#### Parameters\n\n| Name | Type |\n| :--------- | :------------------------------------------------ |\n| `executor` | [`Executor`](../../devkit/index#executor)<`any`\\> |\n\n#### Returns\n\n`any`\n\n---\n\n### convertNxGenerator\n\n▸ **convertNxGenerator**<`T`\\>(`generator`, `skipWritingConfigInOldFormat?`): (`generatorOptions`: `T`) => (`tree`: `any`, `context`: `any`) => `Promise`<`any`\\>\n\nConvert an Nx Generator into an Angular Devkit Schematic.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n#### Parameters\n\n| Name | Type | Default value | Description |\n| :----------------------------- | :------------------------------------------------ | :------------ | :------------------------------------------------------------------------------------------------ |\n| `generator` | [`Generator`](../../devkit/index#generator)<`T`\\> | `undefined` | The Nx generator to convert to an Angular Devkit Schematic. |\n| `skipWritingConfigInOldFormat` | `boolean` | `false` | Whether to skip writing the configuration in the old format (the one used by the Angular DevKit). |\n\n#### Returns\n\n`fn`\n\n▸ (`generatorOptions`): (`tree`: `any`, `context`: `any`) => `Promise`<`any`\\>\n\n##### Parameters\n\n| Name | Type |\n| :----------------- | :--- |\n| `generatorOptions` | `T` |\n\n##### Returns\n\n`fn`\n\n▸ (`tree`, `context`): `Promise`<`any`\\>\n\n##### Parameters\n\n| Name | Type |\n| :-------- | :---- |\n| `tree` | `any` |\n| `context` | `any` |\n\n##### Returns\n\n`Promise`<`any`\\>\n\n---\n\n### createProjectGraphAsync\n\n▸ **createProjectGraphAsync**(): `Promise`<[`ProjectGraph`](../../devkit/index#projectgraph)\\>\n\nComputes and returns a ProjectGraph.\n\nNx will compute the graph either in a daemon process or in the current process.\n\nNx will compute it in the current process if:\n\n- The process is running in CI (CI env variable is to true or other common variables used by CI providers are set).\n- It is running in the docker container.\n- The daemon process is disabled because of the previous error when starting the daemon.\n- `NX_DAEMON` is set to `false`.\n- `useDaemon` is set to false in `nx.json`\n\n`NX_DAEMON` env variable takes precedence:\n\n- If it is set to true, the daemon will always be used.\n- If it is set to false, the graph will always be computed in the current process.\n\nTip: If you want to debug project graph creation, run your command with NX_DAEMON=false.\n\nNx uses two layers of caching: the information about explicit dependencies stored on the disk and the information\nstored in the daemon process. To reset both run: `nx reset`.\n\n#### Returns\n\n`Promise`<[`ProjectGraph`](../../devkit/index#projectgraph)\\>\n\n---\n\n### defaultTasksRunner\n\n▸ `Const` **defaultTasksRunner**(`tasks`, `options`, `context?`): `any`\n\n#### Parameters\n\n| Name | Type |\n| :--------------------------- | :------------------------------------------------------------------------------------ |\n| `tasks` | [`Task`](../../devkit/index#task)[] |\n| `options` | [`DefaultTasksRunnerOptions`](../../devkit/index#defaulttasksrunneroptions) |\n| `context?` | `Object` |\n| `context.initiatingProject?` | `string` |\n| `context.nxArgs` | `NxArgs` |\n| `context.nxJson` | [`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)<`string`[] \\| `\"*\"`\\> |\n| `context.projectGraph` | [`ProjectGraph`](../../devkit/index#projectgraph)<`any`\\> |\n| `context.target?` | `string` |\n| `context.taskGraph?` | [`TaskGraph`](../../devkit/index#taskgraph) |\n\n#### Returns\n\n`any`\n\n---\n\n### detectPackageManager\n\n▸ **detectPackageManager**(`dir?`): [`PackageManager`](../../devkit/index#packagemanager)\n\nDetects which package manager is used in the workspace based on the lock file.\n\n#### Parameters\n\n| Name | Type | Default value |\n| :---- | :------- | :------------ |\n| `dir` | `string` | `''` |\n\n#### Returns\n\n[`PackageManager`](../../devkit/index#packagemanager)\n\n---\n\n### formatFiles\n\n▸ **formatFiles**(`tree`): `Promise`<`void`\\>\n\nFormats all the created or updated files using Prettier\n\n#### Parameters\n\n| Name | Type | Description |\n| :----- | :-------------------------------- | :------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |\n\n#### Returns\n\n`Promise`<`void`\\>\n\n---\n\n### generateFiles\n\n▸ **generateFiles**(`tree`, `srcFolder`, `target`, `substitutions`): `void`\n\nGenerates a folder of files based on provided templates.\n\nWhile doing so it performs two substitutions:\n\n- Substitutes segments of file names surrounded by \\_\\_\n- Uses ejs to substitute values in templates\n\nExamples:\n\n```typescript\ngenerateFiles(tree, path.join(__dirname, 'files'), './tools/scripts', {\n tmpl: '',\n name: 'myscript',\n});\n```\n\nThis command will take all the files from the `files` directory next to the place where the command is invoked from.\nIt will replace all `__tmpl__` with '' and all `__name__` with 'myscript' in the file names, and will replace all\n`<%= name %>` with `myscript` in the files themselves.\n`tmpl: ''` is a common pattern. With it you can name files like this: `index.ts__tmpl__`, so your editor\ndoesn't get confused about incorrect TypeScript files.\n\n#### Parameters\n\n| Name | Type | Description |\n| :-------------- | :-------------------------------- | :-------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |\n| `srcFolder` | `string` | the source folder of files (absolute path) |\n| `target` | `string` | the target folder (relative to the tree root) |\n| `substitutions` | `Object` | an object of key-value pairs |\n\n#### Returns\n\n`void`\n\n---\n\n### getOutputsForTargetAndConfiguration\n\n▸ **getOutputsForTargetAndConfiguration**(`task`, `node`): `any`\n\nReturns the list of outputs that will be cached.\n\n#### Parameters\n\n| Name | Type | Description |\n| :----- | :------------------------------------------------------------------------------ | :-------------------------------------------------------- |\n| `task` | `Pick`<[`Task`](../../devkit/index#task), `\"target\"` \\| `\"overrides\"`\\> | target + overrides |\n| `node` | [`ProjectGraphProjectNode`](../../devkit/index#projectgraphprojectnode)<`any`\\> | ProjectGraphProjectNode object that the task runs against |\n\n#### Returns\n\n`any`\n\n---\n\n### getPackageManagerCommand\n\n▸ **getPackageManagerCommand**(`packageManager?`): `PackageManagerCommands`\n\nReturns commands for the package manager used in the workspace.\nBy default, the package manager is derived based on the lock file,\nbut it can also be passed in explicitly.\n\nExample:\n\n```javascript\nexecSync(`${getPackageManagerCommand().addDev} my-dev-package`);\n```\n\n#### Parameters\n\n| Name | Type |\n| :--------------- | :---------------------------------------------------- |\n| `packageManager` | [`PackageManager`](../../devkit/index#packagemanager) |\n\n#### Returns\n\n`PackageManagerCommands`\n\n---\n\n### getPackageManagerVersion\n\n▸ **getPackageManagerVersion**(`packageManager?`): `string`\n\nReturns the version of the package manager used in the workspace.\nBy default, the package manager is derived based on the lock file,\nbut it can also be passed in explicitly.\n\n#### Parameters\n\n| Name | Type |\n| :--------------- | :---------------------------------------------------- |\n| `packageManager` | [`PackageManager`](../../devkit/index#packagemanager) |\n\n#### Returns\n\n`string`\n\n---\n\n### getProjects\n\n▸ **getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../devkit/index#projectconfiguration)\\>\n\nGet a map of all projects in a workspace.\n\nUse [readProjectConfiguration](../../devkit/index#readprojectconfiguration) if only one project is needed.\n\n#### Parameters\n\n| Name | Type |\n| :----- | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n\n#### Returns\n\n`Map`<`string`, [`ProjectConfiguration`](../../devkit/index#projectconfiguration)\\>\n\n---\n\n### getWorkspaceLayout\n\n▸ **getWorkspaceLayout**(`tree`): `Object`\n\nReturns workspace defaults. It includes defaults folders for apps and libs,\nand the default scope.\n\nExample:\n\n```typescript\n{ appsDir: 'apps', libsDir: 'libs', npmScope: 'myorg' }\n```\n\n#### Parameters\n\n| Name | Type | Description |\n| :----- | :-------------------------------- | :--------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | file system tree |\n\n#### Returns\n\n`Object`\n\n| Name | Type |\n| :-------------------- | :-------- |\n| `appsDir` | `string` |\n| `libsDir` | `string` |\n| `npmScope` | `string` |\n| `standaloneAsDefault` | `boolean` |\n\n---\n\n### getWorkspacePath\n\n▸ **getWorkspacePath**(`tree`): `\"/angular.json\"` \\| `\"/workspace.json\"` \\| `null`\n\n#### Parameters\n\n| Name | Type |\n| :----- | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n\n#### Returns\n\n`\"/angular.json\"` \\| `\"/workspace.json\"` \\| `null`\n\n---\n\n### installPackagesTask\n\n▸ **installPackagesTask**(`tree`, `alwaysRun?`, `cwd?`, `packageManager?`): `void`\n\nRuns `npm install` or `yarn install`. It will skip running the install if\n`package.json` hasn't changed at all or it hasn't changed since the last invocation.\n\n#### Parameters\n\n| Name | Type | Default value | Description |\n| :--------------- | :---------------------------------------------------- | :------------ | :------------------------------------------------------------ |\n| `tree` | [`Tree`](../../devkit/index#tree) | `undefined` | the file system tree |\n| `alwaysRun` | `boolean` | `false` | always run the command even if `package.json` hasn't changed. |\n| `cwd` | `string` | `''` | - |\n| `packageManager` | [`PackageManager`](../../devkit/index#packagemanager) | `undefined` | - |\n\n#### Returns\n\n`void`\n\n---\n\n### isStandaloneProject\n\n▸ **isStandaloneProject**(`tree`, `project`): `boolean`\n\nReturns if a project has a standalone configuration (project.json).\n\n#### Parameters\n\n| Name | Type | Description |\n| :-------- | :-------------------------------- | :------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |\n| `project` | `string` | the project name |\n\n#### Returns\n\n`boolean`\n\n---\n\n### joinPathFragments\n\n▸ **joinPathFragments**(...`fragments`): `string`\n\nNormalized path fragments and joins them\n\n#### Parameters\n\n| Name | Type |\n| :------------- | :--------- |\n| `...fragments` | `string`[] |\n\n#### Returns\n\n`string`\n\n---\n\n### moveFilesToNewDirectory\n\n▸ **moveFilesToNewDirectory**(`tree`, `oldDir`, `newDir`): `void`\n\nAnalogous to cp -r oldDir newDir\n\n#### Parameters\n\n| Name | Type |\n| :------- | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n| `oldDir` | `string` |\n| `newDir` | `string` |\n\n#### Returns\n\n`void`\n\n---\n\n### names\n\n▸ **names**(`name`): `Object`\n\nUtil function to generate different strings based off the provided name.\n\nExamples:\n\n```typescript\nnames('my-name'); // {name: 'my-name', className: 'MyName', propertyName: 'myName', constantName: 'MY_NAME', fileName: 'my-name'}\nnames('myName'); // {name: 'myName', className: 'MyName', propertyName: 'myName', constantName: 'MY_NAME', fileName: 'my-name'}\n```\n\n#### Parameters\n\n| Name | Type |\n| :----- | :------- |\n| `name` | `string` |\n\n#### Returns\n\n`Object`\n\n| Name | Type |\n| :------------- | :------- |\n| `className` | `string` |\n| `constantName` | `string` |\n| `fileName` | `string` |\n| `name` | `string` |\n| `propertyName` | `string` |\n\n---\n\n### normalizePath\n\n▸ **normalizePath**(`osSpecificPath`): `string`\n\nCoverts an os specific path to a unix style path\n\n#### Parameters\n\n| Name | Type |\n| :--------------- | :------- |\n| `osSpecificPath` | `string` |\n\n#### Returns\n\n`string`\n\n---\n\n### offsetFromRoot\n\n▸ **offsetFromRoot**(`fullPathToDir`): `string`\n\nCalculates an offset from the root of the workspace, which is useful for\nconstructing relative URLs.\n\nExamples:\n\n```typescript\noffsetFromRoot('apps/mydir/myapp/'); // returns \"../../../\"\n```\n\n#### Parameters\n\n| Name | Type | Description |\n| :-------------- | :------- | :------------- |\n| `fullPathToDir` | `string` | directory path |\n\n#### Returns\n\n`string`\n\n---\n\n### parseJson\n\n▸ **parseJson**<`T`\\>(`input`, `options?`): `T`\n\nParses the given JSON string and returns the object the JSON content represents.\nBy default javascript-style comments are allowed.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :----------------------- |\n| `T` | extends `object` = `any` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :-------------------------------------------------------- | :--------------------- |\n| `input` | `string` | JSON content as string |\n| `options?` | [`JsonParseOptions`](../../devkit/index#jsonparseoptions) | JSON parse options |\n\n#### Returns\n\n`T`\n\nObject the JSON content represents\n\n---\n\n### parseTargetString\n\n▸ **parseTargetString**(`targetString`): [`Target`](../../devkit/index#target)\n\nParses a target string into {project, target, configuration}\n\nExamples:\n\n```typescript\nparseTargetString('proj:test'); // returns { project: \"proj\", target: \"test\" }\nparseTargetString('proj:test:production'); // returns { project: \"proj\", target: \"test\", configuration: \"production\" }\n```\n\n#### Parameters\n\n| Name | Type | Description |\n| :------------- | :------- | :--------------- |\n| `targetString` | `string` | target reference |\n\n#### Returns\n\n[`Target`](../../devkit/index#target)\n\n---\n\n### readCachedProjectGraph\n\n▸ **readCachedProjectGraph**(): [`ProjectGraph`](../../devkit/index#projectgraph)\n\nSynchronously reads the latest cached copy of the workspace's ProjectGraph.\n\n**`throws`** {Error} if there is no cached ProjectGraph to read from\n\n#### Returns\n\n[`ProjectGraph`](../../devkit/index#projectgraph)\n\n---\n\n### readJson\n\n▸ **readJson**<`T`\\>(`tree`, `path`, `options?`): `T`\n\nReads a json file, removes all comments and parses JSON.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :----------------------- |\n| `T` | extends `object` = `any` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :-------------------------------------------------------- | :-------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | file system tree |\n| `path` | `string` | file path |\n| `options?` | [`JsonParseOptions`](../../devkit/index#jsonparseoptions) | Optional JSON Parse Options |\n\n#### Returns\n\n`T`\n\n---\n\n### readJsonFile\n\n▸ **readJsonFile**<`T`\\>(`path`, `options?`): `T`\n\nReads a JSON file and returns the object the JSON content represents.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :----------------------- |\n| `T` | extends `object` = `any` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :---------------- | :----------------- |\n| `path` | `string` | A path to a file. |\n| `options?` | `JsonReadOptions` | JSON parse options |\n\n#### Returns\n\n`T`\n\nObject the JSON content of the file represents\n\n---\n\n### readNxJson\n\n▸ **readNxJson**(`path?`): [`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)\n\nReturns the contents of nx.json.\n\nIf nx.json extends another config file, it will be inlined here.\n\n#### Parameters\n\n| Name | Type |\n| :----- | :------- |\n| `path` | `string` |\n\n#### Returns\n\n[`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)\n\n---\n\n### readProjectConfiguration\n\n▸ **readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../devkit/index#projectconfiguration)\n\nReads a project configuration.\n\nThe project configuration is stored in workspace.json or the associated project.json file.\nThe utility will read from either file.\n\n**`throws`** If supplied projectName cannot be found\n\n#### Parameters\n\n| Name | Type | Description |\n| :------------ | :-------------------------------- | :---------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |\n| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) |\n\n#### Returns\n\n[`ProjectConfiguration`](../../devkit/index#projectconfiguration)\n\n---\n\n### readTargetOptions\n\n▸ **readTargetOptions**<`T`\\>(`__namedParameters`, `context`): `T`\n\nReads and combines options for a given target.\n\nWorks as if you invoked the target yourself without passing any command lint overrides.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n#### Parameters\n\n| Name | Type |\n| :------------------ | :------------------------------------------------------ |\n| `__namedParameters` | [`Target`](../../devkit/index#target) |\n| `context` | [`ExecutorContext`](../../devkit/index#executorcontext) |\n\n#### Returns\n\n`T`\n\n---\n\n### readWorkspaceConfiguration\n\n▸ **readWorkspaceConfiguration**(`tree`): [`WorkspaceConfiguration`](../../devkit/index#workspaceconfiguration)\n\nRead general workspace configuration such as the default project or cli settings\n\nThis does _not_ provide projects configuration, use [readProjectConfiguration](../../devkit/index#readprojectconfiguration) instead.\n\n#### Parameters\n\n| Name | Type |\n| :----- | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n\n#### Returns\n\n[`WorkspaceConfiguration`](../../devkit/index#workspaceconfiguration)\n\n---\n\n### removeDependenciesFromPackageJson\n\n▸ **removeDependenciesFromPackageJson**(`tree`, `dependencies`, `devDependencies`, `packageJsonPath?`): [`GeneratorCallback`](../../devkit/index#generatorcallback)\n\nRemove Dependencies and Dev Dependencies from package.json\n\nFor example:\n\n```typescript\nremoveDependenciesFromPackageJson(tree, ['react'], ['jest']);\n```\n\nThis will **remove** `react` and `jest` from the dependencies and devDependencies sections of package.json respectively.\n\n#### Parameters\n\n| Name | Type | Default value | Description |\n| :---------------- | :-------------------------------- | :--------------- | :-------------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | `undefined` | - |\n| `dependencies` | `string`[] | `undefined` | Dependencies to be removed from the dependencies section of package.json |\n| `devDependencies` | `string`[] | `undefined` | Dependencies to be removed from the devDependencies section of package.json |\n| `packageJsonPath` | `string` | `'package.json'` | - |\n\n#### Returns\n\n[`GeneratorCallback`](../../devkit/index#generatorcallback)\n\nCallback to uninstall dependencies only if necessary. undefined is returned if changes are not necessary.\n\n---\n\n### removeProjectConfiguration\n\n▸ **removeProjectConfiguration**(`tree`, `projectName`): `void`\n\nRemoves the configuration of an existing project.\n\nThe project configuration is stored in workspace.json or the associated project.json file.\nThe utility will update either file.\n\n#### Parameters\n\n| Name | Type |\n| :------------ | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n| `projectName` | `string` |\n\n#### Returns\n\n`void`\n\n---\n\n### reverse\n\n▸ **reverse**(`graph`): [`ProjectGraph`](../../devkit/index#projectgraph)\n\nReturns a new project graph where all the edges are reversed.\n\nFor instance, if project A depends on B, in the reversed graph\nB will depend on A.\n\n#### Parameters\n\n| Name | Type |\n| :------ | :-------------------------------------------------------- |\n| `graph` | [`ProjectGraph`](../../devkit/index#projectgraph)<`any`\\> |\n\n#### Returns\n\n[`ProjectGraph`](../../devkit/index#projectgraph)\n\n---\n\n### runExecutor\n\n▸ **runExecutor**<`T`\\>(`targetDescription`, `options`, `context`): `Promise`<`AsyncIterableIterator`<`T`\\>\\>\n\nLoads and invokes executor.\n\nThis is analogous to invoking executor from the terminal, with the exception\nthat the params aren't parsed from the string, but instead provided parsed already.\n\nApart from that, it works the same way:\n\n- it will load the workspace configuration\n- it will resolve the target\n- it will load the executor and the schema\n- it will load the options for the appropriate configuration\n- it will run the validations and will set the default\n- and, of course, it will invoke the executor\n\nExample:\n\n```typescript\nfor await (const s of await runExecutor(\n { project: 'myproj', target: 'serve' },\n { watch: true },\n context\n)) {\n // s.success\n}\n```\n\nNote that the return value is a promise of an iterator, so you need to await before iterating over it.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :--------------- |\n| `T` | extends `Object` |\n\n#### Parameters\n\n| Name | Type |\n| :--------------------------------- | :------------------------------------------------------ |\n| `targetDescription` | `Object` |\n| `targetDescription.configuration?` | `string` |\n| `targetDescription.project` | `string` |\n| `targetDescription.target` | `string` |\n| `options` | `Object` |\n| `context` | [`ExecutorContext`](../../devkit/index#executorcontext) |\n\n#### Returns\n\n`Promise`<`AsyncIterableIterator`<`T`\\>\\>\n\n---\n\n### serializeJson\n\n▸ **serializeJson**<`T`\\>(`input`, `options?`): `string`\n\nSerializes the given data to a JSON string.\nBy default the JSON string is formatted with a 2 space intendation to be easy readable.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :-------------------------- |\n| `T` | extends `object` = `object` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :---------------------------------------------------------------- | :---------------------------------------- |\n| `input` | `T` | Object which should be serialized to JSON |\n| `options?` | [`JsonSerializeOptions`](../../devkit/index#jsonserializeoptions) | JSON serialize options |\n\n#### Returns\n\n`string`\n\nthe formatted JSON representation of the object\n\n---\n\n### stripIndents\n\n▸ **stripIndents**(`strings`, ...`values`): `string`\n\nRemoves indents, which is useful for printing warning and messages.\n\nExample:\n\n```typescript\nstripIndents`\n Options:\n - option1\n - option2\n`;\n```\n\n#### Parameters\n\n| Name | Type |\n| :---------- | :--------------------- |\n| `strings` | `TemplateStringsArray` |\n| `...values` | `any`[] |\n\n#### Returns\n\n`string`\n\n---\n\n### stripJsonComments\n\n▸ `Const` **stripJsonComments**(`text`, `replaceCh?`): `string`\n\nTakes JSON with JavaScript-style comments and remove\nthem. Optionally replaces every none-newline character\nof comments with a replaceCharacter\n\n#### Parameters\n\n| Name | Type |\n| :----------- | :------- |\n| `text` | `string` |\n| `replaceCh?` | `string` |\n\n#### Returns\n\n`string`\n\n---\n\n### targetToTargetString\n\n▸ **targetToTargetString**(`target`): `string`\n\nReturns a string in the format \"project:target[:configuration]\" for the target\n\n#### Parameters\n\n| Name | Type | Description |\n| :------- | :------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `target` | [`Target`](../../devkit/index#target) | target object Examples: `typescript targetToTargetString({ project: \"proj\", target: \"test\" }) // returns \"proj:test\" targetToTargetString({ project: \"proj\", target: \"test\", configuration: \"production\" }) // returns \"proj:test:production\" ` |\n\n#### Returns\n\n`string`\n\n---\n\n### toJS\n\n▸ **toJS**(`tree`): `void`\n\nRename and transpile any new typescript files created to javascript files\n\n#### Parameters\n\n| Name | Type |\n| :----- | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n\n#### Returns\n\n`void`\n\n---\n\n### updateJson\n\n▸ **updateJson**<`T`, `U`\\>(`tree`, `path`, `updater`, `options?`): `void`\n\nUpdates a JSON value to the file system tree\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :----------------------- |\n| `T` | extends `object` = `any` |\n| `U` | extends `object` = `T` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :---------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | File system tree |\n| `path` | `string` | Path of JSON file in the Tree |\n| `updater` | (`value`: `T`) => `U` | Function that maps the current value of a JSON document to a new value to be written to the document |\n| `options?` | [`JsonParseOptions`](../../devkit/index#jsonparseoptions) & [`JsonSerializeOptions`](../../devkit/index#jsonserializeoptions) | Optional JSON Parse and Serialize Options |\n\n#### Returns\n\n`void`\n\n---\n\n### updateProjectConfiguration\n\n▸ **updateProjectConfiguration**(`tree`, `projectName`, `projectConfiguration`): `void`\n\nUpdates the configuration of an existing project.\n\nThe project configuration is stored in workspace.json or the associated project.json file.\nThe utility will update either files.\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------------------- | :---------------------------------------------------------------- | :---------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |\n| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) |\n| `projectConfiguration` | [`ProjectConfiguration`](../../devkit/index#projectconfiguration) | project configuration |\n\n#### Returns\n\n`void`\n\n---\n\n### updateTsConfigsToJs\n\n▸ **updateTsConfigsToJs**(`tree`, `options`): `void`\n\n#### Parameters\n\n| Name | Type |\n| :-------------------- | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n| `options` | `Object` |\n| `options.projectRoot` | `string` |\n\n#### Returns\n\n`void`\n\n---\n\n### updateWorkspaceConfiguration\n\n▸ **updateWorkspaceConfiguration**(`tree`, `workspaceConfig`): `void`\n\nUpdate general workspace configuration such as the default project or cli settings.\n\nThis does _not_ update projects configuration, use [updateProjectConfiguration](../../devkit/index#updateprojectconfiguration) or [addProjectConfiguration](../../devkit/index#addprojectconfiguration) instead.\n\n#### Parameters\n\n| Name | Type |\n| :---------------- | :-------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n| `workspaceConfig` | [`WorkspaceConfiguration`](../../devkit/index#workspaceconfiguration) |\n\n#### Returns\n\n`void`\n\n---\n\n### visitNotIgnoredFiles\n\n▸ **visitNotIgnoredFiles**(`tree`, `dirPath?`, `visitor`): `void`\n\nUtility to act on all files in a tree that are not ignored by git.\n\n#### Parameters\n\n| Name | Type | Default value |\n| :-------- | :-------------------------------- | :------------ |\n| `tree` | [`Tree`](../../devkit/index#tree) | `undefined` |\n| `dirPath` | `string` | `tree.root` |\n| `visitor` | (`path`: `string`) => `void` | `undefined` |\n\n#### Returns\n\n`void`\n\n---\n\n### workspaceLayout\n\n▸ **workspaceLayout**(): `Object`\n\nReturns information about where apps and libs will be created.\n\n#### Returns\n\n`Object`\n\n| Name | Type |\n| :-------- | :------- |\n| `appsDir` | `string` |\n| `libsDir` | `string` |\n\n---\n\n### writeJson\n\n▸ **writeJson**<`T`\\>(`tree`, `path`, `value`, `options?`): `void`\n\nWrites a JSON value to the file system tree\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :-------------------------- |\n| `T` | extends `object` = `object` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :---------------------------------------------------------------- | :------------------------------ |\n| `tree` | [`Tree`](../../devkit/index#tree) | File system tree |\n| `path` | `string` | Path of JSON file in the Tree |\n| `value` | `T` | Serializable value to write |\n| `options?` | [`JsonSerializeOptions`](../../devkit/index#jsonserializeoptions) | Optional JSON Serialize Options |\n\n#### Returns\n\n`void`\n\n---\n\n### writeJsonFile\n\n▸ **writeJsonFile**<`T`\\>(`path`, `data`, `options?`): `void`\n\nSerializes the given data to JSON and writes it to a file.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :-------------------------- |\n| `T` | extends `object` = `object` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :----------------- | :-------------------------------------------------------------- |\n| `path` | `string` | A path to a file. |\n| `data` | `T` | data which should be serialized to JSON and written to the file |\n| `options?` | `JsonWriteOptions` | JSON serialize options |\n\n#### Returns\n\n`void`\n" + "content": "# Module: index\n\nThe Nx Devkit is the underlying technology used to customize Nx to support\ndifferent technologies and custom use-cases. It contains many utility\nfunctions for reading and writing files, updating configuration,\nworking with Abstract Syntax Trees(ASTs), and more.\n\nAs with most things in Nx, the core of Nx Devkit is very simple.\nIt only uses language primitives and immutable objects\n(the tree being the only exception).\n\n## Table of contents\n\n### Project Graph Enumerations\n\n- [DependencyType](../../devkit/index#dependencytype)\n\n### Utils Enumerations\n\n- [ChangeType](../../devkit/index#changetype)\n\n### Project Graph Classes\n\n- [ProjectGraphBuilder](../../devkit/index#projectgraphbuilder)\n\n### Utils Classes\n\n- [Hasher](../../devkit/index#hasher)\n\n### Workspace Classes\n\n- [Workspaces](../../devkit/index#workspaces)\n\n### Commands Interfaces\n\n- [Target](../../devkit/index#target)\n\n### Other Interfaces\n\n- [NxPlugin](../../devkit/index#nxplugin)\n\n### Project Graph Interfaces\n\n- [FileData](../../devkit/index#filedata)\n- [ProjectFileMap](../../devkit/index#projectfilemap)\n- [ProjectGraph](../../devkit/index#projectgraph)\n- [ProjectGraphDependency](../../devkit/index#projectgraphdependency)\n- [ProjectGraphExternalNode](../../devkit/index#projectgraphexternalnode)\n- [ProjectGraphProcessorContext](../../devkit/index#projectgraphprocessorcontext)\n- [ProjectGraphProjectNode](../../devkit/index#projectgraphprojectnode)\n- [ProjectGraphV4](../../devkit/index#projectgraphv4)\n\n### Tree Interfaces\n\n- [FileChange](../../devkit/index#filechange)\n- [Tree](../../devkit/index#tree)\n\n### Utils Interfaces\n\n- [DefaultTasksRunnerOptions](../../devkit/index#defaulttasksrunneroptions)\n- [Hash](../../devkit/index#hash)\n- [JsonParseOptions](../../devkit/index#jsonparseoptions)\n- [JsonSerializeOptions](../../devkit/index#jsonserializeoptions)\n- [RemoteCache](../../devkit/index#remotecache)\n- [StringDeletion](../../devkit/index#stringdeletion)\n- [StringInsertion](../../devkit/index#stringinsertion)\n\n### Workspace Interfaces\n\n- [ExecutorContext](../../devkit/index#executorcontext)\n- [ExecutorsJson](../../devkit/index#executorsjson)\n- [GeneratorsJson](../../devkit/index#generatorsjson)\n- [HasherContext](../../devkit/index#hashercontext)\n- [ImplicitJsonSubsetDependency](../../devkit/index#implicitjsonsubsetdependency)\n- [MigrationsJson](../../devkit/index#migrationsjson)\n- [NxAffectedConfig](../../devkit/index#nxaffectedconfig)\n- [NxJsonConfiguration](../../devkit/index#nxjsonconfiguration)\n- [ProjectConfiguration](../../devkit/index#projectconfiguration)\n- [ProjectsConfigurations](../../devkit/index#projectsconfigurations)\n- [TargetConfiguration](../../devkit/index#targetconfiguration)\n- [TargetDependencyConfig](../../devkit/index#targetdependencyconfig)\n- [Task](../../devkit/index#task)\n- [TaskGraph](../../devkit/index#taskgraph)\n- [Workspace](../../devkit/index#workspace)\n\n### Generators Type aliases\n\n- [WorkspaceConfiguration](../../devkit/index#workspaceconfiguration)\n\n### Other Type aliases\n\n- [ProjectTargetConfigurator](../../devkit/index#projecttargetconfigurator)\n\n### Package Manager Type aliases\n\n- [PackageManager](../../devkit/index#packagemanager)\n\n### Project Graph Type aliases\n\n- [ProjectGraphNode](../../devkit/index#projectgraphnode)\n\n### Utils Type aliases\n\n- [StringChange](../../devkit/index#stringchange)\n\n### Workspace Type aliases\n\n- [CustomHasher](../../devkit/index#customhasher)\n- [Executor](../../devkit/index#executor)\n- [Generator](../../devkit/index#generator)\n- [GeneratorCallback](../../devkit/index#generatorcallback)\n- [ImplicitDependencyEntry](../../devkit/index#implicitdependencyentry)\n- [ProjectType](../../devkit/index#projecttype)\n- [TaskGraphExecutor](../../devkit/index#taskgraphexecutor)\n- [WorkspaceJsonConfiguration](../../devkit/index#workspacejsonconfiguration)\n\n### Logger Variables\n\n- [logger](../../devkit/index#logger)\n\n### Utils Variables\n\n- [appRootPath](../../devkit/index#approotpath)\n- [cacheDir](../../devkit/index#cachedir)\n- [output](../../devkit/index#output)\n- [workspaceRoot](../../devkit/index#workspaceroot)\n\n### Functions\n\n- [addDependenciesToPackageJson](../../devkit/index#adddependenciestopackagejson)\n- [addProjectConfiguration](../../devkit/index#addprojectconfiguration)\n- [applyChangesToString](../../devkit/index#applychangestostring)\n- [convertNxExecutor](../../devkit/index#convertnxexecutor)\n- [convertNxGenerator](../../devkit/index#convertnxgenerator)\n- [createProjectGraphAsync](../../devkit/index#createprojectgraphasync)\n- [defaultTasksRunner](../../devkit/index#defaulttasksrunner)\n- [detectPackageManager](../../devkit/index#detectpackagemanager)\n- [formatFiles](../../devkit/index#formatfiles)\n- [generateFiles](../../devkit/index#generatefiles)\n- [getOutputsForTargetAndConfiguration](../../devkit/index#getoutputsfortargetandconfiguration)\n- [getPackageManagerCommand](../../devkit/index#getpackagemanagercommand)\n- [getPackageManagerVersion](../../devkit/index#getpackagemanagerversion)\n- [getProjects](../../devkit/index#getprojects)\n- [getWorkspaceLayout](../../devkit/index#getworkspacelayout)\n- [getWorkspacePath](../../devkit/index#getworkspacepath)\n- [installPackagesTask](../../devkit/index#installpackagestask)\n- [isStandaloneProject](../../devkit/index#isstandaloneproject)\n- [joinPathFragments](../../devkit/index#joinpathfragments)\n- [moveFilesToNewDirectory](../../devkit/index#movefilestonewdirectory)\n- [names](../../devkit/index#names)\n- [normalizePath](../../devkit/index#normalizepath)\n- [offsetFromRoot](../../devkit/index#offsetfromroot)\n- [parseJson](../../devkit/index#parsejson)\n- [parseTargetString](../../devkit/index#parsetargetstring)\n- [readAllWorkspaceConfiguration](../../devkit/index#readallworkspaceconfiguration)\n- [readCachedProjectGraph](../../devkit/index#readcachedprojectgraph)\n- [readJson](../../devkit/index#readjson)\n- [readJsonFile](../../devkit/index#readjsonfile)\n- [readNxJson](../../devkit/index#readnxjson)\n- [readProjectConfiguration](../../devkit/index#readprojectconfiguration)\n- [readTargetOptions](../../devkit/index#readtargetoptions)\n- [readWorkspaceConfiguration](../../devkit/index#readworkspaceconfiguration)\n- [removeDependenciesFromPackageJson](../../devkit/index#removedependenciesfrompackagejson)\n- [removeProjectConfiguration](../../devkit/index#removeprojectconfiguration)\n- [reverse](../../devkit/index#reverse)\n- [runExecutor](../../devkit/index#runexecutor)\n- [serializeJson](../../devkit/index#serializejson)\n- [stripIndents](../../devkit/index#stripindents)\n- [stripJsonComments](../../devkit/index#stripjsoncomments)\n- [targetToTargetString](../../devkit/index#targettotargetstring)\n- [toJS](../../devkit/index#tojs)\n- [updateJson](../../devkit/index#updatejson)\n- [updateProjectConfiguration](../../devkit/index#updateprojectconfiguration)\n- [updateTsConfigsToJs](../../devkit/index#updatetsconfigstojs)\n- [updateWorkspaceConfiguration](../../devkit/index#updateworkspaceconfiguration)\n- [visitNotIgnoredFiles](../../devkit/index#visitnotignoredfiles)\n- [workspaceLayout](../../devkit/index#workspacelayout)\n- [writeJson](../../devkit/index#writejson)\n- [writeJsonFile](../../devkit/index#writejsonfile)\n\n## Project Graph Enumerations\n\n### DependencyType\n\n• **DependencyType**: `Object`\n\n---\n\n## Utils Enumerations\n\n### ChangeType\n\n• **ChangeType**: `Object`\n\n## Project Graph Classes\n\n### ProjectGraphBuilder\n\n• **ProjectGraphBuilder**: `Object`\n\n---\n\n## Utils Classes\n\n### Hasher\n\n• **Hasher**: `Object`\n\n---\n\n## Workspace Classes\n\n### Workspaces\n\n• **Workspaces**: `Object`\n\n## Commands Interfaces\n\n### Target\n\n• **Target**: `Object`\n\n---\n\n## Other Interfaces\n\n### NxPlugin\n\n• **NxPlugin**: `Object`\n\nA plugin for Nx\n\n---\n\n## Project Graph Interfaces\n\n### FileData\n\n• **FileData**: `Object`\n\n---\n\n### ProjectFileMap\n\n• **ProjectFileMap**: `Object`\n\n---\n\n### ProjectGraph\n\n• **ProjectGraph**<`T`\\>: `Object`\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n---\n\n### ProjectGraphDependency\n\n• **ProjectGraphDependency**: `Object`\n\n---\n\n### ProjectGraphExternalNode\n\n• **ProjectGraphExternalNode**: `Object`\n\n---\n\n### ProjectGraphProcessorContext\n\n• **ProjectGraphProcessorContext**: `Object`\n\n---\n\n### ProjectGraphProjectNode\n\n• **ProjectGraphProjectNode**<`T`\\>: `Object`\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n---\n\n### ProjectGraphV4\n\n• **ProjectGraphV4**<`T`\\>: `Object`\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n---\n\n## Tree Interfaces\n\n### FileChange\n\n• **FileChange**: `Object`\n\n---\n\n### Tree\n\n• **Tree**: `Object`\n\n---\n\n## Utils Interfaces\n\n### DefaultTasksRunnerOptions\n\n• **DefaultTasksRunnerOptions**: `Object`\n\n---\n\n### Hash\n\n• **Hash**: `Object`\n\n---\n\n### JsonParseOptions\n\n• **JsonParseOptions**: `Object`\n\n---\n\n### JsonSerializeOptions\n\n• **JsonSerializeOptions**: `Object`\n\n---\n\n### RemoteCache\n\n• **RemoteCache**: `Object`\n\n---\n\n### StringDeletion\n\n• **StringDeletion**: `Object`\n\n---\n\n### StringInsertion\n\n• **StringInsertion**: `Object`\n\n---\n\n## Workspace Interfaces\n\n### ExecutorContext\n\n• **ExecutorContext**: `Object`\n\n---\n\n### ExecutorsJson\n\n• **ExecutorsJson**: `Object`\n\n---\n\n### GeneratorsJson\n\n• **GeneratorsJson**: `Object`\n\n---\n\n### HasherContext\n\n• **HasherContext**: `Object`\n\n---\n\n### ImplicitJsonSubsetDependency\n\n• **ImplicitJsonSubsetDependency**<`T`\\>: `Object`\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :------------------ |\n| `T` | `\"*\"` \\| `string`[] |\n\n---\n\n### MigrationsJson\n\n• **MigrationsJson**: `Object`\n\n---\n\n### NxAffectedConfig\n\n• **NxAffectedConfig**: `Object`\n\n---\n\n### NxJsonConfiguration\n\n• **NxJsonConfiguration**<`T`\\>: `Object`\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :------------------ |\n| `T` | `\"*\"` \\| `string`[] |\n\n---\n\n### ProjectConfiguration\n\n• **ProjectConfiguration**: `Object`\n\n---\n\n### ProjectsConfigurations\n\n• **ProjectsConfigurations**: `Object`\n\n---\n\n### TargetConfiguration\n\n• **TargetConfiguration**: `Object`\n\n---\n\n### TargetDependencyConfig\n\n• **TargetDependencyConfig**: `Object`\n\n---\n\n### Task\n\n• **Task**: `Object`\n\n---\n\n### TaskGraph\n\n• **TaskGraph**: `Object`\n\n---\n\n### Workspace\n\n• **Workspace**: `Object`\n\n## Generators Type aliases\n\n### WorkspaceConfiguration\n\nƬ **WorkspaceConfiguration**: `Omit`<[`ProjectsConfigurations`](../../devkit/index#projectsconfigurations), `\"projects\"`\\> & `Partial`<[`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)\\>\n\n---\n\n## Other Type aliases\n\n### ProjectTargetConfigurator\n\nƬ **ProjectTargetConfigurator**: (`file`: `string`) => `Record`<`string`, [`TargetConfiguration`](../../devkit/index#targetconfiguration)\\>\n\n#### Type declaration\n\n▸ (`file`): `Record`<`string`, [`TargetConfiguration`](../../devkit/index#targetconfiguration)\\>\n\n##### Parameters\n\n| Name | Type |\n| :----- | :------- |\n| `file` | `string` |\n\n##### Returns\n\n`Record`<`string`, [`TargetConfiguration`](../../devkit/index#targetconfiguration)\\>\n\n---\n\n## Package Manager Type aliases\n\n### PackageManager\n\nƬ **PackageManager**: `\"yarn\"` \\| `\"pnpm\"` \\| `\"npm\"`\n\n---\n\n## Project Graph Type aliases\n\n### ProjectGraphNode\n\nƬ **ProjectGraphNode**<`T`\\>: [`ProjectGraphProjectNode`](../../devkit/index#projectgraphprojectnode)<`T`\\> \\| [`ProjectGraphExternalNode`](../../devkit/index#projectgraphexternalnode)\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n---\n\n## Utils Type aliases\n\n### StringChange\n\nƬ **StringChange**: [`StringInsertion`](../../devkit/index#stringinsertion) \\| [`StringDeletion`](../../devkit/index#stringdeletion)\n\n---\n\n## Workspace Type aliases\n\n### CustomHasher\n\nƬ **CustomHasher**: (`task`: [`Task`](../../devkit/index#task), `context`: [`HasherContext`](../../devkit/index#hashercontext)) => `Promise`<[`Hash`](../../devkit/index#hash)\\>\n\n#### Type declaration\n\n▸ (`task`, `context`): `Promise`<[`Hash`](../../devkit/index#hash)\\>\n\n##### Parameters\n\n| Name | Type |\n| :-------- | :-------------------------------------------------- |\n| `task` | [`Task`](../../devkit/index#task) |\n| `context` | [`HasherContext`](../../devkit/index#hashercontext) |\n\n##### Returns\n\n`Promise`<[`Hash`](../../devkit/index#hash)\\>\n\n---\n\n### Executor\n\nƬ **Executor**<`T`\\>: (`options`: `T`, `context`: [`ExecutorContext`](../../devkit/index#executorcontext)) => `Promise`<`Object`\\> \\| `AsyncIterableIterator`<`Object`\\>\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n#### Type declaration\n\n▸ (`options`, `context`): `Promise`<`Object`\\> \\| `AsyncIterableIterator`<`Object`\\>\n\nImplementation of a target of a project\n\n##### Parameters\n\n| Name | Type |\n| :-------- | :------------------------------------------------------ |\n| `options` | `T` |\n| `context` | [`ExecutorContext`](../../devkit/index#executorcontext) |\n\n##### Returns\n\n`Promise`<`Object`\\> \\| `AsyncIterableIterator`<`Object`\\>\n\n---\n\n### Generator\n\nƬ **Generator**<`T`\\>: (`tree`: `any`, `schema`: `T`) => `void` \\| [`GeneratorCallback`](../../devkit/index#generatorcallback) \\| `Promise`<`void` \\| [`GeneratorCallback`](../../devkit/index#generatorcallback)\\>\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :-------- |\n| `T` | `unknown` |\n\n#### Type declaration\n\n▸ (`tree`, `schema`): `void` \\| [`GeneratorCallback`](../../devkit/index#generatorcallback) \\| `Promise`<`void` \\| [`GeneratorCallback`](../../devkit/index#generatorcallback)\\>\n\nA function that schedules updates to the filesystem to be done atomically\n\n##### Parameters\n\n| Name | Type |\n| :------- | :---- |\n| `tree` | `any` |\n| `schema` | `T` |\n\n##### Returns\n\n`void` \\| [`GeneratorCallback`](../../devkit/index#generatorcallback) \\| `Promise`<`void` \\| [`GeneratorCallback`](../../devkit/index#generatorcallback)\\>\n\n---\n\n### GeneratorCallback\n\nƬ **GeneratorCallback**: () => `void` \\| `Promise`<`void`\\>\n\n#### Type declaration\n\n▸ (): `void` \\| `Promise`<`void`\\>\n\nA callback function that is executed after changes are made to the file system\n\n##### Returns\n\n`void` \\| `Promise`<`void`\\>\n\n---\n\n### ImplicitDependencyEntry\n\nƬ **ImplicitDependencyEntry**<`T`\\>: `Object`\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :------------------ |\n| `T` | `\"*\"` \\| `string`[] |\n\n#### Index signature\n\n▪ [key: `string`]: `T` \\| [`ImplicitJsonSubsetDependency`](../../devkit/index#implicitjsonsubsetdependency)<`T`\\>\n\n---\n\n### ProjectType\n\nƬ **ProjectType**: `\"library\"` \\| `\"application\"`\n\n---\n\n### TaskGraphExecutor\n\nƬ **TaskGraphExecutor**<`T`\\>: (`taskGraph`: [`TaskGraph`](../../devkit/index#taskgraph), `options`: `Record`<`string`, `T`\\>, `overrides`: `T`, `context`: [`ExecutorContext`](../../devkit/index#executorcontext)) => `Promise`<`Record`<`string`, `Object`\\>\\>\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n#### Type declaration\n\n▸ (`taskGraph`, `options`, `overrides`, `context`): `Promise`<`Record`<`string`, `Object`\\>\\>\n\nImplementation of a target of a project that handles multiple projects to be batched\n\n##### Parameters\n\n| Name | Type |\n| :---------- | :------------------------------------------------------ |\n| `taskGraph` | [`TaskGraph`](../../devkit/index#taskgraph) |\n| `options` | `Record`<`string`, `T`\\> |\n| `overrides` | `T` |\n| `context` | [`ExecutorContext`](../../devkit/index#executorcontext) |\n\n##### Returns\n\n`Promise`<`Record`<`string`, `Object`\\>\\>\n\n---\n\n### WorkspaceJsonConfiguration\n\nƬ **WorkspaceJsonConfiguration**: [`ProjectsConfigurations`](../../devkit/index#projectsconfigurations)\n\n## Logger Variables\n\n### logger\n\n• **logger**: `Object`\n\n#### Type declaration\n\n| Name | Type |\n| :------ | :-------------------------- |\n| `debug` | (...`s`: `any`[]) => `void` |\n| `error` | (`s`: `any`) => `void` |\n| `fatal` | (...`s`: `any`[]) => `void` |\n| `info` | (`s`: `any`) => `void` |\n| `log` | (...`s`: `any`[]) => `void` |\n| `warn` | (`s`: `any`) => `void` |\n\n---\n\n## Utils Variables\n\n### appRootPath\n\n• **appRootPath**: `string` = `workspaceRoot`\n\n---\n\n### cacheDir\n\n• **cacheDir**: `string`\n\n---\n\n### output\n\n• **output**: `CLIOutput`\n\n---\n\n### workspaceRoot\n\n• **workspaceRoot**: `string`\n\n## Functions\n\n### addDependenciesToPackageJson\n\n▸ **addDependenciesToPackageJson**(`tree`, `dependencies`, `devDependencies`, `packageJsonPath?`): [`GeneratorCallback`](../../devkit/index#generatorcallback)\n\nAdd Dependencies and Dev Dependencies to package.json\n\nFor example:\n\n```typescript\naddDependenciesToPackageJson(tree, { react: 'latest' }, { jest: 'latest' });\n```\n\nThis will **add** `react` and `jest` to the dependencies and devDependencies sections of package.json respectively.\n\n#### Parameters\n\n| Name | Type | Default value | Description |\n| :---------------- | :-------------------------------- | :--------------- | :---------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | `undefined` | Tree representing file system to modify |\n| `dependencies` | `Record`<`string`, `string`\\> | `undefined` | Dependencies to be added to the dependencies section of package.json |\n| `devDependencies` | `Record`<`string`, `string`\\> | `undefined` | Dependencies to be added to the devDependencies section of package.json |\n| `packageJsonPath` | `string` | `'package.json'` | Path to package.json |\n\n#### Returns\n\n[`GeneratorCallback`](../../devkit/index#generatorcallback)\n\nCallback to install dependencies only if necessary. undefined is returned if changes are not necessary.\n\n---\n\n### addProjectConfiguration\n\n▸ **addProjectConfiguration**(`tree`, `projectName`, `projectConfiguration`, `standalone?`): `void`\n\nAdds project configuration to the Nx workspace.\n\nThe project configuration is stored in workspace.json or the associated project.json file.\nThe utility will update either files.\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------------------- | :---------------------------------------------------------------- | :----------------------------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |\n| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) |\n| `projectConfiguration` | [`ProjectConfiguration`](../../devkit/index#projectconfiguration) | project configuration |\n| `standalone?` | `boolean` | should the project use package.json? If false, the project config is inside workspace.json |\n\n#### Returns\n\n`void`\n\n---\n\n### applyChangesToString\n\n▸ **applyChangesToString**(`text`, `changes`): `string`\n\nApplies a list of changes to a string's original value.\n\nThis is useful when working with ASTs.\n\nFor Example, to rename a property in a method's options:\n\n```typescript\nconst code = `bootstrap({\n target: document.querySelector('#app')\n})`;\n\nconst indexOfPropertyName = 13; // Usually determined by analyzing an AST.\nconst updatedCode = applyChangesToString(code, [\n {\n type: ChangeType.Insert,\n index: indexOfPropertyName,\n text: 'element',\n },\n {\n type: ChangeType.Delete,\n start: indexOfPropertyName,\n length: 6,\n },\n]);\n\nbootstrap({\n element: document.querySelector('#app'),\n});\n```\n\n#### Parameters\n\n| Name | Type |\n| :-------- | :-------------------------------------------------- |\n| `text` | `string` |\n| `changes` | [`StringChange`](../../devkit/index#stringchange)[] |\n\n#### Returns\n\n`string`\n\n---\n\n### convertNxExecutor\n\n▸ **convertNxExecutor**(`executor`): `any`\n\nConvert an Nx Executor into an Angular Devkit Builder\n\nUse this to expose a compatible Angular Builder\n\n#### Parameters\n\n| Name | Type |\n| :--------- | :------------------------------------------------ |\n| `executor` | [`Executor`](../../devkit/index#executor)<`any`\\> |\n\n#### Returns\n\n`any`\n\n---\n\n### convertNxGenerator\n\n▸ **convertNxGenerator**<`T`\\>(`generator`, `skipWritingConfigInOldFormat?`): (`generatorOptions`: `T`) => (`tree`: `any`, `context`: `any`) => `Promise`<`any`\\>\n\nConvert an Nx Generator into an Angular Devkit Schematic.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n#### Parameters\n\n| Name | Type | Default value | Description |\n| :----------------------------- | :------------------------------------------------ | :------------ | :------------------------------------------------------------------------------------------------ |\n| `generator` | [`Generator`](../../devkit/index#generator)<`T`\\> | `undefined` | The Nx generator to convert to an Angular Devkit Schematic. |\n| `skipWritingConfigInOldFormat` | `boolean` | `false` | Whether to skip writing the configuration in the old format (the one used by the Angular DevKit). |\n\n#### Returns\n\n`fn`\n\n▸ (`generatorOptions`): (`tree`: `any`, `context`: `any`) => `Promise`<`any`\\>\n\n##### Parameters\n\n| Name | Type |\n| :----------------- | :--- |\n| `generatorOptions` | `T` |\n\n##### Returns\n\n`fn`\n\n▸ (`tree`, `context`): `Promise`<`any`\\>\n\n##### Parameters\n\n| Name | Type |\n| :-------- | :---- |\n| `tree` | `any` |\n| `context` | `any` |\n\n##### Returns\n\n`Promise`<`any`\\>\n\n---\n\n### createProjectGraphAsync\n\n▸ **createProjectGraphAsync**(): `Promise`<[`ProjectGraph`](../../devkit/index#projectgraph)\\>\n\nComputes and returns a ProjectGraph.\n\nNx will compute the graph either in a daemon process or in the current process.\n\nNx will compute it in the current process if:\n\n- The process is running in CI (CI env variable is to true or other common variables used by CI providers are set).\n- It is running in the docker container.\n- The daemon process is disabled because of the previous error when starting the daemon.\n- `NX_DAEMON` is set to `false`.\n- `useDaemon` is set to false in `nx.json`\n\n`NX_DAEMON` env variable takes precedence:\n\n- If it is set to true, the daemon will always be used.\n- If it is set to false, the graph will always be computed in the current process.\n\nTip: If you want to debug project graph creation, run your command with NX_DAEMON=false.\n\nNx uses two layers of caching: the information about explicit dependencies stored on the disk and the information\nstored in the daemon process. To reset both run: `nx reset`.\n\n#### Returns\n\n`Promise`<[`ProjectGraph`](../../devkit/index#projectgraph)\\>\n\n---\n\n### defaultTasksRunner\n\n▸ `Const` **defaultTasksRunner**(`tasks`, `options`, `context?`): `any`\n\n#### Parameters\n\n| Name | Type |\n| :--------------------------- | :------------------------------------------------------------------------------------ |\n| `tasks` | [`Task`](../../devkit/index#task)[] |\n| `options` | [`DefaultTasksRunnerOptions`](../../devkit/index#defaulttasksrunneroptions) |\n| `context?` | `Object` |\n| `context.initiatingProject?` | `string` |\n| `context.nxArgs` | `NxArgs` |\n| `context.nxJson` | [`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)<`string`[] \\| `\"*\"`\\> |\n| `context.projectGraph` | [`ProjectGraph`](../../devkit/index#projectgraph)<`any`\\> |\n| `context.target?` | `string` |\n| `context.taskGraph?` | [`TaskGraph`](../../devkit/index#taskgraph) |\n\n#### Returns\n\n`any`\n\n---\n\n### detectPackageManager\n\n▸ **detectPackageManager**(`dir?`): [`PackageManager`](../../devkit/index#packagemanager)\n\nDetects which package manager is used in the workspace based on the lock file.\n\n#### Parameters\n\n| Name | Type | Default value |\n| :---- | :------- | :------------ |\n| `dir` | `string` | `''` |\n\n#### Returns\n\n[`PackageManager`](../../devkit/index#packagemanager)\n\n---\n\n### formatFiles\n\n▸ **formatFiles**(`tree`): `Promise`<`void`\\>\n\nFormats all the created or updated files using Prettier\n\n#### Parameters\n\n| Name | Type | Description |\n| :----- | :-------------------------------- | :------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |\n\n#### Returns\n\n`Promise`<`void`\\>\n\n---\n\n### generateFiles\n\n▸ **generateFiles**(`tree`, `srcFolder`, `target`, `substitutions`): `void`\n\nGenerates a folder of files based on provided templates.\n\nWhile doing so it performs two substitutions:\n\n- Substitutes segments of file names surrounded by \\_\\_\n- Uses ejs to substitute values in templates\n\nExamples:\n\n```typescript\ngenerateFiles(tree, path.join(__dirname, 'files'), './tools/scripts', {\n tmpl: '',\n name: 'myscript',\n});\n```\n\nThis command will take all the files from the `files` directory next to the place where the command is invoked from.\nIt will replace all `__tmpl__` with '' and all `__name__` with 'myscript' in the file names, and will replace all\n`<%= name %>` with `myscript` in the files themselves.\n`tmpl: ''` is a common pattern. With it you can name files like this: `index.ts__tmpl__`, so your editor\ndoesn't get confused about incorrect TypeScript files.\n\n#### Parameters\n\n| Name | Type | Description |\n| :-------------- | :-------------------------------- | :-------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |\n| `srcFolder` | `string` | the source folder of files (absolute path) |\n| `target` | `string` | the target folder (relative to the tree root) |\n| `substitutions` | `Object` | an object of key-value pairs |\n\n#### Returns\n\n`void`\n\n---\n\n### getOutputsForTargetAndConfiguration\n\n▸ **getOutputsForTargetAndConfiguration**(`task`, `node`): `any`\n\nReturns the list of outputs that will be cached.\n\n#### Parameters\n\n| Name | Type | Description |\n| :----- | :------------------------------------------------------------------------------ | :-------------------------------------------------------- |\n| `task` | `Pick`<[`Task`](../../devkit/index#task), `\"target\"` \\| `\"overrides\"`\\> | target + overrides |\n| `node` | [`ProjectGraphProjectNode`](../../devkit/index#projectgraphprojectnode)<`any`\\> | ProjectGraphProjectNode object that the task runs against |\n\n#### Returns\n\n`any`\n\n---\n\n### getPackageManagerCommand\n\n▸ **getPackageManagerCommand**(`packageManager?`): `PackageManagerCommands`\n\nReturns commands for the package manager used in the workspace.\nBy default, the package manager is derived based on the lock file,\nbut it can also be passed in explicitly.\n\nExample:\n\n```javascript\nexecSync(`${getPackageManagerCommand().addDev} my-dev-package`);\n```\n\n#### Parameters\n\n| Name | Type |\n| :--------------- | :---------------------------------------------------- |\n| `packageManager` | [`PackageManager`](../../devkit/index#packagemanager) |\n\n#### Returns\n\n`PackageManagerCommands`\n\n---\n\n### getPackageManagerVersion\n\n▸ **getPackageManagerVersion**(`packageManager?`): `string`\n\nReturns the version of the package manager used in the workspace.\nBy default, the package manager is derived based on the lock file,\nbut it can also be passed in explicitly.\n\n#### Parameters\n\n| Name | Type |\n| :--------------- | :---------------------------------------------------- |\n| `packageManager` | [`PackageManager`](../../devkit/index#packagemanager) |\n\n#### Returns\n\n`string`\n\n---\n\n### getProjects\n\n▸ **getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../devkit/index#projectconfiguration)\\>\n\nGet a map of all projects in a workspace.\n\nUse [readProjectConfiguration](../../devkit/index#readprojectconfiguration) if only one project is needed.\n\n#### Parameters\n\n| Name | Type |\n| :----- | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n\n#### Returns\n\n`Map`<`string`, [`ProjectConfiguration`](../../devkit/index#projectconfiguration)\\>\n\n---\n\n### getWorkspaceLayout\n\n▸ **getWorkspaceLayout**(`tree`): `Object`\n\nReturns workspace defaults. It includes defaults folders for apps and libs,\nand the default scope.\n\nExample:\n\n```typescript\n{ appsDir: 'apps', libsDir: 'libs', npmScope: 'myorg' }\n```\n\n#### Parameters\n\n| Name | Type | Description |\n| :----- | :-------------------------------- | :--------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | file system tree |\n\n#### Returns\n\n`Object`\n\n| Name | Type |\n| :-------------------- | :-------- |\n| `appsDir` | `string` |\n| `libsDir` | `string` |\n| `npmScope` | `string` |\n| `standaloneAsDefault` | `boolean` |\n\n---\n\n### getWorkspacePath\n\n▸ **getWorkspacePath**(`tree`): `\"/angular.json\"` \\| `\"/workspace.json\"` \\| `null`\n\n#### Parameters\n\n| Name | Type |\n| :----- | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n\n#### Returns\n\n`\"/angular.json\"` \\| `\"/workspace.json\"` \\| `null`\n\n---\n\n### installPackagesTask\n\n▸ **installPackagesTask**(`tree`, `alwaysRun?`, `cwd?`, `packageManager?`): `void`\n\nRuns `npm install` or `yarn install`. It will skip running the install if\n`package.json` hasn't changed at all or it hasn't changed since the last invocation.\n\n#### Parameters\n\n| Name | Type | Default value | Description |\n| :--------------- | :---------------------------------------------------- | :------------ | :------------------------------------------------------------ |\n| `tree` | [`Tree`](../../devkit/index#tree) | `undefined` | the file system tree |\n| `alwaysRun` | `boolean` | `false` | always run the command even if `package.json` hasn't changed. |\n| `cwd` | `string` | `''` | - |\n| `packageManager` | [`PackageManager`](../../devkit/index#packagemanager) | `undefined` | - |\n\n#### Returns\n\n`void`\n\n---\n\n### isStandaloneProject\n\n▸ **isStandaloneProject**(`tree`, `project`): `boolean`\n\nReturns if a project has a standalone configuration (project.json).\n\n#### Parameters\n\n| Name | Type | Description |\n| :-------- | :-------------------------------- | :------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |\n| `project` | `string` | the project name |\n\n#### Returns\n\n`boolean`\n\n---\n\n### joinPathFragments\n\n▸ **joinPathFragments**(...`fragments`): `string`\n\nNormalized path fragments and joins them\n\n#### Parameters\n\n| Name | Type |\n| :------------- | :--------- |\n| `...fragments` | `string`[] |\n\n#### Returns\n\n`string`\n\n---\n\n### moveFilesToNewDirectory\n\n▸ **moveFilesToNewDirectory**(`tree`, `oldDir`, `newDir`): `void`\n\nAnalogous to cp -r oldDir newDir\n\n#### Parameters\n\n| Name | Type |\n| :------- | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n| `oldDir` | `string` |\n| `newDir` | `string` |\n\n#### Returns\n\n`void`\n\n---\n\n### names\n\n▸ **names**(`name`): `Object`\n\nUtil function to generate different strings based off the provided name.\n\nExamples:\n\n```typescript\nnames('my-name'); // {name: 'my-name', className: 'MyName', propertyName: 'myName', constantName: 'MY_NAME', fileName: 'my-name'}\nnames('myName'); // {name: 'myName', className: 'MyName', propertyName: 'myName', constantName: 'MY_NAME', fileName: 'my-name'}\n```\n\n#### Parameters\n\n| Name | Type |\n| :----- | :------- |\n| `name` | `string` |\n\n#### Returns\n\n`Object`\n\n| Name | Type |\n| :------------- | :------- |\n| `className` | `string` |\n| `constantName` | `string` |\n| `fileName` | `string` |\n| `name` | `string` |\n| `propertyName` | `string` |\n\n---\n\n### normalizePath\n\n▸ **normalizePath**(`osSpecificPath`): `string`\n\nCoverts an os specific path to a unix style path\n\n#### Parameters\n\n| Name | Type |\n| :--------------- | :------- |\n| `osSpecificPath` | `string` |\n\n#### Returns\n\n`string`\n\n---\n\n### offsetFromRoot\n\n▸ **offsetFromRoot**(`fullPathToDir`): `string`\n\nCalculates an offset from the root of the workspace, which is useful for\nconstructing relative URLs.\n\nExamples:\n\n```typescript\noffsetFromRoot('apps/mydir/myapp/'); // returns \"../../../\"\n```\n\n#### Parameters\n\n| Name | Type | Description |\n| :-------------- | :------- | :------------- |\n| `fullPathToDir` | `string` | directory path |\n\n#### Returns\n\n`string`\n\n---\n\n### parseJson\n\n▸ **parseJson**<`T`\\>(`input`, `options?`): `T`\n\nParses the given JSON string and returns the object the JSON content represents.\nBy default javascript-style comments are allowed.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :----------------------- |\n| `T` | extends `object` = `any` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :-------------------------------------------------------- | :--------------------- |\n| `input` | `string` | JSON content as string |\n| `options?` | [`JsonParseOptions`](../../devkit/index#jsonparseoptions) | JSON parse options |\n\n#### Returns\n\n`T`\n\nObject the JSON content represents\n\n---\n\n### parseTargetString\n\n▸ **parseTargetString**(`targetString`): [`Target`](../../devkit/index#target)\n\nParses a target string into {project, target, configuration}\n\nExamples:\n\n```typescript\nparseTargetString('proj:test'); // returns { project: \"proj\", target: \"test\" }\nparseTargetString('proj:test:production'); // returns { project: \"proj\", target: \"test\", configuration: \"production\" }\n```\n\n#### Parameters\n\n| Name | Type | Description |\n| :------------- | :------- | :--------------- |\n| `targetString` | `string` | target reference |\n\n#### Returns\n\n[`Target`](../../devkit/index#target)\n\n---\n\n### readAllWorkspaceConfiguration\n\n▸ **readAllWorkspaceConfiguration**(): [`ProjectsConfigurations`](../../devkit/index#projectsconfigurations) & [`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)\n\n#### Returns\n\n[`ProjectsConfigurations`](../../devkit/index#projectsconfigurations) & [`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)\n\n---\n\n### readCachedProjectGraph\n\n▸ **readCachedProjectGraph**(): [`ProjectGraph`](../../devkit/index#projectgraph)\n\nSynchronously reads the latest cached copy of the workspace's ProjectGraph.\n\n**`throws`** {Error} if there is no cached ProjectGraph to read from\n\n#### Returns\n\n[`ProjectGraph`](../../devkit/index#projectgraph)\n\n---\n\n### readJson\n\n▸ **readJson**<`T`\\>(`tree`, `path`, `options?`): `T`\n\nReads a json file, removes all comments and parses JSON.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :----------------------- |\n| `T` | extends `object` = `any` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :-------------------------------------------------------- | :-------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | file system tree |\n| `path` | `string` | file path |\n| `options?` | [`JsonParseOptions`](../../devkit/index#jsonparseoptions) | Optional JSON Parse Options |\n\n#### Returns\n\n`T`\n\n---\n\n### readJsonFile\n\n▸ **readJsonFile**<`T`\\>(`path`, `options?`): `T`\n\nReads a JSON file and returns the object the JSON content represents.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :----------------------- |\n| `T` | extends `object` = `any` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :---------------- | :----------------- |\n| `path` | `string` | A path to a file. |\n| `options?` | `JsonReadOptions` | JSON parse options |\n\n#### Returns\n\n`T`\n\nObject the JSON content of the file represents\n\n---\n\n### readNxJson\n\n▸ **readNxJson**(): [`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)\n\n#### Returns\n\n[`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)\n\n---\n\n### readProjectConfiguration\n\n▸ **readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../devkit/index#projectconfiguration)\n\nReads a project configuration.\n\nThe project configuration is stored in workspace.json or the associated project.json file.\nThe utility will read from either file.\n\n**`throws`** If supplied projectName cannot be found\n\n#### Parameters\n\n| Name | Type | Description |\n| :------------ | :-------------------------------- | :---------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |\n| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) |\n\n#### Returns\n\n[`ProjectConfiguration`](../../devkit/index#projectconfiguration)\n\n---\n\n### readTargetOptions\n\n▸ **readTargetOptions**<`T`\\>(`__namedParameters`, `context`): `T`\n\nReads and combines options for a given target.\n\nWorks as if you invoked the target yourself without passing any command lint overrides.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :---- |\n| `T` | `any` |\n\n#### Parameters\n\n| Name | Type |\n| :------------------ | :------------------------------------------------------ |\n| `__namedParameters` | [`Target`](../../devkit/index#target) |\n| `context` | [`ExecutorContext`](../../devkit/index#executorcontext) |\n\n#### Returns\n\n`T`\n\n---\n\n### readWorkspaceConfiguration\n\n▸ **readWorkspaceConfiguration**(`tree`): [`WorkspaceConfiguration`](../../devkit/index#workspaceconfiguration)\n\nRead general workspace configuration such as the default project or cli settings\n\nThis does _not_ provide projects configuration, use [readProjectConfiguration](../../devkit/index#readprojectconfiguration) instead.\n\n#### Parameters\n\n| Name | Type |\n| :----- | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n\n#### Returns\n\n[`WorkspaceConfiguration`](../../devkit/index#workspaceconfiguration)\n\n---\n\n### removeDependenciesFromPackageJson\n\n▸ **removeDependenciesFromPackageJson**(`tree`, `dependencies`, `devDependencies`, `packageJsonPath?`): [`GeneratorCallback`](../../devkit/index#generatorcallback)\n\nRemove Dependencies and Dev Dependencies from package.json\n\nFor example:\n\n```typescript\nremoveDependenciesFromPackageJson(tree, ['react'], ['jest']);\n```\n\nThis will **remove** `react` and `jest` from the dependencies and devDependencies sections of package.json respectively.\n\n#### Parameters\n\n| Name | Type | Default value | Description |\n| :---------------- | :-------------------------------- | :--------------- | :-------------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | `undefined` | - |\n| `dependencies` | `string`[] | `undefined` | Dependencies to be removed from the dependencies section of package.json |\n| `devDependencies` | `string`[] | `undefined` | Dependencies to be removed from the devDependencies section of package.json |\n| `packageJsonPath` | `string` | `'package.json'` | - |\n\n#### Returns\n\n[`GeneratorCallback`](../../devkit/index#generatorcallback)\n\nCallback to uninstall dependencies only if necessary. undefined is returned if changes are not necessary.\n\n---\n\n### removeProjectConfiguration\n\n▸ **removeProjectConfiguration**(`tree`, `projectName`): `void`\n\nRemoves the configuration of an existing project.\n\nThe project configuration is stored in workspace.json or the associated project.json file.\nThe utility will update either file.\n\n#### Parameters\n\n| Name | Type |\n| :------------ | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n| `projectName` | `string` |\n\n#### Returns\n\n`void`\n\n---\n\n### reverse\n\n▸ **reverse**(`graph`): [`ProjectGraph`](../../devkit/index#projectgraph)\n\nReturns a new project graph where all the edges are reversed.\n\nFor instance, if project A depends on B, in the reversed graph\nB will depend on A.\n\n#### Parameters\n\n| Name | Type |\n| :------ | :-------------------------------------------------------- |\n| `graph` | [`ProjectGraph`](../../devkit/index#projectgraph)<`any`\\> |\n\n#### Returns\n\n[`ProjectGraph`](../../devkit/index#projectgraph)\n\n---\n\n### runExecutor\n\n▸ **runExecutor**<`T`\\>(`targetDescription`, `options`, `context`): `Promise`<`AsyncIterableIterator`<`T`\\>\\>\n\nLoads and invokes executor.\n\nThis is analogous to invoking executor from the terminal, with the exception\nthat the params aren't parsed from the string, but instead provided parsed already.\n\nApart from that, it works the same way:\n\n- it will load the workspace configuration\n- it will resolve the target\n- it will load the executor and the schema\n- it will load the options for the appropriate configuration\n- it will run the validations and will set the default\n- and, of course, it will invoke the executor\n\nExample:\n\n```typescript\nfor await (const s of await runExecutor(\n { project: 'myproj', target: 'serve' },\n { watch: true },\n context\n)) {\n // s.success\n}\n```\n\nNote that the return value is a promise of an iterator, so you need to await before iterating over it.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :--------------- |\n| `T` | extends `Object` |\n\n#### Parameters\n\n| Name | Type |\n| :--------------------------------- | :------------------------------------------------------ |\n| `targetDescription` | `Object` |\n| `targetDescription.configuration?` | `string` |\n| `targetDescription.project` | `string` |\n| `targetDescription.target` | `string` |\n| `options` | `Object` |\n| `context` | [`ExecutorContext`](../../devkit/index#executorcontext) |\n\n#### Returns\n\n`Promise`<`AsyncIterableIterator`<`T`\\>\\>\n\n---\n\n### serializeJson\n\n▸ **serializeJson**<`T`\\>(`input`, `options?`): `string`\n\nSerializes the given data to a JSON string.\nBy default the JSON string is formatted with a 2 space intendation to be easy readable.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :-------------------------- |\n| `T` | extends `object` = `object` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :---------------------------------------------------------------- | :---------------------------------------- |\n| `input` | `T` | Object which should be serialized to JSON |\n| `options?` | [`JsonSerializeOptions`](../../devkit/index#jsonserializeoptions) | JSON serialize options |\n\n#### Returns\n\n`string`\n\nthe formatted JSON representation of the object\n\n---\n\n### stripIndents\n\n▸ **stripIndents**(`strings`, ...`values`): `string`\n\nRemoves indents, which is useful for printing warning and messages.\n\nExample:\n\n```typescript\nstripIndents`\n Options:\n - option1\n - option2\n`;\n```\n\n#### Parameters\n\n| Name | Type |\n| :---------- | :--------------------- |\n| `strings` | `TemplateStringsArray` |\n| `...values` | `any`[] |\n\n#### Returns\n\n`string`\n\n---\n\n### stripJsonComments\n\n▸ `Const` **stripJsonComments**(`text`, `replaceCh?`): `string`\n\nTakes JSON with JavaScript-style comments and remove\nthem. Optionally replaces every none-newline character\nof comments with a replaceCharacter\n\n#### Parameters\n\n| Name | Type |\n| :----------- | :------- |\n| `text` | `string` |\n| `replaceCh?` | `string` |\n\n#### Returns\n\n`string`\n\n---\n\n### targetToTargetString\n\n▸ **targetToTargetString**(`target`): `string`\n\nReturns a string in the format \"project:target[:configuration]\" for the target\n\n#### Parameters\n\n| Name | Type | Description |\n| :------- | :------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `target` | [`Target`](../../devkit/index#target) | target object Examples: `typescript targetToTargetString({ project: \"proj\", target: \"test\" }) // returns \"proj:test\" targetToTargetString({ project: \"proj\", target: \"test\", configuration: \"production\" }) // returns \"proj:test:production\" ` |\n\n#### Returns\n\n`string`\n\n---\n\n### toJS\n\n▸ **toJS**(`tree`): `void`\n\nRename and transpile any new typescript files created to javascript files\n\n#### Parameters\n\n| Name | Type |\n| :----- | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n\n#### Returns\n\n`void`\n\n---\n\n### updateJson\n\n▸ **updateJson**<`T`, `U`\\>(`tree`, `path`, `updater`, `options?`): `void`\n\nUpdates a JSON value to the file system tree\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :----------------------- |\n| `T` | extends `object` = `any` |\n| `U` | extends `object` = `T` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :---------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | File system tree |\n| `path` | `string` | Path of JSON file in the Tree |\n| `updater` | (`value`: `T`) => `U` | Function that maps the current value of a JSON document to a new value to be written to the document |\n| `options?` | [`JsonParseOptions`](../../devkit/index#jsonparseoptions) & [`JsonSerializeOptions`](../../devkit/index#jsonserializeoptions) | Optional JSON Parse and Serialize Options |\n\n#### Returns\n\n`void`\n\n---\n\n### updateProjectConfiguration\n\n▸ **updateProjectConfiguration**(`tree`, `projectName`, `projectConfiguration`): `void`\n\nUpdates the configuration of an existing project.\n\nThe project configuration is stored in workspace.json or the associated project.json file.\nThe utility will update either files.\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------------------- | :---------------------------------------------------------------- | :---------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |\n| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) |\n| `projectConfiguration` | [`ProjectConfiguration`](../../devkit/index#projectconfiguration) | project configuration |\n\n#### Returns\n\n`void`\n\n---\n\n### updateTsConfigsToJs\n\n▸ **updateTsConfigsToJs**(`tree`, `options`): `void`\n\n#### Parameters\n\n| Name | Type |\n| :-------------------- | :-------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n| `options` | `Object` |\n| `options.projectRoot` | `string` |\n\n#### Returns\n\n`void`\n\n---\n\n### updateWorkspaceConfiguration\n\n▸ **updateWorkspaceConfiguration**(`tree`, `workspaceConfig`): `void`\n\nUpdate general workspace configuration such as the default project or cli settings.\n\nThis does _not_ update projects configuration, use [updateProjectConfiguration](../../devkit/index#updateprojectconfiguration) or [addProjectConfiguration](../../devkit/index#addprojectconfiguration) instead.\n\n#### Parameters\n\n| Name | Type |\n| :---------------- | :-------------------------------------------------------------------- |\n| `tree` | [`Tree`](../../devkit/index#tree) |\n| `workspaceConfig` | [`WorkspaceConfiguration`](../../devkit/index#workspaceconfiguration) |\n\n#### Returns\n\n`void`\n\n---\n\n### visitNotIgnoredFiles\n\n▸ **visitNotIgnoredFiles**(`tree`, `dirPath?`, `visitor`): `void`\n\nUtility to act on all files in a tree that are not ignored by git.\n\n#### Parameters\n\n| Name | Type | Default value |\n| :-------- | :-------------------------------- | :------------ |\n| `tree` | [`Tree`](../../devkit/index#tree) | `undefined` |\n| `dirPath` | `string` | `tree.root` |\n| `visitor` | (`path`: `string`) => `void` | `undefined` |\n\n#### Returns\n\n`void`\n\n---\n\n### workspaceLayout\n\n▸ **workspaceLayout**(): `Object`\n\nReturns information about where apps and libs will be created.\n\n#### Returns\n\n`Object`\n\n| Name | Type |\n| :-------- | :------- |\n| `appsDir` | `string` |\n| `libsDir` | `string` |\n\n---\n\n### writeJson\n\n▸ **writeJson**<`T`\\>(`tree`, `path`, `value`, `options?`): `void`\n\nWrites a JSON value to the file system tree\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :-------------------------- |\n| `T` | extends `object` = `object` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :---------------------------------------------------------------- | :------------------------------ |\n| `tree` | [`Tree`](../../devkit/index#tree) | File system tree |\n| `path` | `string` | Path of JSON file in the Tree |\n| `value` | `T` | Serializable value to write |\n| `options?` | [`JsonSerializeOptions`](../../devkit/index#jsonserializeoptions) | Optional JSON Serialize Options |\n\n#### Returns\n\n`void`\n\n---\n\n### writeJsonFile\n\n▸ **writeJsonFile**<`T`\\>(`path`, `data`, `options?`): `void`\n\nSerializes the given data to JSON and writes it to a file.\n\n#### Type parameters\n\n| Name | Type |\n| :--- | :-------------------------- |\n| `T` | extends `object` = `object` |\n\n#### Parameters\n\n| Name | Type | Description |\n| :--------- | :----------------- | :-------------------------------------------------------------- |\n| `path` | `string` | A path to a file. |\n| `data` | `T` | data which should be serialized to JSON and written to the file |\n| `options?` | `JsonWriteOptions` | JSON serialize options |\n\n#### Returns\n\n`void`\n" }, { "id": "ngcli_adapter", diff --git a/docs/map.json b/docs/map.json index 93e81b3197a30..8634967ff2cce 100644 --- a/docs/map.json +++ b/docs/map.json @@ -870,6 +870,7 @@ "id": "create-nx-workspace", "file": "generated/cli/create-nx-workspace" }, + { "name": "init", "id": "init", "file": "generated/cli/init" }, { "name": "generate", "id": "generate", diff --git a/docs/shared/nx-core.md b/docs/shared/nx-core.md index abc751eb8cae1..f8581bff30f8c 100644 --- a/docs/shared/nx-core.md +++ b/docs/shared/nx-core.md @@ -42,7 +42,6 @@ package.json ```json { "extends": "nx/presets/core.json", - "npmScope": "myorg", "tasksRunnerOptions": { "default": { "runner": "nx/tasks-runners/default", diff --git a/e2e/add-nx-to-monorepo/project.json b/e2e/add-nx-to-monorepo/project.json index 743b6f6cfa18b..7cfa0663599bc 100644 --- a/e2e/add-nx-to-monorepo/project.json +++ b/e2e/add-nx-to-monorepo/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/add-nx-to-monorepo/src/add-nx-to-monorepo.test.ts b/e2e/add-nx-to-monorepo/src/add-nx-to-monorepo.test.ts index 3fbe705f23c95..d7f6ea98c9c3d 100644 --- a/e2e/add-nx-to-monorepo/src/add-nx-to-monorepo.test.ts +++ b/e2e/add-nx-to-monorepo/src/add-nx-to-monorepo.test.ts @@ -23,12 +23,20 @@ describe('add-nx-to-monorepo', () => { 'packages/package-a/package.json', JSON.stringify({ name: 'package-a', + scripts: { + serve: 'some serve', + build: 'some build', + test: 'some test', + }, }) ); updateFile( 'packages/package-b/package.json', JSON.stringify({ name: 'package-b', + scripts: { + lint: 'some lint', + }, }) ); @@ -40,6 +48,13 @@ describe('add-nx-to-monorepo', () => { expect(output).toContain('🎉 Done!'); expect(readWorkspaceConfig().projects['package-a']).toBeTruthy(); expect(readWorkspaceConfig().projects['package-b']).toBeTruthy(); + expect(readWorkspaceConfig().targetDependencies).toEqual({ + build: [{ projects: 'dependencies', target: 'build' }], + }); + expect( + readWorkspaceConfig().tasksRunnerOptions['default'].options + .cacheableOperations + ).toEqual(['build', 'test', 'lint']); } }); diff --git a/e2e/angular-core/project.json b/e2e/angular-core/project.json index 3826612afb6b8..88e063028a720 100644 --- a/e2e/angular-core/project.json +++ b/e2e/angular-core/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/angular-extensions/project.json b/e2e/angular-extensions/project.json index b8e695089aaac..1fadc931e522d 100644 --- a/e2e/angular-extensions/project.json +++ b/e2e/angular-extensions/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/cli/project.json b/e2e/cli/project.json index 6ba1bd5a96e61..88ee366312ca3 100644 --- a/e2e/cli/project.json +++ b/e2e/cli/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/cypress/project.json b/e2e/cypress/project.json index 3639cc278bd12..1b6f131fea924 100644 --- a/e2e/cypress/project.json +++ b/e2e/cypress/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/detox/project.json b/e2e/detox/project.json index fc86bc54142ed..f22adbb59d6a8 100644 --- a/e2e/detox/project.json +++ b/e2e/detox/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/jest/project.json b/e2e/jest/project.json index 0d6732ec1b155..9692e1681abaa 100644 --- a/e2e/jest/project.json +++ b/e2e/jest/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/js/project.json b/e2e/js/project.json index 30e86cf9fc6aa..77032b74bf129 100644 --- a/e2e/js/project.json +++ b/e2e/js/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/linter/project.json b/e2e/linter/project.json index bc12bce15128d..a77df597d2fba 100644 --- a/e2e/linter/project.json +++ b/e2e/linter/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/next/project.json b/e2e/next/project.json index 1f162dba9e106..ba2a3df705579 100644 --- a/e2e/next/project.json +++ b/e2e/next/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/node/project.json b/e2e/node/project.json index a05b5633b10a1..4c1573b9b2705 100644 --- a/e2e/node/project.json +++ b/e2e/node/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/nx-init/jest.config.ts b/e2e/nx-init/jest.config.ts new file mode 100644 index 0000000000000..9fac71516c8f5 --- /dev/null +++ b/e2e/nx-init/jest.config.ts @@ -0,0 +1,10 @@ +export default { + transform: { + '^.+\\.[tj]sx?$': 'ts-jest', + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'], + maxWorkers: 1, + globals: { 'ts-jest': { tsconfig: '/tsconfig.spec.json' } }, + displayName: 'e2e-nx-init', + preset: '../../jest.preset.js', +}; diff --git a/e2e/nx-init/project.json b/e2e/nx-init/project.json new file mode 100644 index 0000000000000..4e79b374b8087 --- /dev/null +++ b/e2e/nx-init/project.json @@ -0,0 +1,34 @@ +{ + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "e2e/nx-init", + "projectType": "application", + "targets": { + "e2e": { + "executor": "nx:run-commands", + "options": { + "commands": [ + { + "command": "yarn e2e-start-local-registry" + }, + { + "command": "yarn e2e-build-package-publish" + }, + { + "command": "nx run-e2e-tests e2e-nx-init" + } + ], + "parallel": false + } + }, + "run-e2e-tests": { + "executor": "@nrwl/jest:jest", + "options": { + "jestConfig": "e2e/nx-init/jest.config.ts", + "passWithNoTests": true, + "runInBand": true + }, + "outputs": ["coverage/e2e/nx-init"] + } + }, + "implicitDependencies": ["nx"] +} diff --git a/e2e/nx-init/src/nx-init.test.ts b/e2e/nx-init/src/nx-init.test.ts new file mode 100644 index 0000000000000..d84e9fbd81355 --- /dev/null +++ b/e2e/nx-init/src/nx-init.test.ts @@ -0,0 +1,37 @@ +import { + createNonNxProjectDirectory, + getPackageManagerCommand, + getSelectedPackageManager, + renameFile, + runCLI, + runCommand, + updateFile, +} from '@nrwl/e2e/utils'; + +describe('nx init', () => { + const packageManagerCommand = getPackageManagerCommand({ + packageManager: getSelectedPackageManager(), + }).runUninstalledPackage; + + it('should work', () => { + createNonNxProjectDirectory(); + updateFile( + 'packages/package/package.json', + JSON.stringify({ + name: 'package', + scripts: { + echo: 'echo 123', + }, + }) + ); + + const output = runCommand(`${packageManagerCommand} nx init`); + expect(output).toContain('Nx has been installed'); + expect(output).toContain('nx.json has been created'); + + expect(runCLI('run package:echo')).toContain('123'); + renameFile('nx.json', 'nx.json.old'); + + expect(runCLI('run package:echo')).toContain('123'); + }); +}); diff --git a/e2e/nx-init/tsconfig.json b/e2e/nx-init/tsconfig.json new file mode 100644 index 0000000000000..6d5abf8483200 --- /dev/null +++ b/e2e/nx-init/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "types": ["node", "jest"] + }, + "include": [], + "files": [], + "references": [ + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/e2e/nx-init/tsconfig.spec.json b/e2e/nx-init/tsconfig.spec.json new file mode 100644 index 0000000000000..1a24bfb0a1353 --- /dev/null +++ b/e2e/nx-init/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "**/*.test.ts", + "**/*.spec.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx", + "**/*.d.ts", + "jest.config.ts" + ] +} diff --git a/e2e/nx-plugin/project.json b/e2e/nx-plugin/project.json index 79168bd818eb4..291f8b45e9157 100644 --- a/e2e/nx-plugin/project.json +++ b/e2e/nx-plugin/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/react-native/project.json b/e2e/react-native/project.json index 8b3a56b31d436..2ca2e0d4019c1 100644 --- a/e2e/react-native/project.json +++ b/e2e/react-native/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/react/project.json b/e2e/react/project.json index a655b56596b9b..b1fc9e38ede36 100644 --- a/e2e/react/project.json +++ b/e2e/react/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/storybook/project.json b/e2e/storybook/project.json index 17837853d4540..13a28e7410e00 100644 --- a/e2e/storybook/project.json +++ b/e2e/storybook/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/utils/index.ts b/e2e/utils/index.ts index 433533bc37fb1..e5e0a05dce658 100644 --- a/e2e/utils/index.ts +++ b/e2e/utils/index.ts @@ -3,7 +3,7 @@ import { parseJson, ProjectConfiguration, readJsonFile, - WorkspaceJsonConfiguration, + ProjectsConfigurations, } from '@nrwl/devkit'; import { angularCliVersion } from '@nrwl/workspace/src/utils/versions'; import { ChildProcess, exec, execSync, ExecSyncOptions } from 'child_process'; @@ -101,7 +101,7 @@ export function updateProjectConfig( * if you need a project's configuration. */ export function readWorkspaceConfig(): Omit< - WorkspaceJsonConfiguration, + ProjectsConfigurations, 'projects' > { const w = readJson(workspaceConfigName()); diff --git a/e2e/web/project.json b/e2e/web/project.json index f93111b14e5b7..b4fc5ccc702f7 100644 --- a/e2e/web/project.json +++ b/e2e/web/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/workspace-core/project.json b/e2e/workspace-core/project.json index aaa664db00425..8e6a5cf2c26ab 100644 --- a/e2e/workspace-core/project.json +++ b/e2e/workspace-core/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/workspace-create/project.json b/e2e/workspace-create/project.json index aca52fae94331..bf0d2d3c1dd65 100644 --- a/e2e/workspace-create/project.json +++ b/e2e/workspace-create/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/e2e/workspace-integrations/project.json b/e2e/workspace-integrations/project.json index 97993369d1056..0da54a74931cd 100644 --- a/e2e/workspace-integrations/project.json +++ b/e2e/workspace-integrations/project.json @@ -4,7 +4,7 @@ "projectType": "application", "targets": { "e2e": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/lerna.json b/lerna.json index 066c3ad2a44e0..ba6471c7e9eac 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "packages": ["build/packages/*"], - "version": "14.1.9", + "version": "14.2.0", "granularPathspec": false, "command": { "publish": { diff --git a/nx-dev/nx-dev/project.json b/nx-dev/nx-dev/project.json index b5732dc3274f4..af347f9b3fa63 100644 --- a/nx-dev/nx-dev/project.json +++ b/nx-dev/nx-dev/project.json @@ -10,28 +10,28 @@ "projects": "self" } ], - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "outputPath": "dist/nx-dev/nx-dev", "command": "nx run nx-dev:sitemap" } }, "sitemap": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": [], "options": { "command": "yarn next-sitemap --config ./nx-dev/nx-dev/next-sitemap.js" } }, "sync-documentation": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["nx-dev/nx-dev/public/documentation"], "options": { "command": "ts-node -P ./scripts/tsconfig.scripts.json ./scripts/documentation/nx-dev-docs-latest-sync.ts" } }, "generate-og-images": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["nx-dev/nx-dev/public/images/open-graph"], "options": { "command": "ts-node -P ./scripts/tsconfig.scripts.json ./scripts/documentation/open-graph/generate-images.ts" @@ -68,7 +68,7 @@ "defaultConfiguration": "development" }, "deploy-build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["nx-dev/nx-dev/public/documentation"], "options": { "commands": [ diff --git a/packages/add-nx-to-monorepo/project.json b/packages/add-nx-to-monorepo/project.json index 568cc0ec91412..88f26a69b2e7b 100644 --- a/packages/add-nx-to-monorepo/project.json +++ b/packages/add-nx-to-monorepo/project.json @@ -37,7 +37,7 @@ } }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/add-nx-to-monorepo"], "options": { "commands": [ @@ -52,7 +52,7 @@ } }, "test-against-repo": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "commands": [ { diff --git a/packages/add-nx-to-monorepo/src/add-nx-to-monorepo.ts b/packages/add-nx-to-monorepo/src/add-nx-to-monorepo.ts index bcb9f05dc5983..a8357b28a3bb3 100644 --- a/packages/add-nx-to-monorepo/src/add-nx-to-monorepo.ts +++ b/packages/add-nx-to-monorepo/src/add-nx-to-monorepo.ts @@ -41,7 +41,7 @@ export async function addNxToMonorepo() { process.exit(1); } - createNxJsonFile(repoRoot); + createNxJsonFile(repoRoot, pds); addDepsToPackageJson(repoRoot, useCloud); @@ -135,6 +135,7 @@ interface ProjectDesc { name: string; dir: string; mainFilePath: string; + scripts: string[]; } function createProjectDesc( @@ -147,61 +148,64 @@ function createProjectDesc( const packageJson = readJsonFile(path.join(repoRoot, p)); if (!packageJson.name) return; + const scripts = Object.keys(packageJson.scripts || {}); if (packageJson.main) { res.push({ name: packageJson.name, dir, mainFilePath: path.join(dir, packageJson.main), + scripts, }); } else if (packageJson.index) { res.push({ name: packageJson.name, dir, mainFilePath: path.join(dir, packageJson.index), + scripts, }); } else { - res.push({ name: packageJson.name, dir, mainFilePath: null }); + res.push({ name: packageJson.name, dir, mainFilePath: null, scripts }); } }); return res; } -function detectWorkspaceScope(repoRoot: string) { - let scope = readJsonFile(path.join(repoRoot, `package.json`)).name; - if (!scope) return 'undetermined'; - - if (scope.startsWith('@')) { - scope = scope.substring(1); +function createNxJsonFile(repoRoot: string, projects: ProjectDesc[]) { + const allScripts = {}; + for (const p of projects) { + for (const s of p.scripts) { + allScripts[s] = true; + } } - return scope.split('/')[0]; -} + const cacheableOperations = Object.keys(allScripts).filter( + (s) => s.indexOf('serve') === -1 && s.indexOf('start') === -1 + ); + const targetDependencies = cacheableOperations + .filter((c) => c === 'build' || c === 'prepare' || c === 'package') + .reduce( + (m, c) => ({ + ...m, + [c]: [{ target: c, projects: 'dependencies' }], + }), + {} + ); -function createNxJsonFile(repoRoot: string) { const res = { - extends: 'nx/presets/npm.json', + extends: 'nx/presets/core.json', tasksRunnerOptions: { default: { runner: 'nx/tasks-runners/default', options: { - cacheableOperations: ['build', 'test', 'lint', 'package', 'prepare'], + cacheableOperations, }, }, }, - targetDependencies: { - build: [{ target: 'build', projects: 'dependencies' }], - prepare: [{ target: 'prepare', projects: 'dependencies' }], - package: [{ target: 'package', projects: 'dependencies' }], - }, + targetDependencies, affected: { defaultBase: deduceDefaultBase(), }, workspaceLayout: deduceWorkspaceLayout(repoRoot), - pluginsConfig: { - '@nrwl/js': { - analyzeSourceFiles: false, - }, - }, }; writeJsonFile(`${repoRoot}/nx.json`, res); diff --git a/packages/angular/project.json b/packages/angular/project.json index c7d79e61021b5..205d1a4e11889 100644 --- a/packages/angular/project.json +++ b/packages/angular/project.json @@ -61,7 +61,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/angular"], "options": { "commands": [ diff --git a/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts index 697945f20e23e..9e601f24de632 100644 --- a/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -1,5 +1,8 @@ import type { Schema } from './schema'; -import { ProjectConfiguration, Workspaces } from '@nrwl/devkit'; +import { + ProjectConfiguration, + readAllWorkspaceConfiguration, +} from '@nrwl/devkit'; import { scheduleTarget } from 'nx/src/adapter/ngcli-adapter'; import { BuilderContext, createBuilder } from '@angular-devkit/architect'; import { JsonObject } from '@angular-devkit/core'; @@ -59,9 +62,7 @@ export function executeModuleFederationDevServerBuilder( schema: Schema, context: BuilderContext ) { - const workspaces = new Workspaces(context.workspaceRoot); - const workspaceConfig = workspaces.readWorkspaceConfiguration(); - + const workspaceConfig = readAllWorkspaceConfiguration(); const p = workspaceConfig.projects[context.target.project]; const mfConfigPath = join( diff --git a/packages/angular/src/builders/webpack-server/webpack-server.impl.ts b/packages/angular/src/builders/webpack-server/webpack-server.impl.ts index 60c003096a895..737625cbc0ea6 100644 --- a/packages/angular/src/builders/webpack-server/webpack-server.impl.ts +++ b/packages/angular/src/builders/webpack-server/webpack-server.impl.ts @@ -4,7 +4,12 @@ import { serveWebpackBrowser, } from '@angular-devkit/build-angular/src/builders/dev-server'; import { JsonObject } from '@angular-devkit/core'; -import { joinPathFragments, parseTargetString, Workspaces } from '@nrwl/devkit'; +import { + joinPathFragments, + parseTargetString, + readAllWorkspaceConfiguration, + Workspaces, +} from '@nrwl/devkit'; import { existsSync } from 'fs'; import { merge } from 'webpack-merge'; import { resolveCustomWebpackConfig } from '../utilities/webpack'; @@ -21,9 +26,7 @@ export function executeWebpackServerBuilder( ); const options = normalizeOptions(schema); - const workspaceConfig = new Workspaces( - context.workspaceRoot - ).readWorkspaceConfiguration(); + const workspaceConfig = readAllWorkspaceConfiguration(); const parsedBrowserTarget = parseTargetString(options.browserTarget); const buildTarget = diff --git a/packages/angular/src/utils/mfe/__snapshots__/with-module-federation.spec.ts.snap b/packages/angular/src/utils/mfe/__snapshots__/with-module-federation.spec.ts.snap deleted file mode 100644 index e0e4ecd6a53e7..0000000000000 --- a/packages/angular/src/utils/mfe/__snapshots__/with-module-federation.spec.ts.snap +++ /dev/null @@ -1,257 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`withModuleFederation should apply additional shared dependencies when specified 1`] = ` -Array [ - ModuleFederationPlugin { - "_options": Object { - "exposes": Object { - "./Module": "apps/remote1/src/module.ts", - }, - "filename": "remoteEntry.mjs", - "library": Object { - "type": "module", - }, - "name": "remote1", - "remotes": Object {}, - "shared": Object { - "@angular/common": Object { - "requiredVersion": "~13.2.0", - "singleton": true, - "strictVersion": true, - }, - "@angular/core": Object { - "singleton": true, - "strictVersion": false, - }, - "@angular/router": Object { - "requiredVersion": "^13.0.0", - "singleton": false, - "strictVersion": true, - }, - "shared": Object { - "requiredVersion": false, - }, - }, - }, - }, - NormalModuleReplacementPlugin { - "newResource": [Function], - "resourceRegExp": /\\./, - }, -] -`; - -exports[`withModuleFederation should apply the user-specified shared function correctly 1`] = ` -Array [ - ModuleFederationPlugin { - "_options": Object { - "exposes": Object { - "./Module": "apps/remote1/src/module.ts", - }, - "filename": "remoteEntry.mjs", - "library": Object { - "type": "module", - }, - "name": "remote1", - "remotes": Object {}, - "shared": Object { - "@angular/core": Object { - "requiredVersion": undefined, - "singleton": true, - "strictVersion": false, - }, - "shared": Object { - "eager": undefined, - "requiredVersion": false, - }, - }, - }, - }, - NormalModuleReplacementPlugin { - "newResource": [Function], - "resourceRegExp": /\\./, - }, -] -`; - -exports[`withModuleFederation should collect dependencies correctly 1`] = ` -Array [ - ModuleFederationPlugin { - "_options": Object { - "exposes": Object { - "./Module": "apps/remote1/src/module.ts", - }, - "filename": "remoteEntry.mjs", - "library": Object { - "type": "module", - }, - "name": "remote1", - "remotes": Object {}, - "shared": Object { - "@angular/core": Object { - "requiredVersion": "~13.2.0", - "singleton": true, - "strictVersion": true, - }, - "core": Object { - "eager": undefined, - "requiredVersion": false, - }, - "lodash": Object { - "requiredVersion": "~4.17.20", - "singleton": true, - "strictVersion": true, - }, - "shared": Object { - "eager": undefined, - "requiredVersion": false, - }, - }, - }, - }, - NormalModuleReplacementPlugin { - "newResource": [Function], - "resourceRegExp": /\\./, - }, -] -`; - -exports[`withModuleFederation should create a host config correctly 1`] = ` -Array [ - ModuleFederationPlugin { - "_options": Object { - "exposes": undefined, - "filename": "remoteEntry.mjs", - "library": Object { - "type": "module", - }, - "name": "host", - "remotes": Object { - "remote1": "http://localhost:4201/remoteEntry.mjs", - }, - "shared": Object { - "@angular/core": Object { - "requiredVersion": "~13.2.0", - "singleton": true, - "strictVersion": true, - }, - "shared": Object { - "eager": undefined, - "requiredVersion": false, - }, - }, - }, - }, - NormalModuleReplacementPlugin { - "newResource": [Function], - "resourceRegExp": /\\./, - }, -] -`; - -exports[`withModuleFederation should create a remote config correctly 1`] = ` -Array [ - ModuleFederationPlugin { - "_options": Object { - "exposes": Object { - "./Module": "apps/remote1/src/module.ts", - }, - "filename": "remoteEntry.mjs", - "library": Object { - "type": "module", - }, - "name": "remote1", - "remotes": Object {}, - "shared": Object { - "@angular/core": Object { - "requiredVersion": "~13.2.0", - "singleton": true, - "strictVersion": true, - }, - "shared": Object { - "eager": undefined, - "requiredVersion": false, - }, - }, - }, - }, - NormalModuleReplacementPlugin { - "newResource": [Function], - "resourceRegExp": /\\./, - }, -] -`; - -exports[`withModuleFederation should map dependencies from project name to import name 1`] = ` -Array [ - ModuleFederationPlugin { - "_options": Object { - "exposes": Object { - "./Module": "apps/remote1/src/module.ts", - }, - "filename": "remoteEntry.mjs", - "library": Object { - "type": "module", - }, - "name": "remote1", - "remotes": Object {}, - "shared": Object { - "@angular/core": Object { - "requiredVersion": "~13.2.0", - "singleton": true, - "strictVersion": true, - }, - "@myorg/core": Object { - "eager": undefined, - "requiredVersion": false, - }, - "shared": Object { - "eager": undefined, - "requiredVersion": false, - }, - }, - }, - }, - NormalModuleReplacementPlugin { - "newResource": [Function], - "resourceRegExp": /\\./, - }, -] -`; - -exports[`withModuleFederation should not have duplicated entries for duplicated dependencies 1`] = ` -Array [ - ModuleFederationPlugin { - "_options": Object { - "exposes": Object { - "./Module": "apps/remote1/src/module.ts", - }, - "filename": "remoteEntry.mjs", - "library": Object { - "type": "module", - }, - "name": "remote1", - "remotes": Object {}, - "shared": Object { - "@angular/core": Object { - "requiredVersion": "~13.2.0", - "singleton": true, - "strictVersion": true, - }, - "core": Object { - "eager": undefined, - "requiredVersion": false, - }, - "shared": Object { - "eager": undefined, - "requiredVersion": false, - }, - }, - }, - }, - NormalModuleReplacementPlugin { - "newResource": [Function], - "resourceRegExp": /\\./, - }, -] -`; diff --git a/packages/angular/src/utils/mfe/with-module-federation.spec.ts b/packages/angular/src/utils/mfe/with-module-federation.spec.ts deleted file mode 100644 index 2fb9b92380c30..0000000000000 --- a/packages/angular/src/utils/mfe/with-module-federation.spec.ts +++ /dev/null @@ -1,475 +0,0 @@ -jest.mock('fs'); -jest.mock('@nrwl/devkit'); -jest.mock('@nrwl/workspace/src/utilities/typescript'); -jest.mock('nx/src/project-graph/file-utils'); -import * as graph from '@nrwl/devkit'; -import * as typescriptUtils from '@nrwl/workspace/src/utilities/typescript'; -import * as workspace from 'nx/src/project-graph/file-utils'; -import * as fs from 'fs'; -import * as devkit from '@nrwl/devkit'; - -import { withModuleFederation } from './with-module-federation'; - -describe('withModuleFederation', () => { - afterEach(() => jest.clearAllMocks()); - - it('should create a host config correctly', async () => { - // ARRANGE - (graph.readCachedProjectGraph as jest.Mock).mockReturnValue({ - dependencies: { - host: [ - { target: 'npm:@angular/core' }, - { target: 'npm:zone.js' }, - { target: 'shared' }, - ], - }, - }); - - (workspace.readWorkspaceJson as jest.Mock).mockReturnValue({ - projects: { - remote1: { - targets: { - serve: { - options: { - publicHost: 'http://localhost:4201', - }, - }, - }, - }, - }, - }); - - (fs.existsSync as jest.Mock).mockReturnValue(true); - jest.spyOn(devkit, 'readJsonFile').mockImplementation(() => ({ - dependencies: { '@angular/core': '~13.2.0' }, - })); - - (typescriptUtils.readTsConfig as jest.Mock).mockReturnValue({ - options: { - paths: { - shared: ['/libs/shared/src/index.ts'], - }, - }, - }); - - (graph.Workspaces as jest.Mock).mockReturnValue({ - readWorkspaceConfiguration: () => ({ - projects: { - shared: { - sourceRoot: '/libs/shared/src/', - }, - }, - }), - }); - - (fs.readdirSync as jest.Mock).mockReturnValue([]); - - // ACT - const config = ( - await withModuleFederation({ - name: 'host', - remotes: ['remote1'], - }) - )({}); - - // ASSERT - expect(config.plugins).toMatchSnapshot(); - }); - - it('should create a remote config correctly', async () => { - // ARRANGE - (graph.readCachedProjectGraph as jest.Mock).mockReturnValue({ - dependencies: { - remote1: [ - { target: 'npm:@angular/core' }, - { target: 'npm:zone.js' }, - { target: 'shared' }, - ], - }, - }); - - (fs.existsSync as jest.Mock).mockReturnValue(true); - jest.spyOn(devkit, 'readJsonFile').mockImplementation(() => ({ - dependencies: { '@angular/core': '~13.2.0' }, - })); - - (typescriptUtils.readTsConfig as jest.Mock).mockReturnValue({ - options: { - paths: { - shared: ['/libs/shared/src/index.ts'], - }, - }, - }); - - (graph.Workspaces as jest.Mock).mockReturnValue({ - readWorkspaceConfiguration: () => ({ - projects: { - shared: { - sourceRoot: '/libs/shared/src/', - }, - }, - }), - }); - - (fs.readdirSync as jest.Mock).mockReturnValue([]); - - // ACT - const config = ( - await withModuleFederation({ - name: 'remote1', - exposes: { './Module': 'apps/remote1/src/module.ts' }, - }) - )({}); - - // ASSERT - expect(config.plugins).toMatchSnapshot(); - }); - - it('should collect dependencies correctly', async () => { - // ARRANGE - (graph.readCachedProjectGraph as jest.Mock).mockReturnValue({ - dependencies: { - remote1: [ - { target: 'npm:@angular/core' }, - { target: 'npm:zone.js' }, - { target: 'core' }, - ], - core: [{ target: 'shared' }, { target: 'npm:lodash' }], - }, - }); - - (fs.existsSync as jest.Mock).mockReturnValue(true); - jest.spyOn(devkit, 'readJsonFile').mockImplementation(() => ({ - dependencies: { '@angular/core': '~13.2.0', lodash: '~4.17.20' }, - })); - - (typescriptUtils.readTsConfig as jest.Mock).mockReturnValue({ - options: { - paths: { - shared: ['/libs/shared/src/index.ts'], - core: ['/libs/core/src/index.ts'], - }, - }, - }); - - (graph.Workspaces as jest.Mock).mockReturnValue({ - readWorkspaceConfiguration: () => ({ - projects: { - shared: { - sourceRoot: '/libs/shared/src/', - }, - core: { - sourceRoot: '/libs/core/src/', - }, - }, - }), - }); - - (fs.readdirSync as jest.Mock).mockReturnValue([]); - - // ACT - const config = ( - await withModuleFederation({ - name: 'remote1', - exposes: { './Module': 'apps/remote1/src/module.ts' }, - }) - )({}); - - // ASSERT - expect(config.plugins).toMatchSnapshot(); - }); - - it('should not have duplicated entries for duplicated dependencies', async () => { - // ARRANGE - (graph.readCachedProjectGraph as jest.Mock).mockReturnValue({ - dependencies: { - remote1: [ - { target: 'npm:@angular/core' }, - { target: 'npm:zone.js' }, - { target: 'core' }, - ], - core: [{ target: 'shared' }, { target: 'npm:@angular/core' }], - }, - }); - - (fs.existsSync as jest.Mock).mockReturnValue(true); - jest.spyOn(devkit, 'readJsonFile').mockImplementation(() => ({ - dependencies: { '@angular/core': '~13.2.0' }, - })); - - (typescriptUtils.readTsConfig as jest.Mock).mockReturnValue({ - options: { - paths: { - shared: ['/libs/shared/src/index.ts'], - core: ['/libs/core/src/index.ts'], - }, - }, - }); - - (graph.Workspaces as jest.Mock).mockReturnValue({ - readWorkspaceConfiguration: () => ({ - projects: { - shared: { - sourceRoot: '/libs/shared/src/', - }, - core: { - sourceRoot: '/libs/core/src/', - }, - }, - }), - }); - - (fs.readdirSync as jest.Mock).mockReturnValue([]); - - // ACT - const config = ( - await withModuleFederation({ - name: 'remote1', - exposes: { './Module': 'apps/remote1/src/module.ts' }, - }) - )({}); - - // ASSERT - expect(config.plugins).toMatchSnapshot(); - }); - - it('should map dependencies from project name to import name', async () => { - // ARRANGE - (graph.readCachedProjectGraph as jest.Mock).mockReturnValue({ - dependencies: { - remote1: [ - { target: 'npm:@angular/core' }, - { target: 'npm:zone.js' }, - { target: 'core' }, - ], - core: [{ target: 'shared' }], - }, - }); - - (fs.existsSync as jest.Mock).mockReturnValue(true); - jest.spyOn(devkit, 'readJsonFile').mockImplementation(() => ({ - dependencies: { '@angular/core': '~13.2.0' }, - })); - - (typescriptUtils.readTsConfig as jest.Mock).mockImplementation(() => ({ - options: { - paths: { - shared: ['/libs/shared/src/index.ts'], - '@myorg/core': ['/libs/core/src/index.ts'], - }, - }, - })); - - (graph.Workspaces as jest.Mock).mockReturnValue({ - readWorkspaceConfiguration: () => ({ - projects: { - shared: { - sourceRoot: '/libs/shared/src/', - }, - core: { - sourceRoot: '/libs/core/src/', - }, - }, - }), - }); - - (fs.readdirSync as jest.Mock).mockReturnValue([]); - - // ACT - const config = ( - await withModuleFederation({ - name: 'remote1', - exposes: { './Module': 'apps/remote1/src/module.ts' }, - }) - )({}); - - // ASSERT - expect(config.plugins).toMatchSnapshot(); - }); - - it('should apply the user-specified shared function correctly', async () => { - // ARRANGE - (graph.readCachedProjectGraph as jest.Mock).mockReturnValue({ - dependencies: { - remote1: [ - { target: 'npm:@angular/core' }, - { target: 'npm:zone.js' }, - { target: 'core' }, - ], - core: [{ target: 'shared' }, { target: 'npm:@angular/core' }], - }, - }); - (fs.existsSync as jest.Mock).mockReturnValue(true); - jest.spyOn(devkit, 'readJsonFile').mockImplementation(() => ({ - dependencies: { '@angular/core': '~13.2.0' }, - })); - (typescriptUtils.readTsConfig as jest.Mock).mockReturnValue({ - options: { - paths: { - shared: ['/libs/shared/src/index.ts'], - core: ['/libs/core/src/index.ts'], - }, - }, - }); - (graph.Workspaces as jest.Mock).mockReturnValue({ - readWorkspaceConfiguration: () => ({ - projects: { - shared: { - sourceRoot: '/libs/shared/src/', - }, - core: { - sourceRoot: '/libs/core/src/', - }, - }, - }), - }); - (fs.readdirSync as jest.Mock).mockReturnValue([]); - - // ACT - const config = ( - await withModuleFederation({ - name: 'remote1', - exposes: { './Module': 'apps/remote1/src/module.ts' }, - shared: (dep, config) => { - if (dep === 'core') { - return false; - } - if (dep === '@angular/core') { - return { - ...config, - strictVersion: false, - requiredVersion: undefined, - }; - } - }, - }) - )({}); - - // ASSERT - expect(config.plugins).toMatchSnapshot(); - }); - - it('should apply additional shared dependencies when specified', async () => { - // ARRANGE - (graph.readCachedProjectGraph as jest.Mock).mockReturnValue({ - dependencies: { - remote1: [{ target: 'npm:@angular/core' }, { target: 'core' }], - core: [{ target: 'npm:@angular/core' }], - }, - nodes: { shared: {} }, - externalNodes: { '@angular/common': {} }, - }); - (fs.existsSync as jest.Mock).mockReturnValue(true); - jest.spyOn(devkit, 'readJsonFile').mockImplementation(() => ({ - dependencies: { - '@angular/core': '~13.2.0', - '@angular/common': '~13.2.0', - '@angular/router': '~13.2.0', - }, - })); - (typescriptUtils.readTsConfig as jest.Mock).mockReturnValue({ - options: { - paths: { - shared: ['/libs/shared/src/index.ts'], - core: ['/libs/core/src/index.ts'], - }, - }, - }); - (graph.Workspaces as jest.Mock).mockReturnValue({ - readWorkspaceConfiguration: () => ({ - projects: { - shared: { - sourceRoot: '/libs/shared/src/', - }, - core: { - sourceRoot: '/libs/core/src/', - }, - }, - }), - }); - (fs.readdirSync as jest.Mock).mockReturnValue([]); - - // ACT - const config = ( - await withModuleFederation({ - name: 'remote1', - exposes: { './Module': 'apps/remote1/src/module.ts' }, - shared: (dep, config) => { - if (dep === 'core') { - return false; - } - }, - additionalShared: [ - '@angular/common', - [ - '@angular/core', - { - strictVersion: false, - singleton: true, - }, - ], - { - libraryName: '@angular/router', - sharedConfig: { - requiredVersion: '^13.0.0', - singleton: false, - strictVersion: true, - }, - }, - 'shared', - ], - }) - )({}); - - // ASSERT - expect(config.plugins).toMatchSnapshot(); - }); - - it('should throw when an additionalShared entry is a string and it is not in the project graph', async () => { - // ARRANGE - (graph.readCachedProjectGraph as jest.Mock).mockReturnValue({ - dependencies: { - remote1: [{ target: 'npm:@angular/core' }, { target: 'core' }], - core: [{ target: 'npm:@angular/core' }], - }, - nodes: {}, - externalNodes: {}, - }); - (fs.existsSync as jest.Mock).mockReturnValue(true); - jest.spyOn(devkit, 'readJsonFile').mockImplementation(() => ({ - dependencies: { '@angular/core': '~13.2.0' }, - })); - (typescriptUtils.readTsConfig as jest.Mock).mockReturnValue({ - options: { - paths: { - shared: ['/libs/shared/src/index.ts'], - core: ['/libs/core/src/index.ts'], - }, - }, - }); - (graph.Workspaces as jest.Mock).mockReturnValue({ - readWorkspaceConfiguration: () => ({ - projects: { - shared: { - sourceRoot: '/libs/shared/src/', - }, - core: { - sourceRoot: '/libs/core/src/', - }, - }, - }), - }); - (fs.readdirSync as jest.Mock).mockReturnValue([]); - - // ACT & ASSERT - await expect( - withModuleFederation({ - name: 'remote1', - exposes: { './Module': 'apps/remote1/src/module.ts' }, - additionalShared: ['shared'], - }) - ).rejects.toThrow( - 'The specified dependency "shared" in the additionalShared configuration does not exist in the project graph.' - ); - }); -}); diff --git a/packages/angular/src/utils/mfe/with-module-federation.ts b/packages/angular/src/utils/mfe/with-module-federation.ts index b9e446c031d57..b8932f23fb4ab 100644 --- a/packages/angular/src/utils/mfe/with-module-federation.ts +++ b/packages/angular/src/utils/mfe/with-module-federation.ts @@ -7,16 +7,14 @@ import { import { createProjectGraphAsync, ProjectGraph, + readAllWorkspaceConfiguration, readCachedProjectGraph, - workspaceRoot, - Workspaces, } from '@nrwl/devkit'; import { getRootTsConfigPath, readTsConfig, } from '@nrwl/workspace/src/utilities/typescript'; import { ParsedCommandLine } from 'typescript'; -import { readWorkspaceJson } from 'nx/src/project-graph/file-utils'; import { readRootPackageJson } from './utils'; import { extname, join } from 'path'; import ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); @@ -71,9 +69,7 @@ function collectDependencies( } function mapWorkspaceLibrariesToTsConfigImport(workspaceLibraries: string[]) { - const { projects } = new Workspaces( - workspaceRoot - ).readWorkspaceConfiguration(); + const { projects } = readAllWorkspaceConfiguration(); const tsConfigPath = process.env.NX_TSCONFIG_PATH ?? getRootTsConfigPath(); const tsConfig: ParsedCommandLine = readTsConfig(tsConfigPath); @@ -123,7 +119,7 @@ async function getDependentPackagesForProject( } function determineRemoteUrl(remote: string) { - const workspace = readWorkspaceJson(); + const workspace = readAllWorkspaceConfiguration(); let publicHost = ''; try { publicHost = workspace.projects[remote].targets.serve.options.publicHost; diff --git a/packages/cli/project.json b/packages/cli/project.json index 368ab3411696a..d4b88f5e1f9b7 100644 --- a/packages/cli/project.json +++ b/packages/cli/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/cli"], "options": { "commands": [ diff --git a/packages/cra-to-nx/project.json b/packages/cra-to-nx/project.json index 3f8f389694cab..f3c92459fb498 100644 --- a/packages/cra-to-nx/project.json +++ b/packages/cra-to-nx/project.json @@ -38,7 +38,7 @@ } }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/cra-to-nx"], "options": { "commands": [ @@ -53,7 +53,7 @@ } }, "publish": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "command": "node tools/scripts/publish.js cra-to-nx {args.ver} {args.tag} {args.local}" } diff --git a/packages/create-nx-plugin/project.json b/packages/create-nx-plugin/project.json index 90d22838d809c..08fda468cdb72 100644 --- a/packages/create-nx-plugin/project.json +++ b/packages/create-nx-plugin/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/create-nx-plugin"], "options": { "commands": [ diff --git a/packages/create-nx-workspace/project.json b/packages/create-nx-workspace/project.json index 4b07e0ee07eae..90c6936de7a9d 100644 --- a/packages/create-nx-workspace/project.json +++ b/packages/create-nx-workspace/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/create-nx-workspace"], "options": { "commands": [ diff --git a/packages/cypress/project.json b/packages/cypress/project.json index 101c1f9e1edf5..991cbbfb7607a 100644 --- a/packages/cypress/project.json +++ b/packages/cypress/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/cypress"], "options": { "command": "node ./scripts/copy-readme.js cypress" diff --git a/packages/cypress/src/executors/cypress/hasher.ts b/packages/cypress/src/executors/cypress/hasher.ts index 56ed758f79ec4..3b581787b2c04 100644 --- a/packages/cypress/src/executors/cypress/hasher.ts +++ b/packages/cypress/src/executors/cypress/hasher.ts @@ -5,7 +5,7 @@ import { ProjectGraph, Task, TaskGraph, - WorkspaceJsonConfiguration, + ProjectsConfigurations, } from '@nrwl/devkit'; export default async function run( @@ -14,7 +14,7 @@ export default async function run( hasher: Hasher; projectGraph: ProjectGraph; taskGraph: TaskGraph; - workspaceConfig: WorkspaceJsonConfiguration & NxJsonConfiguration; + workspaceConfig: ProjectsConfigurations & NxJsonConfiguration; } ): Promise { const cypressPluginConfig = context.workspaceConfig.pluginsConfig diff --git a/packages/detox/project.json b/packages/detox/project.json index e4d9b5c9eee06..747ba0f3d096a 100644 --- a/packages/detox/project.json +++ b/packages/detox/project.json @@ -71,7 +71,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/detox"], "options": { "command": "node ./scripts/copy-readme.js detox" diff --git a/packages/devkit/index.ts b/packages/devkit/index.ts index ae9185e8c40c8..5bb13fb4556c8 100644 --- a/packages/devkit/index.ts +++ b/packages/devkit/index.ts @@ -19,6 +19,7 @@ export type { Tree, FileChange } from 'nx/src/generators/tree'; */ export type { WorkspaceJsonConfiguration, + ProjectsConfigurations, TargetDependencyConfig, TargetConfiguration, ProjectConfiguration, @@ -47,6 +48,12 @@ export type { */ export { Workspaces } from 'nx/src/config/workspaces'; +export { + readNxJson, + readAllWorkspaceConfiguration, + workspaceLayout, +} from 'nx/src/config/configuration'; + export type { NxPlugin, ProjectTargetConfigurator, @@ -275,7 +282,7 @@ export { moveFilesToNewDirectory } from './src/utils/move-dir'; /** * @category Utils */ -export { workspaceRoot, appRootPath } from 'nx/src/utils/app-root'; +export { workspaceRoot, appRootPath } from 'nx/src/utils/workspace-root'; /** * @category Utils @@ -289,11 +296,6 @@ export { readCachedProjectGraph, } from 'nx/src/project-graph/project-graph'; -/** - * @category Utils - */ -export { readNxJson, workspaceLayout } from 'nx/src/project-graph/file-utils'; - /** * @category Utils */ diff --git a/packages/devkit/project.json b/packages/devkit/project.json index 58abdc08c588c..f30970aeeb604 100644 --- a/packages/devkit/project.json +++ b/packages/devkit/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/devkit"], "options": { "command": "node ./scripts/copy-readme.js devkit" diff --git a/packages/eslint-plugin-nx/project.json b/packages/eslint-plugin-nx/project.json index 53fc514d5a3ba..d467800b77660 100644 --- a/packages/eslint-plugin-nx/project.json +++ b/packages/eslint-plugin-nx/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/eslint-plugin-nx"], "options": { "command": "node ./scripts/copy-readme.js eslint-plugin-nx" diff --git a/packages/eslint-plugin-nx/src/rules/enforce-module-boundaries.spec.ts b/packages/eslint-plugin-nx/src/rules/enforce-module-boundaries.spec.ts index cb3a138d7e407..1a08ce5874251 100644 --- a/packages/eslint-plugin-nx/src/rules/enforce-module-boundaries.spec.ts +++ b/packages/eslint-plugin-nx/src/rules/enforce-module-boundaries.spec.ts @@ -16,7 +16,7 @@ jest.mock('@nrwl/devkit', () => ({ workspaceRoot: '/root', })); -jest.mock('nx/src/utils/app-root', () => ({ +jest.mock('nx/src/utils/workspace-root', () => ({ workspaceRoot: '/root', })); diff --git a/packages/express/project.json b/packages/express/project.json index cec6ead867e53..5882f62139f6e 100644 --- a/packages/express/project.json +++ b/packages/express/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/express"], "options": { "command": "node ./scripts/copy-readme.js express" diff --git a/packages/jest/project.json b/packages/jest/project.json index 6a97f3ad236f6..19273c05177c6 100644 --- a/packages/jest/project.json +++ b/packages/jest/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/jest"], "options": { "command": "node ./scripts/copy-readme.js jest" diff --git a/packages/jest/src/utils/config/get-jest-projects.ts b/packages/jest/src/utils/config/get-jest-projects.ts index 4774020caf57e..c282d30e6c796 100644 --- a/packages/jest/src/utils/config/get-jest-projects.ts +++ b/packages/jest/src/utils/config/get-jest-projects.ts @@ -1,5 +1,5 @@ import { dirname, join } from 'path'; -import type { WorkspaceJsonConfiguration } from '@nrwl/devkit'; +import type { ProjectsConfigurations } from '@nrwl/devkit'; import { readWorkspaceConfig } from 'nx/src/project-graph/file-utils'; const JEST_RUNNER_TOKEN = '@nrwl/jest:jest'; @@ -11,7 +11,7 @@ function getJestConfigProjectPath(projectJestConfigPath: string): string { export function getJestProjects() { const ws = readWorkspaceConfig({ format: 'nx', - }) as WorkspaceJsonConfiguration; + }) as ProjectsConfigurations; const jestConfigurationSet = new Set(); for (const projectConfig of Object.values(ws.projects)) { if (!projectConfig.targets) { diff --git a/packages/js/project.json b/packages/js/project.json index ff9f7df67a9ec..36ef124a05075 100644 --- a/packages/js/project.json +++ b/packages/js/project.json @@ -67,7 +67,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/js"], "options": { "command": "node ./scripts/copy-readme.js js" diff --git a/packages/linter/project.json b/packages/linter/project.json index 4287cd7b65062..131695872d8b9 100644 --- a/packages/linter/project.json +++ b/packages/linter/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/linter"], "options": { "command": "node ./scripts/copy-readme.js linter" diff --git a/packages/linter/src/executors/eslint/hasher.ts b/packages/linter/src/executors/eslint/hasher.ts index 9e5c51dc1f925..0c05df9163668 100644 --- a/packages/linter/src/executors/eslint/hasher.ts +++ b/packages/linter/src/executors/eslint/hasher.ts @@ -2,7 +2,7 @@ import { ProjectGraph, Task, TaskGraph, - WorkspaceJsonConfiguration, + ProjectsConfigurations, Hasher, Hash, } from '@nrwl/devkit'; @@ -13,7 +13,7 @@ export default async function run( hasher: Hasher; projectGraph: ProjectGraph; taskGraph: TaskGraph; - workspaceConfig: WorkspaceJsonConfiguration; + workspaceConfig: ProjectsConfigurations; } ): Promise { if (task.overrides['hasTypeAwareRules'] === true) { diff --git a/packages/make-angular-cli-faster/project.json b/packages/make-angular-cli-faster/project.json index 09c85b17e2313..ffe545310b2dc 100644 --- a/packages/make-angular-cli-faster/project.json +++ b/packages/make-angular-cli-faster/project.json @@ -25,7 +25,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/make-angular-cli-faster"], "options": { "commands": [ diff --git a/packages/nest/project.json b/packages/nest/project.json index 9772cc45da831..4fdebef07fdbd 100644 --- a/packages/nest/project.json +++ b/packages/nest/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/nest"], "options": { "command": "node ./scripts/copy-readme.js nest" diff --git a/packages/next/project.json b/packages/next/project.json index 66ccb6e0bee38..e4d939dfa65c8 100644 --- a/packages/next/project.json +++ b/packages/next/project.json @@ -61,7 +61,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/next"], "options": { "command": "node ./scripts/copy-readme.js next" diff --git a/packages/node/project.json b/packages/node/project.json index 9df139eb6faad..b61a616bb43c8 100644 --- a/packages/node/project.json +++ b/packages/node/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/node"], "options": { "command": "node ./scripts/copy-readme.js node" diff --git a/packages/nx-plugin/project.json b/packages/nx-plugin/project.json index 8e7fddea83ac9..9986ec08dd859 100644 --- a/packages/nx-plugin/project.json +++ b/packages/nx-plugin/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/nx-plugin"], "options": { "command": "node ./scripts/copy-readme.js nx-plugin" diff --git a/packages/nx/bin/init.ts b/packages/nx/bin/compute-project-graph.ts similarity index 100% rename from packages/nx/bin/init.ts rename to packages/nx/bin/compute-project-graph.ts diff --git a/packages/nx/bin/nx.ts b/packages/nx/bin/nx.ts index 9518f8d8e209c..7b408aba4bcc9 100644 --- a/packages/nx/bin/nx.ts +++ b/packages/nx/bin/nx.ts @@ -9,7 +9,11 @@ import { detectPackageManager } from '../src/utils/package-manager'; import { output } from '../src/utils/output'; // new is a special case because there is no local workspace to load -if (process.argv[2] === 'new' || process.argv[2] === '_migrate') { +if ( + process.argv[2] === 'new' || + process.argv[2] === '_migrate' || + process.argv[2] === 'init' +) { require('nx/src/command-line/nx-commands').commandsObject.argv; } else { const workspace = findWorkspaceRoot(process.cwd()); @@ -27,6 +31,12 @@ if (process.argv[2] === 'new' || process.argv[2] === '_migrate') { bodyLines: [ `To create a workspace run:`, chalk.bold.white(`npx create-nx-workspace@latest `), + '', + `To add Nx to existing workspace run with a workspace-specific nx.json:`, + chalk.bold.white(`npx add-nx-to-monorepo@latest`), + '', + `To add the default nx.json file run:`, + chalk.bold.white(`nx init`), ], }); diff --git a/packages/nx/package.json b/packages/nx/package.json index bb9d3fd8f134f..8d658b5a2a78e 100644 --- a/packages/nx/package.json +++ b/packages/nx/package.json @@ -8,7 +8,7 @@ "directory": "packages/nx" }, "scripts": { - "postinstall": "node ./bin/init" + "postinstall": "node ./bin/compute-project-graph" }, "keywords": [ "Monorepo", diff --git a/packages/nx/presets/core.json b/packages/nx/presets/core.json index b77e169d8cede..da77b195126a7 100644 --- a/packages/nx/presets/core.json +++ b/packages/nx/presets/core.json @@ -6,16 +6,21 @@ }, ".eslintrc.json": "*" }, - "targetDependencies": { - "build": [ - { - "target": "build", - "projects": "dependencies" + "tasksRunnerOptions": { + "default": { + "runner": "nx/tasks-runners/default", + "options": { + "cacheableOperations": [] } - ] + } }, "workspaceLayout": { - "appsDir": "packages", - "libsDir": "packages" + "libsDir": "packages", + "appsDir": "packages" + }, + "pluginsConfig": { + "@nrwl/js": { + "analyzeSourceFiles": false + } } } diff --git a/packages/nx/presets/npm.json b/packages/nx/presets/npm.json index 727296550088f..da77b195126a7 100644 --- a/packages/nx/presets/npm.json +++ b/packages/nx/presets/npm.json @@ -6,15 +6,21 @@ }, ".eslintrc.json": "*" }, - "targetDependencies": { - "build": [ - { - "target": "build", - "projects": "dependencies" + "tasksRunnerOptions": { + "default": { + "runner": "nx/tasks-runners/default", + "options": { + "cacheableOperations": [] } - ] + } }, "workspaceLayout": { - "libsDir": "packages" + "libsDir": "packages", + "appsDir": "packages" + }, + "pluginsConfig": { + "@nrwl/js": { + "analyzeSourceFiles": false + } } } diff --git a/packages/nx/project.json b/packages/nx/project.json index 2b117388499ef..1d002f0e8a018 100644 --- a/packages/nx/project.json +++ b/packages/nx/project.json @@ -56,7 +56,7 @@ } }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/nx"], "options": { "commands": [ diff --git a/packages/nx/src/adapter/compat.ts b/packages/nx/src/adapter/compat.ts index ae9f24884a447..4bba550e37702 100644 --- a/packages/nx/src/adapter/compat.ts +++ b/packages/nx/src/adapter/compat.ts @@ -4,7 +4,7 @@ import { workspaceConfigName, Workspaces, } from '../config/workspaces'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; /* eslint-disable */ const Module = require('module'); diff --git a/packages/nx/src/adapter/ngcli-adapter.ts b/packages/nx/src/adapter/ngcli-adapter.ts index 3e1e0106f8cef..cc627cf39c5fd 100644 --- a/packages/nx/src/adapter/ngcli-adapter.ts +++ b/packages/nx/src/adapter/ngcli-adapter.ts @@ -35,8 +35,8 @@ import { parseJson, serializeJson } from '../utils/json'; import { NxJsonConfiguration } from '../config/nx-json'; import { ProjectConfiguration, - RawWorkspaceJsonConfiguration, - WorkspaceJsonConfiguration, + RawProjectsConfigurations, + ProjectsConfigurations, } from '../config/workspace-json-project-json'; import { readNxJson } from '../generators/utils/project-configuration'; @@ -210,7 +210,7 @@ async function runSchematic( return { status: 0, loggingQueue: record.loggingQueue }; } -type AngularJsonConfiguration = WorkspaceJsonConfiguration & +type AngularJsonConfiguration = ProjectsConfigurations & Pick & { schematics?: NxJsonConfiguration['generators']; cli?: NxJsonConfiguration['cli'] & { @@ -218,7 +218,7 @@ type AngularJsonConfiguration = WorkspaceJsonConfiguration & }; }; export class NxScopedHost extends virtualFs.ScopedHost { - protected __nxInMemoryWorkspace: WorkspaceJsonConfiguration | null; + protected __nxInMemoryWorkspace: ProjectsConfigurations | null; constructor(private root: string) { super(new NodeJsSyncHost(), normalize(root)); @@ -227,7 +227,7 @@ export class NxScopedHost extends virtualFs.ScopedHost { protected __readWorkspaceConfiguration = ( configFileName: ChangeContext['actualConfigFileName'], overrides?: { - workspace?: Observable; + workspace?: Observable; nx?: Observable; } ): Observable => { @@ -238,7 +238,7 @@ export class NxScopedHost extends virtualFs.ScopedHost { const readWorkspaceJsonFile = ( nxJson: NxJsonConfiguration - ): Observable => { + ): Observable => { if (overrides?.workspace) { return overrides.workspace; } else if (this.__nxInMemoryWorkspace) { @@ -286,7 +286,7 @@ export class NxScopedHost extends virtualFs.ScopedHost { } else { nxJsonObservable = of({} as NxJsonConfiguration); } - const workspaceJsonObservable: Observable = + const workspaceJsonObservable: Observable = nxJsonObservable.pipe(switchMap((x) => readWorkspaceJsonFile(x))); return forkJoin([nxJsonObservable, workspaceJsonObservable]); }), @@ -534,8 +534,8 @@ export class NxScopedHost extends virtualFs.ScopedHost { } protected resolveInlineProjectConfigurations( - config: RawWorkspaceJsonConfiguration - ): Observable { + config: RawProjectsConfigurations + ): 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 @@ -572,7 +572,7 @@ export class NxScopedHost extends virtualFs.ScopedHost { configs.forEach(({ project, projectConfig }) => { config.projects[project] = projectConfig; }); - return config as WorkspaceJsonConfiguration; + return config as ProjectsConfigurations; }) ); } @@ -598,7 +598,7 @@ export class NxScopeHostUsedForWrappedSchematics extends NxScopedHost { const nxJsonChange = findMatchingFileChange(this.host, 'nx.json' as Path); const match = findWorkspaceConfigFileChange(this.host); - let workspaceJsonOverride: Observable; + let workspaceJsonOverride: Observable; let actualConfigFileName: ConfigFilePath = [ '/workspace.json', '/angular.json', diff --git a/packages/nx/src/command-line/affected.ts b/packages/nx/src/command-line/affected.ts index e4acada32757a..75e6e53f13485 100644 --- a/packages/nx/src/command-line/affected.ts +++ b/packages/nx/src/command-line/affected.ts @@ -23,19 +23,20 @@ export async function affected( parsedArgs: yargs.Arguments & RawNxArgs ): Promise { performance.mark('command-execution-begins'); + const env = readEnvironment(); const { nxArgs, overrides } = splitArgsIntoNxArgsAndOverrides( parsedArgs, 'affected', { printWarnings: command !== 'print-affected' && !parsedArgs.plain, - } + }, + env.nxJson ); await connectToNxCloudUsingScan(nxArgs.scan); const projectGraph = await createProjectGraphAsync(); const projects = projectsToRun(nxArgs, projectGraph); - const env = readEnvironment(); try { switch (command) { diff --git a/packages/nx/src/command-line/connect-to-nx-cloud.ts b/packages/nx/src/command-line/connect-to-nx-cloud.ts index 12b34b971a719..e36c0103818df 100644 --- a/packages/nx/src/command-line/connect-to-nx-cloud.ts +++ b/packages/nx/src/command-line/connect-to-nx-cloud.ts @@ -1,7 +1,7 @@ -import { readNxJson } from '../project-graph/file-utils'; import { output } from '../utils/output'; import { getPackageManagerCommand } from '../utils/package-manager'; import { execSync } from 'child_process'; +import { readNxJson } from '../config/configuration'; export async function connectToNxCloudUsingScan(scan: boolean): Promise { if (!scan) return; diff --git a/packages/nx/src/command-line/dep-graph.ts b/packages/nx/src/command-line/dep-graph.ts index a3b9db0da3b59..ba67d487d97c6 100644 --- a/packages/nx/src/command-line/dep-graph.ts +++ b/packages/nx/src/command-line/dep-graph.ts @@ -1,4 +1,4 @@ -import { workspaceRoot } from 'nx/src/utils/app-root'; +import { workspaceRoot } from 'nx/src/utils/workspace-root'; import { watch } from 'chokidar'; import { createHash } from 'crypto'; import { existsSync, readFileSync, statSync, writeFileSync } from 'fs'; @@ -9,7 +9,7 @@ import * as open from 'open'; import { basename, dirname, extname, isAbsolute, join, parse } from 'path'; import { performance } from 'perf_hooks'; import { URL, URLSearchParams } from 'url'; -import { workspaceLayout } from '../project-graph/file-utils'; +import { workspaceLayout } from '../config/configuration'; import { defaultFileHasher } from '../hasher/file-hasher'; import { output } from '../utils/output'; import { writeJsonFile } from '../utils/fileutils'; diff --git a/packages/nx/src/command-line/format.ts b/packages/nx/src/command-line/format.ts index 0ac3d33364a6b..8787bf42d0128 100644 --- a/packages/nx/src/command-line/format.ts +++ b/packages/nx/src/command-line/format.ts @@ -13,7 +13,7 @@ import { reformattedWorkspaceJsonOrNull, workspaceConfigName, } from '../config/workspaces'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import * as prettier from 'prettier'; import { sortObjectByKeys } from '../utils/object-sort'; import { @@ -26,8 +26,9 @@ import { createProjectGraphAsync } from '../project-graph/project-graph'; import { filterAffected } from '../project-graph/affected/affected-project-graph'; import { ProjectConfiguration, - WorkspaceJsonConfiguration, + ProjectsConfigurations, } from '../config/workspace-json-project-json'; +import { readNxJson } from '../config/configuration'; const PRETTIER_PATH = require.resolve('prettier/bin-prettier'); @@ -35,7 +36,12 @@ export async function format( command: 'check' | 'write', args: yargs.Arguments ): Promise { - const { nxArgs } = splitArgsIntoNxArgsAndOverrides(args, 'affected'); + const { nxArgs } = splitArgsIntoNxArgsAndOverrides( + args, + 'affected', + { printWarnings: true }, + readNxJson() + ); const patterns = (await getPatterns({ ...args, ...nxArgs } as any)).map( (p) => `"${p}"` ); @@ -242,11 +248,11 @@ function sortTsConfig() { function movePropertiesToNewLocations(workspaceJsonPath: string) { try { const workspaceJson = readJsonFile< - NxJsonConfiguration & WorkspaceJsonConfiguration + NxJsonConfiguration & ProjectsConfigurations >(workspaceJsonPath); - const nxJson = readJsonFile< - NxJsonConfiguration & WorkspaceJsonConfiguration - >('nx.json'); + const nxJson = readJsonFile( + 'nx.json' + ); if ( workspaceJson.cli || workspaceJson.generators || @@ -273,7 +279,7 @@ function movePropertiesToNewLocations(workspaceJsonPath: string) { } export function moveTagsAndImplicitDepsFromNxJsonToWorkspaceJson( - workspaceJson: WorkspaceJsonConfiguration, + workspaceJson: ProjectsConfigurations, nxJson: NxJsonConfiguration & { projects: Record< string, diff --git a/packages/nx/src/command-line/generate.ts b/packages/nx/src/command-line/generate.ts index d0c19c3464878..22bab0d22a68e 100644 --- a/packages/nx/src/command-line/generate.ts +++ b/packages/nx/src/command-line/generate.ts @@ -8,7 +8,7 @@ import { Workspaces } from '../config/workspaces'; import { FileChange, flushChanges, FsTree } from '../generators/tree'; import { logger } from '../utils/logger'; import * as chalk from 'chalk'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { NxJsonConfiguration } from '../config/nx-json'; import { printHelp } from '../utils/print-help'; import { prompt } from 'enquirer'; diff --git a/packages/nx/src/command-line/init.ts b/packages/nx/src/command-line/init.ts new file mode 100644 index 0000000000000..993c61ef43505 --- /dev/null +++ b/packages/nx/src/command-line/init.ts @@ -0,0 +1,40 @@ +import { execSync } from 'child_process'; +import { join } from 'path'; +import { output } from '../utils/output'; +import { getPackageManagerCommand } from '../utils/package-manager'; +import { fileExists } from '../utils/workspace-root'; +import { readJsonFile, writeJsonFile } from '../utils/fileutils'; + +export function initHandler() { + const nxIsInstalled = !!execSync(getPackageManagerCommand().list) + .toString() + .split('\n') + .find((line) => line.indexOf(' nx@') > -1); + + if (nxIsInstalled) { + output.log({ + title: 'Nx is already installed', + }); + } else { + output.log({ + title: 'Installing Nx...', + }); + execSync(`${getPackageManagerCommand().addDev} nx@latest`, { + stdio: [0, 1, 2], + }); + output.success({ + title: 'Nx has been installed', + }); + } + + if (!fileExists('nx.json')) { + writeJsonFile( + 'nx.json', + readJsonFile(join(__dirname, '..', '..', 'presets', 'core.json')) + ); + + output.success({ + title: 'nx.json has been created', + }); + } +} diff --git a/packages/nx/src/command-line/lint.ts b/packages/nx/src/command-line/lint.ts index 192d7717c7568..174ac42cc45f7 100644 --- a/packages/nx/src/command-line/lint.ts +++ b/packages/nx/src/command-line/lint.ts @@ -1,5 +1,6 @@ import { WorkspaceIntegrityChecks } from './workspace-integrity-checks'; -import { FileData, workspaceLayout } from '../project-graph/file-utils'; +import { FileData } from '../project-graph/file-utils'; +import { workspaceLayout } from '../config/configuration'; import { output } from '../utils/output'; import * as path from 'path'; import { createProjectGraphAsync } from '../project-graph/project-graph'; diff --git a/packages/nx/src/command-line/list.ts b/packages/nx/src/command-line/list.ts index 0547619a13c97..0a776dd0982c9 100644 --- a/packages/nx/src/command-line/list.ts +++ b/packages/nx/src/command-line/list.ts @@ -1,4 +1,4 @@ -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { output } from '../utils/output'; import { fetchCommunityPlugins, diff --git a/packages/nx/src/command-line/nx-commands.ts b/packages/nx/src/command-line/nx-commands.ts index 7af0d8d3cfcd5..b81e138560bfb 100644 --- a/packages/nx/src/command-line/nx-commands.ts +++ b/packages/nx/src/command-line/nx-commands.ts @@ -5,7 +5,7 @@ import * as yargs from 'yargs'; import { generateDaemonHelpOutput } from '../daemon/client/generate-help-output'; import { nxVersion } from '../utils/versions'; import { examples } from './examples'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { getPackageManagerCommand } from '../utils/package-manager'; import { writeJsonFile } from '../utils/fileutils'; @@ -270,6 +270,11 @@ ${daemonHelpOutput} 'Reports useful version numbers to copy into the Nx issue template', handler: async () => (await import('./report')).reportHandler(), }) + .command({ + command: 'init', + describe: 'Adds nx.json file and installs nx if not installed already', + handler: async () => (await import('./init')).initHandler(), + }) .command({ command: 'list [plugin]', describe: diff --git a/packages/nx/src/command-line/read-environment.ts b/packages/nx/src/command-line/read-environment.ts index c4eb524cb8125..2d020b7595b27 100644 --- a/packages/nx/src/command-line/read-environment.ts +++ b/packages/nx/src/command-line/read-environment.ts @@ -1,5 +1,8 @@ -import { readNxJson, readWorkspaceJson } from '../project-graph/file-utils'; import { NxJsonConfiguration } from '../config/nx-json'; +import { + readNxJson, + readAllWorkspaceConfiguration, +} from '../config/configuration'; export interface Environment { nxJson: NxJsonConfiguration; @@ -14,6 +17,6 @@ export interface Environment { export function readEnvironment(): Environment { const nxJson = readNxJson(); - const workspaceJson = readWorkspaceJson(); + const workspaceJson = readAllWorkspaceConfiguration(); return { nxJson, workspaceJson, workspaceResults: null } as any; } diff --git a/packages/nx/src/command-line/report.spec.ts b/packages/nx/src/command-line/report.spec.ts index e97d4c7007482..31705f48cf1e1 100644 --- a/packages/nx/src/command-line/report.spec.ts +++ b/packages/nx/src/command-line/report.spec.ts @@ -1,7 +1,7 @@ // import * as devkit from '@nrwl/devkit'; import * as fileUtils from '../utils/fileutils'; -jest.mock('nx/src/utils/app-root', () => ({ +jest.mock('nx/src/utils/workspace-root', () => ({ workspaceRoot: '', })); diff --git a/packages/nx/src/command-line/report.ts b/packages/nx/src/command-line/report.ts index 5ceb5dd324b0d..305dfa20467c9 100644 --- a/packages/nx/src/command-line/report.ts +++ b/packages/nx/src/command-line/report.ts @@ -1,5 +1,5 @@ import * as chalk from 'chalk'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { output } from '../utils/output'; import { join } from 'path'; import { diff --git a/packages/nx/src/command-line/run-many.ts b/packages/nx/src/command-line/run-many.ts index 0fda9fadcd1e7..56a0f7a0b537a 100644 --- a/packages/nx/src/command-line/run-many.ts +++ b/packages/nx/src/command-line/run-many.ts @@ -12,16 +12,18 @@ import { readEnvironment } from './read-environment'; export async function runMany(parsedArgs: yargs.Arguments & RawNxArgs) { performance.mark('command-execution-begins'); + const env = readEnvironment(); const { nxArgs, overrides } = splitArgsIntoNxArgsAndOverrides( parsedArgs, - 'run-many' + 'run-many', + { printWarnings: true }, + env.nxJson ); await connectToNxCloudUsingScan(nxArgs.scan); const projectGraph = await createProjectGraphAsync(); const projects = projectsToRun(nxArgs, projectGraph); - const env = readEnvironment(); await runCommand(projects, projectGraph, env, nxArgs, overrides, null); } diff --git a/packages/nx/src/command-line/run-one.ts b/packages/nx/src/command-line/run-one.ts index 4695c4206400a..86a90d92351c8 100644 --- a/packages/nx/src/command-line/run-one.ts +++ b/packages/nx/src/command-line/run-one.ts @@ -5,11 +5,11 @@ import { performance } from 'perf_hooks'; import { createProjectGraphAsync } from '../project-graph/project-graph'; import { ProjectGraph } from '../config/project-graph'; import { NxJsonConfiguration } from '../config/nx-json'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { splitTarget } from '../utils/split-target'; import { output } from '../utils/output'; import { readEnvironment } from './read-environment'; -import { WorkspaceJsonConfiguration } from '../config/workspace-json-project-json'; +import { ProjectsConfigurations } from '../config/workspace-json-project-json'; export async function runOne( cwd: string, @@ -27,7 +27,9 @@ export async function runOne( configuration: opts.configuration, target: opts.target, }, - 'run-one' + 'run-one', + { printWarnings: true }, + env.nxJson ); if (nxArgs.help) { @@ -79,7 +81,7 @@ const targetAliases = { function parseRunOneOptions( cwd: string, parsedArgs: { [k: string]: any }, - workspaceConfiguration: WorkspaceJsonConfiguration & NxJsonConfiguration + workspaceConfiguration: ProjectsConfigurations & NxJsonConfiguration ): { project; target; configuration; parsedArgs } { const defaultProjectName = calculateDefaultProjectName( cwd, @@ -135,7 +137,7 @@ function parseRunOneOptions( function calculateDefaultProjectName( cwd: string, root: string, - workspaceConfiguration: WorkspaceJsonConfiguration & NxJsonConfiguration + workspaceConfiguration: ProjectsConfigurations & NxJsonConfiguration ) { let relativeCwd = cwd.replace(/\\/g, '/').split(root.replace(/\\/g, '/'))[1]; if (relativeCwd) { diff --git a/packages/nx/src/command-line/run.ts b/packages/nx/src/command-line/run.ts index a2d67a1b0b4cb..012d3c9dd9f81 100644 --- a/packages/nx/src/command-line/run.ts +++ b/packages/nx/src/command-line/run.ts @@ -17,7 +17,7 @@ import { import { ProjectConfiguration, TargetConfiguration, - WorkspaceJsonConfiguration, + ProjectsConfigurations, } from '../config/workspace-json-project-json'; import { Executor, ExecutorContext } from '../config/misc-interfaces'; @@ -39,7 +39,7 @@ export function printRunHelp( } export function validateProject( - workspace: WorkspaceJsonConfiguration, + workspace: ProjectsConfigurations, projectName: string ) { const project = workspace.projects[projectName]; @@ -126,7 +126,7 @@ async function runExecutorInternal( options: { [k: string]: any }, root: string, cwd: string, - workspace: WorkspaceJsonConfiguration & NxJsonConfiguration, + workspace: ProjectsConfigurations & NxJsonConfiguration, isVerbose: boolean, printHelp: boolean ): Promise> { diff --git a/packages/nx/src/command-line/workspace-generators.ts b/packages/nx/src/command-line/workspace-generators.ts index 4e42dd336b741..7b7f137950ad0 100644 --- a/packages/nx/src/command-line/workspace-generators.ts +++ b/packages/nx/src/command-line/workspace-generators.ts @@ -4,7 +4,7 @@ import { readdirSync, existsSync } from 'fs'; import { copySync, removeSync } from 'fs-extra'; import * as path from 'path'; import * as yargsParser from 'yargs-parser'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { fileExists } from '../utils/fileutils'; import { output } from '../utils/output'; import type { CompilerOptions } from 'typescript'; diff --git a/packages/nx/src/config/configuration.ts b/packages/nx/src/config/configuration.ts new file mode 100644 index 0000000000000..2b7227999f35d --- /dev/null +++ b/packages/nx/src/config/configuration.ts @@ -0,0 +1,24 @@ +import { Workspaces } from './workspaces'; +import { workspaceRoot } from '../utils/workspace-root'; +import { NxJsonConfiguration } from './nx-json'; +import { ProjectsConfigurations } from './workspace-json-project-json'; + +export function readNxJson(): NxJsonConfiguration { + return new Workspaces(workspaceRoot).readNxJson(); +} + +export function readAllWorkspaceConfiguration(): ProjectsConfigurations & + NxJsonConfiguration { + return new Workspaces(workspaceRoot).readWorkspaceConfiguration(); +} + +/** + * Returns information about where apps and libs will be created. + */ +export function workspaceLayout(): { appsDir: string; libsDir: string } { + const nxJson = readNxJson(); + return { + appsDir: nxJson.workspaceLayout?.appsDir ?? 'apps', + libsDir: nxJson.workspaceLayout?.libsDir ?? 'libs', + }; +} diff --git a/packages/nx/src/config/misc-interfaces.ts b/packages/nx/src/config/misc-interfaces.ts index 8cdd213ddf4df..7a930e69b78ba 100644 --- a/packages/nx/src/config/misc-interfaces.ts +++ b/packages/nx/src/config/misc-interfaces.ts @@ -3,7 +3,7 @@ import { ProjectGraph } from './project-graph'; import { Task, TaskGraph } from './task-graph'; import { TargetConfiguration, - WorkspaceJsonConfiguration, + ProjectsConfigurations, } from './workspace-json-project-json'; import type { NxJsonConfiguration } from './nx-json'; @@ -107,7 +107,7 @@ export interface HasherContext { hasher: Hasher; projectGraph: ProjectGraph; taskGraph: TaskGraph; - workspaceConfig: WorkspaceJsonConfiguration & NxJsonConfiguration; + workspaceConfig: ProjectsConfigurations & NxJsonConfiguration; } export type CustomHasher = ( @@ -166,7 +166,7 @@ export interface ExecutorContext { /** * The full workspace configuration */ - workspace: WorkspaceJsonConfiguration & NxJsonConfiguration; + workspace: ProjectsConfigurations & NxJsonConfiguration; /** * The current working directory diff --git a/packages/nx/src/config/workspace-json-project-json.ts b/packages/nx/src/config/workspace-json-project-json.ts index 6e8613070f277..026a74828f0c6 100644 --- a/packages/nx/src/config/workspace-json-project-json.ts +++ b/packages/nx/src/config/workspace-json-project-json.ts @@ -1,15 +1,18 @@ import type { NxJsonConfiguration } from './nx-json'; -export interface Workspace - extends WorkspaceJsonConfiguration, - NxJsonConfiguration { +export interface Workspace extends ProjectsConfigurations, NxJsonConfiguration { projects: Record; } /** - * Workspace configuration + * @deprecated use ProjectsConfigurations */ -export interface WorkspaceJsonConfiguration { +export type WorkspaceJsonConfiguration = ProjectsConfigurations; + +/** + * Projects Configurations + */ +export interface ProjectsConfigurations { /** * Version of the configuration format */ @@ -22,8 +25,8 @@ export interface WorkspaceJsonConfiguration { }; } -export interface RawWorkspaceJsonConfiguration - extends Omit { +export interface RawProjectsConfigurations + extends Omit { projects: { [projectName: string]: ProjectConfiguration | string }; } diff --git a/packages/nx/src/config/workspaces.ts b/packages/nx/src/config/workspaces.ts index 9a8727f6e21c6..a0cbf2347c500 100644 --- a/packages/nx/src/config/workspaces.ts +++ b/packages/nx/src/config/workspaces.ts @@ -5,7 +5,7 @@ import * as path from 'path'; import { basename, dirname, join } from 'path'; import { performance } from 'perf_hooks'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { readJsonFile } from '../utils/fileutils'; import { logger } from '../utils/logger'; import { loadNxPlugins, readPluginPackageJson } from '../utils/nx-plugin'; @@ -13,7 +13,7 @@ import { loadNxPlugins, readPluginPackageJson } from '../utils/nx-plugin'; import type { NxJsonConfiguration } from './nx-json'; import { ProjectConfiguration, - WorkspaceJsonConfiguration, + ProjectsConfigurations, } from './workspace-json-project-json'; import { Executor, @@ -38,8 +38,7 @@ export function workspaceConfigName(root: string) { } export class Workspaces { - private cachedWorkspaceConfig: WorkspaceJsonConfiguration & - NxJsonConfiguration; + private cachedWorkspaceConfig: ProjectsConfigurations & NxJsonConfiguration; constructor(private root: string) {} @@ -49,7 +48,7 @@ export class Workspaces { calculateDefaultProjectName( cwd: string, - wc: WorkspaceJsonConfiguration & NxJsonConfiguration + wc: ProjectsConfigurations & NxJsonConfiguration ) { const relativeCwd = this.relativeCwd(cwd); if (relativeCwd) { @@ -67,10 +66,9 @@ export class Workspaces { readWorkspaceConfiguration(opts?: { _ignorePluginInference?: boolean; - }): WorkspaceJsonConfiguration & NxJsonConfiguration { + }): ProjectsConfigurations & NxJsonConfiguration { if (this.cachedWorkspaceConfig) return this.cachedWorkspaceConfig; - const nxJsonPath = path.join(this.root, 'nx.json'); - const nxJson = readNxJson(nxJsonPath); + const nxJson = this.readNxJson(); const workspaceFile = workspaceConfigName(this.root); const workspacePath = workspaceFile ? path.join(this.root, workspaceFile) @@ -179,6 +177,31 @@ export class Workspaces { } } + readNxJson(): NxJsonConfiguration { + const nxJson = path.join(this.root, 'nx.json'); + if (existsSync(nxJson)) { + const nxJsonConfig = readJsonFile(nxJson); + if (nxJsonConfig.extends) { + const extendedNxJsonPath = require.resolve(nxJsonConfig.extends, { + paths: [dirname(nxJson)], + }); + const baseNxJson = + readJsonFile(extendedNxJsonPath); + return { ...baseNxJson, ...nxJsonConfig }; + } else { + return nxJsonConfig; + } + } else { + try { + return readJsonFile( + join(__dirname, '..', '..', 'presets', 'core.json') + ); + } catch (e) { + return {}; + } + } + } + private getImplementationFactory( implementation: string, directory: string @@ -326,7 +349,7 @@ export function reformattedWorkspaceJsonOrNull(w: any) { return workspaceJson; } -export function toNewFormat(w: any): WorkspaceJsonConfiguration { +export function toNewFormat(w: any): ProjectsConfigurations { const f = toNewFormatOrNull(w); return f ?? w; } @@ -431,22 +454,6 @@ function inlineProjectConfigurations(w: any, root: string = workspaceRoot) { /** * Reads an nx.json file from a given path or extends a local nx.json config. */ -function readNxJson(nxJson: string): NxJsonConfiguration { - let nxJsonConfig: NxJsonConfiguration; - if (existsSync(nxJson)) { - nxJsonConfig = readJsonFile(nxJson); - } else { - nxJsonConfig = {} as NxJsonConfiguration; - } - if (nxJsonConfig.extends) { - const extendedNxJsonPath = require.resolve(nxJsonConfig.extends, { - paths: [dirname(nxJson)], - }); - const baseNxJson = readJsonFile(extendedNxJsonPath); - nxJsonConfig = { ...baseNxJson, ...nxJsonConfig }; - } - return nxJsonConfig; -} /** * Pulled from toFileName in names from @nrwl/devkit. @@ -641,7 +648,7 @@ export function buildWorkspaceConfigurationFromGlobs( nxJson: NxJsonConfiguration, projectFiles: string[], // making this parameter allows devkit to pick up newly created projects readJson: (string) => any = readJsonFile // making this an arg allows us to reuse in devkit -): WorkspaceJsonConfiguration { +): ProjectsConfigurations { const projects: Record = {}; for (const file of projectFiles) { diff --git a/packages/nx/src/daemon/client/client.ts b/packages/nx/src/daemon/client/client.ts index 533d9e3738435..8ebe0098b41a4 100644 --- a/packages/nx/src/daemon/client/client.ts +++ b/packages/nx/src/daemon/client/client.ts @@ -1,4 +1,4 @@ -import { workspaceRoot } from '../../utils/app-root'; +import { workspaceRoot } from '../../utils/workspace-root'; import { ChildProcess, spawn, spawnSync } from 'child_process'; import { openSync, readFileSync } from 'fs'; import { ensureDirSync, ensureFileSync } from 'fs-extra'; diff --git a/packages/nx/src/daemon/server/project-graph-incremental-recomputation.ts b/packages/nx/src/daemon/server/project-graph-incremental-recomputation.ts index 05bfd4a525261..f5b7beec53352 100644 --- a/packages/nx/src/daemon/server/project-graph-incremental-recomputation.ts +++ b/packages/nx/src/daemon/server/project-graph-incremental-recomputation.ts @@ -1,5 +1,5 @@ import { performance } from 'perf_hooks'; -import { readWorkspaceJson } from '../../project-graph/file-utils'; +import { readAllWorkspaceConfiguration } from '../../config/configuration'; import { defaultFileHasher } from '../../hasher/file-hasher'; import { serverLogger } from './logger'; import { buildProjectGraphUsingProjectFileMap } from '../../project-graph/build-project-graph'; @@ -101,7 +101,7 @@ async function processCollectedUpdatedAndDeletedFiles() { 'hash-watched-changes-end' ); defaultFileHasher.incrementalUpdate(updatedFiles, deletedFiles); - const workspaceJson = readWorkspaceJson(); + const workspaceJson = readAllWorkspaceConfiguration(); const workspaceConfigHash = computeWorkspaceConfigHash(workspaceJson); serverLogger.requestLog( `Updated file-hasher based on watched changes, recomputing project graph...` @@ -170,7 +170,7 @@ function copyFileMap(m: ProjectFileMap) { async function createAndSerializeProjectGraph() { try { performance.mark('create-project-graph-start'); - const workspaceJson = readWorkspaceJson(); + const workspaceJson = readAllWorkspaceConfiguration(); const { projectGraph, projectGraphCache } = await buildProjectGraphUsingProjectFileMap( workspaceJson, diff --git a/packages/nx/src/daemon/server/server.ts b/packages/nx/src/daemon/server/server.ts index caea0d6313420..3300e95881951 100644 --- a/packages/nx/src/daemon/server/server.ts +++ b/packages/nx/src/daemon/server/server.ts @@ -1,4 +1,4 @@ -import { workspaceRoot } from '../../utils/app-root'; +import { workspaceRoot } from '../../utils/workspace-root'; import { createServer, Server, Socket } from 'net'; import { join } from 'path'; import { performance, PerformanceObserver } from 'perf_hooks'; diff --git a/packages/nx/src/daemon/server/shutdown-utils.ts b/packages/nx/src/daemon/server/shutdown-utils.ts index 481ee1da4a883..6a6799b7ab58b 100644 --- a/packages/nx/src/daemon/server/shutdown-utils.ts +++ b/packages/nx/src/daemon/server/shutdown-utils.ts @@ -1,4 +1,4 @@ -import { workspaceRoot } from '../../utils/app-root'; +import { workspaceRoot } from '../../utils/workspace-root'; import type { Server } from 'net'; import { serverLogger } from './logger'; import type { WatcherSubscription } from './watcher'; diff --git a/packages/nx/src/daemon/server/watcher.ts b/packages/nx/src/daemon/server/watcher.ts index d61d78c438e29..0c1a98c70f635 100644 --- a/packages/nx/src/daemon/server/watcher.ts +++ b/packages/nx/src/daemon/server/watcher.ts @@ -5,7 +5,7 @@ * * See https://github.com/parcel-bundler/watcher for more details. */ -import { workspaceRoot } from '../../utils/app-root'; +import { workspaceRoot } from '../../utils/workspace-root'; import type { AsyncSubscription, Event } from '@parcel/watcher'; import { readFileSync } from 'fs'; import { join, relative } from 'path'; diff --git a/packages/nx/src/generators/utils/project-configuration.ts b/packages/nx/src/generators/utils/project-configuration.ts index 7b6613dc99c39..665faa7ea037b 100644 --- a/packages/nx/src/generators/utils/project-configuration.ts +++ b/packages/nx/src/generators/utils/project-configuration.ts @@ -2,8 +2,8 @@ import { basename, dirname, join, relative } from 'path'; import type { NxJsonConfiguration } from '../../config/nx-json'; import { ProjectConfiguration, - RawWorkspaceJsonConfiguration, - WorkspaceJsonConfiguration, + RawProjectsConfigurations, + ProjectsConfigurations, } from '../../config/workspace-json-project-json'; import { buildWorkspaceConfigurationFromGlobs, @@ -18,10 +18,7 @@ import type { Tree } from '../tree'; import { readJson, updateJson, writeJson } from './json'; -export type WorkspaceConfiguration = Omit< - WorkspaceJsonConfiguration, - 'projects' -> & +export type WorkspaceConfiguration = Omit & Partial; /** @@ -181,7 +178,7 @@ export function updateWorkspaceConfiguration( // in project config. const workspacePath = getWorkspacePath(tree); if (workspacePath) { - updateJson(tree, workspacePath, (json) => { + updateJson(tree, workspacePath, (json) => { const config = { ...json, version: workspaceConfig.version, @@ -257,7 +254,7 @@ export function isStandaloneProject(tree: Tree, project: string): boolean { const path = getWorkspacePath(tree); const rawWorkspace = path && tree.exists(path) - ? readJson(tree, path) + ? readJson(tree, path) : null; if (rawWorkspace) { const projectConfig = rawWorkspace.projects?.[project]; @@ -268,7 +265,7 @@ export function isStandaloneProject(tree: Tree, project: string): boolean { function getProjectConfiguration( projectName: string, - workspace: WorkspaceJsonConfiguration + workspace: ProjectsConfigurations ): ProjectConfiguration { return { ...readWorkspaceSection(workspace, projectName), @@ -276,7 +273,7 @@ function getProjectConfiguration( } function readWorkspaceSection( - workspace: WorkspaceJsonConfiguration, + workspace: ProjectsConfigurations, projectName: string ) { return workspace.projects[projectName]; @@ -391,7 +388,7 @@ function addProjectToWorkspaceJson( /** * Read the workspace configuration, including projects. */ -export function readWorkspace(tree: Tree): WorkspaceJsonConfiguration { +export function readWorkspace(tree: Tree): ProjectsConfigurations { const workspaceJson = inlineProjectConfigurationsWithTree(tree); const originalVersion = workspaceJson.version; return { @@ -408,7 +405,7 @@ export function readWorkspace(tree: Tree): WorkspaceJsonConfiguration { */ function inlineProjectConfigurationsWithTree( tree: Tree -): WorkspaceJsonConfiguration { +): ProjectsConfigurations { const workspaceJson = readRawWorkspaceJson(tree); Object.entries(workspaceJson.projects || {}).forEach(([project, config]) => { if (typeof config === 'string') { @@ -419,7 +416,7 @@ function inlineProjectConfigurationsWithTree( }; } }); - return workspaceJson as WorkspaceJsonConfiguration; + return workspaceJson as ProjectsConfigurations; } /** @@ -458,12 +455,12 @@ function findDeletedProjects(tree: Tree) { }); } -let staticFSWorkspace: RawWorkspaceJsonConfiguration; -function readRawWorkspaceJson(tree: Tree): RawWorkspaceJsonConfiguration { +let staticFSWorkspace: RawProjectsConfigurations; +function readRawWorkspaceJson(tree: Tree): RawProjectsConfigurations { const path = getWorkspacePath(tree); if (path && tree.exists(path)) { // `workspace.json` exists, use it. - return readJson(tree, path); + return readJson(tree, path); } else { const nxJson = readNxJson(tree); const createdProjects = buildWorkspaceConfigurationFromGlobs( @@ -513,10 +510,7 @@ function getProjectFileLocation(tree: Tree, project: string): string | null { function validateProjectConfigurationOperationsGivenWorkspaceJson( mode: 'create' | 'update' | 'delete', - workspaceJson: - | RawWorkspaceJsonConfiguration - | WorkspaceJsonConfiguration - | null, + workspaceJson: RawProjectsConfigurations | ProjectsConfigurations | null, projectName: string ) { if (mode == 'create' && workspaceJson.projects[projectName]) { @@ -569,7 +563,7 @@ export function shouldDefaultToUsingStandaloneConfigs(tree: Tree): boolean { const workspacePath = getWorkspacePath(tree); const rawWorkspace = workspacePath && tree.exists(workspacePath) - ? readJson(tree, workspacePath) + ? readJson(tree, workspacePath) : null; return !rawWorkspace ? true // if workspace.json doesn't exist, all projects **must** be standalone diff --git a/packages/nx/src/hasher/file-hasher-base.ts b/packages/nx/src/hasher/file-hasher-base.ts index d95603a879ed2..d1ac75537c989 100644 --- a/packages/nx/src/hasher/file-hasher-base.ts +++ b/packages/nx/src/hasher/file-hasher-base.ts @@ -1,4 +1,4 @@ -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { performance } from 'perf_hooks'; import { defaultHashing } from './hashing-impl'; import { FileData } from '../config/project-graph'; diff --git a/packages/nx/src/hasher/file-hasher.ts b/packages/nx/src/hasher/file-hasher.ts index 336403841c13e..9a49308546010 100644 --- a/packages/nx/src/hasher/file-hasher.ts +++ b/packages/nx/src/hasher/file-hasher.ts @@ -1,5 +1,5 @@ import { GitBasedFileHasher } from './git-based-file-hasher'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { NodeBasedFileHasher } from './node-based-file-hasher'; import { FileHasherBase } from './file-hasher-base'; import { execSync } from 'child_process'; diff --git a/packages/nx/src/hasher/git-based-file-hasher.ts b/packages/nx/src/hasher/git-based-file-hasher.ts index 7104a790d508d..f296e5c110e23 100644 --- a/packages/nx/src/hasher/git-based-file-hasher.ts +++ b/packages/nx/src/hasher/git-based-file-hasher.ts @@ -1,4 +1,4 @@ -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { performance } from 'perf_hooks'; import { getFileHashes, getGitHashForFiles } from './git-hasher'; import { existsSync, readFileSync } from 'fs'; diff --git a/packages/nx/src/hasher/hasher.spec.ts b/packages/nx/src/hasher/hasher.spec.ts index 89ffacba30e6b..a449adc85c1e0 100644 --- a/packages/nx/src/hasher/hasher.spec.ts +++ b/packages/nx/src/hasher/hasher.spec.ts @@ -1,7 +1,7 @@ // This must come before the Hasher import import { DependencyType } from '../config/project-graph'; -jest.doMock('../utils/app-root', () => { +jest.doMock('../utils/workspace-root', () => { return { workspaceRoot: '', }; diff --git a/packages/nx/src/hasher/hasher.ts b/packages/nx/src/hasher/hasher.ts index 6081e4a5794d9..b3496cde2a816 100644 --- a/packages/nx/src/hasher/hasher.ts +++ b/packages/nx/src/hasher/hasher.ts @@ -5,14 +5,14 @@ import * as minimatch from 'minimatch'; import { join } from 'path'; import { performance } from 'perf_hooks'; import { getRootTsConfigFileName } from '../utils/typescript'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { workspaceFileName } from '../project-graph/file-utils'; import { defaultHashing, HashingImpl } from './hashing-impl'; import { ProjectGraph } from '../config/project-graph'; import { NxJsonConfiguration } from '../config/nx-json'; import { Task } from '../config/task-graph'; import { readJsonFile } from '../utils/fileutils'; -import { WorkspaceJsonConfiguration } from '../config/workspace-json-project-json'; +import { ProjectsConfigurations } from '../config/workspace-json-project-json'; /** * A data structure returned by the default hasher. @@ -309,7 +309,7 @@ export class Hasher { class ProjectHasher { private sourceHashes: { [projectName: string]: Promise } = {}; - private workspaceJson: WorkspaceJsonConfiguration; + private workspaceJson: ProjectsConfigurations; private nxJson: NxJsonConfiguration; private tsConfigJson: TsconfigJsonConfiguration; @@ -478,7 +478,7 @@ class ProjectHasher { } } - private readWorkspaceConfigFile(path: string): WorkspaceJsonConfiguration { + private readWorkspaceConfigFile(path: string): ProjectsConfigurations { try { const res = readJsonFile(path); res.projects ??= {}; diff --git a/packages/nx/src/hasher/node-based-file-hasher.ts b/packages/nx/src/hasher/node-based-file-hasher.ts index aca20b97c4dbd..98297ada207fb 100644 --- a/packages/nx/src/hasher/node-based-file-hasher.ts +++ b/packages/nx/src/hasher/node-based-file-hasher.ts @@ -1,4 +1,4 @@ -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { performance } from 'perf_hooks'; import { FileData } from '../config/project-graph'; import { join, relative } from 'path'; diff --git a/packages/nx/src/project-graph/affected/affected-project-graph.spec.ts b/packages/nx/src/project-graph/affected/affected-project-graph.spec.ts index 900c0db72979c..9c0175b395c22 100644 --- a/packages/nx/src/project-graph/affected/affected-project-graph.spec.ts +++ b/packages/nx/src/project-graph/affected/affected-project-graph.spec.ts @@ -9,7 +9,7 @@ import { NxJsonConfiguration } from '../../config/nx-json'; import { stripIndents } from '../../utils/strip-indents'; jest.mock('fs', () => require('memfs').fs); -jest.mock('nx/src/utils/app-root', () => ({ +jest.mock('nx/src/utils/workspace-root', () => ({ workspaceRoot: '/root', })); diff --git a/packages/nx/src/project-graph/affected/affected-project-graph.ts b/packages/nx/src/project-graph/affected/affected-project-graph.ts index 0a42f5559c532..235fd47ff3d6d 100644 --- a/packages/nx/src/project-graph/affected/affected-project-graph.ts +++ b/packages/nx/src/project-graph/affected/affected-project-graph.ts @@ -1,9 +1,4 @@ -import { - FileChange, - readNxJson, - readPackageJson, - readWorkspaceJson, -} from '../file-utils'; +import { FileChange, readPackageJson } from '../file-utils'; import { getImplicitlyTouchedProjects, getTouchedProjects, @@ -20,12 +15,16 @@ import { getTouchedProjectsFromTsConfig } from './locators/tsconfig-json-changes import { NxJsonConfiguration } from '../../config/nx-json'; import { ProjectGraph } from '../../config/project-graph'; import { reverse } from '../operators'; -import { WorkspaceJsonConfiguration } from '../../config/workspace-json-project-json'; +import { ProjectsConfigurations } from '../../config/workspace-json-project-json'; +import { + readAllWorkspaceConfiguration, + readNxJson, +} from '../../config/configuration'; export function filterAffected( graph: ProjectGraph, touchedFiles: FileChange[], - workspaceJson: WorkspaceJsonConfiguration = readWorkspaceJson(), + workspaceJson: ProjectsConfigurations = readAllWorkspaceConfiguration(), nxJson: NxJsonConfiguration = readNxJson(), packageJson: any = readPackageJson() ): ProjectGraph { diff --git a/packages/nx/src/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts b/packages/nx/src/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts index cb8d9b9e76b79..00985c3fdf3bc 100644 --- a/packages/nx/src/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts +++ b/packages/nx/src/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts @@ -9,7 +9,7 @@ import { import { ProjectGraphBuilder } from '../project-graph-builder'; jest.mock('fs', () => require('memfs').fs); -jest.mock('nx/src/utils/app-root', () => ({ +jest.mock('nx/src/utils/workspace-root', () => ({ workspaceRoot: '/root', })); diff --git a/packages/nx/src/project-graph/build-dependencies/explicit-project-dependencies.spec.ts b/packages/nx/src/project-graph/build-dependencies/explicit-project-dependencies.spec.ts index 67b6c2e798eb5..c57f57caa1204 100644 --- a/packages/nx/src/project-graph/build-dependencies/explicit-project-dependencies.spec.ts +++ b/packages/nx/src/project-graph/build-dependencies/explicit-project-dependencies.spec.ts @@ -6,7 +6,7 @@ import { ProjectGraphBuilder } from '../project-graph-builder'; import { buildExplicitTypeScriptDependencies } from './explicit-project-dependencies'; jest.mock('fs', () => require('memfs').fs); -jest.mock('nx/src/utils/app-root', () => ({ +jest.mock('nx/src/utils/workspace-root', () => ({ workspaceRoot: '/root', })); diff --git a/packages/nx/src/project-graph/build-dependencies/implict-project-dependencies.spec.ts b/packages/nx/src/project-graph/build-dependencies/implict-project-dependencies.spec.ts index 853e15c7f12e1..a63f2a9aa8cfa 100644 --- a/packages/nx/src/project-graph/build-dependencies/implict-project-dependencies.spec.ts +++ b/packages/nx/src/project-graph/build-dependencies/implict-project-dependencies.spec.ts @@ -3,7 +3,7 @@ import { ProjectGraphBuilder } from '../project-graph-builder'; import { buildImplicitProjectDependencies } from './implicit-project-dependencies'; jest.mock('fs', () => require('memfs').fs); -jest.mock('nx/src/utils/app-root', () => ({ +jest.mock('nx/src/utils/workspace-root', () => ({ workspaceRoot: '/root', })); diff --git a/packages/nx/src/project-graph/build-nodes/npm-packages.ts b/packages/nx/src/project-graph/build-nodes/npm-packages.ts index 33ed11d350ede..1e2113495e636 100644 --- a/packages/nx/src/project-graph/build-nodes/npm-packages.ts +++ b/packages/nx/src/project-graph/build-nodes/npm-packages.ts @@ -1,5 +1,5 @@ import { join } from 'path'; -import { workspaceRoot } from 'nx/src/utils/app-root'; +import { workspaceRoot } from 'nx/src/utils/workspace-root'; import { readJsonFile } from 'nx/src/utils/fileutils'; import { ProjectGraphBuilder } from '../project-graph-builder'; diff --git a/packages/nx/src/project-graph/build-nodes/workspace-projects.ts b/packages/nx/src/project-graph/build-nodes/workspace-projects.ts index b4014daecd910..ab6489ffe2437 100644 --- a/packages/nx/src/project-graph/build-nodes/workspace-projects.ts +++ b/packages/nx/src/project-graph/build-nodes/workspace-projects.ts @@ -1,6 +1,6 @@ import { join } from 'path'; import { existsSync } from 'fs'; -import { workspaceRoot } from 'nx/src/utils/app-root'; +import { workspaceRoot } from 'nx/src/utils/workspace-root'; import { loadNxPlugins, mergePluginTargetsWithNxTargets, diff --git a/packages/nx/src/project-graph/build-project-graph.spec.ts b/packages/nx/src/project-graph/build-project-graph.spec.ts index 8f284c94cd4c4..8fbd65306bc85 100644 --- a/packages/nx/src/project-graph/build-project-graph.spec.ts +++ b/packages/nx/src/project-graph/build-project-graph.spec.ts @@ -1,7 +1,7 @@ import { vol, fs } from 'memfs'; jest.mock('fs', () => require('memfs').fs); -jest.mock('nx/src/utils/app-root', () => ({ +jest.mock('nx/src/utils/workspace-root', () => ({ workspaceRoot: '/root', })); import { buildProjectGraph } from './build-project-graph'; diff --git a/packages/nx/src/project-graph/build-project-graph.ts b/packages/nx/src/project-graph/build-project-graph.ts index b6f296d168e1c..b462f25f9904a 100644 --- a/packages/nx/src/project-graph/build-project-graph.ts +++ b/packages/nx/src/project-graph/build-project-graph.ts @@ -1,8 +1,8 @@ -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { join } from 'path'; import { performance } from 'perf_hooks'; import { assertWorkspaceValidity } from '../utils/assert-workspace-validity'; -import { FileData, readNxJson, readWorkspaceJson } from './file-utils'; +import { FileData } from './file-utils'; import { normalizeNxJson } from './normalize-nx-json'; import { createCache, @@ -34,11 +34,15 @@ import { logger } from '../utils/logger'; import { ProjectGraphBuilder } from './project-graph-builder'; import { ProjectConfiguration, - WorkspaceJsonConfiguration, + ProjectsConfigurations, } from '../config/workspace-json-project-json'; +import { + readAllWorkspaceConfiguration, + readNxJson, +} from '../config/configuration'; export async function buildProjectGraph() { - const workspaceJson = readWorkspaceJson(); + const workspaceJson = readAllWorkspaceConfiguration(); const { projectFileMap, allWorkspaceFiles } = createProjectFileMap( workspaceJson, defaultFileHasher.allFileData() @@ -58,7 +62,7 @@ export async function buildProjectGraph() { } export async function buildProjectGraphUsingProjectFileMap( - workspaceJson: WorkspaceJsonConfiguration, + workspaceJson: ProjectsConfigurations, projectFileMap: ProjectFileMap, allWorkspaceFiles: FileData[], cache: ProjectGraphCache | null, @@ -348,7 +352,7 @@ function getNumberOfWorkers(): number { } function createContext( - workspaceJson: WorkspaceJsonConfiguration, + workspaceJson: ProjectsConfigurations, nxJson: NxJsonConfiguration, fileMap: ProjectFileMap, filesToProcess: ProjectFileMap diff --git a/packages/nx/src/project-graph/file-utils.ts b/packages/nx/src/project-graph/file-utils.ts index f12207fbdbd0a..7631bedea7f3f 100644 --- a/packages/nx/src/project-graph/file-utils.ts +++ b/packages/nx/src/project-graph/file-utils.ts @@ -3,14 +3,14 @@ import { execSync } from 'child_process'; import { existsSync, readFileSync } from 'fs'; import { extname, join, relative, sep } from 'path'; import type { NxArgs } from '../utils/command-line-utils'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { fileExists } from '../utils/fileutils'; import { jsonDiff } from '../utils/json-diff'; import ignore from 'ignore'; import { FileData } from '../config/project-graph'; import { readJsonFile } from '../utils/fileutils'; import { NxJsonConfiguration } from '../config/nx-json'; -import { WorkspaceJsonConfiguration } from '../config/workspace-json-project-json'; +import { ProjectsConfigurations } from '../config/workspace-json-project-json'; export interface Change { type: string; @@ -112,13 +112,6 @@ function defaultReadFileAtRevision( } } -export function readWorkspaceJson(): WorkspaceJsonConfiguration { - return readWorkspaceConfig({ - format: 'nx', - path: workspaceRoot, - }); -} - export function readWorkspaceConfig(opts: { format: 'angularCli' | 'nx'; path?: string; @@ -148,45 +141,5 @@ export function defaultFileRead(filePath: string): string | null { export function readPackageJson(): any { return readJsonFile(`${workspaceRoot}/package.json`); } - -/** - * Returns the contents of nx.json. - * - * If nx.json extends another config file, it will be inlined here. - */ -export function readNxJson( - path: string = `${workspaceRoot}/nx.json` -): NxJsonConfiguration { - let config = readJsonFile(path); - - if (config.extends) { - config = { - ...resolveNxJsonExtends(config.extends), - ...config, - }; - } - - return config; -} - -function resolveNxJsonExtends(extendedNxJsonPath: string) { - try { - return readJsonFile(require.resolve(extendedNxJsonPath)); - } catch (e) { - throw new Error(`Unable to resolve nx.json extends. Error: ${e.message}`); - } -} - -/** - * Returns information about where apps and libs will be created. - */ -export function workspaceLayout(): { appsDir: string; libsDir: string } { - const nxJson = readNxJson(); - return { - appsDir: nxJson.workspaceLayout?.appsDir ?? 'apps', - libsDir: nxJson.workspaceLayout?.libsDir ?? 'libs', - }; -} - // Original Exports export { FileData }; diff --git a/packages/nx/src/project-graph/nx-deps-cache.ts b/packages/nx/src/project-graph/nx-deps-cache.ts index 4cd3fa5845fd0..b74acaab9402b 100644 --- a/packages/nx/src/project-graph/nx-deps-cache.ts +++ b/packages/nx/src/project-graph/nx-deps-cache.ts @@ -14,7 +14,7 @@ import { } from '../config/project-graph'; import { readJsonFile, writeJsonFile } from '../utils/fileutils'; import { NxJsonConfiguration } from '../config/nx-json'; -import { WorkspaceJsonConfiguration } from '../config/workspace-json-project-json'; +import { ProjectsConfigurations } from '../config/workspace-json-project-json'; export interface ProjectGraphCache { version: string; @@ -107,7 +107,7 @@ export function writeCache(cache: ProjectGraphCache): void { export function shouldRecomputeWholeGraph( cache: ProjectGraphCache, packageJsonDeps: Record, - workspaceJson: WorkspaceJsonConfiguration, + workspaceJson: ProjectsConfigurations, nxJson: NxJsonConfiguration, tsConfig: { compilerOptions: { paths: { [k: string]: any } } } ): boolean { diff --git a/packages/nx/src/project-graph/project-graph.ts b/packages/nx/src/project-graph/project-graph.ts index e1a1b3f023258..2955509f33545 100644 --- a/packages/nx/src/project-graph/project-graph.ts +++ b/packages/nx/src/project-graph/project-graph.ts @@ -1,6 +1,6 @@ import { ProjectGraphCache, readCache } from './nx-deps-cache'; import { buildProjectGraph } from './build-project-graph'; -import { readNxJson, workspaceFileName } from './file-utils'; +import { workspaceFileName } from './file-utils'; import { output } from '../utils/output'; import { isCI } from '../utils/is-ci'; import { defaultFileHasher } from '../hasher/file-hasher'; @@ -12,6 +12,7 @@ import { import { statSync } from 'fs'; import { ProjectGraph, ProjectGraphV4 } from '../config/project-graph'; import { stripIndents } from '../utils/strip-indents'; +import { readNxJson } from '../config/configuration'; /** * Synchronously reads the latest cached copy of the workspace's ProjectGraph. diff --git a/packages/nx/src/tasks-runner/batch/run-batch.ts b/packages/nx/src/tasks-runner/batch/run-batch.ts index 6bed7e4334f0c..5a1243c4b4807 100644 --- a/packages/nx/src/tasks-runner/batch/run-batch.ts +++ b/packages/nx/src/tasks-runner/batch/run-batch.ts @@ -4,10 +4,11 @@ import { BatchMessageType, } from './batch-messages'; import { Workspaces } from '../../config/workspaces'; -import { workspaceRoot } from '../../utils/app-root'; +import { workspaceRoot } from '../../utils/workspace-root'; import { combineOptionsForExecutor } from '../../utils/params'; import { TaskGraph } from '../../config/task-graph'; import { ExecutorContext } from '../../config/misc-interfaces'; +import { readAllWorkspaceConfiguration } from 'nx/src/config/configuration'; function getBatchExecutor(executorName: string) { const workspace = new Workspaces(workspaceRoot); @@ -17,8 +18,7 @@ function getBatchExecutor(executorName: string) { async function runTasks(executorName: string, taskGraph: TaskGraph) { const input: Record = {}; - const workspace = new Workspaces(workspaceRoot); - const workspaceConfig = workspace.readWorkspaceConfiguration(); + const workspaceConfig = readAllWorkspaceConfiguration(); const batchExecutor = getBatchExecutor(executorName); const tasks = Object.values(taskGraph.tasks); @@ -29,8 +29,7 @@ async function runTasks(executorName: string, taskGraph: TaskGraph) { isVerbose: false, }; for (const task of tasks) { - const projectConfiguration = - workspace.readWorkspaceConfiguration().projects[task.target.project]; + const projectConfiguration = workspaceConfig.projects[task.target.project]; const targetConfiguration = projectConfiguration.targets[task.target.target]; input[task.id] = combineOptionsForExecutor( diff --git a/packages/nx/src/tasks-runner/cache.ts b/packages/nx/src/tasks-runner/cache.ts index 8c89b3d975ee1..c90b84b34bcce 100644 --- a/packages/nx/src/tasks-runner/cache.ts +++ b/packages/nx/src/tasks-runner/cache.ts @@ -1,4 +1,4 @@ -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { copy, mkdir, diff --git a/packages/nx/src/tasks-runner/forked-process-task-runner.ts b/packages/nx/src/tasks-runner/forked-process-task-runner.ts index b4add7fb26bb6..028047c0808c6 100644 --- a/packages/nx/src/tasks-runner/forked-process-task-runner.ts +++ b/packages/nx/src/tasks-runner/forked-process-task-runner.ts @@ -1,7 +1,7 @@ import { readFileSync, writeFileSync } from 'fs'; import * as dotenv from 'dotenv'; import { ChildProcess, fork } from 'child_process'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { DefaultTasksRunnerOptions } from './default-tasks-runner'; import { output } from '../utils/output'; import { diff --git a/packages/nx/src/tasks-runner/run-command.ts b/packages/nx/src/tasks-runner/run-command.ts index 056a4329dc894..464b4fc88ac24 100644 --- a/packages/nx/src/tasks-runner/run-command.ts +++ b/packages/nx/src/tasks-runner/run-command.ts @@ -1,6 +1,6 @@ import { TasksRunner, TaskStatus } from './tasks-runner'; import { join } from 'path'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { NxArgs } from '../utils/command-line-utils'; import { isRelativePath } from '../utils/fileutils'; import { output } from '../utils/output'; diff --git a/packages/nx/src/tasks-runner/task-orchestrator.ts b/packages/nx/src/tasks-runner/task-orchestrator.ts index 16151b3804f7f..c3a08e0b3dae4 100644 --- a/packages/nx/src/tasks-runner/task-orchestrator.ts +++ b/packages/nx/src/tasks-runner/task-orchestrator.ts @@ -2,7 +2,7 @@ import { Workspaces } from '../config/workspaces'; import { performance } from 'perf_hooks'; import { Hasher } from '../hasher/hasher'; import { ForkedProcessTaskRunner } from './forked-process-task-runner'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; import { Cache } from './cache'; import { DefaultTasksRunnerOptions } from './default-tasks-runner'; import { TaskStatus } from './tasks-runner'; diff --git a/packages/nx/src/tasks-runner/utils.ts b/packages/nx/src/tasks-runner/utils.ts index bb9125e92952b..d0790170df079 100644 --- a/packages/nx/src/tasks-runner/utils.ts +++ b/packages/nx/src/tasks-runner/utils.ts @@ -12,7 +12,7 @@ import { Task, TaskGraph } from '../config/task-graph'; import { getPackageManagerCommand } from '../utils/package-manager'; import { ProjectGraph, ProjectGraphProjectNode } from '../config/project-graph'; import { TargetDependencyConfig } from '../config/workspace-json-project-json'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from '../utils/workspace-root'; export function getCommandAsString(task: Task) { const execCommand = getPackageManagerCommand().exec; diff --git a/packages/nx/src/utils/app-root.ts b/packages/nx/src/utils/app-root.ts deleted file mode 100644 index 716fe9a345ff0..0000000000000 --- a/packages/nx/src/utils/app-root.ts +++ /dev/null @@ -1,37 +0,0 @@ -import * as path from 'path'; -import { statSync } from 'fs'; - -/** - * The root of the workspace. - * - * @deprecated use workspaceRoot instead - */ -export const appRootPath = pathInner(__dirname); - -/** - * The root of the workspace - */ -export const workspaceRoot = appRootPath; - -function pathInner(dir: string): string { - if (process.env.NX_WORKSPACE_ROOT_PATH) - return process.env.NX_WORKSPACE_ROOT_PATH; - if (path.dirname(dir) === dir) return process.cwd(); - if ( - fileExists(path.join(dir, 'workspace.json')) || - fileExists(path.join(dir, 'nx.json')) || - fileExists(path.join(dir, 'angular.json')) - ) { - return dir; - } else { - return pathInner(path.dirname(dir)); - } -} - -export function fileExists(filePath: string): boolean { - try { - return statSync(filePath).isFile(); - } catch (err) { - return false; - } -} diff --git a/packages/nx/src/utils/cache-directory.ts b/packages/nx/src/utils/cache-directory.ts index 18203a422a4fc..ee515b5802b4a 100644 --- a/packages/nx/src/utils/cache-directory.ts +++ b/packages/nx/src/utils/cache-directory.ts @@ -1,5 +1,5 @@ import { join, isAbsolute } from 'path'; -import { workspaceRoot } from './app-root'; +import { workspaceRoot } from './workspace-root'; import { readJsonFile } from './fileutils'; import { NxJsonConfiguration } from '../config/nx-json'; diff --git a/packages/nx/src/utils/command-line-utils.spec.ts b/packages/nx/src/utils/command-line-utils.spec.ts index b1dc13171b272..8b158190e2436 100644 --- a/packages/nx/src/utils/command-line-utils.spec.ts +++ b/packages/nx/src/utils/command-line-utils.spec.ts @@ -1,15 +1,8 @@ -import { - getAffectedConfig, - splitArgsIntoNxArgsAndOverrides, -} from './command-line-utils'; -import * as fileUtils from '../project-graph/file-utils'; +import { splitArgsIntoNxArgsAndOverrides } from './command-line-utils'; jest.mock('../project-graph/file-utils'); describe('splitArgs', () => { - beforeEach(() => { - jest.spyOn(fileUtils, 'readNxJson').mockReturnThis(); - }); it('should split nx specific arguments into nxArgs', () => { expect( splitArgsIntoNxArgsAndOverrides( @@ -20,7 +13,9 @@ describe('splitArgs', () => { _: ['--override'], $0: '', }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs ).toEqual({ base: 'sha1', @@ -37,7 +32,9 @@ describe('splitArgs', () => { _: ['--override'], $0: '', }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs; expect(nxArgs['nxKey']).toEqual('some-value'); }); @@ -50,7 +47,9 @@ describe('splitArgs', () => { _: ['--override'], $0: '', }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs ).toEqual({ base: 'main', @@ -59,12 +58,6 @@ describe('splitArgs', () => { }); it('should return configured base branch from nx.json', () => { - jest.spyOn(fileUtils, 'readNxJson').mockReturnValue({ - npmScope: 'testing', - affected: { - defaultBase: 'develop', - }, - }); expect( splitArgsIntoNxArgsAndOverrides( { @@ -72,7 +65,9 @@ describe('splitArgs', () => { _: ['--override'], $0: '', }, - 'affected' + 'affected', + {} as any, + { affected: { defaultBase: 'develop' } } ).nxArgs ).toEqual({ base: 'develop', @@ -81,9 +76,6 @@ describe('splitArgs', () => { }); it('should return a default base branch if not configured in nx.json', () => { - jest.spyOn(fileUtils, 'readNxJson').mockReturnValue({ - npmScope: 'testing', - }); expect( splitArgsIntoNxArgsAndOverrides( { @@ -91,7 +83,9 @@ describe('splitArgs', () => { _: ['--override'], $0: '', }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs ).toEqual({ base: 'main', @@ -108,7 +102,9 @@ describe('splitArgs', () => { _: ['--override'], $0: '', }, - 'affected' + 'affected', + {} as any, + {} as any ).overrides ).toEqual({ notNxArg: true, @@ -123,7 +119,9 @@ describe('splitArgs', () => { _: ['affected', '--name', 'bob', 'sha1', 'sha2', '--override'], $0: '', }, - 'affected' + 'affected', + {} as any, + {} as any ); expect(nxArgs).toEqual({ @@ -151,7 +149,9 @@ describe('splitArgs', () => { _: ['--override'], $0: '', }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs ).toEqual({ base: 'envVarSha1', @@ -167,7 +167,9 @@ describe('splitArgs', () => { $0: '', head: 'directlyOnCommandSha1', // higher priority than $NX_HEAD }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs ).toEqual({ base: 'envVarSha1', @@ -183,7 +185,9 @@ describe('splitArgs', () => { $0: '', base: 'directlyOnCommandSha2', // higher priority than $NX_BASE }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs ).toEqual({ base: 'directlyOnCommandSha2', @@ -203,7 +207,9 @@ describe('splitArgs', () => { _: ['--exclude=file'], $0: '', }, - 'run-one' + 'run-one', + {} as any, + {} as any ); expect(nxArgs).toEqual({ @@ -223,7 +229,9 @@ describe('splitArgs', () => { $0: '', parallel: '5', }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs.parallel; expect(parallel).toEqual(5); @@ -236,7 +244,9 @@ describe('splitArgs', () => { $0: '', parallel: '', }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs.parallel; expect(parallel).toEqual(3); @@ -249,7 +259,9 @@ describe('splitArgs', () => { $0: '', parallel: 'true', }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs.parallel; expect(parallel).toEqual(3); @@ -262,7 +274,9 @@ describe('splitArgs', () => { $0: '', parallel: 'false', }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs.parallel; expect(parallel).toEqual(1); @@ -276,7 +290,9 @@ describe('splitArgs', () => { parallel: '', maxParallel: 5, }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs.parallel; expect(parallel).toEqual(5); @@ -290,29 +306,12 @@ describe('splitArgs', () => { parallel: '', maxParallel: 5, }, - 'affected' + 'affected', + {} as any, + {} as any ).nxArgs.parallel; expect(parallel).toEqual(5); }); }); }); - -describe('getAffectedConfig', () => { - it('should return defaults when affected is undefined in nx.json', () => { - jest.spyOn(fileUtils, 'readNxJson').mockReturnThis(); - - expect(getAffectedConfig().defaultBase).toEqual('main'); - }); - - it('should return default base branch when its defined in nx.json', () => { - jest.spyOn(fileUtils, 'readNxJson').mockReturnValue({ - npmScope: 'testing', - affected: { - defaultBase: 'testing', - }, - }); - - expect(getAffectedConfig().defaultBase).toEqual('testing'); - }); -}); diff --git a/packages/nx/src/utils/command-line-utils.ts b/packages/nx/src/utils/command-line-utils.ts index e0b210a7fefd0..acf1cd235c722 100644 --- a/packages/nx/src/utils/command-line-utils.ts +++ b/packages/nx/src/utils/command-line-utils.ts @@ -1,13 +1,13 @@ import * as yargsParser from 'yargs-parser'; import * as yargs from 'yargs'; -import { - readNxJson, - readWorkspaceJson, - TEN_MEGABYTES, -} from '../project-graph/file-utils'; +import { TEN_MEGABYTES } from '../project-graph/file-utils'; import { output } from './output'; -import { NxAffectedConfig } from '../config/nx-json'; +import { NxAffectedConfig, NxJsonConfiguration } from '../config/nx-json'; import { execSync } from 'child_process'; +import { + readAllWorkspaceConfiguration, + readNxJson, +} from '../config/configuration'; export function names(name: string): { name: string; @@ -138,7 +138,8 @@ const ignoreArgs = ['$0', '_']; export function splitArgsIntoNxArgsAndOverrides( args: yargs.Arguments, mode: 'run-one' | 'run-many' | 'affected' | 'print-affected', - options = { printWarnings: true } + options = { printWarnings: true }, + nxJson: NxJsonConfiguration ): { nxArgs: NxArgs; overrides: yargs.Arguments } { const nxSpecific = mode === 'run-one' ? runOne : mode === 'run-many' ? runMany : runAffected; @@ -238,8 +239,7 @@ export function splitArgsIntoNxArgsAndOverrides( } if (!nxArgs.base) { - const affectedConfig = getAffectedConfig(); - nxArgs.base = affectedConfig.defaultBase; + nxArgs.base = nxJson.affected?.defaultBase || 'main'; // No user-provided arguments to set the affected criteria, so inform the user of the defaults being used if ( @@ -280,14 +280,6 @@ export function splitArgsIntoNxArgsAndOverrides( return { nxArgs, overrides } as any; } -export function getAffectedConfig(): NxAffectedConfig { - const config = readNxJson(); - - return { - defaultBase: config.affected?.defaultBase || 'main', - }; -} - export function parseFiles(options: NxArgs): { files: string[] } { const { files, uncommitted, untracked, base, head } = options; @@ -357,6 +349,6 @@ function parseGitOutput(command: string): string[] { } export function getProjectRoots(projectNames: string[]): string[] { - const { projects } = readWorkspaceJson(); + const { projects } = readAllWorkspaceConfiguration(); return projectNames.map((name) => projects[name].root); } diff --git a/packages/nx/src/utils/find-workspace-root.ts b/packages/nx/src/utils/find-workspace-root.ts index 8e556627d65ce..bf352f1e1004c 100644 --- a/packages/nx/src/utils/find-workspace-root.ts +++ b/packages/nx/src/utils/find-workspace-root.ts @@ -1,5 +1,6 @@ import { existsSync } from 'fs'; import * as path from 'path'; +import { workspaceRootInner } from './workspace-root'; /** * Recursive function that walks back up the directory @@ -8,19 +9,21 @@ import * as path from 'path'; * @param dir Directory to start searching with */ export function findWorkspaceRoot(dir: string): WorkspaceTypeAndRoot | null { - if (existsSync(path.join(dir, 'angular.json'))) { - return { type: 'angular', dir }; + const r = workspaceRootInner(dir, null); + + if (existsSync(path.join(r, 'angular.json'))) { + return { type: 'angular', dir: r }; } - if (existsSync(path.join(dir, 'nx.json'))) { - return { type: 'nx', dir }; + if (existsSync(path.join(r, 'nx.json'))) { + return { type: 'nx', dir: r }; } - if (path.dirname(dir) === dir) { - return null; + if (existsSync(path.join(r, 'node_modules', 'nx', 'package.json'))) { + return { type: 'nx', dir: r }; } - return findWorkspaceRoot(path.dirname(dir)); + return null; } export interface WorkspaceTypeAndRoot { diff --git a/packages/nx/src/utils/nx-plugin.ts b/packages/nx/src/utils/nx-plugin.ts index 70da02ec6c389..37bc88d887881 100644 --- a/packages/nx/src/utils/nx-plugin.ts +++ b/packages/nx/src/utils/nx-plugin.ts @@ -4,14 +4,14 @@ import * as path from 'path'; import { ProjectGraphProcessor } from '../config/project-graph'; import { Workspaces } from '../config/workspaces'; -import { workspaceRoot } from '../utils/app-root'; +import { workspaceRoot } from './workspace-root'; import { readJsonFile } from '../utils/fileutils'; import { PackageJson } from './package-json'; import { registerTsProject } from './register'; import { ProjectConfiguration, TargetConfiguration, - WorkspaceJsonConfiguration, + ProjectsConfigurations, } from '../config/workspace-json-project-json'; import { findMatchingProjectForPath } from './target-project-locator'; import { logger } from './logger'; @@ -185,7 +185,7 @@ function lookupLocalPlugin(importPath: string, root = workspaceRoot) { function findNxProjectForImportPath( importPath: string, - workspace: WorkspaceJsonConfiguration, + workspace: ProjectsConfigurations, root = workspaceRoot ): string | null { const tsConfigPaths: Record = readTsConfigPaths(root); diff --git a/packages/nx/src/utils/params.ts b/packages/nx/src/utils/params.ts index 13bf2ff5d03f7..0dfdbbd47ee05 100644 --- a/packages/nx/src/utils/params.ts +++ b/packages/nx/src/utils/params.ts @@ -2,7 +2,7 @@ import { logger } from './logger'; import { NxJsonConfiguration } from '../config/nx-json'; import { TargetConfiguration, - WorkspaceJsonConfiguration, + ProjectsConfigurations, } from '../config/workspace-json-project-json'; type PropertyDescription = { @@ -554,7 +554,7 @@ export async function combineOptionsForGenerator( commandLineOpts: Options, collectionName: string, generatorName: string, - wc: (WorkspaceJsonConfiguration & NxJsonConfiguration) | null, + wc: (ProjectsConfigurations & NxJsonConfiguration) | null, schema: Schema, isInteractive: boolean, defaultProjectName: string | null, @@ -646,7 +646,7 @@ export function convertSmartDefaultsIntoNamedParams( function getGeneratorDefaults( projectName: string | null, - wc: (WorkspaceJsonConfiguration & NxJsonConfiguration) | null, + wc: (ProjectsConfigurations & NxJsonConfiguration) | null, collectionName: string, generatorName: string ) { diff --git a/packages/nx/src/utils/plugins/plugin-capabilities.ts b/packages/nx/src/utils/plugins/plugin-capabilities.ts index 9d51f1f34a88d..4675bb3c6f73e 100644 --- a/packages/nx/src/utils/plugins/plugin-capabilities.ts +++ b/packages/nx/src/utils/plugins/plugin-capabilities.ts @@ -1,4 +1,4 @@ -import { workspaceRoot } from '../app-root'; +import { workspaceRoot } from '../workspace-root'; import * as chalk from 'chalk'; import { dirname, join } from 'path'; import { output } from '../output'; diff --git a/packages/nx/src/utils/target-project-locator.spec.ts b/packages/nx/src/utils/target-project-locator.spec.ts index bd82768d94df6..cadf8622bdda8 100644 --- a/packages/nx/src/utils/target-project-locator.spec.ts +++ b/packages/nx/src/utils/target-project-locator.spec.ts @@ -6,7 +6,7 @@ import { ProjectGraphProjectNode, } from '../config/project-graph'; -jest.mock('nx/src/utils/app-root', () => ({ +jest.mock('nx/src/utils/workspace-root', () => ({ workspaceRoot: '/root', })); jest.mock('fs', () => require('memfs').fs); diff --git a/packages/nx/src/utils/target-project-locator.ts b/packages/nx/src/utils/target-project-locator.ts index cd3345c914816..bc653152fa93d 100644 --- a/packages/nx/src/utils/target-project-locator.ts +++ b/packages/nx/src/utils/target-project-locator.ts @@ -1,7 +1,7 @@ import { getRootTsConfigFileName, resolveModuleByImport } from './typescript'; import { isRelativePath } from './fileutils'; import { dirname, join, posix } from 'path'; -import { workspaceRoot } from './app-root'; +import { workspaceRoot } from './workspace-root'; import { readFileSync } from 'fs'; import { ProjectGraphExternalNode, diff --git a/packages/nx/src/utils/typescript.ts b/packages/nx/src/utils/typescript.ts index 8993fc5ea118c..c364ccf0bb683 100644 --- a/packages/nx/src/utils/typescript.ts +++ b/packages/nx/src/utils/typescript.ts @@ -1,4 +1,4 @@ -import { workspaceRoot } from './app-root'; +import { workspaceRoot } from './workspace-root'; import { existsSync } from 'fs'; import { dirname, join } from 'path'; import type * as ts from 'typescript'; diff --git a/packages/nx/src/utils/workspace-root.ts b/packages/nx/src/utils/workspace-root.ts new file mode 100644 index 0000000000000..05f0cc9252eda --- /dev/null +++ b/packages/nx/src/utils/workspace-root.ts @@ -0,0 +1,38 @@ +import * as path from 'path'; +import { statSync } from 'fs'; + +/** + * The root of the workspace + */ +export const workspaceRoot = workspaceRootInner(__dirname, null); + +/** + * The root of the workspace. + * + * @deprecated use workspaceRoot instead + */ +export const appRootPath = workspaceRoot; + +export function workspaceRootInner( + dir: string, + candidateRoot: string | null +): string { + if (process.env.NX_WORKSPACE_ROOT_PATH) + return process.env.NX_WORKSPACE_ROOT_PATH; + if (path.dirname(dir) === dir) return candidateRoot || process.cwd(); + if (fileExists(path.join(dir, 'nx.json'))) { + return dir; + } else if (fileExists(path.join(dir, 'node_modules', 'nx', 'package.json'))) { + return workspaceRootInner(path.dirname(dir), dir); + } else { + return workspaceRootInner(path.dirname(dir), candidateRoot); + } +} + +export function fileExists(filePath: string): boolean { + try { + return statSync(filePath).isFile(); + } catch (err) { + return false; + } +} diff --git a/packages/react-native/project.json b/packages/react-native/project.json index 274299bf3ef48..a430d062f403c 100644 --- a/packages/react-native/project.json +++ b/packages/react-native/project.json @@ -77,7 +77,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/react-native"], "options": { "command": "node ./scripts/copy-readme.js react-native" diff --git a/packages/react/project.json b/packages/react/project.json index df90d670c0c8c..2021b518bd949 100644 --- a/packages/react/project.json +++ b/packages/react/project.json @@ -66,7 +66,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/react"], "options": { "command": "node ./scripts/copy-readme.js react" diff --git a/packages/react/src/module-federation/with-module-federation.ts b/packages/react/src/module-federation/with-module-federation.ts index 618439a9221f0..6a3dc17acf9f8 100644 --- a/packages/react/src/module-federation/with-module-federation.ts +++ b/packages/react/src/module-federation/with-module-federation.ts @@ -6,16 +6,14 @@ import { import { createProjectGraphAsync, ProjectGraph, + readAllWorkspaceConfiguration, readCachedProjectGraph, - workspaceRoot, - Workspaces, } from '@nrwl/devkit'; import { getRootTsConfigPath, readTsConfig, } from '@nrwl/workspace/src/utilities/typescript'; import { ParsedCommandLine } from 'typescript'; -import { readWorkspaceJson } from 'nx/src/project-graph/file-utils'; import { AdditionalSharedConfig, ModuleFederationConfig, @@ -57,9 +55,7 @@ function collectDependencies( } function mapWorkspaceLibrariesToTsConfigImport(workspaceLibraries: string[]) { - const { projects } = new Workspaces( - workspaceRoot - ).readWorkspaceConfiguration(); + const { projects } = readAllWorkspaceConfiguration(); const tsConfigPath = process.env.NX_TSCONFIG_PATH ?? getRootTsConfigPath(); const tsConfig: ParsedCommandLine = readTsConfig(tsConfigPath); @@ -109,7 +105,7 @@ async function getDependentPackagesForProject( } function determineRemoteUrl(remote: string) { - const workspace = readWorkspaceJson(); + const workspace = readAllWorkspaceConfiguration(); const serveTarget = workspace.projects[remote]?.targets?.serve; if (!serveTarget) { @@ -215,7 +211,7 @@ function applyAdditionalShared( export async function withModuleFederation(options: ModuleFederationConfig) { const reactWebpackConfig = require('../../plugins/webpack'); - const ws = readWorkspaceJson(); + const ws = readAllWorkspaceConfiguration(); const project = ws.projects[options.name]; if (!project) { diff --git a/packages/storybook/migrations.json b/packages/storybook/migrations.json index f471ab540c8b7..99ea047eb61b9 100644 --- a/packages/storybook/migrations.json +++ b/packages/storybook/migrations.json @@ -1,16 +1,5 @@ { "schematics": { - "update-builder-8.8.2": { - "version": "8.8.2", - "description": "Update storybook builder and tsconfig", - "factory": "./src/migrations/update-8-8-2/update-builder-8-8-2" - }, - "update-9.2.0": { - "version": "9.2.0-beta.1", - "cli": "nx", - "description": "Add build-storybook to cacheable operations", - "factory": "./src/migrations/update-9-2-0/update-9-2-0" - }, "update-10.2.1": { "version": "10.2.1-beta.1", "description": "Adjusts the tsconfig mapping", diff --git a/packages/storybook/project.json b/packages/storybook/project.json index 0cdab33728a35..c37b36b12346d 100644 --- a/packages/storybook/project.json +++ b/packages/storybook/project.json @@ -66,7 +66,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/storybook"], "options": { "command": "node ./scripts/copy-readme.js storybook" diff --git a/packages/storybook/src/migrations/update-8-8-2/update-builder-8-8-2.spec.ts b/packages/storybook/src/migrations/update-8-8-2/update-builder-8-8-2.spec.ts deleted file mode 100644 index 614b77a9b40ed..0000000000000 --- a/packages/storybook/src/migrations/update-8-8-2/update-builder-8-8-2.spec.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { Tree } from '@angular-devkit/schematics'; -import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; -import { - updateJsonInTree, - readJsonInTree, - updateWorkspaceInTree, - readWorkspace, - getWorkspacePath, -} from '@nrwl/workspace'; - -import * as path from 'path'; - -describe('Update 8-8-2', () => { - let tree: Tree; - let schematicRunner: SchematicTestRunner; - - beforeEach(async () => { - tree = Tree.empty(); - schematicRunner = new SchematicTestRunner( - '@nrwl/storybook', - path.join(__dirname, '../../../migrations.json') - ); - }); - - it(`should remove headless/watch as options for e2e builder`, async () => { - tree.create( - 'workspace.json', - JSON.stringify({ - projects: { - ['home-ui']: { - projectType: 'library', - root: 'libs/home/ui', - sourceRoot: 'libs/home/ui/src', - prefix: 'app', - architect: { - storybook: { - builder: '@nrwl/storybook:storybook', - options: { - uiFramework: '@storybook/angular', - port: 4400, - config: { - configFolder: 'libs/home/ui/.storybook', - }, - }, - }, - }, - }, - ['home-ui-e2e']: { - root: 'apps/home-ui-e2e', - sourceRoot: 'apps/home-ui-e2e/src', - architect: { - e2e: { - builder: '@nrwl/cypress:cypress', - options: { - cypressConfig: 'apps/home-ui-e2e/cypress.json', - tsConfig: 'apps/home-ui-e2e/tsconfig.e2e.json', - devServerTarget: 'home-ui:storybook', - headless: false, - watch: true, - }, - configurations: { - headless: { - devServerTarget: 'home-ui:storybook:ci', - headless: true, - }, - }, - }, - }, - }, - }, - }) - ); - - tree = await schematicRunner - .runSchematicAsync('update-builder-8.8.2', {}, tree) - .toPromise(); - - const config = readWorkspace(tree); - expect( - config.projects['home-ui-e2e'].architect.e2e.options.headless - ).toBeUndefined(); - expect( - config.projects['home-ui-e2e'].architect.e2e.options.watch - ).toBeUndefined(); - expect( - config.projects['home-ui-e2e'].architect.e2e.configurations - ).toBeUndefined(); - }); - - it(`should add emitDecoratorMetadata to storybook tsconfig.json`, async () => { - tree.create( - 'libs/home/ui/.storybook/tsconfig.json', - JSON.stringify({ - extends: '../tsconfig.json', - exclude: ['../src/test.ts', '../**/*.spec.ts'], - include: ['../src/**/*'], - }) - ); - tree.create( - 'workspace.json', - JSON.stringify({ - projects: { - ['home-ui']: { - projectType: 'library', - root: 'libs/home/ui', - sourceRoot: 'libs/home/ui/src', - prefix: 'app', - architect: { - storybook: { - builder: '@nrwl/storybook:storybook', - options: { - uiFramework: '@storybook/angular', - port: 4400, - config: { - configFolder: 'libs/home/ui/.storybook', - }, - }, - }, - }, - }, - ['home-ui-e2e']: { - root: 'apps/home-ui-e2e', - sourceRoot: 'apps/home-ui-e2e/src', - architect: { - e2e: { - builder: '@nrwl/cypress:cypress', - options: { - cypressConfig: 'apps/home-ui-e2e/cypress.json', - tsConfig: 'apps/home-ui-e2e/tsconfig.e2e.json', - devServerTarget: 'home-ui:storybook', - headless: false, - watch: true, - }, - configurations: { - headless: { - devServerTarget: 'home-ui:storybook:ci', - headless: true, - }, - }, - }, - }, - }, - }, - }) - ); - - tree = await schematicRunner - .runSchematicAsync('update-builder-8.8.2', {}, tree) - .toPromise(); - - const tsconfig = readJsonInTree( - tree, - 'libs/home/ui/.storybook/tsconfig.json' - ); - expect(tsconfig.compilerOptions.emitDecoratorMetadata).toBe(true); - }); -}); diff --git a/packages/storybook/src/migrations/update-8-8-2/update-builder-8-8-2.ts b/packages/storybook/src/migrations/update-8-8-2/update-builder-8-8-2.ts deleted file mode 100644 index 27afb07e114da..0000000000000 --- a/packages/storybook/src/migrations/update-8-8-2/update-builder-8-8-2.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Rule, chain } from '@angular-devkit/schematics'; -import { - updateWorkspaceInTree, - readWorkspaceJson, - readWorkspace, - updateJsonInTree, - formatFiles, -} from '@nrwl/workspace'; - -export default function update(): Rule { - return chain([ - updateWorkspaceInTree((config) => { - const filteredProjects: Array> = []; - Object.keys(config.projects).forEach((name) => { - if ( - config.projects[name].architect && - config.projects[name].architect.e2e && - config.projects[name].architect.e2e.builder === - '@nrwl/cypress:cypress' && - config.projects[name].architect.e2e.options.devServerTarget.endsWith( - ':storybook' - ) - ) { - filteredProjects.push(config.projects[name]); - } - }); - filteredProjects.forEach((p) => { - delete p.architect.e2e.options.headless; - delete p.architect.e2e.options.watch; - delete p.architect.e2e.configurations; - }); - return config; - }), - (tree, context) => { - const workspace = readWorkspace(tree); - const tsconfigUpdateRules: Rule[] = []; - Object.keys(workspace.projects).forEach((name) => { - if ( - workspace.projects[name].architect && - workspace.projects[name].architect.storybook && - workspace.projects[name].architect.storybook.builder === - '@nrwl/storybook:storybook' && - workspace.projects[name].architect.storybook.options.config - .configFolder - ) { - const storybookFolderPath = - workspace.projects[name].architect.storybook.options.config - .configFolder; - tsconfigUpdateRules.push( - updateJsonInTree( - `${storybookFolderPath}/tsconfig.json`, - (json) => ({ - ...json, - compilerOptions: { - emitDecoratorMetadata: true, - }, - }) - ) - ); - } - }); - return chain(tsconfigUpdateRules); - }, - formatFiles(), - ]); -} diff --git a/packages/storybook/src/migrations/update-9-0-0/update-9-0-0.ts b/packages/storybook/src/migrations/update-9-0-0/update-9-0-0.ts deleted file mode 100644 index 89beb2d13d301..0000000000000 --- a/packages/storybook/src/migrations/update-9-0-0/update-9-0-0.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { chain } from '@angular-devkit/schematics'; -import { formatFiles, updatePackagesInPackageJson } from '@nrwl/workspace'; -import { join } from 'path'; - -const updatePackages = updatePackagesInPackageJson( - join(__dirname, '../../../', 'migrations.json'), - '9.0.0' -); - -export default function () { - return chain([updatePackages, formatFiles()]); -} diff --git a/packages/storybook/src/migrations/update-9-2-0/update-9-2-0.ts b/packages/storybook/src/migrations/update-9-2-0/update-9-2-0.ts deleted file mode 100644 index 1886746d668c4..0000000000000 --- a/packages/storybook/src/migrations/update-9-2-0/update-9-2-0.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Tree, formatFiles } from '@nrwl/devkit'; -import { addCacheableOperation } from '../../generators/init/init'; - -export default async function (tree: Tree) { - addCacheableOperation(tree); - await formatFiles(tree); -} diff --git a/packages/tao/project.json b/packages/tao/project.json index 20c6508af0301..26427fc93b92d 100644 --- a/packages/tao/project.json +++ b/packages/tao/project.json @@ -56,7 +56,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/tao"], "options": { "commands": [ diff --git a/packages/tao/src/utils/app-root.ts b/packages/tao/src/utils/app-root.ts index 17a6782a45737..a4e612047e6d1 100644 --- a/packages/tao/src/utils/app-root.ts +++ b/packages/tao/src/utils/app-root.ts @@ -1 +1 @@ -export * from 'nx/src/utils/app-root'; +export * from 'nx/src/utils/workspace-root'; diff --git a/packages/web/project.json b/packages/web/project.json index 0c2ce5e9111ae..7d58add8224f0 100644 --- a/packages/web/project.json +++ b/packages/web/project.json @@ -61,7 +61,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/web"], "options": { "command": "node ./scripts/copy-readme.js web" diff --git a/packages/workspace/index.ts b/packages/workspace/index.ts index 30429502c5d20..63a3fa07d63e8 100644 --- a/packages/workspace/index.ts +++ b/packages/workspace/index.ts @@ -17,8 +17,6 @@ export { export { output } from './src/utilities/output'; export { - readWorkspaceJson, - readNxJson, readWorkspaceConfig, readPackageJson, } from 'nx/src/project-graph/file-utils'; diff --git a/packages/workspace/project.json b/packages/workspace/project.json index d7fb6c587ad64..817cfbadc6863 100644 --- a/packages/workspace/project.json +++ b/packages/workspace/project.json @@ -62,7 +62,7 @@ "outputs": ["{options.outputPath}"] }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "outputs": ["build/packages/workspace"], "options": { "commands": [ diff --git a/packages/workspace/src/tslint/nxEnforceModuleBoundariesRule.spec.ts b/packages/workspace/src/tslint/nxEnforceModuleBoundariesRule.spec.ts index 2a8bac4d3e05d..78ac58238b1b6 100644 --- a/packages/workspace/src/tslint/nxEnforceModuleBoundariesRule.spec.ts +++ b/packages/workspace/src/tslint/nxEnforceModuleBoundariesRule.spec.ts @@ -7,7 +7,7 @@ import { TargetProjectLocator } from 'nx/src/utils/target-project-locator'; import { mapProjectGraphFiles } from '@nrwl/workspace/src/utils/runtime-lint-utils'; jest.mock('fs', () => require('memfs').fs); -jest.mock('nx/src/utils/app-root', () => ({ +jest.mock('nx/src/utils/workspace-root', () => ({ workspaceRoot: '/root', })); diff --git a/packages/workspace/src/utilities/app-root.ts b/packages/workspace/src/utilities/app-root.ts index 17a6782a45737..a4e612047e6d1 100644 --- a/packages/workspace/src/utilities/app-root.ts +++ b/packages/workspace/src/utilities/app-root.ts @@ -1 +1 @@ -export * from 'nx/src/utils/app-root'; +export * from 'nx/src/utils/workspace-root'; diff --git a/packages/workspace/src/utilities/generate-globs.ts b/packages/workspace/src/utilities/generate-globs.ts index 3a3638b567e91..18b782bb291b0 100644 --- a/packages/workspace/src/utilities/generate-globs.ts +++ b/packages/workspace/src/utilities/generate-globs.ts @@ -1,5 +1,5 @@ import { joinPathFragments } from '@nrwl/devkit'; -import { workspaceRoot } from 'nx/src/utils/app-root'; +import { workspaceRoot } from 'nx/src/utils/workspace-root'; import { relative, resolve } from 'path'; import { readCachedProjectGraph } from 'nx/src/project-graph/project-graph'; import { diff --git a/packages/workspace/src/utils/app-root.ts b/packages/workspace/src/utils/app-root.ts index c80cb178ba075..48861468aa8dd 100644 --- a/packages/workspace/src/utils/app-root.ts +++ b/packages/workspace/src/utils/app-root.ts @@ -1 +1 @@ -export { appRootPath, workspaceRoot } from 'nx/src/utils/app-root'; +export { appRootPath, workspaceRoot } from 'nx/src/utils/workspace-root'; diff --git a/packages/workspace/src/utils/ast-utils.ts b/packages/workspace/src/utils/ast-utils.ts index 3711f271c8c09..e2a87d4775d77 100644 --- a/packages/workspace/src/utils/ast-utils.ts +++ b/packages/workspace/src/utils/ast-utils.ts @@ -26,10 +26,7 @@ import { } from '@nrwl/devkit'; import { getWorkspacePath } from './cli-config-utils'; import { extname, join, normalize, Path } from '@angular-devkit/core'; -import type { - NxJsonConfiguration, - WorkspaceJsonConfiguration, -} from '@nrwl/devkit'; +import type { NxJsonConfiguration, ProjectsConfigurations } from '@nrwl/devkit'; import { addInstallTask } from './rules/add-install-task'; import { findNodes } from '../utilities/typescript/find-nodes'; import { getSourceNodes } from '../utilities/typescript/get-source-nodes'; diff --git a/typedoc-theme/project.json b/typedoc-theme/project.json index 409b9e3364985..47ecfbe171807 100644 --- a/typedoc-theme/project.json +++ b/typedoc-theme/project.json @@ -14,7 +14,7 @@ } }, "build": { - "executor": "@nrwl/workspace:run-commands", + "executor": "nx:run-commands", "options": { "outputPath": "dist/typedoc-theme", "command": "echo 'Building TypeDoc custom theme'" diff --git a/workspace.json b/workspace.json index 1bbf12cc365dc..3ce4b497901b9 100644 --- a/workspace.json +++ b/workspace.json @@ -24,6 +24,7 @@ "e2e-linter": "e2e/linter", "e2e-next": "e2e/next", "e2e-node": "e2e/node", + "e2e-nx-init": "e2e/nx-init", "e2e-nx-plugin": "e2e/nx-plugin", "e2e-react": "e2e/react", "e2e-react-native": "e2e/react-native",