From 2e621f324cf4eda499c09540e93378c7ae5b7220 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Thu, 2 May 2024 13:37:12 -0400 Subject: [PATCH] feat(misc): v19 cleanup for Nx plugins (#23104) This PR removes deprecated code that's been slated for removal in Nx 19 - mentioned as `TODO(v19)` comments. ## Breaking Changes - **CNW:** `create-nx-workspace` no longer support `--preset=empty` and `--preset=core`, use `--preset=apps` and `--preset=npm` respectively. Deprecated in Nx 15.9. - **Next.js:** `NX_` environment variables are no longer bundled into Next.js apps, use `NEXT_PUBLIC` instead. Deprecated in Nx 16.8. - **Webpack, Storybook, Esbuild:** `NX_` environment variables are no longer bundled into browser bundles, use `NX_PUBLIC` instead. This removes the possibility of intentional bundling of `NX_` variables. Deprecated in Nx 18. - **Cypress:** `cypressComponentConfiguration` generator removed from `@nx/cypress`, use `configurationGenerator`instead. Deprecated in Nx 16.8. - **Cypress:** `cypressProjectGenerator` generator removed from `@nx/cypress`, use `configurationGenerator` instead. Deprecated in Nx 15.9. - **Expo:** `withNxWebpack` removed from `@nx/expo`, use [metro bundler](https://docs.expo.dev/guides/customizing-metro/) (https://docs.expo.dev/guides/customizing-metro/) in app.json instead. There is a migration to handle this in Nx 19. Deprecated in Nx 15.8. ## Deferred to v20 - **JS:** `classProperties.loose` option removed from `@nx/js/babel` preset, use `loose` instead. Deprecated in Nx 17.0. - **ESLint:** Low priority task to "deviations from @typescript-eslint/recommended" for our lint rules. @JamesHenry will look at this later before Nx 20, but it is unimportant. - **React:** component testing does not work with Project Crystal, and we need the executor + built-in webpack configs to run CT. Will do a follow-up on this after Nx 19 release. Related issue: https://github.com/nrwl/nx/issues/21546 - **Next.js:** `withStylus` removal from `@nx/next`, use SASS instead. It hasn't worked, but we kept the file to throw an error when used. Deprecated in Nx 17.0. - **Next.js**: `@nx/next:component` and `@nx/next:page` generators to not derive the `components` and `app`/`pages` directory. Use `nx g @nx/next:component apps/myapp/components/button` instead. Deprecated in Nx 17.0. - **Webpack:** `isolatedConfig` option removal from `@nx/webpack:webpack` executor. There is a migration to handle this in Nx 19. Deprecated in in Nx 17.2. - **Angular:** `executeWebpackDevServerBuilder` removal from `@nx/angular/executors`, use `executeDevServerBuilder` instead. Deprecated in Nx 17.0. --- docs/generated/cli/create-nx-workspace.md | 2 +- docs/generated/manifests/menus.json | 8 - docs/generated/manifests/nx-api.json | 9 - docs/generated/packages-metadata.json | 9 - .../cypress/generators/cypress-project.json | 84 --- .../nx/documents/create-nx-workspace.md | 2 +- .../packages/webpack/executors/webpack.json | 2 +- docs/shared/reference/sitemap.md | 1 - e2e/cypress/src/cypress.test.ts | 4 +- e2e/next/src/next-component-tests.test.ts | 4 +- e2e/web/src/web-legacy.test.ts | 4 +- e2e/web/src/web.test.ts | 40 +- e2e/webpack/src/webpack.test.ts | 7 +- nx-dev/nx-dev-e2e/src/packages.spec.ts | 4 - .../expo/plugins/with-nx-webpack.ts | 1 - packages/angular/executors.ts | 4 +- .../bin/create-nx-workspace.ts | 31 +- .../src/utils/preset/preset.ts | 2 - packages/cypress/generators.json | 6 - packages/cypress/index.ts | 17 +- packages/cypress/package.json | 1 - .../cypress-project.spec.ts.snap | 240 ------- .../cypress-project/cypress-project.spec.ts | 602 ------------------ .../cypress-project/cypress-project.ts | 297 --------- .../v10-and-after/cypress.config.ts__tmpl__ | 10 - .../v10-and-after/src/e2e/app.cy.ts__tmpl__ | 13 - .../src/fixtures/example.json__tmpl__ | 4 - .../src/support/app.po.ts__tmpl__ | 1 - .../src/support/commands.ts__tmpl__ | 33 - .../v10-and-after/src/support/e2e.ts__tmpl__ | 17 - .../files/v10-and-after/tsconfig.json | 10 - .../files/v9-and-under/cypress.json | 12 - .../src/fixtures/example.json__tmpl__ | 4 - .../src/integration/app.spec.ts__tmpl__ | 13 - .../files/v9-and-under/src/plugins/index.js | 22 - .../src/support/app.po.ts__tmpl__ | 1 - .../src/support/commands.ts__tmpl__ | 33 - .../v9-and-under/src/support/index.ts__tmpl__ | 17 - .../files/v9-and-under/tsconfig.json | 10 - .../generators/cypress-project/schema.d.ts | 17 - .../generators/cypress-project/schema.json | 78 --- .../migrate-to-cypress-11.spec.ts.snap | 20 - .../migrate-to-cypress-11.spec.ts | 57 +- .../src/utils/environment-variables.ts | 11 +- .../eslint-plugin/src/configs/javascript.ts | 2 +- .../eslint-plugin/src/configs/typescript.ts | 2 +- packages/expo/migrations.json | 6 + packages/expo/package.json | 1 - packages/expo/plugins/with-nx-webpack.ts | 54 -- .../change-webpack-to-metro.spec.ts | 56 ++ .../update-19-0-0/change-webpack-to-metro.ts | 38 ++ packages/js/babel.ts | 2 +- packages/next/plugins/with-nx.ts | 41 +- packages/next/plugins/with-stylus.ts | 2 +- .../src/generators/component/component.ts | 2 +- packages/next/src/generators/page/page.ts | 2 +- .../react/plugins/component-testing/index.ts | 5 +- packages/react/plugins/storybook/index.ts | 12 +- .../docs/webpack-build-executor-examples.md | 86 +-- .../webpack/src/executors/webpack/schema.d.ts | 2 +- .../src/utils/get-client-environment.ts | 10 +- ...interpolate-env-variables-to-index.spec.ts | 10 +- .../interpolate-env-variables-to-index.ts | 8 +- 63 files changed, 233 insertions(+), 1872 deletions(-) delete mode 100644 docs/generated/packages/cypress/generators/cypress-project.json delete mode 100644 packages-legacy/expo/plugins/with-nx-webpack.ts delete mode 100644 packages/cypress/src/generators/cypress-project/__snapshots__/cypress-project.spec.ts.snap delete mode 100644 packages/cypress/src/generators/cypress-project/cypress-project.spec.ts delete mode 100644 packages/cypress/src/generators/cypress-project/cypress-project.ts delete mode 100644 packages/cypress/src/generators/cypress-project/files/v10-and-after/cypress.config.ts__tmpl__ delete mode 100644 packages/cypress/src/generators/cypress-project/files/v10-and-after/src/e2e/app.cy.ts__tmpl__ delete mode 100644 packages/cypress/src/generators/cypress-project/files/v10-and-after/src/fixtures/example.json__tmpl__ delete mode 100644 packages/cypress/src/generators/cypress-project/files/v10-and-after/src/support/app.po.ts__tmpl__ delete mode 100644 packages/cypress/src/generators/cypress-project/files/v10-and-after/src/support/commands.ts__tmpl__ delete mode 100644 packages/cypress/src/generators/cypress-project/files/v10-and-after/src/support/e2e.ts__tmpl__ delete mode 100644 packages/cypress/src/generators/cypress-project/files/v10-and-after/tsconfig.json delete mode 100644 packages/cypress/src/generators/cypress-project/files/v9-and-under/cypress.json delete mode 100644 packages/cypress/src/generators/cypress-project/files/v9-and-under/src/fixtures/example.json__tmpl__ delete mode 100644 packages/cypress/src/generators/cypress-project/files/v9-and-under/src/integration/app.spec.ts__tmpl__ delete mode 100644 packages/cypress/src/generators/cypress-project/files/v9-and-under/src/plugins/index.js delete mode 100644 packages/cypress/src/generators/cypress-project/files/v9-and-under/src/support/app.po.ts__tmpl__ delete mode 100644 packages/cypress/src/generators/cypress-project/files/v9-and-under/src/support/commands.ts__tmpl__ delete mode 100644 packages/cypress/src/generators/cypress-project/files/v9-and-under/src/support/index.ts__tmpl__ delete mode 100644 packages/cypress/src/generators/cypress-project/files/v9-and-under/tsconfig.json delete mode 100644 packages/cypress/src/generators/cypress-project/schema.d.ts delete mode 100644 packages/cypress/src/generators/cypress-project/schema.json delete mode 100644 packages/expo/plugins/with-nx-webpack.ts create mode 100644 packages/expo/src/migrations/update-19-0-0/change-webpack-to-metro.spec.ts create mode 100644 packages/expo/src/migrations/update-19-0-0/change-webpack-to-metro.ts diff --git a/docs/generated/cli/create-nx-workspace.md b/docs/generated/cli/create-nx-workspace.md index 620926a2a6..007a441633 100644 --- a/docs/generated/cli/create-nx-workspace.md +++ b/docs/generated/cli/create-nx-workspace.md @@ -145,7 +145,7 @@ Prefix to use for Angular component and directive selectors. Type: `string` -Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "nuxt", "nuxt-standalone", "next", "nextjs-standalone", "remix-monorepo", "remix-standalone", "react-native", "expo", "nest", "express", "react", "vue", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset +Customizes the initial content of your workspace. Default presets include: ["apps", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "nuxt", "nuxt-standalone", "next", "nextjs-standalone", "remix-monorepo", "remix-standalone", "react-native", "expo", "nest", "express", "react", "vue", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset ### routing diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 65b4cebc23..7d7ebbeb53 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -7017,14 +7017,6 @@ "isExternal": false, "disableCollapsible": false }, - { - "id": "cypress-project", - "path": "/nx-api/cypress/generators/cypress-project", - "name": "cypress-project", - "children": [], - "isExternal": false, - "disableCollapsible": false - }, { "id": "configuration", "path": "/nx-api/cypress/generators/configuration", diff --git a/docs/generated/manifests/nx-api.json b/docs/generated/manifests/nx-api.json index af43e2d99b..0b95e0d931 100644 --- a/docs/generated/manifests/nx-api.json +++ b/docs/generated/manifests/nx-api.json @@ -510,15 +510,6 @@ "path": "/nx-api/cypress/generators/init", "type": "generator" }, - "/nx-api/cypress/generators/cypress-project": { - "description": "Add a Cypress E2E Project.", - "file": "generated/packages/cypress/generators/cypress-project.json", - "hidden": true, - "name": "cypress-project", - "originalFilePath": "/packages/cypress/src/generators/cypress-project/schema.json", - "path": "/nx-api/cypress/generators/cypress-project", - "type": "generator" - }, "/nx-api/cypress/generators/configuration": { "description": "Add a Cypress E2E Configuration to an existing project.", "file": "generated/packages/cypress/generators/configuration.json", diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index f0f22d24a4..6960472363 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -502,15 +502,6 @@ "path": "cypress/generators/init", "type": "generator" }, - { - "description": "Add a Cypress E2E Project.", - "file": "generated/packages/cypress/generators/cypress-project.json", - "hidden": true, - "name": "cypress-project", - "originalFilePath": "/packages/cypress/src/generators/cypress-project/schema.json", - "path": "cypress/generators/cypress-project", - "type": "generator" - }, { "description": "Add a Cypress E2E Configuration to an existing project.", "file": "generated/packages/cypress/generators/configuration.json", diff --git a/docs/generated/packages/cypress/generators/cypress-project.json b/docs/generated/packages/cypress/generators/cypress-project.json deleted file mode 100644 index 42b1e98c83..0000000000 --- a/docs/generated/packages/cypress/generators/cypress-project.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "name": "cypress-project", - "factory": "./src/generators/cypress-project/cypress-project#cypressProjectGeneratorInternal", - "schema": { - "$schema": "https://json-schema.org/schema", - "$id": "NxCypressProjectGeneratorSchema", - "cli": "nx", - "title": "Create Cypress Configuration for the workspace", - "description": "Create Cypress Configuration for the workspace.", - "type": "object", - "properties": { - "project": { - "type": "string", - "description": "The name of the frontend project to test.", - "$default": { "$source": "projectName" }, - "x-priority": "important" - }, - "baseUrl": { - "type": "string", - "description": "The address (with the port) which your application is running on." - }, - "name": { - "type": "string", - "description": "Name of the E2E Project.", - "$default": { "$source": "argv", "index": 0 }, - "x-prompt": "What name would you like to use for the e2e project?" - }, - "directory": { - "type": "string", - "description": "A directory where the project is placed.", - "x-priority": "important" - }, - "projectNameAndRootFormat": { - "description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).", - "type": "string", - "enum": ["as-provided", "derived"] - }, - "linter": { - "description": "The tool to use for running lint checks.", - "type": "string", - "enum": ["eslint", "none"], - "default": "eslint" - }, - "js": { - "description": "Generate JavaScript files rather than TypeScript files.", - "type": "boolean", - "default": false - }, - "skipFormat": { - "description": "Skip formatting files.", - "type": "boolean", - "default": false, - "x-priority": "internal" - }, - "setParserOptionsProject": { - "type": "boolean", - "description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.", - "default": false - }, - "skipPackageJson": { - "type": "boolean", - "default": false, - "description": "Do not add dependencies to `package.json`.", - "x-priority": "internal" - }, - "bundler": { - "description": "The Cypress bundler to use.", - "type": "string", - "enum": ["vite", "webpack", "none"], - "x-prompt": "Which Cypress bundler do you want to use?", - "default": "webpack" - } - }, - "required": ["name"], - "examplesFile": "Adding Cypress to an existing application requires two options. The name of the e2e app to create and what project that e2e app is for.\n\n```bash\nnx g configuration --name=my-app-e2e --project=my-app\n```\n\nWhen providing `--project` option, the generator will look for the `serve` target in that given project. This allows the [cypress executor](/packages/cypress/executors/cypress) to spin up the project and start the cypress runner.\n\nIf you prefer to not have the project served automatically, you can provide a `--base-url` argument in place of `--project`\n\n```bash\nnx g configuration --name=my-app-e2e --base-url=http://localhost:1234\n```\n\n{% callout type=\"note\" title=\"What about API Projects?\" %}\nYou can also run the `configuration` generator against API projects like a [Nest API](/packages/nest/generators/application#@nx/nest:application).\nIf there is a URL to visit then you can test it with Cypress!\n{% /callout %}\n\n## Using Cypress with Vite.js\n\nNow, you can generate your Cypress project with Vite.js as the bundler:\n\n```bash\nnx g configuration --name=my-app-e2e --project=my-app --bundler=vite\n```\n\nThis generator will pass the `bundler` information (`bundler: 'vite'`) to our `nxE2EPreset`, in your project's `cypress.config.ts` file (eg. `my-app-e2e/cypress.config.ts`).\n\n### Customizing the Vite.js configuration\n\nThe `nxE2EPreset` will then use the `bundler` information to generate the correct settings for your Cypress project to use Vite.js. In the background, the way this works is that it's using a custom Vite preprocessor for your files, that's called on the `file:preprocessor` event. If you want to customize this behaviour, you can do so like this in your project's `cypress.config.ts` file:\n\n```ts\nimport { defineConfig } from 'cypress';\nimport { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';\n\nconst config = nxE2EPreset(__filename, { bundler: 'vite' });\nexport default defineConfig({\n e2e: {\n ...config,\n async setupNodeEvents(on, config) {\n // Ensure that `@nx/cypress` events are set up.\n await config.setupNodeEvents(on, config);\n\n // Your settings here\n },\n },\n});\n```\n", - "presets": [] - }, - "description": "Add a Cypress E2E Project.", - "hidden": true, - "implementation": "/packages/cypress/src/generators/cypress-project/cypress-project#cypressProjectGeneratorInternal.ts", - "aliases": [], - "path": "/packages/cypress/src/generators/cypress-project/schema.json", - "type": "generator" -} diff --git a/docs/generated/packages/nx/documents/create-nx-workspace.md b/docs/generated/packages/nx/documents/create-nx-workspace.md index 620926a2a6..007a441633 100644 --- a/docs/generated/packages/nx/documents/create-nx-workspace.md +++ b/docs/generated/packages/nx/documents/create-nx-workspace.md @@ -145,7 +145,7 @@ Prefix to use for Angular component and directive selectors. Type: `string` -Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "nuxt", "nuxt-standalone", "next", "nextjs-standalone", "remix-monorepo", "remix-standalone", "react-native", "expo", "nest", "express", "react", "vue", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset +Customizes the initial content of your workspace. Default presets include: ["apps", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "nuxt", "nuxt-standalone", "next", "nextjs-standalone", "remix-monorepo", "remix-standalone", "react-native", "expo", "nest", "express", "react", "vue", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset ### routing diff --git a/docs/generated/packages/webpack/executors/webpack.json b/docs/generated/packages/webpack/executors/webpack.json index 5ca86abced..a97c0c07e8 100644 --- a/docs/generated/packages/webpack/executors/webpack.json +++ b/docs/generated/packages/webpack/executors/webpack.json @@ -455,7 +455,7 @@ ] } }, - "examplesFile": "---\ntitle: Examples for the @nx/webpack:webpack build executor\ndescription: Examples and a short guide on how to use the @nx/webpack:webpack build executor\n---\n\n`project.json`:\n\n```json\n//...\n\"my-app\": {\n \"targets\": {\n //...\n \"build\": {\n \"executor\": \"@nx/webpack:webpack\",\n //...\n //...\n \"options\": {\n ...\n },\n //...\n }\n },\n }\n}\n```\n\n```bash\nnx build my-app\n```\n\n## Examples\n\n{% tabs %}\n\n{% tab label=\"Using `babelUpwardRootMode`\" %}\n\nCopying from the [Babel documentation](https://babeljs.io/docs/config-files#root-babelconfigjson-file):\n\n> [...] if you are running your Babel compilation process from within a subpackage, you need to tell Babel where to look for the config. There are a few ways to do that, but the recommended way is the \"rootMode\" option with \"upward\", which will make Babel search from the working directory upward looking for your babel.config.json file, and will use its location as the \"root\" value.\n\nSetting `babelUpwardRootMode` to `true` in your `project.json` will set `rootMode` option to `upward` in the Babel config. You may want the `upward` mode in a monorepo when projects must apply their individual `.babelrc` file. We recommend that you don't set it at all, so it will use the default to `false` as the `upward` mode brings additional complexity to the build process.\n\n```json\n//...\n\"my-app\": {\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/webpack:webpack\",\n \"options\": {\n \"babelUpwardRootMode\": true,\n //...\n },\n //...\n },\n //...\n },\n //...\n}\n```\n\nWhen `babelUpwardRootMode` is `true`, Babel will look for a root `babel.config.json` at the root of the workspace, which should look something like this to include all packages:\n\n```json\n{ \"babelrcRoots\": [\"*\"] }\n```\n\nThen for each package, you must have a `.babelrc` file that will be applied to that package. For example:\n\n```json\n{\n \"presets\": [\"@babel/preset-env\", \"@babel/preset-typescript\"]\n}\n```\n\nAll packages will use its own `.babelrc` file, thus you must ensure the right presets and plugins are set in each config file. This behavior can lead to build discrepancies between packages, so we recommend that you don't set `babelUpwardRootMode` at all.\n\n```treeview\n├── apps\n│ └── demo\n│ └── .babelrc\n├── libs\n│ ├── a\n│ │ └── .babelrc\n│ └── b\n│ └── .babelrc\n└── babel.config.json\n```\n\nIn workspace above, if `demo` imports `a` and `b`, it will apply the config `libs/a/.babelrc` and `libs/b/.babelrc` to the respective packages and not apply its own `apps/demo/.babelrc` to `a` and `b`. Anything in `babel.config.json` will apply to all packages.\n\n{% /tab %}\n\n{% tab label=\"Specify a custom Babel config file\" %}\n\nIf you have a custom Babel config file (i.e. not `.babelrc`), you can use the `configFile` option as follows:\n\n```json\n//...\n\"my-app\": {\n \"targets\": {\n //...\n \"build\": {\n \"executor\": \"@nx/webpack:webpack\",\n //...\n \"options\": {\n //...\n \"babelConfig\": \"apps/my-app/.babelrc.custom.json\",\n },\n \"configurations\": {\n ...\n }\n },\n }\n}\n```\n\nIf you do not set the path to the `.babelrc` file, Nx will look for a `.babelrc` file in the root of your application.\n\nNote that this option does not work if `babelUpwardRootMode` is set to `true`.\n\n{% /tab %}\n\n{% tab label=\"Run webpack with `isolatedConfig`\" %}\n\nSetting `isolatedConfig` to `true` in your `project.json` file means that Nx will not apply the Nx webpack plugins automatically. In that case, the Nx plugins need to be applied in the project's `webpack.config.js` file (e.g. `withNx`, `withReact`, etc.). So don't forget to also specify the path to your webpack config file (using the `webpackConfig` option).\n\nRead more on how to configure Webpack in our [Nx Webpack config guide](/recipes/webpack/webpack-config-setup) an in our [Webpack Plugins guide](/recipes/webpack/webpack-plugins).\n\nNote that this is the new default setup for webpack in the latest version of Nx.\n\nSet `isolatedConfig` to `true` in your `project.json` file in the `build` target options like this:\n\n```json\n//...\n\"my-app\": {\n \"targets\": {\n //...\n \"build\": {\n \"executor\": \"@nx/webpack:webpack\",\n //...\n \"options\": {\n //...\n \"webpackConfig\": \"apps/my-app/webpack.config.js\",\n \"isolatedConfig\": true\n },\n \"configurations\": {\n ...\n }\n },\n }\n}\n```\n\n{% /tab %}\n\n{% /tabs %}\n", + "examplesFile": "---\ntitle: Examples for the @nx/webpack:webpack build executor\ndescription: Examples and a short guide on how to use the @nx/webpack:webpack build executor\n---\n\n`project.json`:\n\n```json5\n//...\n\"my-app\": {\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/webpack:webpack\",\n \"options\": {\n \"webpackConfig\": \"apps/my-app/webpack.config.js\"\n }\n },\n //...\n }\n}\n```\n\n```bash\nnx build my-app\n```\n\n## Examples\n\n{% tabs %}\n\n{% tab label=\"Using `babelUpwardRootMode`\" %}\n\nCopying from the [Babel documentation](https://babeljs.io/docs/config-files#root-babelconfigjson-file):\n\n> [...] if you are running your Babel compilation process from within a subpackage, you need to tell Babel where to look for the config. There are a few ways to do that, but the recommended way is the \"rootMode\" option with \"upward\", which will make Babel search from the working directory upward looking for your babel.config.json file, and will use its location as the \"root\" value.\n\nSetting `babelUpwardRootMode` to `true` in your `project.json` will set `rootMode` option to `upward` in the Babel config. You may want the `upward` mode in a monorepo when projects must apply their individual `.babelrc` file. We recommend that you don't set it at all, so it will use the default to `false` as the `upward` mode brings additional complexity to the build process.\n\n```json5\n//...\n\"my-app\": {\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/webpack:webpack\",\n \"options\": {\n \"webpackConfig\": \"apps/my-app/webpack.config.js\",\n \"babelUpwardRootMode\": true\n }\n },\n //...\n }\n}\n```\n\nWhen `babelUpwardRootMode` is `true`, Babel will look for a root `babel.config.json` at the root of the workspace, which should look something like this to include all packages:\n\n```json\n{ \"babelrcRoots\": [\"*\"] }\n```\n\nThen for each package, you must have a `.babelrc` file that will be applied to that package. For example:\n\n```json\n{\n \"presets\": [\"@babel/preset-env\", \"@babel/preset-typescript\"]\n}\n```\n\nAll packages will use its own `.babelrc` file, thus you must ensure the right presets and plugins are set in each config file. This behavior can lead to build discrepancies between packages, so we recommend that you don't set `babelUpwardRootMode` at all.\n\n```treeview\n├── apps\n│ └── demo\n│ └── .babelrc\n├── libs\n│ ├── a\n│ │ └── .babelrc\n│ └── b\n│ └── .babelrc\n└── babel.config.json\n```\n\nIn workspace above, if `demo` imports `a` and `b`, it will apply the config `libs/a/.babelrc` and `libs/b/.babelrc` to the respective packages and not apply its own `apps/demo/.babelrc` to `a` and `b`. Anything in `babel.config.json` will apply to all packages.\n\n{% /tab %}\n\n{% tab label=\"Specify a custom Babel config file\" %}\n\nIf you have a custom Babel config file (i.e. not `.babelrc`), you can use the `configFile` option as follows:\n\n```json5\n//...\n\"my-app\": {\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/webpack:webpack\",\n \"options\": {\n \"webpackConfig\": \"apps/my-app/webpack.config.js\",\n \"babelConfig\": \"apps/my-app/.babelrc.custom.json\",\n }\n },\n // ...\n }\n}\n```\n\nIf you do not set the path to the `.babelrc` file, Nx will look for a `.babelrc` file in the root of your application.\n\nNote that this option does not work if `babelUpwardRootMode` is set to `true`.\n\n{% /tab %}\n\n{% tab label=\"Run webpack with `isolatedConfig`\" %}\n\nSetting `isolatedConfig` to `true` in your `project.json` file means that Nx will not apply the Nx webpack plugins automatically. In that case, the Nx plugins need to be applied in the project's `webpack.config.js` file (e.g. `withNx`, `withReact`, etc.). So don't forget to also specify the path to your webpack config file (using the `webpackConfig` option).\n\nRead more on how to configure Webpack in our [Nx Webpack config guide](/recipes/webpack/webpack-config-setup) an in our [Webpack Plugins guide](/recipes/webpack/webpack-plugins).\n\nNote that this is the new default setup for webpack in the latest version of Nx.\n\nSet `isolatedConfig` to `true` in your `project.json` file in the `build` target options like this:\n\n```json\n//...\n\"my-app\": {\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/webpack:webpack\",\n \"options\": {\n \"webpackConfig\": \"apps/my-app/webpack.config.js\",\n \"isolatedConfig\": true\n }\n },\n }\n}\n```\n\n{% /tab %}\n\n{% /tabs %}\n", "presets": [] }, "description": "Run webpack build.", diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 12954c9c3a..755c859d24 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -368,7 +368,6 @@ - [cypress](/nx-api/cypress/executors/cypress) - [generators](/nx-api/cypress/generators) - [init](/nx-api/cypress/generators/init) - - [cypress-project](/nx-api/cypress/generators/cypress-project) - [configuration](/nx-api/cypress/generators/configuration) - [component-configuration](/nx-api/cypress/generators/component-configuration) - [migrate-to-cypress-11](/nx-api/cypress/generators/migrate-to-cypress-11) diff --git a/e2e/cypress/src/cypress.test.ts b/e2e/cypress/src/cypress.test.ts index 8e80c004ac..e9552d2537 100644 --- a/e2e/cypress/src/cypress.test.ts +++ b/e2e/cypress/src/cypress.test.ts @@ -154,10 +154,10 @@ export default defineConfig({ async () => { const appName = uniq('next-cy-app'); runCLI( - `generate @nx/next:app ${appName} --e2eTestRunner=none --no-interactive` + `generate @nx/next:app ${appName} --directory=apps/${appName} --e2eTestRunner=none --no-interactive --projectNameAndRootFormat=as-provided` ); runCLI( - `generate @nx/next:component btn --project=${appName} --no-interactive` + `generate @nx/next:component btn --project=${appName} --directory=apps/${appName}/components --nameAndDirectoryFormat=as-provided --no-interactive` ); runCLI( `generate @nx/next:cypress-component-configuration --project=${appName} --generate-tests --no-interactive` diff --git a/e2e/next/src/next-component-tests.test.ts b/e2e/next/src/next-component-tests.test.ts index e25a328a8a..3219f4dafc 100644 --- a/e2e/next/src/next-component-tests.test.ts +++ b/e2e/next/src/next-component-tests.test.ts @@ -118,10 +118,10 @@ function addBabelSupport(path: string) { function createAppWithCt(appName: string) { runCLI( - `generate @nx/next:app ${appName} --no-interactive --appDir=false --src=false` + `generate @nx/next:app ${appName} --directory=apps/${appName} --no-interactive --appDir=false --src=false --projectNameAndRootFormat=as-provided` ); runCLI( - `generate @nx/next:component button --project=${appName} --directory=components --flat --no-interactive` + `generate @nx/next:component button --project=${appName} --directory=apps/${appName}/components --nameAndDirectoryFormat=as-provided --no-interactive` ); createFile( `apps/${appName}/public/data.json`, diff --git a/e2e/web/src/web-legacy.test.ts b/e2e/web/src/web-legacy.test.ts index 05dd083905..c44633e7bd 100644 --- a/e2e/web/src/web-legacy.test.ts +++ b/e2e/web/src/web-legacy.test.ts @@ -244,7 +244,7 @@ describe('index.html interpolation (legacy)', () => {
-
Nx Variable: %NX_VARIABLE%
+
Nx Variable: %NX_PUBLIC_VARIABLE%
Some other variable: %SOME_OTHER_VARIABLE%
Deploy Url: %DEPLOY_URL%
@@ -252,7 +252,7 @@ describe('index.html interpolation (legacy)', () => { `; const envFilePath = `apps/${appName}/.env`; const envFileContents = ` - NX_VARIABLE=foo + NX_PUBLIC_VARIABLE=foo SOME_OTHER_VARIABLE=bar }`; diff --git a/e2e/web/src/web.test.ts b/e2e/web/src/web.test.ts index 67c13f0eb7..46f1910b24 100644 --- a/e2e/web/src/web.test.ts +++ b/e2e/web/src/web.test.ts @@ -243,39 +243,39 @@ describe('CLI - Environment Variables', () => { //test if the Nx CLI loads root .env vars updateFile( `.env`, - 'NX_WS_BASE=ws-base\nNX_SHARED_ENV=shared-in-workspace-base' + 'NX_PUBLIC_WS_BASE=ws-base\nNX_PUBLIC_SHARED_ENV=shared-in-workspace-base' ); updateFile( `.env.local`, - 'NX_WS_ENV_LOCAL=ws-env-local\nNX_SHARED_ENV=shared-in-workspace-env-local' + 'NX_PUBLIC_WS_ENV_LOCAL=ws-env-local\nNX_PUBLIC_SHARED_ENV=shared-in-workspace-env-local' ); updateFile( `.local.env`, - 'NX_WS_LOCAL_ENV=ws-local-env\nNX_SHARED_ENV=shared-in-workspace-local-env' + 'NX_PUBLIC_WS_LOCAL_ENV=ws-local-env\nNX_PUBLIC_SHARED_ENV=shared-in-workspace-local-env' ); updateFile( `apps/${appName}/.env`, - 'NX_APP_BASE=app-base\nNX_SHARED_ENV=shared-in-app-base' + 'NX_PUBLIC_APP_BASE=app-base\nNX_PUBLIC_SHARED_ENV=shared-in-app-base' ); updateFile( `apps/${appName}/.env.local`, - 'NX_APP_ENV_LOCAL=app-env-local\nNX_SHARED_ENV=shared-in-app-env-local' + 'NX_PUBLIC_APP_ENV_LOCAL=app-env-local\nNX_PUBLIC_SHARED_ENV=shared-in-app-env-local' ); updateFile( `apps/${appName}/.local.env`, - 'NX_APP_LOCAL_ENV=app-local-env\nNX_SHARED_ENV=shared-in-app-local-env' + 'NX_PUBLIC_APP_LOCAL_ENV=app-local-env\nNX_PUBLIC_SHARED_ENV=shared-in-app-local-env' ); const main = `apps/${appName}/src/main.ts`; const newCode = ` - const envVars = [process.env.NODE_ENV, process.env.NX_WS_BASE, process.env.NX_WS_ENV_LOCAL, process.env.NX_WS_LOCAL_ENV, process.env.NX_APP_BASE, process.env.NX_APP_ENV_LOCAL, process.env.NX_APP_LOCAL_ENV, process.env.NX_SHARED_ENV]; + const envVars = [process.env.NODE_ENV, process.env.NX_PUBLIC_WS_BASE, process.env.NX_PUBLIC_WS_ENV_LOCAL, process.env.NX_PUBLIC_WS_LOCAL_ENV, process.env.NX_PUBLIC_APP_BASE, process.env.NX_PUBLIC_APP_ENV_LOCAL, process.env.NX_PUBLIC_APP_LOCAL_ENV, process.env.NX_PUBLIC_SHARED_ENV]; const nodeEnv = process.env.NODE_ENV; - const nxWsBase = process.env.NX_WS_BASE; - const nxWsEnvLocal = process.env.NX_WS_ENV_LOCAL; - const nxWsLocalEnv = process.env.NX_WS_LOCAL_ENV; - const nxAppBase = process.env.NX_APP_BASE; - const nxAppEnvLocal = process.env.NX_APP_ENV_LOCAL; - const nxAppLocalEnv = process.env.NX_APP_LOCAL_ENV; - const nxSharedEnv = process.env.NX_SHARED_ENV; + const nxWsBase = process.env.NX_PUBLIC_WS_BASE; + const nxWsEnvLocal = process.env.NX_PUBLIC_WS_ENV_LOCAL; + const nxWsLocalEnv = process.env.NX_PUBLIC_WS_LOCAL_ENV; + const nxAppBase = process.env.NX_PUBLIC_APP_BASE; + const nxAppEnvLocal = process.env.NX_PUBLIC_APP_ENV_LOCAL; + const nxAppLocalEnv = process.env.NX_PUBLIC_APP_LOCAL_ENV; + const nxSharedEnv = process.env.NX_PUBLIC_SHARED_ENV; `; runCLI( @@ -290,18 +290,18 @@ describe('CLI - Environment Variables', () => { updateFile( `apps/${appName2}/.env`, - 'NX_APP_BASE=app2-base\nNX_SHARED_ENV=shared2-in-app-base' + 'NX_PUBLIC_APP_BASE=app2-base\nNX_PUBLIC_SHARED_ENV=shared2-in-app-base' ); updateFile( `apps/${appName2}/.env.local`, - 'NX_APP_ENV_LOCAL=app2-env-local\nNX_SHARED_ENV=shared2-in-app-env-local' + 'NX_PUBLIC_APP_ENV_LOCAL=app2-env-local\nNX_PUBLIC_SHARED_ENV=shared2-in-app-env-local' ); updateFile( `apps/${appName2}/.local.env`, - 'NX_APP_LOCAL_ENV=app2-local-env\nNX_SHARED_ENV=shared2-in-app-local-env' + 'NX_PUBLIC_APP_LOCAL_ENV=app2-local-env\nNX_PUBLIC_SHARED_ENV=shared2-in-app-local-env' ); const main2 = `apps/${appName2}/src/main.ts`; - const newCode2 = `const envVars = [process.env.NODE_ENV, process.env.NX_WS_BASE, process.env.NX_WS_ENV_LOCAL, process.env.NX_WS_LOCAL_ENV, process.env.NX_APP_BASE, process.env.NX_APP_ENV_LOCAL, process.env.NX_APP_LOCAL_ENV, process.env.NX_SHARED_ENV];`; + const newCode2 = `const envVars = [process.env.NODE_ENV, process.env.NX_PUBLIC_WS_BASE, process.env.NX_PUBLIC_WS_ENV_LOCAL, process.env.NX_PUBLIC_WS_LOCAL_ENV, process.env.NX_PUBLIC_APP_BASE, process.env.NX_PUBLIC_APP_ENV_LOCAL, process.env.NX_PUBLIC_APP_LOCAL_ENV, process.env.NX_PUBLIC_SHARED_ENV];`; runCLI( `generate @nx/web:app ${appName2} --bundler=webpack --no-interactive --compiler=babel` @@ -361,14 +361,14 @@ describe('index.html interpolation', () => {
-
Nx Variable: %NX_VARIABLE%
+
Nx Variable: %NX_PUBLIC_VARIABLE%
Some other variable: %SOME_OTHER_VARIABLE%
`; const envFilePath = `apps/${appName}/.env`; const envFileContents = ` - NX_VARIABLE=foo + NX_PUBLIC_VARIABLE=foo SOME_OTHER_VARIABLE=bar }`; diff --git a/e2e/webpack/src/webpack.test.ts b/e2e/webpack/src/webpack.test.ts index a86ad66690..6f6ffb3ad5 100644 --- a/e2e/webpack/src/webpack.test.ts +++ b/e2e/webpack/src/webpack.test.ts @@ -164,22 +164,18 @@ describe('Webpack Plugin', () => { expect(output).toMatch(/Hello/); }, 500_000); - it('should bundle in non-sensitive NX_ environment variables', () => { + it('should bundle in NX_PUBLIC_ environment variables', () => { const appName = uniq('app'); runCLI(`generate @nx/web:app ${appName} --bundler webpack`); updateFile( `apps/${appName}/src/main.ts`, ` - console.log(process.env['NX_CLOUD_ENCRYPTION_KEY']); - console.log(process.env['NX_CLOUD_ACCESS_TOKEN']); console.log(process.env['NX_PUBLIC_TEST']); ` ); runCLI(`build ${appName}`, { env: { - NX_CLOUD_ENCRYPTION_KEY: 'secret', - NX_CLOUD_ACCESS_TOKEN: 'secret', NX_PUBLIC_TEST: 'foobar', }, }); @@ -188,7 +184,6 @@ describe('Webpack Plugin', () => { f.startsWith('main.') ); const content = readFile(`dist/apps/${appName}/${mainFile}`); - expect(content).not.toMatch(/secret/); expect(content).toMatch(/foobar/); }); diff --git a/nx-dev/nx-dev-e2e/src/packages.spec.ts b/nx-dev/nx-dev-e2e/src/packages.spec.ts index 85d13d9b3a..cbf97c6ed1 100644 --- a/nx-dev/nx-dev-e2e/src/packages.spec.ts +++ b/nx-dev/nx-dev-e2e/src/packages.spec.ts @@ -95,10 +95,6 @@ const pages: Array<{ title: string; path: string }> = [ }, { title: '@nx/cypress', path: '/packages/cypress' }, { title: '@nx/cypress:init', path: '/packages/cypress/generators/init' }, - { - title: '@nx/cypress:cypress-project', - path: '/packages/cypress/generators/cypress-project', - }, { title: '@nx/cypress:cypress', path: '/packages/cypress/executors/cypress', diff --git a/packages-legacy/expo/plugins/with-nx-webpack.ts b/packages-legacy/expo/plugins/with-nx-webpack.ts deleted file mode 100644 index 6f99812fc0..0000000000 --- a/packages-legacy/expo/plugins/with-nx-webpack.ts +++ /dev/null @@ -1 +0,0 @@ -export * from '@nx/expo/plugins/with-nx-webpack'; diff --git a/packages/angular/executors.ts b/packages/angular/executors.ts index e874aadc48..c184d0c48f 100644 --- a/packages/angular/executors.ts +++ b/packages/angular/executors.ts @@ -12,9 +12,9 @@ export * from './src/executors/extract-i18n/extract-i18n.impl'; import { executeDevServerBuilder } from './src/builders/dev-server/dev-server.impl'; export { - // TODO(v19): remove this alias + // TODO(v20): remove this alias /** - * @deprecated Use executeDevServerBuilder instead. It will be removed in Nx v19. + * @deprecated Use executeDevServerBuilder instead. It will be removed in Nx v20. */ executeDevServerBuilder as executeWebpackDevServerBuilder, executeDevServerBuilder, diff --git a/packages/create-nx-workspace/bin/create-nx-workspace.ts b/packages/create-nx-workspace/bin/create-nx-workspace.ts index eaa5b52432..2e315217d3 100644 --- a/packages/create-nx-workspace/bin/create-nx-workspace.ts +++ b/packages/create-nx-workspace/bin/create-nx-workspace.ts @@ -196,14 +196,7 @@ export const commandsObject: yargs.Argv = yargs throw error; }); }, - [ - normalizeArgsMiddleware, - normalizeAndWarnOnDeprecatedPreset({ - // TODO(v19): Remove Empty and Core presets - [Preset.Core]: Preset.NPM, - [Preset.Empty]: Preset.Apps, - }), - ] as yargs.MiddlewareFunction<{}>[] + [normalizeArgsMiddleware] as yargs.MiddlewareFunction<{}>[] ) .help('help', chalk.dim`Show help`) .updateLocale(yargsDecorator) @@ -248,28 +241,6 @@ async function main(parsedArgs: yargs.Arguments) { } } -function normalizeAndWarnOnDeprecatedPreset( - deprecatedPresets: Partial> -): (argv: yargs.Arguments) => Promise { - return async (args: yargs.Arguments): Promise => { - if (!args.preset) return; - if (deprecatedPresets[args.preset]) { - output.addVerticalSeparator(); - output.note({ - title: `The "${args.preset}" preset is deprecated.`, - bodyLines: [ - `The "${ - args.preset - }" preset will be removed in a future Nx release. Use the "${ - deprecatedPresets[args.preset] - }" preset instead.`, - ], - }); - args.preset = deprecatedPresets[args.preset] as Preset; - } - }; -} - /** * This function is used to normalize the arguments passed to the command. * It would: diff --git a/packages/create-nx-workspace/src/utils/preset/preset.ts b/packages/create-nx-workspace/src/utils/preset/preset.ts index 433f7e6a0e..c539e06400 100644 --- a/packages/create-nx-workspace/src/utils/preset/preset.ts +++ b/packages/create-nx-workspace/src/utils/preset/preset.ts @@ -1,7 +1,5 @@ export enum Preset { Apps = 'apps', - Empty = 'empty', // same as apps, deprecated - Core = 'core', // same as npm, deprecated NPM = 'npm', TS = 'ts', WebComponents = 'web-components', diff --git a/packages/cypress/generators.json b/packages/cypress/generators.json index 113ad18782..6506e6db05 100644 --- a/packages/cypress/generators.json +++ b/packages/cypress/generators.json @@ -9,12 +9,6 @@ "aliases": ["ng-add"], "hidden": true }, - "cypress-project": { - "factory": "./src/generators/cypress-project/cypress-project#cypressProjectGeneratorInternal", - "schema": "./src/generators/cypress-project/schema.json", - "description": "Add a Cypress E2E Project.", - "hidden": true - }, "configuration": { "aliases": ["cypress-e2e-configuration", "e2e", "e2e-config"], "factory": "./src/generators/configuration/configuration#configurationGeneratorInternal", diff --git a/packages/cypress/index.ts b/packages/cypress/index.ts index 5b1043e1c9..c0fd4cd13f 100644 --- a/packages/cypress/index.ts +++ b/packages/cypress/index.ts @@ -1,17 +1,4 @@ -import { configurationGenerator } from './src/generators/configuration/configuration'; -import { componentConfigurationGenerator } from './src/generators/component-configuration/component-configuration'; -import { cypressProjectGenerator as _cypressProjectGenerator } from './src/generators/cypress-project/cypress-project'; - -export { configurationGenerator, componentConfigurationGenerator }; - -// Maintain backwards compatibility with the old names in case community plugins used them. -// TODO(v19): Remove old name -/** @deprecated Use `configurationGenerator` instead. It will be removed in Nx 19. */ -export const cypressComponentConfiguration = componentConfigurationGenerator; - -export { configurationGenerator as cypressE2EConfigurationGenerator }; -// TODO(v19): Remove project generator -/** @deprecated Add a new project and call `configurationGenerator` instead. It will be removed in Nx 19. */ -export const cypressProjectGenerator = _cypressProjectGenerator; +export { configurationGenerator } from './src/generators/configuration/configuration'; +export { componentConfigurationGenerator } from './src/generators/component-configuration/component-configuration'; export { cypressInitGenerator } from './src/generators/init/init'; export { migrateCypressProject } from './src/generators/migrate-to-cypress-11/migrate-to-cypress-11'; diff --git a/packages/cypress/package.json b/packages/cypress/package.json index 9c19a16d90..cf02a4124b 100644 --- a/packages/cypress/package.json +++ b/packages/cypress/package.json @@ -39,7 +39,6 @@ "@nx/js": "file:../js", "@phenomnomnominal/tsquery": "~5.0.1", "detect-port": "^1.5.1", - "semver": "^7.5.3", "tslib": "^2.3.0" }, "peerDependencies": { diff --git a/packages/cypress/src/generators/cypress-project/__snapshots__/cypress-project.spec.ts.snap b/packages/cypress/src/generators/cypress-project/__snapshots__/cypress-project.spec.ts.snap deleted file mode 100644 index f5aef2d96f..0000000000 --- a/packages/cypress/src/generators/cypress-project/__snapshots__/cypress-project.spec.ts.snap +++ /dev/null @@ -1,240 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Cypress Project < v7 --linter eslint should add eslint-plugin-cypress 1`] = ` -{ - "extends": [ - "plugin:cypress/recommended", - "../.eslintrc.json", - ], - "ignorePatterns": [ - "!**/*", - ], - "overrides": [ - { - "files": [ - "*.ts", - "*.tsx", - "*.js", - "*.jsx", - ], - "rules": {}, - }, - { - "files": [ - "src/plugins/index.js", - ], - "rules": { - "@typescript-eslint/no-var-requires": "off", - "no-undef": "off", - }, - }, - ], -} -`; - -exports[`Cypress Project < v7 nested should update configuration 1`] = ` -{ - "e2e": { - "configurations": { - "production": { - "devServerTarget": "my-dir-my-app:serve:production", - }, - }, - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "my-dir/my-app-e2e/cypress.json", - "devServerTarget": "my-dir-my-app:serve", - "testingType": "e2e", - "tsConfig": "my-dir/my-app-e2e/tsconfig.json", - }, - }, - "lint": { - "executor": "@nx/eslint:lint", - }, -} -`; - -exports[`Cypress Project < v7 project with directory in its name should set right path names in \`cypress.json\` 1`] = ` -"{ - "fileServerFolder": ".", - "fixturesFolder": "./src/fixtures", - "integrationFolder": "./src/integration", - "modifyObstructiveCode": false, - "supportFile": "./src/support/index.ts", - "pluginsFile": "./src/plugins/index", - "video": true, - "videosFolder": "../../dist/cypress/my-dir/my-app-e2e/videos", - "screenshotsFolder": "../../dist/cypress/my-dir/my-app-e2e/screenshots", - "chromeWebSecurity": false -} -" -`; - -exports[`Cypress Project < v7 project with directory in its name should update configuration 1`] = ` -{ - "e2e": { - "configurations": { - "production": { - "devServerTarget": "my-dir-my-app:serve:production", - }, - }, - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "my-dir/my-app-e2e/cypress.json", - "devServerTarget": "my-dir-my-app:serve", - "testingType": "e2e", - "tsConfig": "my-dir/my-app-e2e/tsconfig.json", - }, - }, - "lint": { - "executor": "@nx/eslint:lint", - }, -} -`; - -exports[`Cypress Project < v7 should update project configuration (baseUrl) 1`] = ` -{ - "e2e": { - "executor": "@nx/cypress:cypress", - "options": { - "baseUrl": "http://localhost:3000", - "cypressConfig": "my-app-e2e/cypress.json", - "testingType": "e2e", - "tsConfig": "my-app-e2e/tsconfig.json", - }, - }, - "lint": { - "executor": "@nx/eslint:lint", - }, -} -`; - -exports[`Cypress Project < v7 should update project configuration 1`] = ` -{ - "e2e": { - "configurations": { - "production": { - "devServerTarget": "my-app:serve:production", - }, - }, - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "my-app-e2e/cypress.json", - "devServerTarget": "my-app:serve", - "testingType": "e2e", - "tsConfig": "my-app-e2e/tsconfig.json", - }, - }, - "lint": { - "executor": "@nx/eslint:lint", - }, -} -`; - -exports[`Cypress Project < v7 should update target configurations 1`] = ` -{ - "e2e": { - "configurations": { - "production": { - "devServerTarget": "my-app:serve:production", - }, - }, - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "my-app-e2e/cypress.json", - "devServerTarget": "my-app:serve:development", - "testingType": "e2e", - "tsConfig": "my-app-e2e/tsconfig.json", - }, - }, - "lint": { - "executor": "@nx/eslint:lint", - }, -} -`; - -exports[`Cypress Project > v10 for bundler:vite should pass the bundler info to nxE2EPreset in \`cypress.config.ts\` 1`] = ` -"import { defineConfig } from 'cypress'; -import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset'; - -export default defineConfig({ - e2e: nxE2EPreset(__dirname, { - bundler: 'vite', - }), -}); -" -`; - -exports[`Cypress Project > v10 nested should set right path names in \`cypress.config.ts\` 1`] = ` -"import { defineConfig } from 'cypress'; -import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset'; - -export default defineConfig({ - e2e: nxE2EPreset(__dirname), -}); -" -`; - -exports[`Cypress Project > v10 nested should set right path names in \`tsconfig.e2e.json\` 1`] = ` -{ - "compilerOptions": { - "allowJs": true, - "outDir": "../../dist/out-tsc", - "sourceMap": false, - "types": [ - "cypress", - "node", - ], - }, - "extends": "../../tsconfig.base.json", - "include": [ - "src/**/*.ts", - "src/**/*.js", - "cypress.config.ts", - ], -} -`; - -exports[`Cypress Project > v10 should set right path names in \`cypress.config.ts\` 1`] = ` -"import { defineConfig } from 'cypress'; -import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset'; - -export default defineConfig({ - e2e: nxE2EPreset(__dirname), -}); -" -`; - -exports[`Cypress Project > v10 should set right path names in \`tsconfig.e2e.json\` 1`] = ` -{ - "compilerOptions": { - "allowJs": true, - "outDir": "../dist/out-tsc", - "sourceMap": false, - "types": [ - "cypress", - "node", - ], - }, - "extends": "../tsconfig.base.json", - "include": [ - "src/**/*.ts", - "src/**/*.js", - "cypress.config.ts", - ], -} -`; - -exports[`Cypress Project > v10 should update configuration when eslint is passed 1`] = ` -"{ - "extends": ["plugin:cypress/recommended", "../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {} - } - ] -} -" -`; diff --git a/packages/cypress/src/generators/cypress-project/cypress-project.spec.ts b/packages/cypress/src/generators/cypress-project/cypress-project.spec.ts deleted file mode 100644 index f9f811c116..0000000000 --- a/packages/cypress/src/generators/cypress-project/cypress-project.spec.ts +++ /dev/null @@ -1,602 +0,0 @@ -import 'nx/src/internal-testing-utils/mock-project-graph'; - -import { - addProjectConfiguration, - readJson, - readProjectConfiguration, - Tree, - updateProjectConfiguration, -} from '@nx/devkit'; -import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import { cypressProjectGenerator } from './cypress-project'; -import { Schema } from './schema'; -import { Linter } from '@nx/eslint'; -import { installedCypressVersion } from '../../utils/cypress-version'; -import { cypressInitGenerator } from '../init/init'; - -jest.mock('../../utils/cypress-version'); -jest.mock('../init/init'); -describe('Cypress Project', () => { - let tree: Tree; - const defaultOptions: Omit = { - linter: Linter.EsLint, - }; - let mockedInstalledCypressVersion: jest.Mock< - ReturnType - > = installedCypressVersion as never; - let mockInitCypress: jest.Mock> = - cypressInitGenerator as never; - - beforeEach(() => { - tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); - - addProjectConfiguration(tree, 'my-app', { - root: 'my-app', - targets: { - serve: { - executor: 'serve-executor', - options: {}, - configurations: { - production: {}, - }, - }, - }, - }); - - addProjectConfiguration(tree, 'my-dir-my-app', { - root: 'my-dir/my-app', - targets: { - serve: { - executor: 'serve-executor', - options: {}, - configurations: { - production: {}, - }, - }, - }, - }); - }); - afterEach(() => jest.clearAllMocks()); - - it('should call init if cypress is not installed', async () => { - mockedInstalledCypressVersion.mockReturnValue(null); - - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - projectNameAndRootFormat: 'as-provided', - }); - - expect(mockInitCypress).toHaveBeenCalled(); - }); - - it('should call not init if cypress is installed', async () => { - mockedInstalledCypressVersion.mockReturnValue(10); - - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - projectNameAndRootFormat: 'as-provided', - }); - - expect(mockInitCypress).not.toHaveBeenCalled(); - }); - - describe('> v10', () => { - beforeEach(() => { - mockedInstalledCypressVersion.mockReturnValue(10); - }); - - it('should generate files for v10 and above', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - projectNameAndRootFormat: 'as-provided', - }); - - expect(tree.exists('my-app-e2e/cypress.config.ts')).toBeTruthy(); - expect(tree.exists('my-app-e2e/src/fixtures/example.json')).toBeTruthy(); - expect(tree.exists('my-app-e2e/src/e2e/app.cy.ts')).toBeTruthy(); - expect(tree.exists('my-app-e2e/src/support/app.po.ts')).toBeTruthy(); - expect(tree.exists('my-app-e2e/src/support/commands.ts')).toBeTruthy(); - expect(tree.exists('my-app-e2e/src/support/e2e.ts')).toBeTruthy(); - }); - - it('should update configuration when eslint is passed', async () => { - await cypressProjectGenerator(tree, { - name: 'my-app-e2e', - project: 'my-app', - linter: Linter.EsLint, - projectNameAndRootFormat: 'as-provided', - }); - - expect(tree.read('my-app-e2e/.eslintrc.json', 'utf-8')).toMatchSnapshot(); - }); - - it('should not add lint target when "none" is passed', async () => { - await cypressProjectGenerator(tree, { - name: 'my-app-e2e', - project: 'my-app', - linter: Linter.None, - projectNameAndRootFormat: 'as-provided', - }); - - const project = readProjectConfiguration(tree, 'my-app-e2e'); - expect(project.targets.lint).toBeUndefined(); - }); - - it('should update tags and implicit dependencies', async () => { - await cypressProjectGenerator(tree, { - name: 'my-app-e2e', - project: 'my-app', - linter: Linter.EsLint, - projectNameAndRootFormat: 'as-provided', - }); - - const project = readProjectConfiguration(tree, 'my-app-e2e'); - expect(project.tags).toEqual([]); - expect(project.implicitDependencies).toEqual(['my-app']); - }); - - it('should set right path names in `cypress.config.ts`', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - projectNameAndRootFormat: 'as-provided', - }); - - const cypressConfig = tree.read('my-app-e2e/cypress.config.ts', 'utf-8'); - expect(cypressConfig).toMatchSnapshot(); - }); - - it('should set right path names in `tsconfig.e2e.json`', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - projectNameAndRootFormat: 'as-provided', - }); - - const tsconfigJson = readJson(tree, 'my-app-e2e/tsconfig.json'); - expect(tsconfigJson).toMatchSnapshot(); - }); - - it('should extend from tsconfig.base.json', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - projectNameAndRootFormat: 'as-provided', - }); - - const tsConfig = readJson(tree, 'my-app-e2e/tsconfig.json'); - expect(tsConfig.extends).toBe('../tsconfig.base.json'); - }); - - it('should support a root tsconfig.json instead of tsconfig.base.json', async () => { - tree.rename('tsconfig.base.json', 'tsconfig.json'); - - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - projectNameAndRootFormat: 'as-provided', - }); - - const tsConfig = readJson(tree, 'my-app-e2e/tsconfig.json'); - expect(tsConfig.extends).toBe('../tsconfig.json'); - }); - - describe('for bundler:vite', () => { - it('should pass the bundler info to nxE2EPreset in `cypress.config.ts`', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - bundler: 'vite', - projectNameAndRootFormat: 'as-provided', - }); - - const cypressConfig = tree.read( - 'my-app-e2e/cypress.config.ts', - 'utf-8' - ); - expect(cypressConfig).toMatchSnapshot(); - }); - }); - - describe('nested', () => { - it('should set right path names in `cypress.config.ts`', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-dir-my-app', - directory: 'my-dir/my-app-e2e', - projectNameAndRootFormat: 'as-provided', - }); - - const cypressConfig = tree.read( - 'my-dir/my-app-e2e/cypress.config.ts', - 'utf-8' - ); - expect(cypressConfig).toMatchSnapshot(); - }); - - it('should set right path names in `tsconfig.e2e.json`', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-dir-my-app', - directory: 'my-dir/my-app-e2e', - projectNameAndRootFormat: 'as-provided', - }); - - const tsconfigJson = readJson(tree, 'my-dir/my-app-e2e/tsconfig.json'); - expect(tsconfigJson).toMatchSnapshot(); - }); - - it('should extend from tsconfig.base.json', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - directory: 'my-dir/my-app-e2e', - projectNameAndRootFormat: 'as-provided', - }); - - const tsConfig = readJson(tree, 'my-dir/my-app-e2e/tsconfig.json'); - expect(tsConfig.extends).toBe('../../tsconfig.base.json'); - }); - - it('should support a root tsconfig.json instead of tsconfig.base.json', async () => { - tree.rename('tsconfig.base.json', 'tsconfig.json'); - - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - directory: 'my-dir/my-app-e2e', - projectNameAndRootFormat: 'as-provided', - }); - - const tsConfig = readJson(tree, 'my-dir/my-app-e2e/tsconfig.json'); - expect(tsConfig.extends).toBe('../../tsconfig.json'); - }); - - describe('root project', () => { - it('should generate in option.name when root project detected', async () => { - addProjectConfiguration(tree, 'root', { root: '.' }); - - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'e2e-tests', - baseUrl: 'http://localhost:1234', - project: 'root', - projectNameAndRootFormat: 'as-provided', - }); - - expect(tree.listChanges().map((c) => c.path)).toEqual( - expect.arrayContaining([ - 'e2e-tests/cypress.config.ts', - 'e2e-tests/src/e2e/app.cy.ts', - 'e2e-tests/src/fixtures/example.json', - 'e2e-tests/src/support/app.po.ts', - 'e2e-tests/src/support/commands.ts', - 'e2e-tests/src/support/e2e.ts', - 'e2e-tests/tsconfig.json', - ]) - ); - }); - - it('should not generate a root project when the passed in project is not the root project', async () => { - addProjectConfiguration(tree, 'root', { root: '.' }); - addProjectConfiguration(tree, 'my-cool-app', { root: 'my-cool-app' }); - - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'e2e-tests', - baseUrl: 'http://localhost:1234', - project: 'my-cool-app', - projectNameAndRootFormat: 'as-provided', - }); - - expect(tree.listChanges().map((c) => c.path)).toEqual( - expect.arrayContaining([ - 'e2e-tests/cypress.config.ts', - 'e2e-tests/src/e2e/app.cy.ts', - 'e2e-tests/src/fixtures/example.json', - 'e2e-tests/src/support/app.po.ts', - 'e2e-tests/src/support/commands.ts', - 'e2e-tests/src/support/e2e.ts', - 'e2e-tests/tsconfig.json', - ]) - ); - }); - }); - }); - - describe('--project', () => { - describe('none', () => { - it('should not add any implicit dependencies', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - baseUrl: 'http://localhost:7788', - projectNameAndRootFormat: 'as-provided', - }); - - const projectConfig = readProjectConfiguration(tree, 'my-app-e2e'); - expect(projectConfig.implicitDependencies).not.toBeDefined(); - expect(projectConfig.tags).toEqual([]); - }); - }); - - it('should not throw an error when --project does not have targets', async () => { - const projectConf = readProjectConfiguration(tree, 'my-app'); - delete projectConf.targets; - updateProjectConfiguration(tree, 'my-app', projectConf); - - await cypressProjectGenerator(tree, { - name: 'my-app-e2e', - project: 'my-app', - linter: Linter.EsLint, - projectNameAndRootFormat: 'as-provided', - }); - - const projectConfig = readProjectConfiguration(tree, 'my-app-e2e'); - expect(projectConfig.targets['e2e'].options.devServerTarget).toEqual( - 'my-app:serve' - ); - }); - }); - - it('should generate in the correct folder', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'one-two-other-e2e', - project: 'my-app', - directory: 'one/two/other-e2e', - projectNameAndRootFormat: 'as-provided', - }); - - const project = readProjectConfiguration(tree, 'one-two-other-e2e'); - expect(project).toBeDefined(); - [ - 'one/two/other-e2e/cypress.config.ts', - 'one/two/other-e2e/src/e2e/app.cy.ts', - ].forEach((path) => expect(tree.exists(path)).toBeTruthy()); - }); - - it('should generate in the correct folder when --project-name-and-root-format=derived', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'other-e2e', - project: 'my-app', - directory: 'one/two', - projectNameAndRootFormat: 'derived', - }); - - const project = readProjectConfiguration(tree, 'one-two-other-e2e'); - expect(project).toBeDefined(); - [ - 'apps/one/two/other-e2e/cypress.config.ts', - 'apps/one/two/other-e2e/src/e2e/app.cy.ts', - ].forEach((path) => expect(tree.exists(path)).toBeTruthy()); - }); - - describe('serve-static', () => { - it('should configure Cypress with ci configuration if serve-static is found', async () => { - const appConfig = readProjectConfiguration(tree, 'my-app'); - appConfig.targets['serve-static'] = { - executor: 'serve-static-executor', - options: {}, - configurations: { - production: {}, - }, - }; - updateProjectConfiguration(tree, 'my-app', appConfig); - - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - projectNameAndRootFormat: 'as-provided', - }); - - const e2eConfig = readProjectConfiguration(tree, 'my-app-e2e'); - expect(e2eConfig.targets.e2e).toMatchObject({ - options: { - devServerTarget: 'my-app:serve', - }, - configurations: { - production: { devServerTarget: 'my-app:serve:production' }, - ci: { devServerTarget: 'my-app:serve-static' }, - }, - }); - }); - - it('should not configure Cypress with ci configuration if serve-static is not found', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - projectNameAndRootFormat: 'as-provided', - }); - - const e2eConfig = readProjectConfiguration(tree, 'my-app-e2e'); - expect(e2eConfig.targets.e2e.configurations.ci).toBeUndefined(); - }); - }); - }); - - describe('v9 - v7', () => { - beforeEach(() => { - mockedInstalledCypressVersion.mockReturnValue(9); - }); - - it('should generate files', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - projectNameAndRootFormat: 'as-provided', - }); - - expect(tree.exists('my-app-e2e/cypress.json')).toBeTruthy(); - expect(tree.exists('my-app-e2e/src/fixtures/example.json')).toBeTruthy(); - expect( - tree.exists('my-app-e2e/src/integration/app.spec.ts') - ).toBeTruthy(); - expect(tree.exists('my-app-e2e/src/support/app.po.ts')).toBeTruthy(); - expect(tree.exists('my-app-e2e/src/support/commands.ts')).toBeTruthy(); - expect(tree.exists('my-app-e2e/src/support/index.ts')).toBeTruthy(); - }); - }); - - describe('< v7', () => { - beforeEach(() => { - mockedInstalledCypressVersion.mockReturnValue(6); - }); - - it('should generate a plugin file if cypress is below version 7', async () => { - await cypressProjectGenerator(tree, { - ...defaultOptions, - name: 'my-app-e2e', - project: 'my-app', - projectNameAndRootFormat: 'as-provided', - addPlugin: false, - }); - - expect(tree.exists('my-app-e2e/src/plugins/index.js')).toBeTruthy(); - }); - - it('should update project configuration', async () => { - await cypressProjectGenerator(tree, { - name: 'my-app-e2e', - project: 'my-app', - linter: Linter.EsLint, - projectNameAndRootFormat: 'as-provided', - addPlugin: false, - }); - - const project = readProjectConfiguration(tree, 'my-app-e2e'); - expect(project.root).toEqual('my-app-e2e'); - expect(project.targets).toMatchSnapshot(); - }); - - it('should update project configuration (baseUrl)', async () => { - await cypressProjectGenerator(tree, { - name: 'my-app-e2e', - project: 'my-app', - baseUrl: 'http://localhost:3000', - linter: Linter.EsLint, - projectNameAndRootFormat: 'as-provided', - addPlugin: false, - }); - - const project = readProjectConfiguration(tree, 'my-app-e2e'); - expect(project.root).toEqual('my-app-e2e'); - expect(project.targets).toMatchSnapshot(); - }); - - it('should update target configurations', async () => { - const originalProject = readProjectConfiguration(tree, 'my-app'); - originalProject.targets.serve.defaultConfiguration = 'development'; - originalProject.targets.serve.configurations.development = {}; - updateProjectConfiguration(tree, 'my-app', originalProject); - - await cypressProjectGenerator(tree, { - name: 'my-app-e2e', - project: 'my-app', - linter: Linter.EsLint, - projectNameAndRootFormat: 'as-provided', - addPlugin: false, - }); - - const project = readProjectConfiguration(tree, 'my-app-e2e'); - expect(project.root).toEqual('my-app-e2e'); - expect(project.targets).toMatchSnapshot(); - }); - - describe('nested', () => { - it('should update configuration', async () => { - await cypressProjectGenerator(tree, { - name: 'my-dir-my-app-e2e', - project: 'my-dir-my-app', - directory: 'my-dir/my-app-e2e', - linter: Linter.EsLint, - projectNameAndRootFormat: 'as-provided', - addPlugin: false, - }); - - const projectConfig = readProjectConfiguration( - tree, - 'my-dir-my-app-e2e' - ); - expect(projectConfig).toBeDefined(); - expect(projectConfig.targets).toMatchSnapshot(); - }); - }); - - describe('--linter', () => { - describe('eslint', () => { - it('should add eslint-plugin-cypress', async () => { - await cypressProjectGenerator(tree, { - name: 'my-app-e2e', - project: 'my-app', - linter: Linter.EsLint, - projectNameAndRootFormat: 'as-provided', - addPlugin: false, - }); - - const packageJson = readJson(tree, 'package.json'); - expect( - packageJson.devDependencies['eslint-plugin-cypress'] - ).toBeTruthy(); - const eslintrcJson = readJson(tree, 'my-app-e2e/.eslintrc.json'); - expect(eslintrcJson).toMatchSnapshot(); - }); - }); - }); - - describe('project with directory in its name', () => { - beforeEach(async () => { - await cypressProjectGenerator(tree, { - name: 'my-dir-my-app-e2e', - project: 'my-dir-my-app', - directory: 'my-dir/my-app-e2e', - linter: Linter.EsLint, - projectNameAndRootFormat: 'as-provided', - addPlugin: false, - }); - }); - - it('should update configuration', async () => { - const projectConfig = readProjectConfiguration( - tree, - 'my-dir-my-app-e2e' - ); - expect(projectConfig).toBeDefined(); - expect(projectConfig.targets).toMatchSnapshot(); - }); - - it('should update nx.json', async () => { - const project = readProjectConfiguration(tree, 'my-dir-my-app-e2e'); - expect(project.tags).toEqual([]); - expect(project.implicitDependencies).toEqual(['my-dir-my-app']); - }); - - it('should set right path names in `cypress.json`', async () => { - const cypressConfig = tree.read( - 'my-dir/my-app-e2e/cypress.json', - 'utf-8' - ); - expect(cypressConfig).toMatchSnapshot(); - }); - }); - }); -}); diff --git a/packages/cypress/src/generators/cypress-project/cypress-project.ts b/packages/cypress/src/generators/cypress-project/cypress-project.ts deleted file mode 100644 index 2c7f4016bc..0000000000 --- a/packages/cypress/src/generators/cypress-project/cypress-project.ts +++ /dev/null @@ -1,297 +0,0 @@ -import { - addDependenciesToPackageJson, - addProjectConfiguration, - formatFiles, - generateFiles, - GeneratorCallback, - getProjects, - joinPathFragments, - logger, - offsetFromRoot, - ProjectConfiguration, - readProjectConfiguration, - runTasksInSerial, - stripIndents, - toJS, - Tree, - updateJson, -} from '@nx/devkit'; -import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils'; -import { checkAndCleanWithSemver } from '@nx/devkit/src/utils/semver'; -import { - getRelativePathToRootTsConfig, - initGenerator as jsInitGenerator, -} from '@nx/js'; -import { Linter } from '@nx/eslint'; -import { join } from 'path'; -import { major } from 'semver'; -import { addLinterToCyProject } from '../../utils/add-linter'; -import { installedCypressVersion } from '../../utils/cypress-version'; -import { - cypressVersion, - typesNodeVersion, - viteVersion, -} from '../../utils/versions'; -import { cypressInitGenerator } from '../init/init'; -import { Schema } from './schema'; -import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command'; - -export interface CypressProjectSchema extends Schema { - projectName: string; - projectRoot: string; - rootProject: boolean; -} - -function createFiles(tree: Tree, options: CypressProjectSchema) { - // if not installed or >v10 use v10 folder - // else use v9 folder - const cypressVersion = installedCypressVersion(); - const cypressFiles = - cypressVersion && cypressVersion < 10 ? 'v9-and-under' : 'v10-and-after'; - - generateFiles( - tree, - join(__dirname, './files', cypressFiles), - options.projectRoot, - { - tmpl: '', - ...options, - project: options.project || 'Project', - ext: options.js ? 'js' : 'ts', - offsetFromRoot: offsetFromRoot(options.projectRoot), - rootTsConfigPath: getRelativePathToRootTsConfig( - tree, - options.projectRoot - ), - bundler: options.bundler, - } - ); - - if (cypressVersion && cypressVersion < 7) { - updateJson(tree, join(options.projectRoot, 'cypress.json'), (json) => { - json.pluginsFile = './src/plugins/index'; - return json; - }); - } else if (cypressVersion < 10) { - const pluginPath = join(options.projectRoot, 'src/plugins/index.js'); - if (tree.exists(pluginPath)) { - tree.delete(pluginPath); - } - } - - if (options.js) { - toJS(tree); - } -} - -function addProject(tree: Tree, options: CypressProjectSchema) { - let e2eProjectConfig: ProjectConfiguration; - - const detectedCypressVersion = - installedCypressVersion() ?? - major(checkAndCleanWithSemver('cypress', cypressVersion)); - - const cypressConfig = - detectedCypressVersion < 10 ? 'cypress.json' : 'cypress.config.ts'; - - if (options.baseUrl) { - e2eProjectConfig = { - root: options.projectRoot, - sourceRoot: joinPathFragments(options.projectRoot, 'src'), - projectType: 'application', - targets: { - e2e: { - executor: '@nx/cypress:cypress', - options: { - cypressConfig: joinPathFragments( - options.projectRoot, - cypressConfig - ), - baseUrl: options.baseUrl, - testingType: 'e2e', - }, - }, - }, - tags: [], - implicitDependencies: options.project ? [options.project] : undefined, - }; - } else if (options.project) { - const project = readProjectConfiguration(tree, options.project); - - if (!project.targets) { - logger.warn(stripIndents` - NOTE: Project, "${options.project}", does not have any targets defined and a baseUrl was not provided. Nx will use - "${options.project}:serve" as the devServerTarget. But you may need to define this target within the project, "${options.project}". - `); - } - const devServerTarget = - project.targets?.serve && project.targets?.serve?.defaultConfiguration - ? `${options.project}:serve:${project.targets.serve.defaultConfiguration}` - : `${options.project}:serve`; - e2eProjectConfig = { - root: options.projectRoot, - sourceRoot: joinPathFragments(options.projectRoot, 'src'), - projectType: 'application', - targets: { - e2e: { - executor: '@nx/cypress:cypress', - options: { - cypressConfig: joinPathFragments( - options.projectRoot, - cypressConfig - ), - devServerTarget, - testingType: 'e2e', - }, - configurations: { - production: { - devServerTarget: `${options.project}:serve:production`, - }, - }, - }, - }, - tags: [], - implicitDependencies: options.project ? [options.project] : undefined, - }; - if (project.targets?.['serve-static']) { - e2eProjectConfig.targets.e2e.configurations.ci = { - devServerTarget: `${options.project}:serve-static`, - }; - } - } else { - throw new Error(`Either project or baseUrl should be specified.`); - } - - if (detectedCypressVersion < 7) { - e2eProjectConfig.targets.e2e.options.tsConfig = joinPathFragments( - options.projectRoot, - 'tsconfig.json' - ); - } - addProjectConfiguration(tree, options.projectName, e2eProjectConfig); -} - -/** - * @deprecated use cypressE2EConfigurationGenerator instead - **/ -export async function cypressProjectGenerator(host: Tree, schema: Schema) { - return await cypressProjectGeneratorInternal(host, { - projectNameAndRootFormat: 'derived', - addPlugin: false, - ...schema, - }); -} - -/** - * @deprecated use cypressE2EConfigurationGenerator instead - **/ -export async function cypressProjectGeneratorInternal( - host: Tree, - schema: Schema -) { - const options = await normalizeOptions(host, schema); - const tasks: GeneratorCallback[] = []; - const cypressVersion = installedCypressVersion(); - // if there is an installed cypress version, then we don't call - // init since we want to keep the existing version that is installed - if (!cypressVersion) { - tasks.push(await jsInitGenerator(host, { ...options, skipFormat: true })); - tasks.push( - await cypressInitGenerator(host, { - ...options, - skipFormat: true, - addPlugin: options.addPlugin, - }) - ); - } - - createFiles(host, options); - addProject(host, options); - const installTask = await addLinterToCyProject(host, { - ...options, - cypressDir: 'src', - linter: schema.linter, - project: options.projectName, - overwriteExisting: true, - }); - tasks.push(installTask); - - if (!options.skipPackageJson) { - tasks.push(ensureDependencies(host, options)); - } - - if (!options.skipFormat) { - await formatFiles(host); - } - return runTasksInSerial(...tasks); -} - -function ensureDependencies(tree: Tree, options: CypressProjectSchema) { - const devDependencies: Record = { - '@types/node': typesNodeVersion, - }; - - if (options.bundler === 'vite') { - devDependencies['vite'] = viteVersion; - } - - return runTasksInSerial( - ...[ - addDependenciesToPackageJson(tree, {}, devDependencies), - () => { - logShowProjectCommand(options.projectName); - }, - ] - ); -} - -async function normalizeOptions( - host: Tree, - options: Schema -): Promise { - let maybeRootProject: ProjectConfiguration; - let isRootProject = false; - - const projects = getProjects(host); - // nx will set the project option for generators when ran within a project. - // since the root project will always be set for standalone projects we can just check it here. - if (options.project) { - maybeRootProject = projects.get(options.project); - } - - if ( - maybeRootProject?.root === '.' || - // should still check to see if we are in a standalone based workspace - (!maybeRootProject && - Array.from(projects.values()).some((config) => config.root === '.')) - ) { - isRootProject = true; - } - - let { projectName, projectRoot } = await determineProjectNameAndRootOptions( - host, - { - name: options.name, - projectType: 'application', - directory: isRootProject ? options.name : options.directory, - projectNameAndRootFormat: isRootProject - ? 'as-provided' - : options.projectNameAndRootFormat, - callingGenerator: '@nx/cypress:cypress-project', - } - ); - - options.linter = options.linter || Linter.EsLint; - options.bundler = options.bundler || 'webpack'; - options.addPlugin ??= process.env.NX_ADD_PLUGINS !== 'false'; - - return { - ...options, - // other generators depend on the rootProject flag down stream - rootProject: isRootProject, - projectName, - projectRoot, - }; -} - -export default cypressProjectGenerator; diff --git a/packages/cypress/src/generators/cypress-project/files/v10-and-after/cypress.config.ts__tmpl__ b/packages/cypress/src/generators/cypress-project/files/v10-and-after/cypress.config.ts__tmpl__ deleted file mode 100644 index 89e7991fbb..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v10-and-after/cypress.config.ts__tmpl__ +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from 'cypress'; -import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset'; - -export default defineConfig({ - e2e: nxE2EPreset(__dirname<% if (bundler === 'vite'){ %>, - { - bundler: 'vite' - } - <% } %>) -}); diff --git a/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/e2e/app.cy.ts__tmpl__ b/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/e2e/app.cy.ts__tmpl__ deleted file mode 100644 index 36f5a5cc48..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/e2e/app.cy.ts__tmpl__ +++ /dev/null @@ -1,13 +0,0 @@ -import { getGreeting } from '../support/app.po'; - -describe('<%= project %>', () => { - beforeEach(() => cy.visit('/')); - - it('should display welcome message', () => { - // Custom command example, see `../support/commands.ts` file - cy.login('my-email@something.com', 'myPassword'); - - // Function helper example, see `../support/app.po.ts` file - getGreeting().contains('Welcome <%= project %>'); - }); -}); diff --git a/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/fixtures/example.json__tmpl__ b/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/fixtures/example.json__tmpl__ deleted file mode 100644 index 294cbed6ce..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/fixtures/example.json__tmpl__ +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io" -} diff --git a/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/support/app.po.ts__tmpl__ b/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/support/app.po.ts__tmpl__ deleted file mode 100644 index 3293424696..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/support/app.po.ts__tmpl__ +++ /dev/null @@ -1 +0,0 @@ -export const getGreeting = () => cy.get('h1'); diff --git a/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/support/commands.ts__tmpl__ b/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/support/commands.ts__tmpl__ deleted file mode 100644 index fc4dc5d3d2..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/support/commands.ts__tmpl__ +++ /dev/null @@ -1,33 +0,0 @@ -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -<% if (linter === 'eslint') { %> -// eslint-disable-next-line @typescript-eslint/no-namespace<% } %> -declare namespace Cypress {<% if (linter === 'eslint') { %> - // eslint-disable-next-line @typescript-eslint/no-unused-vars<% } %> - interface Chainable { - login(email: string, password: string): void; - } -} -// -// -- This is a parent command -- -Cypress.Commands.add('login', (email, password) => { - console.log('Custom command example: Login', email, password); -}); -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/support/e2e.ts__tmpl__ b/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/support/e2e.ts__tmpl__ deleted file mode 100644 index 3d469a6b6c..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v10-and-after/src/support/e2e.ts__tmpl__ +++ /dev/null @@ -1,17 +0,0 @@ -// *********************************************************** -// This example support/index.js is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import './commands'; diff --git a/packages/cypress/src/generators/cypress-project/files/v10-and-after/tsconfig.json b/packages/cypress/src/generators/cypress-project/files/v10-and-after/tsconfig.json deleted file mode 100644 index 0c99dafd58..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v10-and-after/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "<%= rootTsConfigPath %>", - "compilerOptions": { - "sourceMap": false, - "outDir": "<%= offsetFromRoot %>dist/out-tsc", - "allowJs": true, - "types": ["cypress", "node"] - }, - "include": ["src/**/*.ts", "src/**/*.js", "cypress.config.ts"] -} diff --git a/packages/cypress/src/generators/cypress-project/files/v9-and-under/cypress.json b/packages/cypress/src/generators/cypress-project/files/v9-and-under/cypress.json deleted file mode 100644 index d8d6fe1c97..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v9-and-under/cypress.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "fileServerFolder": ".", - "fixturesFolder": "./src/fixtures", - "integrationFolder": "./src/integration", - "modifyObstructiveCode": false, - "supportFile": "./src/support/index.<%= ext %>", - "pluginsFile": false, - "video": true, - "videosFolder": "<%= offsetFromRoot %>dist/cypress/<%= projectRoot %>/videos", - "screenshotsFolder": "<%= offsetFromRoot %>dist/cypress/<%= projectRoot %>/screenshots", - "chromeWebSecurity": false -} diff --git a/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/fixtures/example.json__tmpl__ b/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/fixtures/example.json__tmpl__ deleted file mode 100644 index 294cbed6ce..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/fixtures/example.json__tmpl__ +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io" -} diff --git a/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/integration/app.spec.ts__tmpl__ b/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/integration/app.spec.ts__tmpl__ deleted file mode 100644 index 36f5a5cc48..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/integration/app.spec.ts__tmpl__ +++ /dev/null @@ -1,13 +0,0 @@ -import { getGreeting } from '../support/app.po'; - -describe('<%= project %>', () => { - beforeEach(() => cy.visit('/')); - - it('should display welcome message', () => { - // Custom command example, see `../support/commands.ts` file - cy.login('my-email@something.com', 'myPassword'); - - // Function helper example, see `../support/app.po.ts` file - getGreeting().contains('Welcome <%= project %>'); - }); -}); diff --git a/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/plugins/index.js b/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/plugins/index.js deleted file mode 100644 index 63aa33cbe2..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/plugins/index.js +++ /dev/null @@ -1,22 +0,0 @@ -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -const { preprocessTypescript } = require('@nx/cypress/plugins/preprocessor'); - -module.exports = (on, config) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config - - // Preprocess Typescript file using Nx helper - on('file:preprocessor', preprocessTypescript(config)); -}; diff --git a/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/support/app.po.ts__tmpl__ b/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/support/app.po.ts__tmpl__ deleted file mode 100644 index 3293424696..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/support/app.po.ts__tmpl__ +++ /dev/null @@ -1 +0,0 @@ -export const getGreeting = () => cy.get('h1'); diff --git a/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/support/commands.ts__tmpl__ b/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/support/commands.ts__tmpl__ deleted file mode 100644 index fc4dc5d3d2..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/support/commands.ts__tmpl__ +++ /dev/null @@ -1,33 +0,0 @@ -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -<% if (linter === 'eslint') { %> -// eslint-disable-next-line @typescript-eslint/no-namespace<% } %> -declare namespace Cypress {<% if (linter === 'eslint') { %> - // eslint-disable-next-line @typescript-eslint/no-unused-vars<% } %> - interface Chainable { - login(email: string, password: string): void; - } -} -// -// -- This is a parent command -- -Cypress.Commands.add('login', (email, password) => { - console.log('Custom command example: Login', email, password); -}); -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/support/index.ts__tmpl__ b/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/support/index.ts__tmpl__ deleted file mode 100644 index 459189af22..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v9-and-under/src/support/index.ts__tmpl__ +++ /dev/null @@ -1,17 +0,0 @@ -// *********************************************************** -// This example support/index.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.ts using ES2015 syntax: -import './commands'; diff --git a/packages/cypress/src/generators/cypress-project/files/v9-and-under/tsconfig.json b/packages/cypress/src/generators/cypress-project/files/v9-and-under/tsconfig.json deleted file mode 100644 index ab92eb639b..0000000000 --- a/packages/cypress/src/generators/cypress-project/files/v9-and-under/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "<%= offsetFromRoot %>tsconfig.base.json", - "compilerOptions": { - "sourceMap": false, - "outDir": "<%= offsetFromRoot %>dist/out-tsc", - "allowJs": true, - "types": ["cypress", "node"] - }, - "include": ["src/**/*.ts", "src/**/*.js"] -} diff --git a/packages/cypress/src/generators/cypress-project/schema.d.ts b/packages/cypress/src/generators/cypress-project/schema.d.ts deleted file mode 100644 index b743235327..0000000000 --- a/packages/cypress/src/generators/cypress-project/schema.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { ProjectNameAndRootFormat } from '@nx/devkit/src/generators/project-name-and-root-utils'; -import type { Linter } from '@nx/eslint'; - -export interface Schema { - project?: string; - baseUrl?: string; - name: string; - directory?: string; - projectNameAndRootFormat?: ProjectNameAndRootFormat; - linter?: Linter; - js?: boolean; - skipFormat?: boolean; - setParserOptionsProject?: boolean; - skipPackageJson?: boolean; - bundler?: 'webpack' | 'vite' | 'none'; - addPlugin?: boolean; -} diff --git a/packages/cypress/src/generators/cypress-project/schema.json b/packages/cypress/src/generators/cypress-project/schema.json deleted file mode 100644 index e6f53b764f..0000000000 --- a/packages/cypress/src/generators/cypress-project/schema.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "$schema": "https://json-schema.org/schema", - "$id": "NxCypressProjectGeneratorSchema", - "cli": "nx", - "title": "Create Cypress Configuration for the workspace", - "description": "Create Cypress Configuration for the workspace.", - "type": "object", - "properties": { - "project": { - "type": "string", - "description": "The name of the frontend project to test.", - "$default": { - "$source": "projectName" - }, - "x-priority": "important" - }, - "baseUrl": { - "type": "string", - "description": "The address (with the port) which your application is running on." - }, - "name": { - "type": "string", - "description": "Name of the E2E Project.", - "$default": { - "$source": "argv", - "index": 0 - }, - "x-prompt": "What name would you like to use for the e2e project?" - }, - "directory": { - "type": "string", - "description": "A directory where the project is placed.", - "x-priority": "important" - }, - "projectNameAndRootFormat": { - "description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).", - "type": "string", - "enum": ["as-provided", "derived"] - }, - "linter": { - "description": "The tool to use for running lint checks.", - "type": "string", - "enum": ["eslint", "none"], - "default": "eslint" - }, - "js": { - "description": "Generate JavaScript files rather than TypeScript files.", - "type": "boolean", - "default": false - }, - "skipFormat": { - "description": "Skip formatting files.", - "type": "boolean", - "default": false, - "x-priority": "internal" - }, - "setParserOptionsProject": { - "type": "boolean", - "description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.", - "default": false - }, - "skipPackageJson": { - "type": "boolean", - "default": false, - "description": "Do not add dependencies to `package.json`.", - "x-priority": "internal" - }, - "bundler": { - "description": "The Cypress bundler to use.", - "type": "string", - "enum": ["vite", "webpack", "none"], - "x-prompt": "Which Cypress bundler do you want to use?", - "default": "webpack" - } - }, - "required": ["name"], - "examplesFile": "../../../docs/cypress-project-examples.md" -} diff --git a/packages/cypress/src/generators/migrate-to-cypress-11/__snapshots__/migrate-to-cypress-11.spec.ts.snap b/packages/cypress/src/generators/migrate-to-cypress-11/__snapshots__/migrate-to-cypress-11.spec.ts.snap index c8f154449a..c722ebed52 100644 --- a/packages/cypress/src/generators/migrate-to-cypress-11/__snapshots__/migrate-to-cypress-11.spec.ts.snap +++ b/packages/cypress/src/generators/migrate-to-cypress-11/__snapshots__/migrate-to-cypress-11.spec.ts.snap @@ -155,11 +155,6 @@ export default defineConfig({ exports[`convertToCypressTen convertCypressProject should infer targets with --all flag 2`] = ` { "e2e": { - "configurations": { - "production": { - "devServerTarget": "app:serve:production", - }, - }, "executor": "@nx/cypress:cypress", "options": { "cypressConfig": "app-e2e/cypress.config.ts", @@ -168,11 +163,6 @@ exports[`convertToCypressTen convertCypressProject should infer targets with --a }, }, "e2e-custom": { - "configurations": { - "production": { - "devServerTarget": "app:serve:production", - }, - }, "executor": "@nx/cypress:cypress", "options": { "cypressConfig": "app-e2e/cypress.config.ts", @@ -212,11 +202,6 @@ export default defineConfig({ exports[`convertToCypressTen convertCypressProject should not break when an invalid target is passed in 2`] = ` { "e2e": { - "configurations": { - "production": { - "devServerTarget": "app:serve:production", - }, - }, "executor": "@nx/cypress:cypress", "options": { "cypressConfig": "app-e2e/cypress.config.ts", @@ -225,11 +210,6 @@ exports[`convertToCypressTen convertCypressProject should not break when an inva }, }, "e2e-custom": { - "configurations": { - "production": { - "devServerTarget": "app:serve:production", - }, - }, "executor": "@nx/cypress:cypress", "options": { "cypressConfig": "app-e2e/cypress.config.ts", diff --git a/packages/cypress/src/generators/migrate-to-cypress-11/migrate-to-cypress-11.spec.ts b/packages/cypress/src/generators/migrate-to-cypress-11/migrate-to-cypress-11.spec.ts index 99a2a7c040..64b6980200 100644 --- a/packages/cypress/src/generators/migrate-to-cypress-11/migrate-to-cypress-11.spec.ts +++ b/packages/cypress/src/generators/migrate-to-cypress-11/migrate-to-cypress-11.spec.ts @@ -8,10 +8,11 @@ import { Tree, updateJson, updateProjectConfiguration, + writeJson, } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { installedCypressVersion } from '../../utils/cypress-version'; -import { cypressProjectGenerator } from '../cypress-project/cypress-project'; +import { configurationGenerator } from '../configuration/configuration'; import { createSupportFileImport, updateImports, @@ -51,11 +52,23 @@ describe('convertToCypressTen', () => { }); mockedInstalledCypressVersion.mockReturnValue(9); - await cypressProjectGenerator(tree, { - name: 'app-e2e', + addProjectConfiguration(tree, 'app-e2e', { + projectType: 'application', + root: 'app-e2e', + sourceRoot: 'app-e2e/src', + targets: {}, + implicitDependencies: ['app'], + tags: [], + }); + + writeJson(tree, 'app-e2e/tsconfig.json', { + include: ['src/**/*.ts', 'src/**/*.js'], + }); + + await configurationGenerator(tree, { skipFormat: true, - project: 'app', - projectNameAndRootFormat: 'as-provided', + project: 'app-e2e', + devServerTarget: 'app:serve', addPlugin: false, }); }); @@ -296,12 +309,26 @@ describe('convertToCypressTen', () => { }, }); - await cypressProjectGenerator(tree, { - name: 'app-two-e2e', - skipFormat: true, - project: 'app-two', - projectNameAndRootFormat: 'as-provided', + addProjectConfiguration(tree, 'app-two-e2e', { + projectType: 'application', + root: 'app-two-e2e', + sourceRoot: 'app-two-e2e/src', + targets: {}, + implicitDependencies: ['app-two'], + tags: [], }); + + writeJson(tree, 'app-two-e2e/tsconfig.json', { + include: ['src/**/*.ts', 'src/**/*.js'], + }); + + await configurationGenerator(tree, { + skipFormat: true, + project: 'app-two-e2e', + devServerTarget: 'app-two:serve', + addPlugin: false, + }); + const appOneProjectConfig = readProjectConfiguration(tree, 'app-e2e'); appOneProjectConfig.targets['e2e'].options.cypressConfig = 'cypress.json'; updateProjectConfiguration(tree, 'app-e2e', appOneProjectConfig); @@ -338,11 +365,6 @@ describe('convertToCypressTen', () => { devServerTarget: 'app:serve', testingType: 'e2e', }, - configurations: { - production: { - devServerTarget: 'app:serve:production', - }, - }, }); expect(readJson(tree, 'app-two-e2e/tsconfig.json').include).toEqual([ 'src/**/*.ts', @@ -360,11 +382,6 @@ describe('convertToCypressTen', () => { devServerTarget: 'app-two:serve', testingType: 'e2e', }, - configurations: { - production: { - devServerTarget: 'app-two:serve:production', - }, - }, }); }); }); diff --git a/packages/esbuild/src/utils/environment-variables.ts b/packages/esbuild/src/utils/environment-variables.ts index e901291198..a0958e7055 100644 --- a/packages/esbuild/src/utils/environment-variables.ts +++ b/packages/esbuild/src/utils/environment-variables.ts @@ -1,15 +1,8 @@ -// Prevent sensitive keys from being bundled when source code uses entire `process.env` object rather than individual keys (e.g. `process.env.NX_FOO`). -// TODO(v19): Only env vars prefixed with NX_PUBLIC should be bundled. This is a breaking change so we won't do it in v18. -const excludedKeys = ['NX_CLOUD_ACCESS_TOKEN', 'NX_CLOUD_ENCRYPTION_KEY']; - export function getClientEnvironment(): Record { - const NX_APP = /^NX_/i; + const nxPublicKeyRegex = /^NX_PUBLIC_/i; return Object.keys(process.env) - .filter( - (key) => - !excludedKeys.includes(key) && (NX_APP.test(key) || key === 'NODE_ENV') - ) + .filter((key) => nxPublicKeyRegex.test(key) || key === 'NODE_ENV') .reduce((env, key) => { env[`process.env.${key}`] = JSON.stringify(process.env[key]); return env; diff --git a/packages/eslint-plugin/src/configs/javascript.ts b/packages/eslint-plugin/src/configs/javascript.ts index dbdd966900..6fa1f1260b 100644 --- a/packages/eslint-plugin/src/configs/javascript.ts +++ b/packages/eslint-plugin/src/configs/javascript.ts @@ -55,7 +55,7 @@ export default { * previously defined v5 of `@typescript-eslint`. v6 of `@typescript-eslint` * changed how configurations are defined. * - * TODO(v19): re-evalute these deviations from @typescript-eslint/recommended in v19 of Nx + * TODO(v20): re-evalute these deviations from @typescript-eslint/recommended in v19 of Nx */ 'no-extra-semi': 'off', '@typescript-eslint/no-extra-semi': 'error', diff --git a/packages/eslint-plugin/src/configs/typescript.ts b/packages/eslint-plugin/src/configs/typescript.ts index 5cbb3d2f32..870b6910be 100644 --- a/packages/eslint-plugin/src/configs/typescript.ts +++ b/packages/eslint-plugin/src/configs/typescript.ts @@ -38,7 +38,7 @@ export default { * previously defined v5 of `@typescript-eslint`. v6 of `@typescript-eslint` * changed how configurations are defined. * - * TODO(v19): re-evalute these deviations from @typescript-eslint/recommended in v19 of Nx + * TODO(v20): re-evalute these deviations from @typescript-eslint/recommended in v19 of Nx */ 'no-extra-semi': 'off', '@typescript-eslint/no-extra-semi': 'error', diff --git a/packages/expo/migrations.json b/packages/expo/migrations.json index 282036c69b..9109062c3b 100644 --- a/packages/expo/migrations.json +++ b/packages/expo/migrations.json @@ -65,6 +65,12 @@ "version": "18.0.0-beta.0", "description": "Remove the offset from the outputDir of the export target", "implementation": "./src/migrations/update-18-0-0/change-outputDir-export-target" + }, + "update-19-0-0-change-webpack-to-metro": { + "version": "19.0.0-beta.9", + "cli": "nx", + "description": "Change webpack to metro in expo projects", + "factory": "./src/migrations/update-19-0-0/change-webpack-to-metro" } }, "packageJsonUpdates": { diff --git a/packages/expo/package.json b/packages/expo/package.json index 067e7f5c33..b8f5eebf14 100644 --- a/packages/expo/package.json +++ b/packages/expo/package.json @@ -35,7 +35,6 @@ "node-fetch": "^2.6.7", "tslib": "^2.3.0", "tsconfig-paths": "^4.1.2", - "tsconfig-paths-webpack-plugin": "^4.0.0", "@nx/jest": "file:../jest", "@nx/js": "file:../js", "@nx/eslint": "file:../eslint", diff --git a/packages/expo/plugins/with-nx-webpack.ts b/packages/expo/plugins/with-nx-webpack.ts deleted file mode 100644 index af536b44ed..0000000000 --- a/packages/expo/plugins/with-nx-webpack.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin'; -import { resolve } from 'path'; - -/** - * @deprecated TODO(v19) use bundler: 'metro' instead, will be removed in v19 - * This function add additional rules to expo's webpack config to make expo web working - */ -export async function withNxWebpack(config) { - // add additional rule to load files under libs - const rules = config.module.rules.find((rule) => - Array.isArray(rule.oneOf) - )?.oneOf; - if (rules) { - rules.push({ - test: /\.(mjs|[jt]sx?)$/, - exclude: /node_modules/, - use: { - loader: require.resolve('@nx/webpack/src/utils/web-babel-loader.js'), - options: { - presets: [ - [ - '@nx/react/babel', - { - runtime: 'automatic', - }, - ], - ], - }, - }, - }); - } - - if (!config.resolve) { - config.resolve = {}; - } - if (!config.resolve.plugins) { - config.resolve.plugins = []; - } - const extensions = ['.ts', '.tsx', '.mjs', '.js', '.jsx']; - const tsConfigPath = resolve(__dirname, 'tsconfig.json'); - config.resolve.plugins.push( - new TsconfigPathsPlugin({ - configFile: tsConfigPath, - extensions, - }) - ); - config.resolve.fallback = { - ...config.resolve.fallback, - crypto: require.resolve('crypto-browserify'), - stream: require.resolve('stream-browserify'), - }; - - return config; -} diff --git a/packages/expo/src/migrations/update-19-0-0/change-webpack-to-metro.spec.ts b/packages/expo/src/migrations/update-19-0-0/change-webpack-to-metro.spec.ts new file mode 100644 index 0000000000..1b495d8c36 --- /dev/null +++ b/packages/expo/src/migrations/update-19-0-0/change-webpack-to-metro.spec.ts @@ -0,0 +1,56 @@ +import { + addProjectConfiguration, + getProjects, + readJson, + Tree, +} from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import update from './change-webpack-to-metro'; + +describe('change-webpack-to-metro', () => { + let tree: Tree; + + beforeEach(async () => { + tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); + addProjectConfiguration(tree, 'product', { + root: 'apps/product', + sourceRoot: 'apps/product/src', + targets: { + start: { + executor: '@nx/expo:start', + }, + 'export-web': { + executor: '@nx/expo:export', + options: {}, + }, + }, + }); + tree.write( + `apps/product/app.json`, + JSON.stringify({ + expo: { + web: { + bundler: 'webpack', + }, + }, + }) + ); + }); + + it(`should update project.json with target export-web and change app.json`, async () => { + await update(tree); + + getProjects(tree).forEach((project) => { + expect(project.targets['export-web']).toEqual({ + executor: '@nx/expo:export', + options: { + bundler: 'metro', + }, + }); + + expect(project.targets['web']).toBeUndefined(); + const appJson = readJson(tree, `apps/product/app.json`); + expect(appJson.expo.web.bundler).toEqual('metro'); + }); + }); +}); diff --git a/packages/expo/src/migrations/update-19-0-0/change-webpack-to-metro.ts b/packages/expo/src/migrations/update-19-0-0/change-webpack-to-metro.ts new file mode 100644 index 0000000000..86c176d12c --- /dev/null +++ b/packages/expo/src/migrations/update-19-0-0/change-webpack-to-metro.ts @@ -0,0 +1,38 @@ +import { + Tree, + formatFiles, + getProjects, + updateProjectConfiguration, + updateJson, +} from '@nx/devkit'; + +/** + * Migration: + * - change target 'export-web' + * - change bundler to 'metro' + */ +export default async function update(tree: Tree) { + const projects = getProjects(tree); + + for (const [name, config] of projects.entries()) { + if (config.targets?.['start']?.executor === '@nx/expo:start') { + if (config.targets['web']) { + delete config.targets['web']; + } + if (config.targets['export-web']) { + config.targets['export-web'].options.bundler = 'metro'; + } + + updateJson(tree, `${config.root}/app.json`, (appJson) => { + if (appJson.expo?.web) { + appJson.expo.web.bundler = 'metro'; + } + return appJson; + }); + } + + updateProjectConfiguration(tree, name, config); + } + + await formatFiles(tree); +} diff --git a/packages/js/babel.ts b/packages/js/babel.ts index ea91ad9b25..5924ff8a3a 100644 --- a/packages/js/babel.ts +++ b/packages/js/babel.ts @@ -37,7 +37,7 @@ module.exports = function (api: any, options: NxWebBabelPresetOptions = {}) { // Determine settings for `@babel//babel-plugin-transform-class-properties`, // so that we can sync the `loose` option with `@babel/preset-env`. - // TODO(v19): Remove classProperties since it's no longer needed, now that the class props transform is in preset-env. + // TODO(v20): Remove classProperties since it's no longer needed, now that the class props transform is in preset-env. const loose = options.classProperties?.loose ?? options.loose ?? true; if (options.classProperties) { logger.warn( diff --git a/packages/next/plugins/with-nx.ts b/packages/next/plugins/with-nx.ts index 6b1642a2db..c9536b070d 100644 --- a/packages/next/plugins/with-nx.ts +++ b/packages/next/plugins/with-nx.ts @@ -327,12 +327,7 @@ export function getNextConfig( } /** - * 5. Add env variables prefixed with NX_ - */ - addNxEnvVariables(config); - - /** - * 6. Add SVGR support if option is on. + * 5. Add SVGR support if option is on. */ // Default SVGR support to be on for projects. @@ -393,40 +388,6 @@ export function getNextConfig( }; } -// Prevent sensitive keys from being bundled when source code uses entire `process.env` object rather than individual keys (e.g. `process.env.NX_FOO`). -// TODO(v19): BREAKING: Only support NEXT_PUBLIC_ env vars and ignore NX_ vars since this is a standard Next.js feature. -const excludedKeys = ['NX_CLOUD_ACCESS_TOKEN', 'NX_CLOUD_ENCRYPTION_KEY']; - -function getNxEnvironmentVariables() { - return Object.keys(process.env) - .filter((env) => !excludedKeys.includes(env) && /^NX_/i.test(env)) - .reduce((env, key) => { - env[key] = process.env[key]; - return env; - }, {}); -} - -/** - * TODO(v19) - * @deprecated Use Next.js 9.4+ built-in support for environment variables. Reference https://nextjs.org/docs/pages/api-reference/next-config-js/env - */ -function addNxEnvVariables(config: any) { - const maybeDefinePlugin = config.plugins?.find((plugin) => { - return plugin.definitions?.['process.env.NODE_ENV']; - }); - - if (maybeDefinePlugin) { - const env = getNxEnvironmentVariables(); - - Object.entries(env) - .map(([name, value]) => [`process.env.${name}`, `"${value}"`]) - .filter(([name]) => !maybeDefinePlugin.definitions[name]) - .forEach( - ([name, value]) => (maybeDefinePlugin.definitions[name] = value) - ); - } -} - export function getAliasForProject( node: ProjectGraphProjectNode, paths: Record diff --git a/packages/next/plugins/with-stylus.ts b/packages/next/plugins/with-stylus.ts index 35ff041bb2..5512f012ac 100644 --- a/packages/next/plugins/with-stylus.ts +++ b/packages/next/plugins/with-stylus.ts @@ -1,7 +1,7 @@ import { NextConfigFn } from '../src/utils/config'; import { WithNxOptions } from './with-nx'; -// TODO(v19): Remove file, it is here until users migrate over to SASS manually. +// TODO(v20): Remove file, it is here until users migrate over to SASS manually. export function withStylus( configOrFn: WithNxOptions | NextConfigFn ): NextConfigFn { diff --git a/packages/next/src/generators/component/component.ts b/packages/next/src/generators/component/component.ts index a416b5dc9d..6aa0a1b48a 100644 --- a/packages/next/src/generators/component/component.ts +++ b/packages/next/src/generators/component/component.ts @@ -36,7 +36,7 @@ interface Schema { skipFormat?: boolean; } -// TODO(v19): Remove this logic once we no longer derive directory. +// TODO(v20): Remove this logic once we no longer derive directory. function maybeGetDerivedDirectory(host: Tree, options: Schema): string { if (!options.project) return options.directory; const workspace = getProjects(host); diff --git a/packages/next/src/generators/page/page.ts b/packages/next/src/generators/page/page.ts index a5bb0b3778..5ff773876e 100644 --- a/packages/next/src/generators/page/page.ts +++ b/packages/next/src/generators/page/page.ts @@ -56,7 +56,7 @@ async function normalizeOptions(host: Tree, options: Schema) { if (options.project) { // Legacy behavior, detect app vs page router from specified project. - // TODO(v19): remove this logic + // TODO(v20): remove this logic const project = readProjectConfiguration(host, options.project); // app/ is a reserved folder in nextjs so it is safe to check it's existence isAppRouter = diff --git a/packages/react/plugins/component-testing/index.ts b/packages/react/plugins/component-testing/index.ts index d43afb00a2..2803579b4f 100644 --- a/packages/react/plugins/component-testing/index.ts +++ b/packages/react/plugins/component-testing/index.ts @@ -283,7 +283,10 @@ function buildTargetWebpack( return async () => { customWebpack = await customWebpack; - // TODO(v19): Once webpackConfig is always set in @nx/webpack:webpack and isolatedConfig is removed, we no longer need this default. + // TODO(v20): Component testing need to be agnostic of the underlying executor. With Crystal, we're not using `@nx/webpack:webpack` by default. + // We need to decouple CT from the build target of the app, we just care about bundler config (e.g. webpack.config.js). + // The generated setup should support both Webpack and Vite as documented here: https://docs.cypress.io/guides/component-testing/react/overview + // Related issue: https://github.com/nrwl/nx/issues/21546 const configure = composePluginsSync(withNx(), withWeb()); const defaultWebpack = configure( {}, diff --git a/packages/react/plugins/storybook/index.ts b/packages/react/plugins/storybook/index.ts index f8f57a9910..83eb1471f2 100644 --- a/packages/react/plugins/storybook/index.ts +++ b/packages/react/plugins/storybook/index.ts @@ -18,24 +18,16 @@ import { mergePlugins } from './merge-plugins'; import { withReact } from '../with-react'; import { existsSync } from 'fs'; -// Prevent sensitive keys from being bundled when source code uses entire `process.env` object rather than individual keys (e.g. `process.env.NX_FOO`). -// TODO(v19): BREAKING: Only env vars prefixed with NX_PUBLIC should be bundled. This is a breaking change so we won't do it in v18. -const excludedKeys = ['NX_CLOUD_ACCESS_TOKEN', 'NX_CLOUD_ENCRYPTION_KEY']; - // This is shamelessly taken from CRA and modified for NX use // https://github.com/facebook/create-react-app/blob/4784997f0682e75eb32a897b4ffe34d735912e6c/packages/react-scripts/config/env.js#L71 function getClientEnvironment(mode) { // Grab NODE_ENV and NX_* and STORYBOOK_* environment variables and prepare them to be // injected into the application via DefinePlugin in webpack configuration. - const NX_PREFIX = /^NX_/i; + const NX_PREFIX = /^NX_PUBLIC_/i; const STORYBOOK_PREFIX = /^STORYBOOK_/i; const raw = Object.keys(process.env) - .filter( - (key) => - !excludedKeys.includes(key) && - (NX_PREFIX.test(key) || STORYBOOK_PREFIX.test(key)) - ) + .filter((key) => NX_PREFIX.test(key) || STORYBOOK_PREFIX.test(key)) .reduce( (env, key) => { env[key] = process.env[key]; diff --git a/packages/webpack/docs/webpack-build-executor-examples.md b/packages/webpack/docs/webpack-build-executor-examples.md index 7714616f1b..9a706229d6 100644 --- a/packages/webpack/docs/webpack-build-executor-examples.md +++ b/packages/webpack/docs/webpack-build-executor-examples.md @@ -5,22 +5,18 @@ description: Examples and a short guide on how to use the @nx/webpack:webpack bu `project.json`: -```json +```json5 //... "my-app": { - "targets": { - //... - "build": { - "executor": "@nx/webpack:webpack", - //... - //... - "options": { - ... - }, - //... - } - }, - } + "targets": { + "build": { + "executor": "@nx/webpack:webpack", + "options": { + "webpackConfig": "apps/my-app/webpack.config.js" + } + }, + //... + } } ``` @@ -40,21 +36,19 @@ Copying from the [Babel documentation](https://babeljs.io/docs/config-files#root Setting `babelUpwardRootMode` to `true` in your `project.json` will set `rootMode` option to `upward` in the Babel config. You may want the `upward` mode in a monorepo when projects must apply their individual `.babelrc` file. We recommend that you don't set it at all, so it will use the default to `false` as the `upward` mode brings additional complexity to the build process. -```json +```json5 //... "my-app": { "targets": { "build": { "executor": "@nx/webpack:webpack", "options": { - "babelUpwardRootMode": true, - //... - }, - //... + "webpackConfig": "apps/my-app/webpack.config.js", + "babelUpwardRootMode": true + } }, //... - }, - //... + } } ``` @@ -94,23 +88,19 @@ In workspace above, if `demo` imports `a` and `b`, it will apply the config `lib If you have a custom Babel config file (i.e. not `.babelrc`), you can use the `configFile` option as follows: -```json +```json5 //... "my-app": { - "targets": { - //... - "build": { - "executor": "@nx/webpack:webpack", - //... - "options": { - //... - "babelConfig": "apps/my-app/.babelrc.custom.json", - }, - "configurations": { - ... - } - }, - } + "targets": { + "build": { + "executor": "@nx/webpack:webpack", + "options": { + "webpackConfig": "apps/my-app/webpack.config.js", + "babelConfig": "apps/my-app/.babelrc.custom.json", + } + }, + // ... + } } ``` @@ -133,21 +123,15 @@ Set `isolatedConfig` to `true` in your `project.json` file in the `build` target ```json //... "my-app": { - "targets": { - //... - "build": { - "executor": "@nx/webpack:webpack", - //... - "options": { - //... - "webpackConfig": "apps/my-app/webpack.config.js", - "isolatedConfig": true - }, - "configurations": { - ... - } - }, - } + "targets": { + "build": { + "executor": "@nx/webpack:webpack", + "options": { + "webpackConfig": "apps/my-app/webpack.config.js", + "isolatedConfig": true + } + }, + } } ``` diff --git a/packages/webpack/src/executors/webpack/schema.d.ts b/packages/webpack/src/executors/webpack/schema.d.ts index 4f9bbb390d..8fe6a0eddb 100644 --- a/packages/webpack/src/executors/webpack/schema.d.ts +++ b/packages/webpack/src/executors/webpack/schema.d.ts @@ -47,7 +47,7 @@ export interface WebpackExecutorOptions { extractLicenses?: boolean; fileReplacements?: FileReplacement[]; generatePackageJson?: boolean; - // TODO(v19): Remove this option + // TODO(v20): Remove this option /** @deprecated set webpackConfig and provide an explicit webpack.config.js file (See: https://nx.dev/recipes/webpack/webpack-config-setup) */ isolatedConfig?: boolean; standardWebpackConfigFunction?: boolean; diff --git a/packages/webpack/src/utils/get-client-environment.ts b/packages/webpack/src/utils/get-client-environment.ts index db5f3e6694..50f012fc28 100644 --- a/packages/webpack/src/utils/get-client-environment.ts +++ b/packages/webpack/src/utils/get-client-environment.ts @@ -1,14 +1,10 @@ -// Prevent sensitive keys from being bundled when source code uses entire `process.env` object rather than individual keys (e.g. `process.env.NX_FOO`). -// TODO(v19): Only env vars prefixed with NX_PUBLIC should be bundled. This is a breaking change so we won't do it in v18. -const excludedKeys = ['NX_CLOUD_ACCESS_TOKEN', 'NX_CLOUD_ENCRYPTION_KEY']; - export function getClientEnvironment(mode?: string) { - // Grab NODE_ENV and NX_* environment variables and prepare them to be + // Grab NODE_ENV and NX_PUBLIC_* environment variables and prepare them to be // injected into the application via DefinePlugin in webpack configuration. - const NX_APP = /^NX_/i; + const nxPublicKeyRegex = /^NX_PUBLIC_/i; const raw = Object.keys(process.env) - .filter((key) => !excludedKeys.includes(key) && NX_APP.test(key)) + .filter((key) => nxPublicKeyRegex.test(key)) .reduce( (env, key) => { env[key] = process.env[key]; diff --git a/packages/webpack/src/utils/webpack/interpolate-env-variables-to-index.spec.ts b/packages/webpack/src/utils/webpack/interpolate-env-variables-to-index.spec.ts index 45fda63c15..00f5fdce1a 100644 --- a/packages/webpack/src/utils/webpack/interpolate-env-variables-to-index.spec.ts +++ b/packages/webpack/src/utils/webpack/interpolate-env-variables-to-index.spec.ts @@ -2,7 +2,7 @@ import { interpolateEnvironmentVariablesToIndex } from './interpolate-env-variab describe('interpolateEnvironmentVariablesToIndex()', () => { const envDefaults = { - NX_VARIABLE: 'foo', + NX_PUBLIC_VARIABLE: 'foo', SOME_OTHER_VARIABLE: 'bar', DEPLOY_URL: 'baz', }; @@ -14,7 +14,7 @@ describe('interpolateEnvironmentVariablesToIndex()', () => { test('default env variables', () => { const content = ` -
Nx Variable: %NX_VARIABLE%
+
Nx Variable: %NX_PUBLIC_VARIABLE%
Some other variable: %SOME_OTHER_VARIABLE%
Deploy Url: %DEPLOY_URL%
`; @@ -28,7 +28,7 @@ describe('interpolateEnvironmentVariablesToIndex()', () => { test('Deploy url set as option overrides DEPLOY_URL env variable', () => { const content = ` -
Nx Variable: %NX_VARIABLE%
+
Nx Variable: %NX_PUBLIC_VARIABLE%
Some other variable: %SOME_OTHER_VARIABLE%
Deploy Url: %DEPLOY_URL%
`; @@ -45,7 +45,7 @@ describe('interpolateEnvironmentVariablesToIndex()', () => { test('No deploy url provided via either option', () => { delete process.env.DEPLOY_URL; const content = ` -
Nx Variable: %NX_VARIABLE%
+
Nx Variable: %NX_PUBLIC_VARIABLE%
Some other variable: %SOME_OTHER_VARIABLE%
Deploy Url: %DEPLOY_URL%
`; @@ -60,7 +60,7 @@ describe('interpolateEnvironmentVariablesToIndex()', () => { test('NX_ prefixed option present in index.html, but not present in process.env', () => { delete process.env.DEPLOY_URL; const content = ` -
Nx Variable: %NX_VARIABLE%
+
Nx Variable: %NX_PUBLIC_VARIABLE%
Some other variable: %SOME_OTHER_VARIABLE%
Some other nx_variable: %NX_SOME_OTHER_VARIABLE%
Deploy Url: %DEPLOY_URL%
diff --git a/packages/webpack/src/utils/webpack/interpolate-env-variables-to-index.ts b/packages/webpack/src/utils/webpack/interpolate-env-variables-to-index.ts index 2db35b8615..3adb6d840c 100644 --- a/packages/webpack/src/utils/webpack/interpolate-env-variables-to-index.ts +++ b/packages/webpack/src/utils/webpack/interpolate-env-variables-to-index.ts @@ -6,14 +6,10 @@ export function interpolateEnvironmentVariablesToIndex( return interpolateEnvironmentVariables(contents, environmentVariables as any); } -const NX_PREFIX = /^NX_/i; - -// Prevent sensitive keys from being bundled when source code uses entire `process.env` object rather than individual keys (e.g. `process.env.NX_FOO`). -// TODO(v19): Only env vars prefixed with NX_PUBLIC should be bundled. This is a breaking change so we won't do it in v18. -const excludedKeys = ['NX_CLOUD_ACCESS_TOKEN', 'NX_CLOUD_ENCRYPTION_KEY']; +const NX_PREFIX = /^NX_PUBLIC_/i; function isNxEnvironmentKey(x: string): boolean { - return !excludedKeys.includes(x) && NX_PREFIX.test(x); + return NX_PREFIX.test(x); } function getClientEnvironment(deployUrl: string) {