feat(angular): support angular cli v20.0.0-rc.3 (#30715)
Add support for the Angular CLI **20.0.0-rc.3** version.
This commit is contained in:
parent
07baaafb43
commit
752d418f78
@ -51,3 +51,6 @@ CODEOWNERS
|
||||
/.nx/workflows/dynamic-changesets.yaml
|
||||
_files
|
||||
_solution
|
||||
|
||||
# this file uses TS import attributes which the current prettier version does not support
|
||||
tools/documentation/create-embeddings/src/main.mts
|
||||
|
||||
@ -444,6 +444,66 @@
|
||||
}
|
||||
},
|
||||
"migrations": {
|
||||
"/nx-api/angular/migrations/update-angular-cli-version-20-0-0-rc-3": {
|
||||
"description": "Update the @angular/cli package version to 20.0.0-rc.3.",
|
||||
"file": "generated/packages/angular/migrations/update-angular-cli-version-20-0-0-rc-3.json",
|
||||
"hidden": false,
|
||||
"name": "update-angular-cli-version-20-0-0-rc-3",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/angular",
|
||||
"path": "/nx-api/angular/migrations/update-angular-cli-version-20-0-0-rc-3",
|
||||
"type": "migration"
|
||||
},
|
||||
"/nx-api/angular/migrations/migrate-provide-server-rendering-import": {
|
||||
"description": "Migrate imports of `provideServerRendering` from `@angular/platform-server` to `@angular/ssr`.",
|
||||
"file": "generated/packages/angular/migrations/migrate-provide-server-rendering-import.json",
|
||||
"hidden": false,
|
||||
"name": "migrate-provide-server-rendering-import",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/angular",
|
||||
"path": "/nx-api/angular/migrations/migrate-provide-server-rendering-import",
|
||||
"type": "migration"
|
||||
},
|
||||
"/nx-api/angular/migrations/replace-provide-server-routing": {
|
||||
"description": "Replace `provideServerRouting` with `provideServerRendering` using `withRoutes`.",
|
||||
"file": "generated/packages/angular/migrations/replace-provide-server-routing.json",
|
||||
"hidden": false,
|
||||
"name": "replace-provide-server-routing",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/angular",
|
||||
"path": "/nx-api/angular/migrations/replace-provide-server-routing",
|
||||
"type": "migration"
|
||||
},
|
||||
"/nx-api/angular/migrations/set-generator-defaults-for-previous-style-guide": {
|
||||
"description": "Update the generator defaults to maintain the previous style guide behavior.",
|
||||
"file": "generated/packages/angular/migrations/set-generator-defaults-for-previous-style-guide.json",
|
||||
"hidden": false,
|
||||
"name": "set-generator-defaults-for-previous-style-guide",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/angular",
|
||||
"path": "/nx-api/angular/migrations/set-generator-defaults-for-previous-style-guide",
|
||||
"type": "migration"
|
||||
},
|
||||
"/nx-api/angular/migrations/update-module-resolution": {
|
||||
"description": "Update 'moduleResolution' to 'bundler' in TypeScript configurations. You can read more about this here: https://www.typescriptlang.org/tsconfig/#moduleResolution.",
|
||||
"file": "generated/packages/angular/migrations/update-module-resolution.json",
|
||||
"hidden": false,
|
||||
"name": "update-module-resolution",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/angular",
|
||||
"path": "/nx-api/angular/migrations/update-module-resolution",
|
||||
"type": "migration"
|
||||
},
|
||||
"/nx-api/angular/migrations/21.2.0-package-updates": {
|
||||
"description": "",
|
||||
"file": "generated/packages/angular/migrations/21.2.0-package-updates.json",
|
||||
"hidden": false,
|
||||
"name": "21.2.0-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/angular",
|
||||
"path": "/nx-api/angular/migrations/21.2.0-package-updates",
|
||||
"type": "migration"
|
||||
},
|
||||
"/nx-api/angular/migrations/21.1.0-package-updates": {
|
||||
"description": "",
|
||||
"file": "generated/packages/angular/migrations/21.1.0-package-updates.json",
|
||||
@ -1687,6 +1747,26 @@
|
||||
}
|
||||
},
|
||||
"migrations": {
|
||||
"/nx-api/eslint/migrations/21.2.0-typescript-eslint-package-updates": {
|
||||
"description": "",
|
||||
"file": "generated/packages/eslint/migrations/21.2.0-typescript-eslint-package-updates.json",
|
||||
"hidden": false,
|
||||
"name": "21.2.0-typescript-eslint-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/eslint",
|
||||
"path": "/nx-api/eslint/migrations/21.2.0-typescript-eslint-package-updates",
|
||||
"type": "migration"
|
||||
},
|
||||
"/nx-api/eslint/migrations/21.2.0-@typescript-eslint-package-updates": {
|
||||
"description": "",
|
||||
"file": "generated/packages/eslint/migrations/21.2.0-@typescript-eslint-package-updates.json",
|
||||
"hidden": false,
|
||||
"name": "21.2.0-@typescript-eslint-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/eslint",
|
||||
"path": "/nx-api/eslint/migrations/21.2.0-@typescript-eslint-package-updates",
|
||||
"type": "migration"
|
||||
},
|
||||
"/nx-api/eslint/migrations/20.7.0-package-updates": {
|
||||
"description": "",
|
||||
"file": "generated/packages/eslint/migrations/20.7.0-package-updates.json",
|
||||
@ -2454,6 +2534,16 @@
|
||||
}
|
||||
},
|
||||
"migrations": {
|
||||
"/nx-api/js/migrations/21.2.0-package-updates": {
|
||||
"description": "",
|
||||
"file": "generated/packages/js/migrations/21.2.0-package-updates.json",
|
||||
"hidden": false,
|
||||
"name": "21.2.0-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/js",
|
||||
"path": "/nx-api/js/migrations/21.2.0-package-updates",
|
||||
"type": "migration"
|
||||
},
|
||||
"/nx-api/js/migrations/20.7.1-beta.0-package-updates": {
|
||||
"description": "",
|
||||
"file": "generated/packages/js/migrations/20.7.1-beta.0-package-updates.json",
|
||||
@ -5724,6 +5814,16 @@
|
||||
}
|
||||
},
|
||||
"migrations": {
|
||||
"/nx-api/workspace/migrations/21.2.0-package-updates": {
|
||||
"description": "",
|
||||
"file": "generated/packages/workspace/migrations/21.2.0-package-updates.json",
|
||||
"hidden": false,
|
||||
"name": "21.2.0-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/workspace",
|
||||
"path": "/nx-api/workspace/migrations/21.2.0-package-updates",
|
||||
"type": "migration"
|
||||
},
|
||||
"/nx-api/workspace/migrations/20.4.0-package-updates": {
|
||||
"description": "",
|
||||
"file": "generated/packages/workspace/migrations/20.4.0-package-updates.json",
|
||||
|
||||
@ -439,6 +439,66 @@
|
||||
}
|
||||
],
|
||||
"migrations": [
|
||||
{
|
||||
"description": "Update the @angular/cli package version to 20.0.0-rc.3.",
|
||||
"file": "generated/packages/angular/migrations/update-angular-cli-version-20-0-0-rc-3.json",
|
||||
"hidden": false,
|
||||
"name": "update-angular-cli-version-20-0-0-rc-3",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/angular",
|
||||
"path": "angular/migrations/update-angular-cli-version-20-0-0-rc-3",
|
||||
"type": "migration"
|
||||
},
|
||||
{
|
||||
"description": "Migrate imports of `provideServerRendering` from `@angular/platform-server` to `@angular/ssr`.",
|
||||
"file": "generated/packages/angular/migrations/migrate-provide-server-rendering-import.json",
|
||||
"hidden": false,
|
||||
"name": "migrate-provide-server-rendering-import",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/angular",
|
||||
"path": "angular/migrations/migrate-provide-server-rendering-import",
|
||||
"type": "migration"
|
||||
},
|
||||
{
|
||||
"description": "Replace `provideServerRouting` with `provideServerRendering` using `withRoutes`.",
|
||||
"file": "generated/packages/angular/migrations/replace-provide-server-routing.json",
|
||||
"hidden": false,
|
||||
"name": "replace-provide-server-routing",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/angular",
|
||||
"path": "angular/migrations/replace-provide-server-routing",
|
||||
"type": "migration"
|
||||
},
|
||||
{
|
||||
"description": "Update the generator defaults to maintain the previous style guide behavior.",
|
||||
"file": "generated/packages/angular/migrations/set-generator-defaults-for-previous-style-guide.json",
|
||||
"hidden": false,
|
||||
"name": "set-generator-defaults-for-previous-style-guide",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/angular",
|
||||
"path": "angular/migrations/set-generator-defaults-for-previous-style-guide",
|
||||
"type": "migration"
|
||||
},
|
||||
{
|
||||
"description": "Update 'moduleResolution' to 'bundler' in TypeScript configurations. You can read more about this here: https://www.typescriptlang.org/tsconfig/#moduleResolution.",
|
||||
"file": "generated/packages/angular/migrations/update-module-resolution.json",
|
||||
"hidden": false,
|
||||
"name": "update-module-resolution",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/angular",
|
||||
"path": "angular/migrations/update-module-resolution",
|
||||
"type": "migration"
|
||||
},
|
||||
{
|
||||
"description": "",
|
||||
"file": "generated/packages/angular/migrations/21.2.0-package-updates.json",
|
||||
"hidden": false,
|
||||
"name": "21.2.0-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/angular",
|
||||
"path": "angular/migrations/21.2.0-package-updates",
|
||||
"type": "migration"
|
||||
},
|
||||
{
|
||||
"description": "",
|
||||
"file": "generated/packages/angular/migrations/21.1.0-package-updates.json",
|
||||
@ -1675,6 +1735,26 @@
|
||||
}
|
||||
],
|
||||
"migrations": [
|
||||
{
|
||||
"description": "",
|
||||
"file": "generated/packages/eslint/migrations/21.2.0-typescript-eslint-package-updates.json",
|
||||
"hidden": false,
|
||||
"name": "21.2.0-typescript-eslint-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/eslint",
|
||||
"path": "eslint/migrations/21.2.0-typescript-eslint-package-updates",
|
||||
"type": "migration"
|
||||
},
|
||||
{
|
||||
"description": "",
|
||||
"file": "generated/packages/eslint/migrations/21.2.0-@typescript-eslint-package-updates.json",
|
||||
"hidden": false,
|
||||
"name": "21.2.0-@typescript-eslint-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/eslint",
|
||||
"path": "eslint/migrations/21.2.0-@typescript-eslint-package-updates",
|
||||
"type": "migration"
|
||||
},
|
||||
{
|
||||
"description": "",
|
||||
"file": "generated/packages/eslint/migrations/20.7.0-package-updates.json",
|
||||
@ -2436,6 +2516,16 @@
|
||||
}
|
||||
],
|
||||
"migrations": [
|
||||
{
|
||||
"description": "",
|
||||
"file": "generated/packages/js/migrations/21.2.0-package-updates.json",
|
||||
"hidden": false,
|
||||
"name": "21.2.0-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/js",
|
||||
"path": "js/migrations/21.2.0-package-updates",
|
||||
"type": "migration"
|
||||
},
|
||||
{
|
||||
"description": "",
|
||||
"file": "generated/packages/js/migrations/20.7.1-beta.0-package-updates.json",
|
||||
@ -5686,6 +5776,16 @@
|
||||
}
|
||||
],
|
||||
"migrations": [
|
||||
{
|
||||
"description": "",
|
||||
"file": "generated/packages/workspace/migrations/21.2.0-package-updates.json",
|
||||
"hidden": false,
|
||||
"name": "21.2.0-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"originalFilePath": "/packages/workspace",
|
||||
"path": "workspace/migrations/21.2.0-package-updates",
|
||||
"type": "migration"
|
||||
},
|
||||
{
|
||||
"description": "",
|
||||
"file": "generated/packages/workspace/migrations/20.4.0-package-updates.json",
|
||||
|
||||
@ -54,7 +54,6 @@
|
||||
"description": "The full path for the browser entry point to the application, relative to the current workspace."
|
||||
},
|
||||
"server": {
|
||||
"type": "string",
|
||||
"description": "The full path for the server entry point to the application, relative to the current workspace.",
|
||||
"oneOf": [
|
||||
{
|
||||
@ -80,7 +79,7 @@
|
||||
},
|
||||
"deployUrl": {
|
||||
"type": "string",
|
||||
"description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations. _Note: this is only supported in Angular versions >= 17.3.0_."
|
||||
"description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
|
||||
},
|
||||
"security": {
|
||||
"description": "Security features to protect against XSS and other common attacks. _Note: this is only supported in Angular versions >= 19.0.0_.",
|
||||
@ -226,7 +225,7 @@
|
||||
"clearScreen": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Automatically clear the terminal screen during rebuilds. _Note: this is only supported in Angular versions >= 17.2.0_."
|
||||
"description": "Automatically clear the terminal screen during rebuilds."
|
||||
},
|
||||
"optimization": {
|
||||
"description": "Enables optimization of the build output. Including minification of scripts and styles, tree-shaking, dead-code elimination, inlining of critical CSS and fonts inlining. For more information, see https://angular.dev/reference/configs/workspace-config#optimization-configuration.",
|
||||
@ -259,7 +258,7 @@
|
||||
},
|
||||
"removeSpecialComments": {
|
||||
"type": "boolean",
|
||||
"description": "Remove comments in global CSS that contains '@license' or '@preserve' or that starts with '//!' or '/*!'. _Note: this is only supported in Angular versions >= 17.1.0_.",
|
||||
"description": "Remove comments in global CSS that contains '@license' or '@preserve' or that starts with '//!' or '/*!'.",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
@ -293,17 +292,22 @@
|
||||
]
|
||||
},
|
||||
"loader": {
|
||||
"description": "Defines the type of loader to use with a specified file extension when used with a JavaScript `import`. `text` inlines the content as a string; `binary` inlines the content as a Uint8Array; `file` emits the file and provides the runtime location of the file; `empty` considers the content to be empty and not include it in bundles. _Note: this is only supported in Angular versions >= 17.1.0_.",
|
||||
"description": "Defines the type of loader to use with a specified file extension when used with a JavaScript `import`. `text` inlines the content as a string; `binary` inlines the content as a Uint8Array; `file` emits the file and provides the runtime location of the file; `empty` considers the content to be empty and not include it in bundles.",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^\\.\\S+$": { "enum": ["text", "binary", "file", "empty"] }
|
||||
}
|
||||
},
|
||||
"define": {
|
||||
"description": "Defines global identifiers that will be replaced with a specified constant value when found in any JavaScript or TypeScript code including libraries. The value will be used directly. String values must be put in quotes. Identifiers within Angular metadata such as Component Decorators will not be replaced. _Note: this is only supported in Angular versions >= 17.2.0_.",
|
||||
"description": "Defines global identifiers that will be replaced with a specified constant value when found in any JavaScript or TypeScript code including libraries. The value will be used directly. String values must be put in quotes. Identifiers within Angular metadata such as Component Decorators will not be replaced.",
|
||||
"type": "object",
|
||||
"additionalProperties": { "type": "string" }
|
||||
},
|
||||
"conditions": {
|
||||
"description": "Custom package resolution conditions used to resolve conditional exports/imports. Defaults to ['module', 'development'/'production']. The following special conditions are always present if the requirements are satisfied: 'default', 'import', 'require', 'browser', 'node'. _Note: this is only supported in Angular versions >= 20.0.0_.",
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"fileReplacements": {
|
||||
"description": "Replace compilation source files with other compilation source files in the build.",
|
||||
"type": "array",
|
||||
@ -322,7 +326,7 @@
|
||||
"default": []
|
||||
},
|
||||
"outputPath": {
|
||||
"description": "Specify the output path relative to workspace root. _Note: the object notation is only supported in Angular versions >= 17.1.0_.",
|
||||
"description": "Specify the output path relative to workspace root.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
@ -387,6 +391,11 @@
|
||||
"type": "boolean",
|
||||
"description": "Resolve vendor packages source maps.",
|
||||
"default": false
|
||||
},
|
||||
"sourcesContent": {
|
||||
"type": "boolean",
|
||||
"description": "Output original source content for files within the source map. _Note: this is only supported in Angular versions >= 20.0.0_.",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@ -511,7 +520,7 @@
|
||||
"preloadInitial": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Generates 'preload', 'modulepreload', and 'preconnect' link elements for initial application files and resources. _Note: this is only supported in Angular versions >= 17.1.0_."
|
||||
"description": "Generates 'preload', 'modulepreload', and 'preconnect' link elements for initial application files and resources."
|
||||
}
|
||||
},
|
||||
"required": ["input"]
|
||||
@ -694,12 +703,12 @@
|
||||
}
|
||||
},
|
||||
"indexHtmlTransformer": {
|
||||
"description": "Path to a file exposing a default function to transform the `index.html` file. _Note: this is only supported in Angular versions >= 17.1.0_.",
|
||||
"description": "Path to a file exposing a default function to transform the `index.html` file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["outputPath", "index", "browser", "tsConfig"],
|
||||
"required": ["outputPath", "tsConfig"],
|
||||
"definitions": {
|
||||
"assetPattern": {
|
||||
"oneOf": [
|
||||
|
||||
@ -8,18 +8,12 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema",
|
||||
"title": "Schema for Webpack Dev Server",
|
||||
"description": "Serves an Angular application using [webpack](https://webpack.js.org/) when the build target is using a webpack-based executor, or [Vite](https://vitejs.dev/) when the build target uses an [esbuild](https://esbuild.github.io/)-based executor.",
|
||||
"examplesFile": "This executor is a drop-in replacement for the `@angular-devkit/build-angular:dev-server` builder provided by the Angular CLI. In addition to the features provided by the Angular CLI builder, the `@nx/angular:dev-server` executor also supports the following:\n\n- Serving applications with Vite when using the `@nx/angular:application` or `@nx/angular:browser-esbuild` executors to build them\n- Serving applications with webpack when using the `@nx/angular:webpack-browser` executor\n- Providing HTTP request middleware functions when the build target is using an esbuild-based executor\n- Incremental builds\n\n## Examples\n\n{% tabs %}\n{% tab label=\"Using a custom webpack configuration\" %}\n\nThis executor should be used along with `@nx/angular:webpack-browser` to serve an application using a custom webpack configuration.\n\nAdd the `serve` target using the `@nx/angular:dev-server` executor, set the `build` target executor as `@nx/angular:webpack-browser` and set the `customWebpackConfig` option as shown below:\n\n```json {% fileName=\"apps/my-app/project.json\" highlightLines=[2,\"5-7\",\"10-20\"] %}\n\"build\": {\n \"executor\": \"@nx/angular:webpack-browser\",\n \"options\": {\n ...\n \"customWebpackConfig\": {\n \"path\": \"apps/my-app/webpack.config.js\"\n }\n }\n},\n\"serve\": {\n \"executor\": \"@nx/angular:dev-server\",\n \"configurations\": {\n \"production\": {\n \"buildTarget\": \"my-app:build:production\"\n },\n \"development\": {\n \"buildTarget\": \"my-app:build:development\"\n }\n },\n \"defaultConfiguration\": \"development\",\n}\n```\n\n```js {% fileName=\"apps/my-app/webpack.config.js\" %}\nmodule.exports = (config) => {\n // update the config with your custom configuration\n\n return config;\n};\n```\n\n{% /tab %}\n\n{% tab label=\"Providing HTTP request middleware function\" %}\n\n{% callout type=\"warning\" title=\"Overrides\" }\n\nAvailable for workspaces using Angular version 17.0.0 or greater and with `build` targets using an esbuild-based executor.\n\n{% /callout %}\n\nThe executor accepts an `esbuildMiddleware` option that allows you to provide HTTP require middleware functions that will be used by the Vite development server.\n\n```json {% fileName=\"apps/my-app/project.json\" highlightLines=[8] %}\n{\n ...\n \"targets\": {\n \"serve\": {\n \"executor\": \"@nx/angular:dev-server\",\n \"options\": {\n ...\n \"esbuildMiddleware\": [\"apps/my-app/hello-world.middleware.ts\"]\n }\n }\n ...\n }\n}\n```\n\n```ts {% fileName=\"apps/my-app/hello-world.middleware.ts\" %}\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nconst helloWorldMiddleware = (\n req: IncomingMessage,\n res: ServerResponse,\n next: (err?: unknown) => void\n) => {\n if (req.url === '/hello-world') {\n res.end('<h1>Hello World!</h1>');\n } else {\n next();\n }\n};\n\nexport default helloWorldMiddleware;\n```\n\n{% /tab %}\n",
|
||||
"examplesFile": "This executor is a drop-in replacement for the `@angular-devkit/build-angular:dev-server` builder provided by the Angular CLI. In addition to the features provided by the Angular CLI builder, the `@nx/angular:dev-server` executor also supports the following:\n\n- Serving applications with Vite when using the `@nx/angular:application` or `@nx/angular:browser-esbuild` executors to build them\n- Serving applications with webpack when using the `@nx/angular:webpack-browser` executor\n- Providing HTTP request middleware functions when the build target is using an esbuild-based executor\n- Incremental builds\n\n## Examples\n\n{% tabs %}\n{% tab label=\"Using a custom webpack configuration\" %}\n\nThis executor should be used along with `@nx/angular:webpack-browser` to serve an application using a custom webpack configuration.\n\nAdd the `serve` target using the `@nx/angular:dev-server` executor, set the `build` target executor as `@nx/angular:webpack-browser` and set the `customWebpackConfig` option as shown below:\n\n```json {% fileName=\"apps/my-app/project.json\" highlightLines=[2,\"5-7\",\"10-20\"] %}\n\"build\": {\n \"executor\": \"@nx/angular:webpack-browser\",\n \"options\": {\n ...\n \"customWebpackConfig\": {\n \"path\": \"apps/my-app/webpack.config.js\"\n }\n }\n},\n\"serve\": {\n \"executor\": \"@nx/angular:dev-server\",\n \"configurations\": {\n \"production\": {\n \"buildTarget\": \"my-app:build:production\"\n },\n \"development\": {\n \"buildTarget\": \"my-app:build:development\"\n }\n },\n \"defaultConfiguration\": \"development\",\n}\n```\n\n```js {% fileName=\"apps/my-app/webpack.config.js\" %}\nmodule.exports = (config) => {\n // update the config with your custom configuration\n\n return config;\n};\n```\n\n{% /tab %}\n\n{% tab label=\"Providing HTTP request middleware function\" %}\n\nThe executor accepts an `esbuildMiddleware` option that allows you to provide HTTP require middleware functions that will be used by the Vite development server.\n\n```json {% fileName=\"apps/my-app/project.json\" highlightLines=[8] %}\n{\n ...\n \"targets\": {\n \"serve\": {\n \"executor\": \"@nx/angular:dev-server\",\n \"options\": {\n ...\n \"esbuildMiddleware\": [\"apps/my-app/hello-world.middleware.ts\"]\n }\n }\n ...\n }\n}\n```\n\n```ts {% fileName=\"apps/my-app/hello-world.middleware.ts\" %}\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nconst helloWorldMiddleware = (\n req: IncomingMessage,\n res: ServerResponse,\n next: (err?: unknown) => void\n) => {\n if (req.url === '/hello-world') {\n res.end('<h1>Hello World!</h1>');\n } else {\n next();\n }\n};\n\nexport default helloWorldMiddleware;\n```\n\n{% /tab %}\n",
|
||||
"type": "object",
|
||||
"presets": [
|
||||
{ "name": "Using a Different Port", "keys": ["buildTarget", "port"] }
|
||||
],
|
||||
"properties": {
|
||||
"browserTarget": {
|
||||
"type": "string",
|
||||
"description": "A browser builder target to serve in the format of `project:target[:configuration]`. Ignored if `buildTarget` is set.",
|
||||
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$",
|
||||
"x-deprecated": "Use 'buildTarget' instead. It will be removed when Angular v20 is released."
|
||||
},
|
||||
"buildTarget": {
|
||||
"type": "string",
|
||||
"description": "A build builder target to serve in the format of `project:target[:configuration]`.",
|
||||
@ -122,7 +116,7 @@
|
||||
]
|
||||
},
|
||||
"prebundle": {
|
||||
"description": "Enable and control the Vite-based development server's prebundling capabilities. To enable prebundling, the Angular CLI cache must also be enabled. This option has no effect when using the 'browser' or other Webpack-based builders. _Note: this is only supported in Angular versions >= 17.2.0_.",
|
||||
"description": "Enable and control the Vite-based development server's prebundling capabilities. To enable prebundling, the Angular CLI cache must also be enabled. This option has no effect when using the 'browser' or other Webpack-based builders.",
|
||||
"oneOf": [
|
||||
{ "type": "boolean" },
|
||||
{
|
||||
@ -141,7 +135,7 @@
|
||||
},
|
||||
"buildLibsFromSource": {
|
||||
"type": "boolean",
|
||||
"description": "Read buildable libraries from source instead of building them separately. If not set, it will take the value specified in the `browserTarget` options, or it will default to `true` if it's also not set in the `browserTarget` options.",
|
||||
"description": "Read buildable libraries from source instead of building them separately. If not set, it will take the value specified in the `buildTarget` options, or it will default to `true` if it's also not set in the `buildTarget` options.",
|
||||
"x-priority": "important"
|
||||
},
|
||||
"esbuildMiddleware": {
|
||||
@ -159,10 +153,7 @@
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"anyOf": [
|
||||
{ "required": ["buildTarget"] },
|
||||
{ "required": ["browserTarget"] }
|
||||
]
|
||||
"required": ["buildTarget"]
|
||||
},
|
||||
"description": "Serves an Angular application using [webpack](https://webpack.js.org/) when the build target is using a webpack-based executor, or [Vite](https://vitejs.dev/) when the build target uses an [esbuild](https://esbuild.github.io/)-based executor.",
|
||||
"aliases": [],
|
||||
|
||||
@ -41,6 +41,11 @@
|
||||
"outFile": {
|
||||
"type": "string",
|
||||
"description": "Name of the file to output."
|
||||
},
|
||||
"i18nDuplicateTranslation": {
|
||||
"type": "string",
|
||||
"description": "How to handle duplicate translations. _Note: this is only available in Angular 20.0.0 and above._",
|
||||
"enum": ["error", "warning", "ignore"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@ -12,12 +12,6 @@
|
||||
{ "name": "Using a Different Port", "keys": ["buildTarget", "port"] }
|
||||
],
|
||||
"properties": {
|
||||
"browserTarget": {
|
||||
"type": "string",
|
||||
"description": "A browser builder target to serve in the format of `project:target[:configuration]`.",
|
||||
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$",
|
||||
"x-deprecated": "Use 'buildTarget' instead. It will be removed when Angular v20 is released."
|
||||
},
|
||||
"buildTarget": {
|
||||
"type": "string",
|
||||
"description": "A build builder target to serve in the format of `project:target[:configuration]`.",
|
||||
@ -152,15 +146,12 @@
|
||||
},
|
||||
"buildLibsFromSource": {
|
||||
"type": "boolean",
|
||||
"description": "Read buildable libraries from source instead of building them separately. If not set, it will take the value specified in the `browserTarget` options, or it will default to `true` if it's also not set in the `browserTarget` options.",
|
||||
"description": "Read buildable libraries from source instead of building them separately. If not set, it will take the value specified in the `buildTarget` options, or it will default to `true` if it's also not set in the `buildTarget` options.",
|
||||
"x-priority": "important"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"anyOf": [
|
||||
{ "required": ["buildTarget"] },
|
||||
{ "required": ["browserTarget"] }
|
||||
],
|
||||
"required": ["buildTarget"],
|
||||
"examplesFile": "## Examples\n\n{% tabs %}\n\n{% tab label=\"Basic Usage\" %}\nThe Module Federation Dev Server will serve a host application and find the remote applications associated with the host and serve them statically also. \nSee an example set up of it below:\n\n```json\n{\n \"serve\": {\n \"executor\": \"@nx/angular:module-federation-dev-server\",\n \"configurations\": {\n \"production\": {\n \"buildTarget\": \"host:build:production\"\n },\n \"development\": {\n \"buildTarget\": \"host:build:development\"\n }\n },\n \"defaultConfiguration\": \"development\",\n \"options\": {\n \"port\": 4200,\n \"publicHost\": \"http://localhost:4200\"\n }\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"Serve host with remotes that can be live reloaded\" %}\nThe Module Federation Dev Server will serve a host application and find the remote applications associated with the host and serve a set selection with live reloading enabled also. \nSee an example set up of it below:\n\n```json\n{\n \"serve-with-hmr-remotes\": {\n \"executor\": \"@nx/angular:module-federation-dev-server\",\n \"configurations\": {\n \"production\": {\n \"buildTarget\": \"host:build:production\"\n },\n \"development\": {\n \"buildTarget\": \"host:build:development\"\n }\n },\n \"defaultConfiguration\": \"development\",\n \"options\": {\n \"port\": 4200,\n \"publicHost\": \"http://localhost:4200\",\n \"devRemotes\": [\n \"remote1\",\n {\n \"remoteName\": \"remote2\",\n \"configuration\": \"development\"\n }\n ]\n }\n }\n}\n```\n\n{% /tab %}\n\n{% /tabs %}\n"
|
||||
},
|
||||
"description": "Serves host [Module Federation](https://module-federation.io/) applications ([webpack](https://webpack.js.org/)-based) allowing to specify which remote applications should be served with the host.",
|
||||
|
||||
@ -34,11 +34,10 @@
|
||||
},
|
||||
"poll": {
|
||||
"type": "number",
|
||||
"description": "Enable and define the file watching poll time period in milliseconds. _Note: this is only supported in Angular versions >= 18.0.0_."
|
||||
"description": "Enable and define the file watching poll time period in milliseconds."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["project"]
|
||||
"additionalProperties": false
|
||||
},
|
||||
"description": "Builds an Angular library with support for incremental builds.\n\nThis executor is meant to be used with buildable libraries in an incremental build scenario. It is similar to the `@nx/angular:package` executor but it only produces ESM2022 bundles.",
|
||||
"aliases": [],
|
||||
|
||||
@ -36,13 +36,10 @@
|
||||
},
|
||||
"poll": {
|
||||
"type": "number",
|
||||
"description": "Enable and define the file watching poll time period in milliseconds. _Note: this is only supported in Angular versions >= 18.0.0_."
|
||||
"description": "Enable and define the file watching poll time period in milliseconds."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"project"
|
||||
]
|
||||
"additionalProperties": false
|
||||
},
|
||||
"description": "Builds and packages an Angular library producing an output following the Angular Package Format (APF) to be distributed as an NPM package.\n\nThis executor is a drop-in replacement for the `@angular-devkit/build-angular:ng-packagr` and `@angular/build:ng-packagr` builders, with additional support for incremental builds.",
|
||||
"aliases": [],
|
||||
|
||||
@ -174,7 +174,7 @@
|
||||
"default": false
|
||||
},
|
||||
"serverRouting": {
|
||||
"description": "Creates a server application using the Server Routing and App Engine APIs (Developer Preview). _Note: this is only supported in Angular versions >= 19.0.0_.",
|
||||
"description": "Creates a server application using the Server Routing and App Engine APIs for application using the `application` builder (Developer Preview). _Note: this is only supported in Angular versions 19.x.x_. From Angular 20 onwards, SSR will always enable server routing when using the `application` builder.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
|
||||
@ -95,8 +95,7 @@
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Adds a developer-defined type to the filename, in the format `name.type.ts`.",
|
||||
"default": "component"
|
||||
"description": "Append a custom type to the component's filename. It defaults to 'component' for Angular versions below v20. For Angular v20 and above, no type is appended unless specified."
|
||||
},
|
||||
"export": {
|
||||
"type": "boolean",
|
||||
@ -109,6 +108,11 @@
|
||||
"default": false,
|
||||
"description": "Use default export for the component instead of a named export."
|
||||
},
|
||||
"ngHtml": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Generate component template files with an '.ng.html' file extension instead of '.html'."
|
||||
},
|
||||
"skipFormat": {
|
||||
"description": "Skip formatting files.",
|
||||
"type": "boolean",
|
||||
@ -117,7 +121,7 @@
|
||||
}
|
||||
},
|
||||
"required": ["path"],
|
||||
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Simple Component\" %}\n\nGenerate a component named `MyComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component.ts\n```\n\n{% /tab %}\n\n{% tab label=\"Without Providing the File Extension\" %}\n\nGenerate a component named `MyComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component\n```\n\n{% /tab %}\n\n{% tab label=\"With Different Symbol Name\" %}\n\nGenerate a component named `CustomComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --name=custom\n```\n\n{% /tab %}\n\n{% tab label=\"Single File Component\" %}\n\nCreate a component named `my-component` with inline styles and inline template:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --inlineStyle --inlineTemplate\n```\n\n{% /tab %}\n\n{% tab label=\"Component with OnPush Change Detection Strategy\" %}\n\nCreate a component named `my-component` with OnPush Change Detection Strategy:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --changeDetection=OnPush\n```\n\n{% /tab %}\n",
|
||||
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Simple Component\" %}\n\nGenerate a component named `Card` at `apps/my-app/src/lib/card/card.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/card/card.ts\n```\n\n{% /tab %}\n\n{% tab label=\"Without Providing the File Extension\" %}\n\nGenerate a component named `Card` at `apps/my-app/src/lib/card/card.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/card/card\n```\n\n{% /tab %}\n\n{% tab label=\"With Different Symbol Name\" %}\n\nGenerate a component named `Custom` at `apps/my-app/src/lib/card/card.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/card/card --name=custom\n```\n\n{% /tab %}\n\n{% tab label=\"With a Component Type\" %}\n\nGenerate a component named `CardComponent` at `apps/my-app/src/lib/card/card.component.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/card/card --type=component\n```\n\n{% /tab %}\n\n{% tab label=\"Single File Component\" %}\n\nCreate a component named `Card` with inline styles and inline template:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/card/card --inlineStyle --inlineTemplate\n```\n\n{% /tab %}\n\n{% tab label=\"Component with OnPush Change Detection Strategy\" %}\n\nCreate a component named `Card` with `OnPush` Change Detection Strategy:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/card/card --changeDetection=OnPush\n```\n\n{% /tab %}\n",
|
||||
"presets": []
|
||||
},
|
||||
"aliases": ["c"],
|
||||
|
||||
@ -15,11 +15,15 @@
|
||||
"command": "nx g @nx/angular:directive mylib/src/lib/foo.directive.ts"
|
||||
},
|
||||
{
|
||||
"description": "Generate a directive without providing the file extension. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||
"description": "Generate a directive without providing the file extension. It results in the directive `Foo` at `mylib/src/lib/foo.ts`",
|
||||
"command": "nx g @nx/angular:directive mylib/src/lib/foo"
|
||||
},
|
||||
{
|
||||
"description": "Generate a directive with the exported symbol different from the file name. It results in the directive `CustomDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||
"description": "Generate a directive with a given type/suffix. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||
"command": "nx g @nx/angular:directive mylib/src/lib/foo --type=directive"
|
||||
},
|
||||
{
|
||||
"description": "Generate a directive with the exported symbol different from the file name. It results in the directive `Custom` at `mylib/src/lib/foo.ts`",
|
||||
"command": "nx g @nx/angular:directive mylib/src/lib/foo --name=custom"
|
||||
}
|
||||
],
|
||||
@ -73,6 +77,10 @@
|
||||
"default": false,
|
||||
"description": "The declaring NgModule exports this directive."
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Append a custom type to the directive's filename. It defaults to 'directive' for Angular versions below v20. For Angular v20 and above, no type is appended unless specified."
|
||||
},
|
||||
"skipFormat": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
|
||||
@ -175,7 +175,7 @@
|
||||
"x-priority": "important"
|
||||
},
|
||||
"serverRouting": {
|
||||
"description": "Creates a server application using the Server Routing and App Engine APIs (Developer Preview). _Note: this is only supported in Angular versions >= 19.0.0_.",
|
||||
"description": "Creates a server application using the Server Routing and App Engine APIs for application using the `application` builder (Developer Preview). _Note: this is only supported in Angular versions 19.x.x_. From Angular 20 onwards, SSR will always enable server routing when using the `application` builder.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"typescriptConfiguration": {
|
||||
|
||||
@ -11,11 +11,11 @@
|
||||
"type": "object",
|
||||
"examples": [
|
||||
{
|
||||
"command": "nx g @nx/angular:ngrx --root --parent=apps/my-app/src/app/app.module.ts --facade=false placeholder",
|
||||
"command": "nx g @nx/angular:ngrx --root --parent=apps/my-app/src/app/app-module.ts --facade=false placeholder",
|
||||
"description": "Add root ngrx configration to the `my-app` application"
|
||||
},
|
||||
{
|
||||
"command": "nx g @nx/angular:ngrx --parent=libs/my-lib/src/lib/my-lib.module.ts --facade=true --root=false users",
|
||||
"command": "nx g @nx/angular:ngrx --parent=libs/my-lib/src/lib/my-lib-module.ts --facade=true --root=false users",
|
||||
"description": "Add a `users` state with a facade to the `my-lib` library. It will be tracked under the default `+state` folder in the lib"
|
||||
},
|
||||
{
|
||||
@ -42,7 +42,7 @@
|
||||
},
|
||||
"parent": {
|
||||
"type": "string",
|
||||
"description": "The path to the file where the state will be registered. For NgModule usage, this will be your `app.module.ts` for your root state, or your Feature Module for feature state. For Standalone API usage, this will be your `app.config.ts` file for your root state, or the Routes definition file for your feature state. The host directory will create/use the new state directory.",
|
||||
"description": "The path to the file where the state will be registered. For NgModule usage, this will be your `app-module.ts` for your root state, or your Feature Module for feature state. For Standalone API usage, this will be your `app.config.ts` file for your root state, or the Routes definition file for your feature state. The host directory will create/use the new state directory.",
|
||||
"x-prompt": "What is the path to the module or Routes definition where this NgRx state should be registered?",
|
||||
"x-priority": "important"
|
||||
},
|
||||
|
||||
@ -15,11 +15,15 @@
|
||||
"command": "nx g @nx/angular:pipe mylib/src/lib/foo.pipe.ts"
|
||||
},
|
||||
{
|
||||
"description": "Generate a pipe without providing the file extension. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
||||
"description": "Generate a pipe without providing the file extension. It results in the pipe `FooPipe` at `mylib/src/lib/foo-pipe.ts`",
|
||||
"command": "nx g @nx/angular:pipe mylib/src/lib/foo"
|
||||
},
|
||||
{
|
||||
"description": "Generate a pipe with the exported symbol different from the file name. It results in the pipe `CustomPipe` at `mylib/src/lib/foo.pipe.ts`",
|
||||
"description": "Generate a pipe with a different type separator. It results in the pipe `FooPipe` at `mylib/src/lib/foo.pipe.ts`",
|
||||
"command": "nx g @nx/angular:pipe mylib/src/lib/foo --typeSeparator=."
|
||||
},
|
||||
{
|
||||
"description": "Generate a pipe with the exported symbol different from the file name. It results in the pipe `CustomPipe` at `mylib/src/lib/foo-pipe.ts`",
|
||||
"command": "nx g @nx/angular:pipe mylib/src/lib/foo --name=custom"
|
||||
}
|
||||
],
|
||||
@ -59,6 +63,11 @@
|
||||
"default": false,
|
||||
"description": "The declaring NgModule exports this pipe."
|
||||
},
|
||||
"typeSeparator": {
|
||||
"type": "string",
|
||||
"enum": ["-", "."],
|
||||
"description": "The separator character to use before the type within the generated file's name. For example, if you set the option to `.`, the file will be named `example.pipe.ts`. It defaults to '-' for Angular v20+. For versions below v20, it defaults to '.'."
|
||||
},
|
||||
"skipFormat": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
|
||||
@ -168,7 +168,7 @@
|
||||
"default": false
|
||||
},
|
||||
"serverRouting": {
|
||||
"description": "Creates a server application using the Server Routing and App Engine APIs (Developer Preview). _Note: this is only supported in Angular versions >= 19.0.0_.",
|
||||
"description": "Creates a server application using the Server Routing and App Engine APIs for application using the `application` builder (Developer Preview). _Note: this is only supported in Angular versions 19.x.x_. From Angular 20 onwards, SSR will always enable server routing when using the `application` builder.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"typescriptConfiguration": {
|
||||
|
||||
@ -13,11 +13,15 @@
|
||||
"command": "nx g @nx/angular:scam-directive mylib/src/lib/foo.directive.ts"
|
||||
},
|
||||
{
|
||||
"description": "Generate a directive without providing the file extension. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||
"description": "Generate a directive without providing the file extension. It results in the directive `Foo` at `mylib/src/lib/foo.ts`",
|
||||
"command": "nx g @nx/angular:scam-directive mylib/src/lib/foo"
|
||||
},
|
||||
{
|
||||
"description": "Generate a directive with the exported symbol different from the file name. It results in the directive `CustomDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||
"description": "Generate a directive with a given type/suffix. It results in the directive `FooDirective` at `mylib/src/lib/foo.directive.ts`",
|
||||
"command": "nx g @nx/angular:scam-directive mylib/src/lib/foo --type=directive"
|
||||
},
|
||||
{
|
||||
"description": "Generate a directive with the exported symbol different from the file name. It results in the directive `Custom` at `mylib/src/lib/foo.ts`",
|
||||
"command": "nx g @nx/angular:scam-directive mylib/src/lib/foo --name=custom"
|
||||
}
|
||||
],
|
||||
@ -65,6 +69,10 @@
|
||||
"default": true,
|
||||
"x-priority": "important"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Append a custom type to the directive's filename. It defaults to 'directive' for Angular versions below v20. For Angular v20 and above, no type is appended unless specified."
|
||||
},
|
||||
"skipFormat": {
|
||||
"description": "Skip formatting files.",
|
||||
"type": "boolean",
|
||||
|
||||
@ -51,6 +51,11 @@
|
||||
"default": true,
|
||||
"x-priority": "important"
|
||||
},
|
||||
"typeSeparator": {
|
||||
"type": "string",
|
||||
"enum": ["-", "."],
|
||||
"description": "The separator character to use before the type within the generated file's name. For example, if you set the option to `.`, the file will be named `example.pipe.ts`. It defaults to '-' for Angular v20+. For versions below v20, it defaults to '.'."
|
||||
},
|
||||
"skipFormat": {
|
||||
"description": "Skip formatting files.",
|
||||
"type": "boolean",
|
||||
|
||||
@ -94,8 +94,7 @@
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Adds a developer-defined type to the filename, in the format `name.type.ts`.",
|
||||
"default": "component"
|
||||
"description": "Append a custom type to the component's filename. It defaults to 'component' for Angular versions below v20. For Angular v20 and above, no type is appended unless specified."
|
||||
},
|
||||
"prefix": {
|
||||
"type": "string",
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
"default": true
|
||||
},
|
||||
"serverRouting": {
|
||||
"description": "Creates a server application using the Server Routing and App Engine APIs (Developer Preview). _Note: this is only supported in Angular versions >= 19.0.0_.",
|
||||
"description": "Creates a server application using the Server Routing and App Engine APIs for application using the `application` builder (Developer Preview). _Note: this is only supported in Angular versions 19.x.x_. From Angular 20 onwards, SSR will always enable server routing when using the `application` builder.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"skipFormat": {
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
{
|
||||
"name": "21.2.0-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"x-prompt": "Do you want to update the Angular version to v20?",
|
||||
"requires": { "@angular/core": ">=19.2.0 <20.0.0-rc.2" },
|
||||
"packages": {
|
||||
"@angular-devkit/build-angular": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-devkit/core": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-devkit/schematics": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/build": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/pwa": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/ssr": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@schematics/angular": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-devkit/architect": {
|
||||
"version": "0.2000.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-devkit/build-webpack": {
|
||||
"version": "0.2000.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/core": {
|
||||
"version": "20.0.0-rc.2",
|
||||
"alwaysAddToPackageJson": true
|
||||
},
|
||||
"@angular/material": {
|
||||
"version": "20.0.0-rc.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/cdk": {
|
||||
"version": "20.0.0-rc.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/google-maps": {
|
||||
"version": "20.0.0-rc.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"ng-packagr": { "version": "20.0.0-rc.1", "alwaysAddToPackageJson": false }
|
||||
},
|
||||
"aliases": [],
|
||||
"description": "",
|
||||
"hidden": false,
|
||||
"implementation": "",
|
||||
"path": "/packages/angular",
|
||||
"schema": null,
|
||||
"type": "migration"
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "migrate-provide-server-rendering-import",
|
||||
"version": "21.2.0-beta.0",
|
||||
"requires": { "@angular/core": ">=20.0.0-rc.2" },
|
||||
"description": "Migrate imports of `provideServerRendering` from `@angular/platform-server` to `@angular/ssr`.",
|
||||
"factory": "./src/migrations/update-21-2-0/migrate-provide-server-rendering-import",
|
||||
"implementation": "/packages/angular/src/migrations/update-21-2-0/migrate-provide-server-rendering-import.ts",
|
||||
"aliases": [],
|
||||
"hidden": false,
|
||||
"path": "/packages/angular",
|
||||
"schema": null,
|
||||
"type": "migration",
|
||||
"examplesFile": "#### Migrate Imports of `provideServerRendering` from `@angular/platform-server` to `@angular/ssr`\n\nMigrate the imports of `provideServerRendering` from `@angular/platform-server` to `@angular/ssr`. This migration will also add the `@angular/ssr` package to your dependencies if needed.\n\n#### Examples\n\nChange the import of `provideServerRendering` from `@angular/platform-server` to `@angular/ssr`:\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```ts {% fileName=\"app/app.config.server.ts\" highlightLines=[2] %}\nimport { ApplicationConfig } from '@angular/core';\nimport { provideServerRendering } from '@angular/platform-server';\n\nconst serverConfig: ApplicationConfig = {\n providers: [provideServerRendering()],\n};\n```\n\n{% /tab %}\n\n{% tab label=\"After\" %}\n\n```ts {% fileName=\"app/app.config.server.ts\" highlightLines=[2] %}\nimport { ApplicationConfig } from '@angular/core';\nimport { provideServerRendering } from '@angular/ssr';\n\nconst serverConfig: ApplicationConfig = {\n providers: [provideServerRendering()],\n};\n```\n\n{% /tab %}\n{% /tabs %}\n\nIf you already have imports from `@angular/ssr`, the migration will add `provideServerRendering` to the existing import:\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```ts {% fileName=\"app/app.config.server.ts\" highlightLines=[2,3] %}\nimport { ApplicationConfig } from '@angular/core';\nimport { provideServerRendering } from '@angular/platform-server';\nimport { provideServerRouting } from '@angular/ssr';\nimport { serverRoutes } from './app.routes.server';\n\nconst serverConfig: ApplicationConfig = {\n providers: [provideServerRendering(), provideServerRouting(serverRoutes)],\n};\n```\n\n{% /tab %}\n\n{% tab label=\"After\" %}\n\n```ts {% fileName=\"app/app.config.server.ts\" highlightLines=[2] %}\nimport { ApplicationConfig } from '@angular/core';\nimport { provideServerRouting, provideServerRendering } from '@angular/ssr';\nimport { serverRoutes } from './app.routes.server';\n\nconst serverConfig: ApplicationConfig = {\n providers: [provideServerRendering(), provideServerRouting(serverRoutes)],\n};\n```\n\n{% /tab %}\n{% /tabs %}\n"
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "replace-provide-server-routing",
|
||||
"version": "21.2.0-beta.0",
|
||||
"requires": { "@angular/core": ">=20.0.0-rc.2" },
|
||||
"description": "Replace `provideServerRouting` with `provideServerRendering` using `withRoutes`.",
|
||||
"factory": "./src/migrations/update-21-2-0/replace-provide-server-routing",
|
||||
"implementation": "/packages/angular/src/migrations/update-21-2-0/replace-provide-server-routing.ts",
|
||||
"aliases": [],
|
||||
"hidden": false,
|
||||
"path": "/packages/angular",
|
||||
"schema": null,
|
||||
"type": "migration",
|
||||
"examplesFile": "#### Replace `provideServerRouting` with `provideServerRendering`\n\nReplace `provideServerRouting` calls with `provideServerRendering` using `withRoutes`.\n\n#### Examples\n\nRemove `provideServerRouting` from your providers array and update the `provideServerRendering` call to use `withRoutes`:\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```ts {% fileName=\"app/app.config.server.ts\" highlightLines=[2,6] %}\nimport { ApplicationConfig } from '@angular/core';\nimport { provideServerRendering, provideServerRouting } from '@angular/ssr';\nimport { serverRoutes } from './app.routes.server';\n\nconst serverConfig: ApplicationConfig = {\n providers: [provideServerRendering(), provideServerRouting(serverRoutes)],\n};\n```\n\n{% /tab %}\n\n{% tab label=\"After\" %}\n\n```ts {% fileName=\"app/app.config.server.ts\" highlightLines=[2,6] %}\nimport { ApplicationConfig } from '@angular/core';\nimport { provideServerRendering, withRoutes } from '@angular/ssr';\nimport { serverRoutes } from './app.routes.server';\n\nconst serverConfig: ApplicationConfig = {\n providers: [provideServerRendering(withRoutes(serverRoutes))],\n};\n```\n\n{% /tab %}\n{% /tabs %}\n\nIf you have `provideServerRouting` with additional arguments, the migration will preserve them:\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```ts {% fileName=\"app/app.config.server.ts\" highlightLines=[4,11,12] %}\nimport { ApplicationConfig } from '@angular/core';\nimport {\n provideServerRendering,\n provideServerRouting,\n withAppShell,\n} from '@angular/ssr';\nimport { serverRoutes } from './app.routes.server';\n\nconst serverConfig: ApplicationConfig = {\n providers: [\n provideServerRendering(),\n provideServerRouting(serverRoutes, withAppShell(AppShellComponent)),\n ],\n};\n```\n\n{% /tab %}\n\n{% tab label=\"After\" %}\n\n```ts {% fileName=\"app/app.config.server.ts\" highlightLines=[2,\"7-10\"] %}\nimport { ApplicationConfig } from '@angular/core';\nimport { provideServerRendering, withAppShell, withRoutes } from '@angular/ssr';\nimport { serverRoutes } from './app.routes.server';\n\nconst serverConfig: ApplicationConfig = {\n providers: [\n provideServerRendering(\n withRoutes(serverRoutes),\n withAppShell(AppShellComponent)\n ),\n ],\n};\n```\n\n{% /tab %}\n{% /tabs %}\n"
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "set-generator-defaults-for-previous-style-guide",
|
||||
"version": "21.2.0-beta.0",
|
||||
"requires": { "@angular/core": ">=20.0.0-rc.2" },
|
||||
"description": "Update the generator defaults to maintain the previous style guide behavior.",
|
||||
"factory": "./src/migrations/update-21-2-0/set-generator-defaults-for-previous-style-guide",
|
||||
"implementation": "/packages/angular/src/migrations/update-21-2-0/set-generator-defaults-for-previous-style-guide.ts",
|
||||
"aliases": [],
|
||||
"hidden": false,
|
||||
"path": "/packages/angular",
|
||||
"schema": null,
|
||||
"type": "migration",
|
||||
"examplesFile": "#### Set Generator Defaults for Previous Style Guide\n\nUpdates the generator defaults in the `nx.json` file to maintain the previous Angular Style Guide behavior. This ensures that newly generated code in existing workspaces follows the same conventions as the existing codebase.\n\n#### Examples\n\nThe migration will add default configurations for the relevant Angular generators in the workspace's `nx.json` file:\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"nx.json\" %}\n{\n \"generators\": {}\n}\n```\n\n{% /tab %}\n\n{% tab label=\"After\" %}\n\n```json {% fileName=\"nx.json\" %}\n{\n \"generators\": {\n \"@nx/angular:component\": {\n \"type\": \"component\"\n },\n \"@nx/angular:directive\": {\n \"type\": \"directive\"\n },\n \"@nx/angular:service\": {\n \"type\": \"service\"\n },\n \"@nx/angular:scam\": {\n \"type\": \"component\"\n },\n \"@nx/angular:scam-directive\": {\n \"type\": \"directive\"\n },\n \"@nx/angular:guard\": {\n \"typeSeparator\": \".\"\n },\n \"@nx/angular:interceptor\": {\n \"typeSeparator\": \".\"\n },\n \"@nx/angular:module\": {\n \"typeSeparator\": \".\"\n },\n \"@nx/angular:pipe\": {\n \"typeSeparator\": \".\"\n },\n \"@nx/angular:resolver\": {\n \"typeSeparator\": \".\"\n },\n \"@schematics/angular:component\": {\n \"type\": \"component\"\n },\n \"@schematics/angular:directive\": {\n \"type\": \"directive\"\n },\n \"@schematics/angular:service\": {\n \"type\": \"service\"\n },\n \"@schematics/angular:guard\": {\n \"typeSeparator\": \".\"\n },\n \"@schematics/angular:interceptor\": {\n \"typeSeparator\": \".\"\n },\n \"@schematics/angular:module\": {\n \"typeSeparator\": \".\"\n },\n \"@schematics/angular:pipe\": {\n \"typeSeparator\": \".\"\n },\n \"@schematics/angular:resolver\": {\n \"typeSeparator\": \".\"\n }\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n\nIf some of the generator defaults are already set, the migration will not override them:\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"nx.json\" highlightLines=[\"3-14\"] %}\n{\n \"generators\": {\n \"@nx/angular:component\": {\n \"type\": \"cmp\"\n },\n \"@schematics/angular:component\": {\n \"type\": \"cmp\"\n },\n \"@nx/angular:interceptor\": {\n \"typeSeparator\": \"-\"\n },\n \"@schematics/angular:interceptor\": {\n \"typeSeparator\": \"-\"\n }\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"After\" %}\n\n```json {% fileName=\"nx.json\" highlightLines=[\"3-14\"] %}\n{\n \"generators\": {\n \"@nx/angular:component\": {\n \"type\": \"cmp\"\n },\n \"@schematics/angular:component\": {\n \"type\": \"cmp\"\n },\n \"@nx/angular:interceptor\": {\n \"typeSeparator\": \"-\"\n },\n \"@schematics/angular:interceptor\": {\n \"typeSeparator\": \"-\"\n },\n \"@nx/angular:directive\": {\n \"type\": \"directive\"\n },\n \"@nx/angular:service\": {\n \"type\": \"service\"\n },\n \"@nx/angular:scam\": {\n \"type\": \"component\"\n },\n \"@nx/angular:scam-directive\": {\n \"type\": \"directive\"\n },\n \"@nx/angular:guard\": {\n \"typeSeparator\": \".\"\n },\n \"@nx/angular:module\": {\n \"typeSeparator\": \".\"\n },\n \"@nx/angular:pipe\": {\n \"typeSeparator\": \".\"\n },\n \"@nx/angular:resolver\": {\n \"typeSeparator\": \".\"\n },\n \"@schematics/angular:directive\": {\n \"type\": \"directive\"\n },\n \"@schematics/angular:service\": {\n \"type\": \"service\"\n },\n \"@schematics/angular:guard\": {\n \"typeSeparator\": \".\"\n },\n \"@schematics/angular:module\": {\n \"typeSeparator\": \".\"\n },\n \"@schematics/angular:pipe\": {\n \"typeSeparator\": \".\"\n },\n \"@schematics/angular:resolver\": {\n \"typeSeparator\": \".\"\n }\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n"
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "update-angular-cli-version-20-0-0-rc-3",
|
||||
"cli": "nx",
|
||||
"version": "21.2.0-beta.0",
|
||||
"requires": { "@angular/core": ">=20.0.0-rc.2" },
|
||||
"description": "Update the @angular/cli package version to 20.0.0-rc.3.",
|
||||
"factory": "./src/migrations/update-21-2-0/update-angular-cli",
|
||||
"implementation": "/packages/angular/src/migrations/update-21-2-0/update-angular-cli.ts",
|
||||
"aliases": [],
|
||||
"hidden": false,
|
||||
"path": "/packages/angular",
|
||||
"schema": null,
|
||||
"type": "migration",
|
||||
"examplesFile": "#### Sample Code Changes\n\nUpdate the `@angular/cli` package version in the `package.json` file at the workspace root to **~20.0.0**.\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"package.json\" %}\n{\n \"devDependencies\": {\n \"@angular/cli\": \"~19.2.0\"\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"After\" %}\n\n```json {% highlightLines=[3] fileName=\"package.json\" %}\n{\n \"devDependencies\": {\n \"@angular/cli\": \"~20.0.0\"\n }\n}\n```\n\n{% /tab %}\n\n{% /tabs %}\n"
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "update-module-resolution",
|
||||
"version": "21.2.0-beta.0",
|
||||
"requires": { "@angular/core": ">=20.0.0-rc.2" },
|
||||
"description": "Update 'moduleResolution' to 'bundler' in TypeScript configurations. You can read more about this here: https://www.typescriptlang.org/tsconfig/#moduleResolution.",
|
||||
"factory": "./src/migrations/update-21-2-0/update-module-resolution",
|
||||
"implementation": "/packages/angular/src/migrations/update-21-2-0/update-module-resolution.ts",
|
||||
"aliases": [],
|
||||
"hidden": false,
|
||||
"path": "/packages/angular",
|
||||
"schema": null,
|
||||
"type": "migration",
|
||||
"examplesFile": "#### Update `moduleResolution` to `bundler` in TypeScript configurations\n\nUpdates the TypeScript `moduleResolution` option to `'bundler'` for improved compatibility with modern package resolution algorithms used by bundlers like Webpack, Vite, and esbuild.\n\n#### Examples\n\nThe migration will update TypeScript configuration files in your workspace to use the `'bundler'` module resolution strategy:\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"apps/app1/tsconfig.app.json\" highlightLines=[\"4\"] %}\n{\n \"compilerOptions\": {\n \"module\": \"es2020\",\n \"moduleResolution\": \"node\"\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"After\" %}\n\n```json {% fileName=\"apps/app1/tsconfig.app.json\" highlightLines=[\"4\"] %}\n{\n \"compilerOptions\": {\n \"module\": \"es2020\",\n \"moduleResolution\": \"bundler\"\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n\nIf the `moduleResolution` is already set to `'bundler'` or the `module` is set to `'preserve'`, the migration will not modify the configuration:\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"apps/app1/tsconfig.app.json\" highlightLines=[3,4] %}\n{\n \"compilerOptions\": {\n \"module\": \"preserve\",\n \"moduleResolution\": \"node\"\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"After\" %}\n\n```json {% fileName=\"apps/app1/tsconfig.app.json\" highlightLines=[3,4] %}\n{\n \"compilerOptions\": {\n \"module\": \"preserve\",\n \"moduleResolution\": \"node\"\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n"
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "21.2.0-@typescript-eslint-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"requires": { "@typescript-eslint/eslint-plugin": ">8.0.0 <8.29.0" },
|
||||
"packages": {
|
||||
"typescript-eslint": { "version": "^8.29.0" },
|
||||
"@typescript-eslint/eslint-plugin": { "version": "^8.29.0" },
|
||||
"@typescript-eslint/parser": { "version": "^8.29.0" },
|
||||
"@typescript-eslint/utils": { "version": "^8.29.0" },
|
||||
"@typescript-eslint/rule-tester": {
|
||||
"version": "^8.29.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "^8.29.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "^8.29.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
}
|
||||
},
|
||||
"aliases": [],
|
||||
"description": "",
|
||||
"hidden": false,
|
||||
"implementation": "",
|
||||
"path": "/packages/eslint",
|
||||
"schema": null,
|
||||
"type": "migration"
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "21.2.0-typescript-eslint-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"requires": { "typescript-eslint": ">8.0.0 <8.29.0" },
|
||||
"packages": {
|
||||
"typescript-eslint": { "version": "^8.29.0" },
|
||||
"@typescript-eslint/eslint-plugin": { "version": "^8.29.0" },
|
||||
"@typescript-eslint/parser": { "version": "^8.29.0" },
|
||||
"@typescript-eslint/utils": { "version": "^8.29.0" },
|
||||
"@typescript-eslint/rule-tester": {
|
||||
"version": "^8.29.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "^8.29.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "^8.29.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
}
|
||||
},
|
||||
"aliases": [],
|
||||
"description": "",
|
||||
"hidden": false,
|
||||
"implementation": "",
|
||||
"path": "/packages/eslint",
|
||||
"schema": null,
|
||||
"type": "migration"
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "21.2.0-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"x-prompt": "Do you want to update to TypeScript v5.8?",
|
||||
"requires": { "typescript": ">=5.7.0 <5.8.0" },
|
||||
"packages": {
|
||||
"typescript": { "version": "~5.8.2", "alwaysAddToPackageJson": false }
|
||||
},
|
||||
"aliases": [],
|
||||
"description": "",
|
||||
"hidden": false,
|
||||
"implementation": "",
|
||||
"path": "/packages/js",
|
||||
"schema": null,
|
||||
"type": "migration"
|
||||
}
|
||||
@ -90,10 +90,6 @@
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"serverRouting": {
|
||||
"description": "Use the Angular Server Routing and App Engine APIs (Developer Preview).",
|
||||
"type": "boolean"
|
||||
},
|
||||
"prefix": {
|
||||
"description": "The prefix to use for Angular component and directive selectors.",
|
||||
"type": "string"
|
||||
|
||||
@ -107,10 +107,6 @@
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"serverRouting": {
|
||||
"description": "Use the Angular Server Routing and App Engine APIs (Developer Preview).",
|
||||
"type": "boolean"
|
||||
},
|
||||
"prefix": {
|
||||
"description": "The prefix to use for Angular component and directive selectors.",
|
||||
"type": "string"
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "21.2.0-package-updates",
|
||||
"version": "21.2.0-beta.0",
|
||||
"x-prompt": "Do you want to update to TypeScript v5.8?",
|
||||
"requires": { "typescript": ">=5.7.0 <5.8.0" },
|
||||
"packages": {
|
||||
"typescript": { "version": "~5.8.2", "alwaysAddToPackageJson": false }
|
||||
},
|
||||
"aliases": [],
|
||||
"description": "",
|
||||
"hidden": false,
|
||||
"implementation": "",
|
||||
"path": "/packages/workspace",
|
||||
"schema": null,
|
||||
"type": "migration"
|
||||
}
|
||||
@ -13,7 +13,9 @@ describe('angular.json v1 config', () => {
|
||||
|
||||
beforeAll(() => {
|
||||
newProject({ packages: ['@nx/angular'] });
|
||||
runCLI(`generate @nx/angular:app ${app1} --no-interactive`);
|
||||
runCLI(
|
||||
`generate @nx/angular:app ${app1} --bundler=webpack --no-interactive`
|
||||
);
|
||||
// reset workspace to use v1 config
|
||||
updateFile(`angular.json`, angularV1Json(app1));
|
||||
removeFile(`${app1}/project.json`);
|
||||
|
||||
@ -88,7 +88,7 @@ describe('Angular Cypress Component Tests', () => {
|
||||
}
|
||||
);
|
||||
updateFile(
|
||||
`${buildableLibName}/src/lib/input-standalone/input-standalone.component.cy.ts`,
|
||||
`${buildableLibName}/src/lib/input-standalone/input-standalone.cy.ts`,
|
||||
(content) => {
|
||||
// text-green-500 should now apply
|
||||
return content.replace('rgb(0, 0, 0)', 'rgb(34, 197, 94)');
|
||||
@ -149,7 +149,7 @@ function createLib(projectName: string, appName: string, libName: string) {
|
||||
`generate @nx/angular:component ${libName}/src/lib/btn-standalone/btn-standalone --inlineTemplate --inlineStyle --export --standalone --no-interactive`
|
||||
);
|
||||
updateFile(
|
||||
`${libName}/src/lib/btn/btn.component.ts`,
|
||||
`${libName}/src/lib/btn/btn.ts`,
|
||||
`
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
@ -158,13 +158,13 @@ import { Component, Input } from '@angular/core';
|
||||
template: '<button class="text-green-500">{{text}}</button>',
|
||||
styles: []
|
||||
})
|
||||
export class BtnComponent {
|
||||
export class Btn {
|
||||
@Input() text = 'something';
|
||||
}
|
||||
`
|
||||
);
|
||||
updateFile(
|
||||
`${libName}/src/lib/btn-standalone/btn-standalone.component.ts`,
|
||||
`${libName}/src/lib/btn-standalone/btn-standalone.ts`,
|
||||
`
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
@ -175,7 +175,7 @@ import { CommonModule } from '@angular/common';
|
||||
template: '<button class="text-green-500">standlone-{{text}}</button>',
|
||||
styles: [],
|
||||
})
|
||||
export class BtnStandaloneComponent {
|
||||
export class BtnStandalone {
|
||||
@Input() text = 'something';
|
||||
}
|
||||
`
|
||||
@ -187,7 +187,7 @@ function createBuildableLib(projectName: string, libName: string) {
|
||||
runCLI(`generate @nx/angular:lib ${libName} --buildable --no-interactive`);
|
||||
// create cmp for lib
|
||||
runCLI(
|
||||
`generate @nx/angular:component ${libName}/src/lib/input/input --inlineTemplate --inlineStyle --export --no-interactive`
|
||||
`generate @nx/angular:component ${libName}/src/lib/input/input.component --inlineTemplate --inlineStyle --export --no-interactive`
|
||||
);
|
||||
// create standlone cmp for lib
|
||||
runCLI(
|
||||
@ -210,7 +210,7 @@ import {Component, Input} from '@angular/core';
|
||||
`
|
||||
);
|
||||
updateFile(
|
||||
`${libName}/src/lib/input-standalone/input-standalone.component.ts`,
|
||||
`${libName}/src/lib/input-standalone/input-standalone.ts`,
|
||||
`
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
@ -221,7 +221,7 @@ import {CommonModule} from '@angular/common';
|
||||
template: \`<label class="text-green-500">Email: <input class="border-blue-500" type="email" [readOnly]="readOnly"></label>\`,
|
||||
styles : []
|
||||
})
|
||||
export class InputStandaloneComponent{
|
||||
export class InputStandalone{
|
||||
@Input() readOnly = false;
|
||||
}
|
||||
`
|
||||
@ -230,7 +230,7 @@ import {CommonModule} from '@angular/common';
|
||||
|
||||
function useLibInApp(projectName: string, appName: string, libName: string) {
|
||||
createFile(
|
||||
`${appName}/src/app/app.component.html`,
|
||||
`${appName}/src/app/app.html`,
|
||||
`
|
||||
<${projectName}-btn></${projectName}-btn>
|
||||
<${projectName}-btn-standalone></${projectName}-btn-standalone>
|
||||
@ -239,7 +239,7 @@ function useLibInApp(projectName: string, appName: string, libName: string) {
|
||||
);
|
||||
const btnModuleName = names(libName).className;
|
||||
updateFile(
|
||||
`${appName}/src/app/app.component.scss`,
|
||||
`${appName}/src/app/app.scss`,
|
||||
`
|
||||
@use 'styleguide' as *;
|
||||
|
||||
@ -248,20 +248,20 @@ h1 {
|
||||
}`
|
||||
);
|
||||
updateFile(
|
||||
`${appName}/src/app/app.module.ts`,
|
||||
`${appName}/src/app/app-module.ts`,
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import {${btnModuleName}Module} from "@${projectName}/${libName}";
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { App } from './app';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, NxWelcomeComponent],
|
||||
declarations: [App, NxWelcome],
|
||||
imports: [BrowserModule, ${btnModuleName}Module],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
bootstrap: [App],
|
||||
})
|
||||
export class AppModule {}
|
||||
`
|
||||
@ -328,25 +328,25 @@ describe(InputComponent.name, () => {
|
||||
);
|
||||
|
||||
createFile(
|
||||
`${libName}/src/lib/input-standalone/input-standalone.component.cy.ts`,
|
||||
`${libName}/src/lib/input-standalone/input-standalone.cy.ts`,
|
||||
`
|
||||
import { MountConfig } from 'cypress/angular';
|
||||
import { InputStandaloneComponent } from './input-standalone.component';
|
||||
import { InputStandalone } from './input-standalone';
|
||||
|
||||
describe(InputStandaloneComponent.name, () => {
|
||||
const config: MountConfig<InputStandaloneComponent> = {
|
||||
describe(InputStandalone.name, () => {
|
||||
const config: MountConfig<InputStandalone> = {
|
||||
declarations: [],
|
||||
imports: [],
|
||||
providers: [],
|
||||
};
|
||||
|
||||
it('renders', () => {
|
||||
cy.mount(InputStandaloneComponent, config);
|
||||
cy.mount(InputStandalone, config);
|
||||
// make sure tailwind isn't getting applied
|
||||
cy.get('label').should('have.css', 'color', 'rgb(0, 0, 0)');
|
||||
});
|
||||
it('should be readonly', () => {
|
||||
cy.mount(InputStandaloneComponent, {
|
||||
cy.mount(InputStandalone, {
|
||||
...config,
|
||||
componentProperties: {
|
||||
readOnly: true,
|
||||
@ -367,19 +367,19 @@ function useBuildableLibInLib(
|
||||
const buildLibNames = names(buildableLibName);
|
||||
// use the buildable lib in lib so now buildableLib has an indirect dep on app
|
||||
updateFile(
|
||||
`${libName}/src/lib/btn-standalone/btn-standalone.component.ts`,
|
||||
`${libName}/src/lib/btn-standalone/btn-standalone.ts`,
|
||||
`
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { InputStandaloneComponent } from '@${projectName}/${buildLibNames.fileName}';
|
||||
import { InputStandalone } from '@${projectName}/${buildLibNames.fileName}';
|
||||
@Component({
|
||||
selector: '${projectName}-btn-standalone',
|
||||
standalone: true,
|
||||
imports: [CommonModule, InputStandaloneComponent],
|
||||
imports: [CommonModule, InputStandalone],
|
||||
template: '<button class="text-green-500">standlone-{{text}}</button>${projectName} <${projectName}-input-standalone></${projectName}-input-standalone>',
|
||||
styles: [],
|
||||
})
|
||||
export class BtnStandaloneComponent {
|
||||
export class BtnStandalone {
|
||||
@Input() text = 'something';
|
||||
}
|
||||
`
|
||||
@ -394,7 +394,7 @@ function updateBuilableLibTestsToAssertAppStyles(
|
||||
|
||||
removeFile(`${buildableLibName}/src/lib/input/input.component.cy.ts`);
|
||||
updateFile(
|
||||
`${buildableLibName}/src/lib/input-standalone/input-standalone.component.cy.ts`,
|
||||
`${buildableLibName}/src/lib/input-standalone/input-standalone.cy.ts`,
|
||||
(content) => {
|
||||
// app styles should now apply
|
||||
return content.replace('rgb(34, 197, 94)', 'rgb(255, 192, 203)');
|
||||
|
||||
@ -46,10 +46,8 @@ describe('Move Angular Project', () => {
|
||||
expect(moveOutput).toContain(`CREATE ${newPath}/src/main.ts`);
|
||||
expect(moveOutput).toContain(`CREATE ${newPath}/src/styles.css`);
|
||||
expect(moveOutput).toContain(`CREATE ${newPath}/src/test-setup.ts`);
|
||||
expect(moveOutput).toContain(
|
||||
`CREATE ${newPath}/src/app/app.component.html`
|
||||
);
|
||||
expect(moveOutput).toContain(`CREATE ${newPath}/src/app/app.component.ts`);
|
||||
expect(moveOutput).toContain(`CREATE ${newPath}/src/app/app.html`);
|
||||
expect(moveOutput).toContain(`CREATE ${newPath}/src/app/app.ts`);
|
||||
expect(moveOutput).toContain(`CREATE ${newPath}/src/app/app.config.ts`);
|
||||
});
|
||||
|
||||
@ -105,7 +103,7 @@ describe('Move Angular Project', () => {
|
||||
runCLI(`generate @nx/angular:lib ${lib2} --no-standalone --no-interactive`);
|
||||
|
||||
updateFile(
|
||||
`${lib2}/src/lib/${lib2}.module.ts`,
|
||||
`${lib2}/src/lib/${lib2}-module.ts`,
|
||||
`import { ${classify(lib1)}Module } from '@${proj}/${lib1}';
|
||||
|
||||
export class ExtendedModule extends ${classify(lib1)}Module { }`
|
||||
@ -122,7 +120,7 @@ describe('Move Angular Project', () => {
|
||||
expect(moveOutput).toContain(`CREATE ${testSetupPath}`);
|
||||
checkFilesExist(testSetupPath);
|
||||
|
||||
const modulePath = `${newPath}/src/lib/shared-${lib1}.module.ts`;
|
||||
const modulePath = `${newPath}/src/lib/shared-${lib1}-module.ts`;
|
||||
expect(moveOutput).toContain(`CREATE ${modulePath}`);
|
||||
checkFilesExist(modulePath);
|
||||
const moduleFile = readFile(modulePath);
|
||||
@ -132,12 +130,12 @@ describe('Move Angular Project', () => {
|
||||
expect(moveOutput).toContain(`CREATE ${indexPath}`);
|
||||
checkFilesExist(indexPath);
|
||||
const index = readFile(indexPath);
|
||||
expect(index).toContain(`export * from './lib/shared-${lib1}.module'`);
|
||||
expect(index).toContain(`export * from './lib/shared-${lib1}-module'`);
|
||||
|
||||
/**
|
||||
* Check that the import in lib2 has been updated
|
||||
*/
|
||||
const lib2FilePath = `${lib2}/src/lib/${lib2}.module.ts`;
|
||||
const lib2FilePath = `${lib2}/src/lib/${lib2}-module.ts`;
|
||||
const lib2File = readFile(lib2FilePath);
|
||||
expect(lib2File).toContain(
|
||||
`import { ${newModule} } from '@${proj}/shared-${lib1}';`
|
||||
|
||||
@ -2,14 +2,11 @@ import { names } from '@nx/devkit';
|
||||
import {
|
||||
checkFilesExist,
|
||||
cleanupProject,
|
||||
killPorts,
|
||||
killProcessAndPorts,
|
||||
newProject,
|
||||
readFile,
|
||||
readJson,
|
||||
runCLI,
|
||||
runCommandUntil,
|
||||
runE2ETests,
|
||||
uniq,
|
||||
updateFile,
|
||||
updateJson,
|
||||
@ -63,8 +60,8 @@ describe('Angular Module Federation', () => {
|
||||
|
||||
// check files are generated without the layout directory ("apps/")
|
||||
checkFilesExist(
|
||||
`${hostApp}/src/app/app.module.ts`,
|
||||
`${remoteApp1}/src/app/app.module.ts`
|
||||
`${hostApp}/src/app/app-module.ts`,
|
||||
`${remoteApp1}/src/app/app-module.ts`
|
||||
);
|
||||
|
||||
// check default generated host is built successfully
|
||||
@ -96,26 +93,26 @@ describe('Angular Module Federation', () => {
|
||||
|
||||
// update host & remote files to use shared library
|
||||
updateFile(
|
||||
`${hostApp}/src/app/app.module.ts`,
|
||||
`${hostApp}/src/app/app-module.ts`,
|
||||
`import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { ${
|
||||
names(wildcardLib).className
|
||||
}Module } from '@${proj}/${wildcardLib}/${
|
||||
names(secondaryEntry).fileName
|
||||
}.module';
|
||||
}-module';
|
||||
import { ${
|
||||
names(sharedLib).className
|
||||
}Module } from '@${proj}/${sharedLib}';
|
||||
import { ${
|
||||
names(secondaryEntry).className
|
||||
}Module } from '@${proj}/${sharedLib}/${secondaryEntry}';
|
||||
import { AppComponent } from './app.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { App } from './app';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, NxWelcomeComponent],
|
||||
declarations: [App, NxWelcome],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
${names(sharedLib).className}Module,
|
||||
@ -134,13 +131,13 @@ describe('Angular Module Federation', () => {
|
||||
),
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
bootstrap: [App],
|
||||
})
|
||||
export class AppModule {}
|
||||
`
|
||||
);
|
||||
updateFile(
|
||||
`${remoteApp1}/src/app/remote-entry/entry.module.ts`,
|
||||
`${remoteApp1}/src/app/remote-entry/entry-module.ts`,
|
||||
`import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterModule } from '@angular/router';
|
||||
@ -148,18 +145,18 @@ describe('Angular Module Federation', () => {
|
||||
import { ${
|
||||
names(secondaryEntry).className
|
||||
}Module } from '@${proj}/${sharedLib}/${secondaryEntry}';
|
||||
import { RemoteEntryComponent } from './entry.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { RemoteEntry } from './entry';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
|
||||
@NgModule({
|
||||
declarations: [RemoteEntryComponent, NxWelcomeComponent],
|
||||
declarations: [RemoteEntry, NxWelcome],
|
||||
imports: [
|
||||
CommonModule,
|
||||
${names(sharedLib).className}Module,
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: RemoteEntryComponent,
|
||||
component: RemoteEntry,
|
||||
},
|
||||
]),
|
||||
],
|
||||
|
||||
@ -49,8 +49,8 @@ describe('Angular Module Federation', () => {
|
||||
|
||||
// check files are generated without the layout directory ("apps/")
|
||||
checkFilesExist(
|
||||
`${hostApp}/src/app/app.module.ts`,
|
||||
`${remoteApp1}/src/app/app.module.ts`
|
||||
`${hostApp}/src/app/app-module.ts`,
|
||||
`${remoteApp1}/src/app/app-module.ts`
|
||||
);
|
||||
|
||||
// check default generated host is built successfully
|
||||
@ -80,26 +80,26 @@ describe('Angular Module Federation', () => {
|
||||
|
||||
// update host & remote files to use shared library
|
||||
updateFile(
|
||||
`${hostApp}/src/app/app.module.ts`,
|
||||
`${hostApp}/src/app/app-module.ts`,
|
||||
`import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { ${
|
||||
names(wildcardLib).className
|
||||
}Module } from '@${proj}/${wildcardLib}/${
|
||||
names(secondaryEntry).fileName
|
||||
}.module';
|
||||
names(wildcardLib).fileName
|
||||
}-module';
|
||||
import { ${
|
||||
names(sharedLib).className
|
||||
}Module } from '@${proj}/${sharedLib}';
|
||||
import { ${
|
||||
names(secondaryEntry).className
|
||||
}Module } from '@${proj}/${sharedLib}/${secondaryEntry}';
|
||||
import { AppComponent } from './app.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { App } from './app';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, NxWelcomeComponent],
|
||||
declarations: [App, NxWelcome],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
${names(sharedLib).className}Module,
|
||||
@ -118,13 +118,13 @@ describe('Angular Module Federation', () => {
|
||||
),
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
bootstrap: [App],
|
||||
})
|
||||
export class AppModule {}
|
||||
`
|
||||
);
|
||||
updateFile(
|
||||
`${remoteApp1}/src/app/remote-entry/entry.module.ts`,
|
||||
`${remoteApp1}/src/app/remote-entry/entry-module.ts`,
|
||||
`import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterModule } from '@angular/router';
|
||||
@ -132,18 +132,18 @@ describe('Angular Module Federation', () => {
|
||||
import { ${
|
||||
names(secondaryEntry).className
|
||||
}Module } from '@${proj}/${sharedLib}/${secondaryEntry}';
|
||||
import { RemoteEntryComponent } from './entry.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { RemoteEntry } from './entry';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
|
||||
@NgModule({
|
||||
declarations: [RemoteEntryComponent, NxWelcomeComponent],
|
||||
declarations: [RemoteEntry, NxWelcome],
|
||||
imports: [
|
||||
CommonModule,
|
||||
${names(sharedLib).className}Module,
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: RemoteEntryComponent,
|
||||
component: RemoteEntry,
|
||||
},
|
||||
]),
|
||||
],
|
||||
@ -301,7 +301,7 @@ test('renders remotes', async ({ page }) => {
|
||||
|
||||
// Update Host to use the module
|
||||
updateFile(
|
||||
`${host}/src/app/app.component.ts`,
|
||||
`${host}/src/app/app.ts`,
|
||||
`
|
||||
import { Component } from '@angular/core';
|
||||
import { isEven } from '${remote}/${module}';
|
||||
@ -311,7 +311,7 @@ test('renders remotes', async ({ page }) => {
|
||||
template: \`<div class="host">{{title}}</div>\`,
|
||||
standalone: true
|
||||
})
|
||||
export class AppComponent {
|
||||
export class App {
|
||||
title = \`shell is \${isEven(2) ? 'even' : 'odd'}\`;
|
||||
}`
|
||||
);
|
||||
@ -373,7 +373,7 @@ test('renders remotes', async ({ page }) => {
|
||||
|
||||
// Update Host to use the module
|
||||
updateFile(
|
||||
`${remote}/src/app/remote-entry/entry.component.ts`,
|
||||
`${remote}/src/app/remote-entry/entry.ts`,
|
||||
`
|
||||
import { Component } from '@angular/core';
|
||||
import { isEven } from '${childRemote}/${module}';
|
||||
@ -383,7 +383,7 @@ test('renders remotes', async ({ page }) => {
|
||||
template: \`<div class="childremote">{{title}}</div>\`,
|
||||
standalone: true
|
||||
})
|
||||
export class RemoteEntryComponent {
|
||||
export class RemoteEntry {
|
||||
title = \`shell is \${isEven(2) ? 'even' : 'odd'}\`;
|
||||
}`
|
||||
);
|
||||
@ -398,7 +398,7 @@ test('renders remotes', async ({ page }) => {
|
||||
remotes: ['${childRemote}'],
|
||||
exposes: {
|
||||
'./Routes': '${remote}/src/app/remote-entry/entry.routes.ts',
|
||||
'./Module': '${remote}/src/app/remote-entry/entry.component.ts',
|
||||
'./Module': '${remote}/src/app/remote-entry/entry.ts',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -115,7 +115,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
'.prettierrc',
|
||||
`apps/${project}/src/main.ts`,
|
||||
`apps/${project}/src/app/app.config.ts`,
|
||||
`apps/${project}/src/app/app.component.ts`,
|
||||
`apps/${project}/src/app/app.ts`,
|
||||
`apps/${project}/src/app/app.routes.ts`
|
||||
);
|
||||
|
||||
@ -178,10 +178,10 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
const projectConfig = readJson(`apps/${project}/project.json`);
|
||||
expect(projectConfig.sourceRoot).toEqual(`apps/${project}/src`);
|
||||
expect(projectConfig.targets.build).toStrictEqual({
|
||||
executor: '@angular-devkit/build-angular:application',
|
||||
executor: '@angular/build:application',
|
||||
outputs: ['{options.outputPath}'],
|
||||
options: {
|
||||
outputPath: `dist/apps/${project}`,
|
||||
index: `apps/${project}/src/index.html`,
|
||||
outputPath: `dist/${project}`,
|
||||
browser: `apps/${project}/src/main.ts`,
|
||||
polyfills: [`zone.js`],
|
||||
tsConfig: `apps/${project}/tsconfig.app.json`,
|
||||
@ -214,7 +214,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
defaultConfiguration: 'production',
|
||||
});
|
||||
expect(projectConfig.targets.serve).toEqual({
|
||||
executor: '@angular-devkit/build-angular:dev-server',
|
||||
executor: '@angular/build:dev-server',
|
||||
configurations: {
|
||||
production: { buildTarget: `${project}:build:production` },
|
||||
development: { buildTarget: `${project}:build:development` },
|
||||
@ -222,7 +222,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
defaultConfiguration: 'development',
|
||||
});
|
||||
expect(projectConfig.targets.test).toStrictEqual({
|
||||
executor: '@angular-devkit/build-angular:karma',
|
||||
executor: '@angular/build:karma',
|
||||
options: {
|
||||
polyfills: [`zone.js`, `zone.js/testing`],
|
||||
tsConfig: `apps/${project}/tsconfig.spec.json`,
|
||||
@ -249,7 +249,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
});
|
||||
|
||||
runCLI(`build ${project} --configuration production --outputHashing none`);
|
||||
checkFilesExist(`dist/apps/${project}/browser/main.js`);
|
||||
checkFilesExist(`dist/${project}/browser/main.js`);
|
||||
});
|
||||
|
||||
it('should handle a workspace with cypress v9', () => {
|
||||
@ -436,7 +436,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
expect(output).toContain(
|
||||
`Successfully ran target build for project ${project}`
|
||||
);
|
||||
checkFilesExist(`dist/apps/${project}/browser/main.js`);
|
||||
checkFilesExist(`dist/${project}/browser/main.js`);
|
||||
|
||||
output = runCLI(`build ${project} --outputHashing none`);
|
||||
expect(output).toContain(
|
||||
@ -454,7 +454,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
expect(output).toContain(
|
||||
`Successfully ran target build for project ${app1}`
|
||||
);
|
||||
checkFilesExist(`dist/apps/${app1}/browser/main.js`);
|
||||
checkFilesExist(`dist/${app1}/browser/main.js`);
|
||||
|
||||
output = runCLI(`build ${app1} --outputHashing none`);
|
||||
expect(output).toContain(
|
||||
|
||||
@ -26,7 +26,7 @@ describe('Angular Package', () => {
|
||||
|
||||
// Generate root ngrx state management
|
||||
runCLI(
|
||||
`generate @nx/angular:ngrx users --parent=${myapp}/src/app/app.module.ts --root --minimal=false`
|
||||
`generate @nx/angular:ngrx users --parent=${myapp}/src/app/app-module.ts --root --minimal=false`
|
||||
);
|
||||
const packageJson = readJson('package.json');
|
||||
expect(packageJson.dependencies['@ngrx/store']).toBeDefined();
|
||||
@ -38,7 +38,7 @@ describe('Angular Package', () => {
|
||||
// Generate feature library and ngrx state within that library
|
||||
runCLI(`g @nx/angular:lib ${mylib} --prefix=fl --no-standalone`);
|
||||
runCLI(
|
||||
`generate @nx/angular:ngrx flights --parent=${mylib}/src/lib/${mylib}.module.ts --facade`
|
||||
`generate @nx/angular:ngrx flights --parent=${mylib}/src/lib/${mylib}-module.ts --facade`
|
||||
);
|
||||
|
||||
expect(runCLI(`build ${myapp}`)).toMatch(/main-[a-zA-Z0-9]+\.js/);
|
||||
@ -57,7 +57,7 @@ describe('Angular Package', () => {
|
||||
|
||||
// Generate root ngrx state management
|
||||
runCLI(
|
||||
`generate @nx/angular:ngrx users --parent=${myapp}/src/app/app.module.ts --root`
|
||||
`generate @nx/angular:ngrx users --parent=${myapp}/src/app/app-module.ts --root`
|
||||
);
|
||||
const packageJson = readJson('package.json');
|
||||
expect(packageJson.dependencies['@ngrx/entity']).toBeDefined();
|
||||
@ -73,7 +73,7 @@ describe('Angular Package', () => {
|
||||
|
||||
const flags = `--facade --barrels`;
|
||||
runCLI(
|
||||
`generate @nx/angular:ngrx flights --parent=${mylib}/src/lib/${mylib}.module.ts ${flags}`
|
||||
`generate @nx/angular:ngrx flights --parent=${mylib}/src/lib/${mylib}-module.ts ${flags}`
|
||||
);
|
||||
|
||||
expect(runCLI(`build ${myapp}`)).toMatch(/main-[a-zA-Z0-9]+\.js/);
|
||||
@ -92,7 +92,7 @@ describe('Angular Package', () => {
|
||||
|
||||
// Generate root ngrx state management
|
||||
runCLI(
|
||||
`generate @nx/angular:ngrx users --parent=${myapp}/src/app/app.module.ts --root`
|
||||
`generate @nx/angular:ngrx users --parent=${myapp}/src/app/app-module.ts --root`
|
||||
);
|
||||
const packageJson = readJson('package.json');
|
||||
expect(packageJson.dependencies['@ngrx/entity']).toBeDefined();
|
||||
@ -108,7 +108,7 @@ describe('Angular Package', () => {
|
||||
|
||||
const flags = `--facade --barrels`;
|
||||
runCLI(
|
||||
`generate @nx/angular:ngrx flights --module=${mylib}/src/lib/${mylib}.module.ts ${flags}`
|
||||
`generate @nx/angular:ngrx flights --module=${mylib}/src/lib/${mylib}-module.ts ${flags}`
|
||||
);
|
||||
|
||||
expect(runCLI(`build ${myapp}`)).toMatch(/main-[a-zA-Z0-9]+\.js/);
|
||||
|
||||
@ -40,26 +40,21 @@ describe('Angular Projects', () => {
|
||||
`generate @nx/angular:app ${esbuildApp} --bundler=esbuild --no-standalone --no-interactive`
|
||||
);
|
||||
runCLI(`generate @nx/angular:lib ${lib1} --no-interactive`);
|
||||
app1DefaultModule = readFile(`${app1}/src/app/app.module.ts`);
|
||||
app1DefaultComponentTemplate = readFile(
|
||||
`${app1}/src/app/app.component.html`
|
||||
);
|
||||
esbuildAppDefaultModule = readFile(`${esbuildApp}/src/app/app.module.ts`);
|
||||
app1DefaultModule = readFile(`${app1}/src/app/app-module.ts`);
|
||||
app1DefaultComponentTemplate = readFile(`${app1}/src/app/app.html`);
|
||||
esbuildAppDefaultModule = readFile(`${esbuildApp}/src/app/app-module.ts`);
|
||||
esbuildAppDefaultComponentTemplate = readFile(
|
||||
`${esbuildApp}/src/app/app.component.html`
|
||||
`${esbuildApp}/src/app/app.html`
|
||||
);
|
||||
esbuildAppDefaultProjectConfig = readFile(`${esbuildApp}/project.json`);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
updateFile(`${app1}/src/app/app.module.ts`, app1DefaultModule);
|
||||
updateFile(`${app1}/src/app/app-module.ts`, app1DefaultModule);
|
||||
updateFile(`${app1}/src/app/app.html`, app1DefaultComponentTemplate);
|
||||
updateFile(`${esbuildApp}/src/app/app-module.ts`, esbuildAppDefaultModule);
|
||||
updateFile(
|
||||
`${app1}/src/app/app.component.html`,
|
||||
app1DefaultComponentTemplate
|
||||
);
|
||||
updateFile(`${esbuildApp}/src/app/app.module.ts`, esbuildAppDefaultModule);
|
||||
updateFile(
|
||||
`${esbuildApp}/src/app/app.component.html`,
|
||||
`${esbuildApp}/src/app/app.html`,
|
||||
esbuildAppDefaultComponentTemplate
|
||||
);
|
||||
updateFile(`${esbuildApp}/project.json`, esbuildAppDefaultProjectConfig);
|
||||
@ -79,24 +74,24 @@ describe('Angular Projects', () => {
|
||||
);
|
||||
|
||||
updateFile(
|
||||
`${app1}/src/app/app.module.ts`,
|
||||
`${app1}/src/app/app-module.ts`,
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AppComponent } from './app.component';
|
||||
import { App } from './app';
|
||||
import { appRoutes } from './app.routes';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { ${names(lib1).className}Component } from '@${proj}/${lib1}';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
import { ${names(lib1).className} } from '@${proj}/${lib1}';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
RouterModule.forRoot(appRoutes, { initialNavigation: 'enabledBlocking' }),
|
||||
${names(lib1).className}Component
|
||||
${names(lib1).className}
|
||||
],
|
||||
declarations: [AppComponent, NxWelcomeComponent],
|
||||
bootstrap: [AppComponent]
|
||||
declarations: [App, NxWelcome],
|
||||
bootstrap: [App]
|
||||
})
|
||||
export class AppModule {}
|
||||
`
|
||||
@ -193,7 +188,7 @@ describe('Angular Projects', () => {
|
||||
// External HTML template file
|
||||
const templateWhichFailsBananaInBoxLintCheck = `<div ([foo])="bar"></div>`;
|
||||
updateFile(
|
||||
`${app1}/src/app/app.component.html`,
|
||||
`${app1}/src/app/app.html`,
|
||||
templateWhichFailsBananaInBoxLintCheck
|
||||
);
|
||||
// Inline template within component.ts file
|
||||
@ -216,9 +211,7 @@ describe('Angular Projects', () => {
|
||||
const appLintStdOut = runCLI(`lint ${app1}`, {
|
||||
silenceError: true,
|
||||
});
|
||||
expect(appLintStdOut).toContain(
|
||||
normalize(`${app1}/src/app/app.component.html`)
|
||||
);
|
||||
expect(appLintStdOut).toContain(normalize(`${app1}/src/app/app.html`));
|
||||
expect(appLintStdOut).toContain(`1:6`);
|
||||
expect(appLintStdOut).toContain(`Invalid binding syntax`);
|
||||
expect(appLintStdOut).toContain(
|
||||
@ -249,53 +242,53 @@ describe('Angular Projects', () => {
|
||||
|
||||
// update the app module to include a ref to the buildable lib
|
||||
updateFile(
|
||||
`${app1}/src/app/app.module.ts`,
|
||||
`${app1}/src/app/app-module.ts`,
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AppComponent } from './app.component';
|
||||
import { App } from './app';
|
||||
import { appRoutes } from './app.routes';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
import {${
|
||||
names(buildableLib).className
|
||||
}Module} from '@${proj}/${buildableLib}';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, NxWelcomeComponent],
|
||||
declarations: [App, NxWelcome],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
RouterModule.forRoot(appRoutes, { initialNavigation: 'enabledBlocking' }),
|
||||
${names(buildableLib).className}Module
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
bootstrap: [App],
|
||||
})
|
||||
export class AppModule {}
|
||||
`
|
||||
);
|
||||
updateFile(
|
||||
`${esbuildApp}/src/app/app.module.ts`,
|
||||
`${esbuildApp}/src/app/app-module.ts`,
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AppComponent } from './app.component';
|
||||
import { App } from './app';
|
||||
import { appRoutes } from './app.routes';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
import {${
|
||||
names(buildableLib).className
|
||||
}Module} from '@${proj}/${buildableLib}';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, NxWelcomeComponent],
|
||||
declarations: [App, NxWelcome],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
RouterModule.forRoot(appRoutes, { initialNavigation: 'enabledBlocking' }),
|
||||
${names(buildableLib).className}Module
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
bootstrap: [App],
|
||||
})
|
||||
export class AppModule {}
|
||||
`
|
||||
@ -303,7 +296,7 @@ describe('Angular Projects', () => {
|
||||
|
||||
// update the buildable lib module to include a ref to the buildable child lib
|
||||
updateFile(
|
||||
`${buildableLib}/src/lib/${names(buildableLib).fileName}.module.ts`,
|
||||
`${buildableLib}/src/lib/${names(buildableLib).fileName}-module.ts`,
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
@ -333,6 +326,7 @@ describe('Angular Projects', () => {
|
||||
config.targets.build.options = {
|
||||
...config.targets.build.options,
|
||||
outputPath: `dist/${esbuildApp}`,
|
||||
index: `${esbuildApp}/src/index.html`,
|
||||
main: config.targets.build.options.browser,
|
||||
browser: undefined,
|
||||
buildLibsFromSource: false,
|
||||
@ -397,7 +391,7 @@ describe('Angular Projects', () => {
|
||||
export default replaceTextPlugin;`
|
||||
);
|
||||
updateFile(
|
||||
`${esbuildApp}/src/app/app.component.ts`,
|
||||
`${esbuildApp}/src/app/app.ts`,
|
||||
`import { Component } from '@angular/core';
|
||||
|
||||
declare const BUILD_DEFINED: string;
|
||||
@ -405,9 +399,9 @@ describe('Angular Projects', () => {
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
standalone: false,
|
||||
templateUrl: './app.component.html',
|
||||
templateUrl: './app.html',
|
||||
})
|
||||
export class AppComponent {
|
||||
export class App {
|
||||
title = 'esbuild-app';
|
||||
buildDefined = BUILD_DEFINED;
|
||||
}`
|
||||
@ -437,6 +431,7 @@ describe('Angular Projects', () => {
|
||||
...config.targets.build.options,
|
||||
main: config.targets.build.options.browser,
|
||||
browser: undefined,
|
||||
index: `${esbuildApp}/src/index.html`,
|
||||
};
|
||||
return config;
|
||||
});
|
||||
@ -511,7 +506,7 @@ describe('Angular Projects', () => {
|
||||
})
|
||||
export class ${names(lib).className}Module {}`;
|
||||
|
||||
updateFile(`${lib}/src/lib/${lib}.module.ts`, moduleContent);
|
||||
updateFile(`${lib}/src/lib/${lib}-module.ts`, moduleContent);
|
||||
|
||||
// ACT
|
||||
const buildOutput = runCLI(`build ${lib}`, { env: { CI: 'false' } });
|
||||
@ -536,9 +531,7 @@ describe('Angular Projects', () => {
|
||||
// using the project name as the directory when no directory is provided
|
||||
checkFilesExist(
|
||||
`${libName}/src/index.ts`,
|
||||
`${libName}/src/lib/${libName.split('/')[1]}/${
|
||||
libName.split('/')[1]
|
||||
}.component.ts`
|
||||
`${libName}/src/lib/${libName.split('/')[1]}/${libName.split('/')[1]}.ts`
|
||||
);
|
||||
// check build works
|
||||
expect(() => runCLI(`build ${libName}`)).not.toThrow();
|
||||
|
||||
@ -132,7 +132,7 @@ describe('Tailwind support', () => {
|
||||
buttonBgColor: string = defaultButtonBgColor
|
||||
) => {
|
||||
updateFile(
|
||||
`${lib}/src/lib/foo.component.ts`,
|
||||
`${lib}/src/lib/foo.ts`,
|
||||
`import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
@ -145,20 +145,20 @@ describe('Tailwind support', () => {
|
||||
}
|
||||
\`]
|
||||
})
|
||||
export class FooComponent {}
|
||||
export class Foo {}
|
||||
`
|
||||
);
|
||||
|
||||
updateFile(
|
||||
`${lib}/src/lib/${lib}.module.ts`,
|
||||
`${lib}/src/lib/${lib}-module.ts`,
|
||||
`import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FooComponent } from './foo.component';
|
||||
import { Foo } from './foo';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
declarations: [FooComponent],
|
||||
exports: [FooComponent],
|
||||
declarations: [Foo],
|
||||
exports: [Foo],
|
||||
})
|
||||
export class LibModule {}
|
||||
`
|
||||
@ -166,8 +166,8 @@ describe('Tailwind support', () => {
|
||||
|
||||
updateFile(
|
||||
`${lib}/src/index.ts`,
|
||||
`export * from './lib/foo.component';
|
||||
export * from './lib/${lib}.module';
|
||||
`export * from './lib/foo';
|
||||
export * from './lib/${lib}-module';
|
||||
`
|
||||
);
|
||||
};
|
||||
@ -180,7 +180,7 @@ describe('Tailwind support', () => {
|
||||
const builtComponentContent = readFile(
|
||||
isPublishable
|
||||
? `dist/${lib}/fesm2022/${project}-${lib}.mjs`
|
||||
: `dist/${lib}/esm2022/lib/foo.component.mjs`
|
||||
: `dist/${lib}/esm2022/lib/foo.js`
|
||||
);
|
||||
let expectedStylesRegex = new RegExp(
|
||||
`styles: \\[\\"\\.custom\\-btn(\\[_ngcontent\\-%COMP%\\])?{margin:${libSpacing.md};padding:${libSpacing.sm}}(\\\\n)?\\"\\]`
|
||||
@ -356,30 +356,30 @@ describe('Tailwind support', () => {
|
||||
spacing.projectVariant1
|
||||
);
|
||||
updateFile(
|
||||
`${appName}/src/app/app.module.ts`,
|
||||
`${appName}/src/app/app-module.ts`,
|
||||
`import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { LibModule as LibModule1 } from '@${project}/${buildLibWithTailwind.name}';
|
||||
import { LibModule as LibModule2 } from '@${project}/${pubLibWithTailwind.name}';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { App } from './app';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent],
|
||||
imports: [BrowserModule, LibModule1, LibModule2],
|
||||
declarations: [],
|
||||
imports: [BrowserModule, App, LibModule1, LibModule2],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
bootstrap: [App],
|
||||
})
|
||||
export class AppModule {}
|
||||
`
|
||||
);
|
||||
updateFile(
|
||||
`${appName}/src/app/app.component.html`,
|
||||
`${appName}/src/app/app.html`,
|
||||
`<button class="custom-btn text-white">Click me!</button>`
|
||||
);
|
||||
|
||||
updateFile(
|
||||
`${appName}/src/app/app.component.css`,
|
||||
`${appName}/src/app/app.css`,
|
||||
`.custom-btn {
|
||||
@apply m-md p-sm;
|
||||
}`
|
||||
|
||||
@ -85,7 +85,7 @@ describe('nx init (Angular CLI - legacy)', () => {
|
||||
expect(coldBuildOutput).toContain(
|
||||
`Successfully ran target build for project ${project}`
|
||||
);
|
||||
checkFilesExist(`dist/apps/${project}/browser/main.js`);
|
||||
checkFilesExist(`dist/${project}/browser/main.js`);
|
||||
|
||||
// run build again to check is coming from cache
|
||||
const cachedBuildOutput = runCLI(`build ${project} --outputHashing none`);
|
||||
|
||||
@ -230,7 +230,6 @@ describe('release publishable libraries', () => {
|
||||
XXX.XXX kb fesm2022/proj-{project-name}.mjs
|
||||
XXX.XXX kb fesm2022/proj-{project-name}.mjs.map
|
||||
XXB index.d.ts
|
||||
XXB lib/{project-name}/{project-name}.component.d.ts
|
||||
XXXB package.json
|
||||
=== Tarball Details ===
|
||||
name: @proj/{project-name}
|
||||
|
||||
@ -38,7 +38,7 @@ describe('create-nx-workspace', () => {
|
||||
|
||||
checkFilesExist('package.json');
|
||||
checkFilesExist('project.json');
|
||||
checkFilesExist('src/app/app.module.ts');
|
||||
checkFilesExist('src/app/app-module.ts');
|
||||
checkFilesDoNotExist('src/app/app.routes.ts');
|
||||
expectCodeIsFormatted();
|
||||
});
|
||||
@ -61,7 +61,7 @@ describe('create-nx-workspace', () => {
|
||||
checkFilesExist('package.json');
|
||||
checkFilesExist('project.json');
|
||||
checkFilesExist('src/app/app.routes.ts');
|
||||
checkFilesDoNotExist('src/app/app.module.ts');
|
||||
checkFilesDoNotExist('src/app/app-module.ts');
|
||||
expectCodeIsFormatted();
|
||||
});
|
||||
|
||||
|
||||
43
package.json
43
package.json
@ -28,19 +28,21 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/core": "^1.10.0",
|
||||
"@angular-devkit/architect": "0.1902.0",
|
||||
"@angular-devkit/build-angular": "19.2.0",
|
||||
"@angular-devkit/core": "19.2.0",
|
||||
"@angular-devkit/schematics": "19.2.0",
|
||||
"@angular-devkit/architect": "0.2000.0-rc.3",
|
||||
"@angular-devkit/build-angular": "20.0.0-rc.3",
|
||||
"@angular-devkit/core": "20.0.0-rc.3",
|
||||
"@angular-devkit/schematics": "20.0.0-rc.3",
|
||||
"@angular-eslint/eslint-plugin": "19.2.0",
|
||||
"@angular-eslint/eslint-plugin-template": "19.2.0",
|
||||
"@angular-eslint/template-parser": "19.2.0",
|
||||
"@angular/cli": "~19.2.0",
|
||||
"@angular/common": "19.2.0",
|
||||
"@angular/compiler": "19.2.0",
|
||||
"@angular/compiler-cli": "19.2.0",
|
||||
"@angular/core": "19.2.0",
|
||||
"@angular/router": "19.2.0",
|
||||
"@angular/build": "20.0.0-rc.3",
|
||||
"@angular/cli": "20.0.0-rc.3",
|
||||
"@angular/common": "20.0.0-rc.2",
|
||||
"@angular/compiler": "20.0.0-rc.2",
|
||||
"@angular/compiler-cli": "20.0.0-rc.2",
|
||||
"@angular/core": "20.0.0-rc.2",
|
||||
"@angular/platform-browser": "20.0.0-rc.2",
|
||||
"@angular/router": "20.0.0-rc.2",
|
||||
"@astrojs/check": "^0.7.0",
|
||||
"@astrojs/react": "^3.6.2",
|
||||
"@babel/core": "^7.23.2",
|
||||
@ -114,7 +116,7 @@
|
||||
"@rspack/dev-server": "1.1.1",
|
||||
"@rspack/plugin-minify": "^0.7.5",
|
||||
"@rspack/plugin-react-refresh": "^1.0.0",
|
||||
"@schematics/angular": "~19.2.0",
|
||||
"@schematics/angular": "20.0.0-rc.3",
|
||||
"@storybook/addon-essentials": "8.4.6",
|
||||
"@storybook/addon-interactions": "8.4.6",
|
||||
"@storybook/core-server": "8.4.6",
|
||||
@ -160,10 +162,10 @@
|
||||
"@types/tmp": "^0.2.0",
|
||||
"@types/yargs": "17.0.10",
|
||||
"@types/yarnpkg__lockfile": "^1.1.5",
|
||||
"@typescript-eslint/eslint-plugin": "^8.19.0",
|
||||
"@typescript-eslint/rule-tester": "^8.19.0",
|
||||
"@typescript-eslint/type-utils": "^8.19.0",
|
||||
"@typescript-eslint/utils": "^8.19.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.29.0",
|
||||
"@typescript-eslint/rule-tester": "^8.29.0",
|
||||
"@typescript-eslint/type-utils": "^8.29.0",
|
||||
"@typescript-eslint/utils": "^8.29.0",
|
||||
"@vitejs/plugin-react": "^4.2.0",
|
||||
"@webcontainer/api": "1.5.1",
|
||||
"@xstate/immer": "0.3.1",
|
||||
@ -264,7 +266,7 @@
|
||||
"mini-css-extract-plugin": "~2.4.7",
|
||||
"minimatch": "9.0.3",
|
||||
"next-sitemap": "^3.1.10",
|
||||
"ng-packagr": "19.2.0",
|
||||
"ng-packagr": "20.0.0-rc.1",
|
||||
"npm-package-arg": "11.0.1",
|
||||
"nuxt": "^3.10.0",
|
||||
"nx": "21.1.0-beta.2",
|
||||
@ -276,7 +278,6 @@
|
||||
"parse5": "4.0.0",
|
||||
"picocolors": "^1.1.0",
|
||||
"picomatch": "4.0.2",
|
||||
"piscina": "^4.4.0",
|
||||
"postcss": "8.4.38",
|
||||
"postcss-import": "~14.1.0",
|
||||
"postcss-preset-env": "~7.5.0",
|
||||
@ -296,7 +297,7 @@
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
"rollup-plugin-postcss": "^4.0.2",
|
||||
"rollup-plugin-typescript2": "^0.36.0",
|
||||
"rxjs": "^7.8.0",
|
||||
"rxjs": "^7.8.2",
|
||||
"sass": "1.55.0",
|
||||
"sass-embedded": "1.85.1",
|
||||
"sass-loader": "16.0.5",
|
||||
@ -319,14 +320,14 @@
|
||||
"tsconfig-paths-webpack-plugin": "4.0.0",
|
||||
"typedoc": "0.25.12",
|
||||
"typedoc-plugin-markdown": "3.17.1",
|
||||
"typescript": "~5.7.2",
|
||||
"typescript-eslint": "^8.19.0",
|
||||
"typescript": "~5.8.2",
|
||||
"typescript-eslint": "^8.29.0",
|
||||
"unist-builder": "^4.0.0",
|
||||
"use-sync-external-store": "^1.2.0",
|
||||
"verdaccio": "6.0.5",
|
||||
"vite": "6.2.0",
|
||||
"vitest": "3.0.5",
|
||||
"webpack": "5.98.0",
|
||||
"webpack": "5.99.8",
|
||||
"webpack-dev-server": "5.2.1",
|
||||
"webpack-merge": "^5.8.0",
|
||||
"webpack-node-externals": "^3.0.0",
|
||||
|
||||
@ -80,7 +80,6 @@
|
||||
"@storybook/angular",
|
||||
"@module-federation/node",
|
||||
"@nguniversal/builders",
|
||||
"ng-packagr",
|
||||
"injection-js",
|
||||
"browserslist",
|
||||
"cacache",
|
||||
@ -96,7 +95,8 @@
|
||||
"stylus",
|
||||
"tailwindcss",
|
||||
"cypress",
|
||||
"esbuild"
|
||||
"esbuild",
|
||||
"piscina"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -3,50 +3,60 @@
|
||||
{% tabs %}
|
||||
{% tab label="Simple Component" %}
|
||||
|
||||
Generate a component named `MyComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:
|
||||
Generate a component named `Card` at `apps/my-app/src/lib/card/card.ts`:
|
||||
|
||||
```bash
|
||||
nx g @nx/angular:component apps/my-app/src/lib/my-component/my-component.ts
|
||||
nx g @nx/angular:component apps/my-app/src/lib/card/card.ts
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Without Providing the File Extension" %}
|
||||
|
||||
Generate a component named `MyComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:
|
||||
Generate a component named `Card` at `apps/my-app/src/lib/card/card.ts`:
|
||||
|
||||
```bash
|
||||
nx g @nx/angular:component apps/my-app/src/lib/my-component/my-component
|
||||
nx g @nx/angular:component apps/my-app/src/lib/card/card
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="With Different Symbol Name" %}
|
||||
|
||||
Generate a component named `CustomComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:
|
||||
Generate a component named `Custom` at `apps/my-app/src/lib/card/card.ts`:
|
||||
|
||||
```bash
|
||||
nx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --name=custom
|
||||
nx g @nx/angular:component apps/my-app/src/lib/card/card --name=custom
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="With a Component Type" %}
|
||||
|
||||
Generate a component named `CardComponent` at `apps/my-app/src/lib/card/card.component.ts`:
|
||||
|
||||
```bash
|
||||
nx g @nx/angular:component apps/my-app/src/lib/card/card --type=component
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Single File Component" %}
|
||||
|
||||
Create a component named `my-component` with inline styles and inline template:
|
||||
Create a component named `Card` with inline styles and inline template:
|
||||
|
||||
```bash
|
||||
nx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --inlineStyle --inlineTemplate
|
||||
nx g @nx/angular:component apps/my-app/src/lib/card/card --inlineStyle --inlineTemplate
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Component with OnPush Change Detection Strategy" %}
|
||||
|
||||
Create a component named `my-component` with OnPush Change Detection Strategy:
|
||||
Create a component named `Card` with `OnPush` Change Detection Strategy:
|
||||
|
||||
```bash
|
||||
nx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --changeDetection=OnPush
|
||||
nx g @nx/angular:component apps/my-app/src/lib/card/card --changeDetection=OnPush
|
||||
```
|
||||
|
||||
{% /tab %}
|
||||
|
||||
@ -50,12 +50,6 @@ module.exports = (config) => {
|
||||
|
||||
{% tab label="Providing HTTP request middleware function" %}
|
||||
|
||||
{% callout type="warning" title="Overrides" }
|
||||
|
||||
Available for workspaces using Angular version 17.0.0 or greater and with `build` targets using an esbuild-based executor.
|
||||
|
||||
{% /callout %}
|
||||
|
||||
The executor accepts an `esbuildMiddleware` option that allows you to provide HTTP require middleware functions that will be used by the Vite development server.
|
||||
|
||||
```json {% fileName="apps/my-app/project.json" highlightLines=[8] %}
|
||||
|
||||
@ -302,6 +302,47 @@
|
||||
},
|
||||
"description": "Change the data persistence operator imports to '@ngrx/router-store/data-persistence'.",
|
||||
"factory": "./src/migrations/update-21-0-0/change-data-persistence-operators-imports-to-ngrx-router-store-data-persistence"
|
||||
},
|
||||
"update-angular-cli-version-20-0-0-rc-3": {
|
||||
"cli": "nx",
|
||||
"version": "21.2.0-beta.0",
|
||||
"requires": {
|
||||
"@angular/core": ">=20.0.0-rc.2"
|
||||
},
|
||||
"description": "Update the @angular/cli package version to 20.0.0-rc.3.",
|
||||
"factory": "./src/migrations/update-21-2-0/update-angular-cli"
|
||||
},
|
||||
"migrate-provide-server-rendering-import": {
|
||||
"version": "21.2.0-beta.0",
|
||||
"requires": {
|
||||
"@angular/core": ">=20.0.0-rc.2"
|
||||
},
|
||||
"description": "Migrate imports of `provideServerRendering` from `@angular/platform-server` to `@angular/ssr`.",
|
||||
"factory": "./src/migrations/update-21-2-0/migrate-provide-server-rendering-import"
|
||||
},
|
||||
"replace-provide-server-routing": {
|
||||
"version": "21.2.0-beta.0",
|
||||
"requires": {
|
||||
"@angular/core": ">=20.0.0-rc.2"
|
||||
},
|
||||
"description": "Replace `provideServerRouting` with `provideServerRendering` using `withRoutes`.",
|
||||
"factory": "./src/migrations/update-21-2-0/replace-provide-server-routing"
|
||||
},
|
||||
"set-generator-defaults-for-previous-style-guide": {
|
||||
"version": "21.2.0-beta.0",
|
||||
"requires": {
|
||||
"@angular/core": ">=20.0.0-rc.2"
|
||||
},
|
||||
"description": "Update the generator defaults to maintain the previous style guide behavior.",
|
||||
"factory": "./src/migrations/update-21-2-0/set-generator-defaults-for-previous-style-guide"
|
||||
},
|
||||
"update-module-resolution": {
|
||||
"version": "21.2.0-beta.0",
|
||||
"requires": {
|
||||
"@angular/core": ">=20.0.0-rc.2"
|
||||
},
|
||||
"description": "Update 'moduleResolution' to 'bundler' in TypeScript configurations. You can read more about this here: https://www.typescriptlang.org/tsconfig/#moduleResolution.",
|
||||
"factory": "./src/migrations/update-21-2-0/update-module-resolution"
|
||||
}
|
||||
},
|
||||
"packageJsonUpdates": {
|
||||
@ -1624,6 +1665,71 @@
|
||||
"alwaysAddToPackageJson": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"21.2.0": {
|
||||
"version": "21.2.0-beta.0",
|
||||
"x-prompt": "Do you want to update the Angular version to v20?",
|
||||
"requires": {
|
||||
"@angular/core": ">=19.2.0 <20.0.0-rc.2"
|
||||
},
|
||||
"packages": {
|
||||
"@angular-devkit/build-angular": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-devkit/core": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-devkit/schematics": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/build": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/pwa": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/ssr": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@schematics/angular": {
|
||||
"version": "20.0.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-devkit/architect": {
|
||||
"version": "0.2000.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-devkit/build-webpack": {
|
||||
"version": "0.2000.0-rc.3",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/core": {
|
||||
"version": "20.0.0-rc.2",
|
||||
"alwaysAddToPackageJson": true
|
||||
},
|
||||
"@angular/material": {
|
||||
"version": "20.0.0-rc.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/cdk": {
|
||||
"version": "20.0.0-rc.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/google-maps": {
|
||||
"version": "20.0.0-rc.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"ng-packagr": {
|
||||
"version": "20.0.0-rc.1",
|
||||
"alwaysAddToPackageJson": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
"magic-string",
|
||||
"enquirer",
|
||||
"find-cache-dir",
|
||||
"piscina",
|
||||
"webpack"
|
||||
],
|
||||
"keepLifecycleScripts": true
|
||||
|
||||
@ -47,32 +47,44 @@
|
||||
"migrations": "./migrations.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nx/devkit": "file:../devkit",
|
||||
"@nx/eslint": "file:../eslint",
|
||||
"@nx/js": "file:../js",
|
||||
"@nx/module-federation": "file:../module-federation",
|
||||
"@nx/rspack": "file:../rspack",
|
||||
"@nx/web": "file:../web",
|
||||
"@nx/webpack": "file:../webpack",
|
||||
"@nx/workspace": "file:../workspace",
|
||||
"@phenomnomnominal/tsquery": "~5.0.1",
|
||||
"@typescript-eslint/type-utils": "^8.0.0",
|
||||
"enquirer": "~2.3.6",
|
||||
"magic-string": "~0.30.2",
|
||||
"picocolors": "^1.1.0",
|
||||
"picomatch": "4.0.2",
|
||||
"magic-string": "~0.30.2",
|
||||
"semver": "^7.5.3",
|
||||
"tslib": "^2.3.0",
|
||||
"webpack-merge": "^5.8.0",
|
||||
"@nx/devkit": "file:../devkit",
|
||||
"@nx/js": "file:../js",
|
||||
"@nx/eslint": "file:../eslint",
|
||||
"@nx/webpack": "file:../webpack",
|
||||
"@nx/rspack": "file:../rspack",
|
||||
"@nx/module-federation": "file:../module-federation",
|
||||
"@nx/web": "file:../web",
|
||||
"@nx/workspace": "file:../workspace",
|
||||
"piscina": "^4.4.0"
|
||||
"webpack-merge": "^5.8.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular-devkit/build-angular": ">= 17.0.0 < 20.0.0",
|
||||
"@angular-devkit/core": ">= 17.0.0 < 20.0.0",
|
||||
"@angular-devkit/schematics": ">= 17.0.0 < 20.0.0",
|
||||
"@schematics/angular": ">= 17.0.0 < 20.0.0",
|
||||
"@angular/build": ">= 18.0.0 < 21.0.0",
|
||||
"@angular-devkit/build-angular": ">= 18.0.0 < 21.0.0",
|
||||
"@angular-devkit/core": ">= 18.0.0 < 21.0.0",
|
||||
"@angular-devkit/schematics": ">= 18.0.0 < 21.0.0",
|
||||
"@schematics/angular": ">= 18.0.0 < 21.0.0",
|
||||
"ng-packagr": ">= 18.0.0 < 21.0.0",
|
||||
"rxjs": "^6.5.3 || ^7.5.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@angular/build": {
|
||||
"optional": true
|
||||
},
|
||||
"@angular-devkit/build-angular": {
|
||||
"optional": true
|
||||
},
|
||||
"ng-packagr": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
|
||||
@ -195,7 +195,9 @@ function normalizeBuildTargetOptions(
|
||||
},
|
||||
buildContext
|
||||
);
|
||||
const buildOptions = withSchemaDefaults(options);
|
||||
const project =
|
||||
buildContext.projectsConfigurations.projects[buildContext.projectName];
|
||||
const buildOptions = withSchemaDefaults(options, project, buildContext.root);
|
||||
|
||||
// cypress creates a tsconfig if one isn't preset
|
||||
// that contains all the support required for angular and component tests
|
||||
@ -305,9 +307,18 @@ Note: this may fail, setting the correct 'sourceRoot' for ${buildContext.project
|
||||
};
|
||||
}
|
||||
|
||||
function withSchemaDefaults(options: any): BrowserBuilderSchema {
|
||||
function withSchemaDefaults(
|
||||
options: any,
|
||||
project: ProjectConfiguration,
|
||||
workspaceRoot: string
|
||||
): BrowserBuilderSchema {
|
||||
if (!options.main && !options.browser) {
|
||||
throw new Error('Missing executor options "main" and "browser"');
|
||||
const sourceRoot =
|
||||
project.sourceRoot ?? joinPathFragments(project.root, 'src');
|
||||
options.browser = joinPathFragments(sourceRoot, 'main.ts');
|
||||
if (!existsSync(join(workspaceRoot, options.browser))) {
|
||||
throw new Error('Missing executor options "main" and "browser"');
|
||||
}
|
||||
}
|
||||
if (!options.index) {
|
||||
throw new Error('Missing executor options "index"');
|
||||
|
||||
@ -12,12 +12,13 @@ import { getRootTsConfigPath } from '@nx/js';
|
||||
import type { DependentBuildableProjectNode } from '@nx/js/src/utils/buildable-libs-utils';
|
||||
import { WebpackNxBuildCoordinationPlugin } from '@nx/webpack/src/plugins/webpack-nx-build-coordination-plugin';
|
||||
import { existsSync } from 'fs';
|
||||
import { readNxJson } from 'nx/src/config/configuration';
|
||||
import { isNpmProject } from 'nx/src/project-graph/operators';
|
||||
import { readCachedProjectConfiguration } from 'nx/src/project-graph/project-graph';
|
||||
import { relative } from 'path';
|
||||
import { combineLatest, from } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { getInstalledAngularVersionInfo } from '../../executors/utilities/angular-version-utils';
|
||||
import { assertBuilderPackageIsInstalled } from '../../executors/utilities/builder-package';
|
||||
import {
|
||||
loadIndexHtmlTransformer,
|
||||
loadMiddleware,
|
||||
@ -31,13 +32,7 @@ import {
|
||||
resolveIndexHtmlTransformer,
|
||||
} from '../utilities/webpack';
|
||||
import { normalizeOptions, validateOptions } from './lib';
|
||||
import type {
|
||||
NormalizedSchema,
|
||||
Schema,
|
||||
SchemaWithBrowserTarget,
|
||||
} from './schema';
|
||||
import { readNxJson } from 'nx/src/config/configuration';
|
||||
|
||||
import type { NormalizedSchema, Schema } from './schema';
|
||||
type BuildTargetOptions = {
|
||||
tsConfig: string;
|
||||
buildLibsFromSource?: boolean;
|
||||
@ -158,6 +153,7 @@ export function executeDevServerBuilder(
|
||||
|
||||
const delegateBuilderOptions = getDelegateBuilderOptions(options);
|
||||
const isUsingWebpackBuilder = ![
|
||||
'@angular/build:application',
|
||||
'@angular-devkit/build-angular:application',
|
||||
'@angular-devkit/build-angular:browser-esbuild',
|
||||
'@nx/angular:application',
|
||||
@ -171,6 +167,7 @@ export function executeDevServerBuilder(
|
||||
* handle `@nx/angular:*` executors.
|
||||
*/
|
||||
patchBuilderContext(context, !isUsingWebpackBuilder, parsedBuildTarget);
|
||||
assertBuilderPackageIsInstalled('@angular-devkit/build-angular');
|
||||
|
||||
return combineLatest([
|
||||
from(import('@angular-devkit/build-angular')),
|
||||
@ -259,14 +256,6 @@ function getDelegateBuilderOptions(
|
||||
...options,
|
||||
};
|
||||
|
||||
const { major: angularMajorVersion } = getInstalledAngularVersionInfo();
|
||||
if (angularMajorVersion <= 17) {
|
||||
(
|
||||
delegateBuilderOptions as unknown as SchemaWithBrowserTarget
|
||||
).browserTarget = delegateBuilderOptions.buildTarget;
|
||||
delete delegateBuilderOptions.buildTarget;
|
||||
}
|
||||
|
||||
// delete extra option not supported by the delegate builder
|
||||
delete delegateBuilderOptions.buildLibsFromSource;
|
||||
delete delegateBuilderOptions.watchDependencies;
|
||||
|
||||
@ -1,23 +1,11 @@
|
||||
import { getInstalledAngularVersionInfo } from '../../../executors/utilities/angular-version-utils';
|
||||
import type {
|
||||
NormalizedSchema,
|
||||
Schema,
|
||||
SchemaWithBrowserTarget,
|
||||
SchemaWithBuildTarget,
|
||||
} from '../schema';
|
||||
import type { NormalizedSchema, Schema } from '../schema';
|
||||
|
||||
export function normalizeOptions(schema: Schema): NormalizedSchema {
|
||||
let buildTarget = (schema as SchemaWithBuildTarget).buildTarget;
|
||||
if ((schema as SchemaWithBrowserTarget).browserTarget) {
|
||||
buildTarget ??= (schema as SchemaWithBrowserTarget).browserTarget;
|
||||
delete (schema as SchemaWithBrowserTarget).browserTarget;
|
||||
}
|
||||
|
||||
const { major: angularMajorVersion } = getInstalledAngularVersionInfo();
|
||||
|
||||
return {
|
||||
...schema,
|
||||
buildTarget,
|
||||
host: schema.host ?? 'localhost',
|
||||
port: schema.port ?? 4200,
|
||||
liveReload: schema.liveReload ?? true,
|
||||
|
||||
@ -6,11 +6,6 @@ import type { Schema } from '../schema';
|
||||
export function validateOptions(options: Schema): void {
|
||||
const { version: angularVersion } = getInstalledAngularVersionInfo();
|
||||
|
||||
if (lt(angularVersion, '17.2.0') && options.prebundle) {
|
||||
throw new Error(stripIndents`The "prebundle" option is only supported in Angular >= 17.2.0. You are currently using "${angularVersion}".
|
||||
You can resolve this error by removing the "prebundle" option or by migrating to Angular 17.2.0.`);
|
||||
}
|
||||
|
||||
if (lt(angularVersion, '18.1.0') && options.inspect) {
|
||||
throw new Error(stripIndents`The "inspect" option is only supported in Angular >= 18.1.0. You are currently using "${angularVersion}".
|
||||
You can resolve this error by removing the "inspect" option or by migrating to Angular 18.1.0.`);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
interface BaseSchema {
|
||||
interface Schema {
|
||||
buildTarget: string;
|
||||
port?: number;
|
||||
host?: string;
|
||||
proxyConfig?: string;
|
||||
@ -24,20 +25,7 @@ interface BaseSchema {
|
||||
watchDependencies?: boolean;
|
||||
}
|
||||
|
||||
export type SchemaWithBrowserTarget = BaseSchema & {
|
||||
/**
|
||||
* @deprecated Use `buildTarget` instead. It will be removed when Angular v20 is released.
|
||||
*/
|
||||
browserTarget: string;
|
||||
};
|
||||
|
||||
export type SchemaWithBuildTarget = BaseSchema & {
|
||||
buildTarget: string;
|
||||
};
|
||||
|
||||
export type Schema = SchemaWithBrowserTarget | SchemaWithBuildTarget;
|
||||
|
||||
export type NormalizedSchema = SchemaWithBuildTarget & {
|
||||
export type NormalizedSchema = Schema & {
|
||||
liveReload: boolean;
|
||||
open: boolean;
|
||||
ssl: boolean;
|
||||
|
||||
@ -14,12 +14,6 @@
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"browserTarget": {
|
||||
"type": "string",
|
||||
"description": "A browser builder target to serve in the format of `project:target[:configuration]`. Ignored if `buildTarget` is set.",
|
||||
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$",
|
||||
"x-deprecated": "Use 'buildTarget' instead. It will be removed when Angular v20 is released."
|
||||
},
|
||||
"buildTarget": {
|
||||
"type": "string",
|
||||
"description": "A build builder target to serve in the format of `project:target[:configuration]`.",
|
||||
@ -128,7 +122,7 @@
|
||||
]
|
||||
},
|
||||
"prebundle": {
|
||||
"description": "Enable and control the Vite-based development server's prebundling capabilities. To enable prebundling, the Angular CLI cache must also be enabled. This option has no effect when using the 'browser' or other Webpack-based builders. _Note: this is only supported in Angular versions >= 17.2.0_.",
|
||||
"description": "Enable and control the Vite-based development server's prebundling capabilities. To enable prebundling, the Angular CLI cache must also be enabled. This option has no effect when using the 'browser' or other Webpack-based builders.",
|
||||
"oneOf": [
|
||||
{ "type": "boolean" },
|
||||
{
|
||||
@ -147,7 +141,7 @@
|
||||
},
|
||||
"buildLibsFromSource": {
|
||||
"type": "boolean",
|
||||
"description": "Read buildable libraries from source instead of building them separately. If not set, it will take the value specified in the `browserTarget` options, or it will default to `true` if it's also not set in the `browserTarget` options.",
|
||||
"description": "Read buildable libraries from source instead of building them separately. If not set, it will take the value specified in the `buildTarget` options, or it will default to `true` if it's also not set in the `buildTarget` options.",
|
||||
"x-priority": "important"
|
||||
},
|
||||
"esbuildMiddleware": {
|
||||
@ -165,5 +159,5 @@
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"anyOf": [{ "required": ["buildTarget"] }, { "required": ["browserTarget"] }]
|
||||
"required": ["buildTarget"]
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import { getDependencyConfigs } from 'nx/src/tasks-runner/utils';
|
||||
import { relative } from 'path';
|
||||
import { from, Observable } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { assertBuilderPackageIsInstalled } from '../../executors/utilities/builder-package';
|
||||
import { createTmpTsConfigForBuildableLibs } from '../utilities/buildable-libs';
|
||||
import {
|
||||
mergeCustomWebpackConfig,
|
||||
@ -98,6 +99,7 @@ export function executeWebpackBrowserBuilder(
|
||||
);
|
||||
}
|
||||
|
||||
assertBuilderPackageIsInstalled('@angular-devkit/build-angular');
|
||||
return from(import('@angular-devkit/build-angular')).pipe(
|
||||
switchMap(({ executeBrowserBuilder }) =>
|
||||
executeBrowserBuilder(delegateBuilderOptions, context as any, {
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import type { BuilderContext } from '@angular-devkit/architect';
|
||||
import type { ServerBuilderOutput } from '@angular-devkit/build-angular';
|
||||
import {
|
||||
joinPathFragments,
|
||||
normalizePath,
|
||||
@ -7,14 +9,17 @@ import { existsSync } from 'fs';
|
||||
import { relative } from 'path';
|
||||
import { Observable, from } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { assertBuilderPackageIsInstalled } from '../../executors/utilities/builder-package';
|
||||
import { createTmpTsConfigForBuildableLibs } from '../utilities/buildable-libs';
|
||||
import { mergeCustomWebpackConfig } from '../utilities/webpack';
|
||||
import { Schema } from './schema';
|
||||
|
||||
function buildServerApp(
|
||||
options: Schema,
|
||||
context: import('@angular-devkit/architect').BuilderContext
|
||||
): Observable<import('@angular-devkit/build-angular').ServerBuilderOutput> {
|
||||
context: BuilderContext
|
||||
): Observable<ServerBuilderOutput> {
|
||||
assertBuilderPackageIsInstalled('@angular-devkit/build-angular');
|
||||
|
||||
const { buildLibsFromSource, customWebpackConfig, ...delegateOptions } =
|
||||
options;
|
||||
// If there is a path to custom webpack config
|
||||
@ -47,7 +52,7 @@ function buildServerApp(
|
||||
|
||||
function buildServerAppWithCustomWebpackConfiguration(
|
||||
options: Schema,
|
||||
context: import('@angular-devkit/architect').BuilderContext,
|
||||
context: BuilderContext,
|
||||
pathToWebpackConfig: string
|
||||
) {
|
||||
return from(import('@angular-devkit/build-angular')).pipe(
|
||||
@ -89,8 +94,8 @@ function buildServerAppWithCustomWebpackConfiguration(
|
||||
|
||||
export function executeWebpackServerBuilder(
|
||||
options: Schema,
|
||||
context: import('@angular-devkit/architect').BuilderContext
|
||||
): Observable<import('@angular-devkit/build-angular').ServerBuilderOutput> {
|
||||
context: BuilderContext
|
||||
): Observable<ServerBuilderOutput> {
|
||||
options.buildLibsFromSource ??= true;
|
||||
|
||||
process.env.NX_BUILD_LIBS_FROM_SOURCE = `${options.buildLibsFromSource}`;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import type { buildApplication as buildApplicationFn } from '@angular-devkit/build-angular';
|
||||
import type { BuilderOutput } from '@angular-devkit/architect';
|
||||
import type { ExecutorContext } from '@nx/devkit';
|
||||
import type { DependentBuildableProjectNode } from '@nx/js/src/utils/buildable-libs-utils';
|
||||
import { createBuilderContext } from 'nx/src/adapter/ngcli-adapter';
|
||||
import { gte } from 'semver';
|
||||
import { getInstalledAngularVersionInfo } from '../utilities/angular-version-utils';
|
||||
import { createTmpTsConfigForBuildableLibs } from '../utilities/buildable-libs';
|
||||
import { assertBuilderPackageIsInstalled } from '../utilities/builder-package';
|
||||
import {
|
||||
loadIndexHtmlTransformer,
|
||||
loadPlugins,
|
||||
@ -16,7 +16,7 @@ import { validateOptions } from './utils/validate-options';
|
||||
export default async function* applicationExecutor(
|
||||
options: ApplicationExecutorOptions,
|
||||
context: ExecutorContext
|
||||
): ReturnType<typeof buildApplicationFn> {
|
||||
): AsyncIterable<BuilderOutput> {
|
||||
validateOptions(options);
|
||||
options = normalizeOptions(options);
|
||||
|
||||
@ -53,19 +53,20 @@ export default async function* applicationExecutor(
|
||||
context
|
||||
);
|
||||
|
||||
const { version: angularVersion } = getInstalledAngularVersionInfo();
|
||||
if (gte(angularVersion, '17.1.0')) {
|
||||
const { buildApplication } = await import('@angular-devkit/build-angular');
|
||||
const { major: angularMajorVersion } = getInstalledAngularVersionInfo();
|
||||
if (angularMajorVersion >= 20) {
|
||||
assertBuilderPackageIsInstalled('@angular/build');
|
||||
const { buildApplication } = await import('@angular/build');
|
||||
return yield* buildApplication(delegateExecutorOptions, builderContext, {
|
||||
codePlugins: plugins,
|
||||
indexHtmlTransformer,
|
||||
});
|
||||
}
|
||||
|
||||
const { buildApplication } = require('@angular-devkit/build-angular');
|
||||
return yield* buildApplication(
|
||||
delegateExecutorOptions,
|
||||
builderContext,
|
||||
plugins
|
||||
);
|
||||
assertBuilderPackageIsInstalled('@angular-devkit/build-angular');
|
||||
const { buildApplication } = await import('@angular-devkit/build-angular');
|
||||
return yield* buildApplication(delegateExecutorOptions, builderContext, {
|
||||
codePlugins: plugins,
|
||||
indexHtmlTransformer,
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { ApplicationBuilderOptions } from '@angular-devkit/build-angular';
|
||||
import type { ApplicationBuilderOptions } from '@angular/build';
|
||||
import type { PluginSpec } from '../utilities/esbuild-extensions';
|
||||
|
||||
export interface ApplicationExecutorOptions extends ApplicationBuilderOptions {
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
"description": "The full path for the browser entry point to the application, relative to the current workspace."
|
||||
},
|
||||
"server": {
|
||||
"type": "string",
|
||||
"description": "The full path for the server entry point to the application, relative to the current workspace.",
|
||||
"oneOf": [
|
||||
{
|
||||
@ -48,7 +47,7 @@
|
||||
},
|
||||
"deployUrl": {
|
||||
"type": "string",
|
||||
"description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations. _Note: this is only supported in Angular versions >= 17.3.0_."
|
||||
"description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
|
||||
},
|
||||
"security": {
|
||||
"description": "Security features to protect against XSS and other common attacks. _Note: this is only supported in Angular versions >= 19.0.0_.",
|
||||
@ -206,7 +205,7 @@
|
||||
"clearScreen": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Automatically clear the terminal screen during rebuilds. _Note: this is only supported in Angular versions >= 17.2.0_."
|
||||
"description": "Automatically clear the terminal screen during rebuilds."
|
||||
},
|
||||
"optimization": {
|
||||
"description": "Enables optimization of the build output. Including minification of scripts and styles, tree-shaking, dead-code elimination, inlining of critical CSS and fonts inlining. For more information, see https://angular.dev/reference/configs/workspace-config#optimization-configuration.",
|
||||
@ -239,7 +238,7 @@
|
||||
},
|
||||
"removeSpecialComments": {
|
||||
"type": "boolean",
|
||||
"description": "Remove comments in global CSS that contains '@license' or '@preserve' or that starts with '//!' or '/*!'. _Note: this is only supported in Angular versions >= 17.1.0_.",
|
||||
"description": "Remove comments in global CSS that contains '@license' or '@preserve' or that starts with '//!' or '/*!'.",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
@ -279,19 +278,26 @@
|
||||
]
|
||||
},
|
||||
"loader": {
|
||||
"description": "Defines the type of loader to use with a specified file extension when used with a JavaScript `import`. `text` inlines the content as a string; `binary` inlines the content as a Uint8Array; `file` emits the file and provides the runtime location of the file; `empty` considers the content to be empty and not include it in bundles. _Note: this is only supported in Angular versions >= 17.1.0_.",
|
||||
"description": "Defines the type of loader to use with a specified file extension when used with a JavaScript `import`. `text` inlines the content as a string; `binary` inlines the content as a Uint8Array; `file` emits the file and provides the runtime location of the file; `empty` considers the content to be empty and not include it in bundles.",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^\\.\\S+$": { "enum": ["text", "binary", "file", "empty"] }
|
||||
}
|
||||
},
|
||||
"define": {
|
||||
"description": "Defines global identifiers that will be replaced with a specified constant value when found in any JavaScript or TypeScript code including libraries. The value will be used directly. String values must be put in quotes. Identifiers within Angular metadata such as Component Decorators will not be replaced. _Note: this is only supported in Angular versions >= 17.2.0_.",
|
||||
"description": "Defines global identifiers that will be replaced with a specified constant value when found in any JavaScript or TypeScript code including libraries. The value will be used directly. String values must be put in quotes. Identifiers within Angular metadata such as Component Decorators will not be replaced.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"description": "Custom package resolution conditions used to resolve conditional exports/imports. Defaults to ['module', 'development'/'production']. The following special conditions are always present if the requirements are satisfied: 'default', 'import', 'require', 'browser', 'node'. _Note: this is only supported in Angular versions >= 20.0.0_.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"fileReplacements": {
|
||||
"description": "Replace compilation source files with other compilation source files in the build.",
|
||||
"type": "array",
|
||||
@ -301,7 +307,7 @@
|
||||
"default": []
|
||||
},
|
||||
"outputPath": {
|
||||
"description": "Specify the output path relative to workspace root. _Note: the object notation is only supported in Angular versions >= 17.1.0_.",
|
||||
"description": "Specify the output path relative to workspace root.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
@ -368,6 +374,11 @@
|
||||
"type": "boolean",
|
||||
"description": "Resolve vendor packages source maps.",
|
||||
"default": false
|
||||
},
|
||||
"sourcesContent": {
|
||||
"type": "boolean",
|
||||
"description": "Output original source content for files within the source map. _Note: this is only supported in Angular versions >= 20.0.0_.",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@ -500,7 +511,7 @@
|
||||
"preloadInitial": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Generates 'preload', 'modulepreload', and 'preconnect' link elements for initial application files and resources. _Note: this is only supported in Angular versions >= 17.1.0_."
|
||||
"description": "Generates 'preload', 'modulepreload', and 'preconnect' link elements for initial application files and resources."
|
||||
}
|
||||
},
|
||||
"required": ["input"]
|
||||
@ -636,12 +647,12 @@
|
||||
}
|
||||
},
|
||||
"indexHtmlTransformer": {
|
||||
"description": "Path to a file exposing a default function to transform the `index.html` file. _Note: this is only supported in Angular versions >= 17.1.0_.",
|
||||
"description": "Path to a file exposing a default function to transform the `index.html` file.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["outputPath", "index", "browser", "tsConfig"],
|
||||
"required": ["outputPath", "tsConfig"],
|
||||
"definitions": {
|
||||
"assetPattern": {
|
||||
"oneOf": [
|
||||
|
||||
@ -35,5 +35,15 @@ export function normalizeOptions(
|
||||
prerender ??= false;
|
||||
}
|
||||
|
||||
return { ...options, appShell, prerender, security };
|
||||
let sourceMap = options.sourceMap;
|
||||
if (
|
||||
sourceMap &&
|
||||
typeof sourceMap === 'object' &&
|
||||
sourceMap.sourcesContent !== undefined &&
|
||||
angularMajorVersion < 20
|
||||
) {
|
||||
delete sourceMap.sourcesContent;
|
||||
}
|
||||
|
||||
return { ...options, appShell, prerender, security, sourceMap };
|
||||
}
|
||||
|
||||
@ -5,73 +5,6 @@ import type { ApplicationExecutorOptions } from '../schema';
|
||||
export function validateOptions(options: ApplicationExecutorOptions): void {
|
||||
const { version: angularVersion } = getInstalledAngularVersionInfo();
|
||||
|
||||
if (lt(angularVersion, '17.1.0')) {
|
||||
if (options.loader) {
|
||||
throw new Error(
|
||||
`The "loader" option requires Angular version 17.1.0 or greater. You are currently using version ${angularVersion}.`
|
||||
);
|
||||
}
|
||||
|
||||
if (options.indexHtmlTransformer) {
|
||||
throw new Error(
|
||||
`The "indexHtmlTransformer" option requires Angular version 17.1.0 or greater. You are currently using version ${angularVersion}.`
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
typeof options.index === 'object' &&
|
||||
options.index.preloadInitial !== undefined
|
||||
) {
|
||||
throw new Error(
|
||||
`The "index.preloadInitial" option requires Angular version 17.1.0 or greater. You are currently using version ${angularVersion}.`
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
options.optimization &&
|
||||
typeof options.optimization !== 'boolean' &&
|
||||
options.optimization.styles &&
|
||||
typeof options.optimization.styles !== 'boolean'
|
||||
) {
|
||||
if (options.optimization.styles.removeSpecialComments === false) {
|
||||
throw new Error(
|
||||
`The "optimization.styles.removeSpecialComments" option requires Angular version 17.1.0 or greater. You are currently using version ${angularVersion}.`
|
||||
);
|
||||
} else if (options.optimization.styles.removeSpecialComments === true) {
|
||||
// silently remove the option, as it was the default before 17.1.0
|
||||
delete options.optimization.styles.removeSpecialComments;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof options.outputPath === 'object') {
|
||||
throw new Error(
|
||||
`The "outputPath" option as an object requires Angular version 17.1.0 or greater. You are currently using version ${angularVersion}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (lt(angularVersion, '17.2.0')) {
|
||||
if (options.define) {
|
||||
throw new Error(
|
||||
`The "define" option requires Angular version 17.2.0 or greater. You are currently using version ${angularVersion}.`
|
||||
);
|
||||
}
|
||||
|
||||
if (options.clearScreen !== undefined) {
|
||||
throw new Error(
|
||||
`The "clearScreen" option requires Angular version 17.2.0 or greater. You are currently using version ${angularVersion}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (lt(angularVersion, '17.3.0')) {
|
||||
if (options.deployUrl) {
|
||||
throw new Error(
|
||||
`The "deployUrl" option requires Angular version 17.3.0 or greater. You are currently using version ${angularVersion}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (lt(angularVersion, '19.0.0')) {
|
||||
if (options.outputMode) {
|
||||
throw new Error(
|
||||
@ -103,4 +36,22 @@ export function validateOptions(options: ApplicationExecutorOptions): void {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (lt(angularVersion, '20.0.0')) {
|
||||
if (
|
||||
options.sourceMap &&
|
||||
typeof options.sourceMap === 'object' &&
|
||||
options.sourceMap.sourcesContent === false
|
||||
) {
|
||||
throw new Error(
|
||||
`The "sourceMap.sourcesContent" option requires Angular version 20.0.0 or greater. You are currently using version ${angularVersion}.`
|
||||
);
|
||||
}
|
||||
|
||||
if (options.conditions) {
|
||||
throw new Error(
|
||||
`The "conditions" option requires Angular version 20.0.0 or greater. You are currently using version ${angularVersion}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import type { ExtractI18nBuilderOptions } from '@angular-devkit/build-angular';
|
||||
import { parseTargetString, type ExecutorContext } from '@nx/devkit';
|
||||
import { createBuilderContext } from 'nx/src/adapter/ngcli-adapter';
|
||||
import { readCachedProjectConfiguration } from 'nx/src/project-graph/project-graph';
|
||||
import { getInstalledAngularVersionInfo } from '../utilities/angular-version-utils';
|
||||
import { assertBuilderPackageIsInstalled } from '../utilities/builder-package';
|
||||
import { patchBuilderContext } from '../utilities/patch-builder-context';
|
||||
import type { ExtractI18nExecutorOptions } from './schema';
|
||||
|
||||
@ -11,14 +10,15 @@ export default async function* extractI18nExecutor(
|
||||
context: ExecutorContext
|
||||
) {
|
||||
const parsedBuildTarget = parseTargetString(options.buildTarget, context);
|
||||
const browserTargetProjectConfiguration = readCachedProjectConfiguration(
|
||||
const buildTargetProjectConfiguration = readCachedProjectConfiguration(
|
||||
parsedBuildTarget.project
|
||||
);
|
||||
|
||||
const buildTarget =
|
||||
browserTargetProjectConfiguration.targets[parsedBuildTarget.target];
|
||||
buildTargetProjectConfiguration.targets[parsedBuildTarget.target];
|
||||
|
||||
const isUsingEsbuildBuilder = [
|
||||
'@angular/build:application',
|
||||
'@angular-devkit/build-angular:application',
|
||||
'@angular-devkit/build-angular:browser-esbuild',
|
||||
'@nx/angular:application',
|
||||
@ -42,29 +42,10 @@ export default async function* extractI18nExecutor(
|
||||
*/
|
||||
patchBuilderContext(builderContext, isUsingEsbuildBuilder, parsedBuildTarget);
|
||||
|
||||
assertBuilderPackageIsInstalled('@angular-devkit/build-angular');
|
||||
const { executeExtractI18nBuilder } = await import(
|
||||
'@angular-devkit/build-angular'
|
||||
);
|
||||
const delegateBuilderOptions = getDelegateBuilderOptions(options);
|
||||
|
||||
return await executeExtractI18nBuilder(
|
||||
delegateBuilderOptions,
|
||||
builderContext
|
||||
);
|
||||
}
|
||||
|
||||
function getDelegateBuilderOptions(
|
||||
options: ExtractI18nExecutorOptions
|
||||
): ExtractI18nBuilderOptions {
|
||||
const delegateBuilderOptions: ExtractI18nBuilderOptions & {
|
||||
browserTarget?: string;
|
||||
} = { ...options };
|
||||
|
||||
const { major: angularMajorVersion } = getInstalledAngularVersionInfo();
|
||||
if (angularMajorVersion <= 17) {
|
||||
delegateBuilderOptions.browserTarget = delegateBuilderOptions.buildTarget;
|
||||
delete delegateBuilderOptions.buildTarget;
|
||||
}
|
||||
|
||||
return delegateBuilderOptions;
|
||||
return await executeExtractI18nBuilder(options, builderContext);
|
||||
}
|
||||
|
||||
@ -1,8 +1,3 @@
|
||||
import type { ExtractI18nBuilderOptions } from '@angular-devkit/build-angular';
|
||||
|
||||
export type ExtractI18nExecutorOptions = Omit<
|
||||
ExtractI18nBuilderOptions,
|
||||
'browserTarget'
|
||||
> & {
|
||||
buildTarget: string;
|
||||
};
|
||||
export type ExtractI18nExecutorOptions = ExtractI18nBuilderOptions;
|
||||
|
||||
@ -38,6 +38,11 @@
|
||||
"outFile": {
|
||||
"type": "string",
|
||||
"description": "Name of the file to output."
|
||||
},
|
||||
"i18nDuplicateTranslation": {
|
||||
"type": "string",
|
||||
"description": "How to handle duplicate translations. _Note: this is only available in Angular 20.0.0 and above._",
|
||||
"enum": ["error", "warning", "ignore"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
import { lt } from 'semver';
|
||||
import { getInstalledAngularVersionInfo } from '../../utilities/angular-version-utils';
|
||||
import type { ExtractI18nExecutorOptions } from '../schema';
|
||||
|
||||
export function validateOptions(options: ExtractI18nExecutorOptions): void {
|
||||
const { version: angularVersion } = getInstalledAngularVersionInfo();
|
||||
|
||||
if (lt(angularVersion, '20.0.0')) {
|
||||
if (options.i18nDuplicateTranslation) {
|
||||
throw new Error(
|
||||
`The "i18nDuplicateTranslation" option requires Angular version 20.0.0 or greater. You are currently using version ${angularVersion}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,25 +1,14 @@
|
||||
import type {
|
||||
NormalizedSchema,
|
||||
Schema,
|
||||
SchemaWithBrowserTarget,
|
||||
SchemaWithBuildTarget,
|
||||
} from '../schema';
|
||||
import type { NormalizedSchema, Schema } from '../schema';
|
||||
import { join } from 'path';
|
||||
import { workspaceRoot } from '@nx/devkit';
|
||||
|
||||
export function normalizeOptions(schema: Schema): NormalizedSchema {
|
||||
let buildTarget = (schema as SchemaWithBuildTarget).buildTarget;
|
||||
if ((schema as SchemaWithBrowserTarget).browserTarget) {
|
||||
buildTarget ??= (schema as SchemaWithBrowserTarget).browserTarget;
|
||||
delete (schema as SchemaWithBrowserTarget).browserTarget;
|
||||
}
|
||||
schema.buildLibsFromSource ??= true;
|
||||
process.env.NX_BUILD_LIBS_FROM_SOURCE = `${schema.buildLibsFromSource}`;
|
||||
process.env.NX_BUILD_TARGET = `${buildTarget}`;
|
||||
process.env.NX_BUILD_TARGET = `${schema.buildTarget}`;
|
||||
|
||||
return {
|
||||
...schema,
|
||||
buildTarget,
|
||||
devRemotes: schema.devRemotes ?? [],
|
||||
host: schema.host ?? 'localhost',
|
||||
port: schema.port ?? 4200,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import type { DevRemoteDefinition } from '../../builders/utilities/module-federation';
|
||||
|
||||
interface BaseSchema {
|
||||
interface Schema {
|
||||
buildTarget: string;
|
||||
port?: number;
|
||||
host?: string;
|
||||
proxyConfig?: string;
|
||||
@ -28,20 +29,7 @@ interface BaseSchema {
|
||||
buildLibsFromSource?: boolean;
|
||||
}
|
||||
|
||||
export type SchemaWithBrowserTarget = BaseSchema & {
|
||||
/**
|
||||
* @deprecated Use `buildTarget` instead. It will be removed when Angular v20 is released.
|
||||
*/
|
||||
browserTarget: string;
|
||||
};
|
||||
|
||||
export type SchemaWithBuildTarget = BaseSchema & {
|
||||
buildTarget: string;
|
||||
};
|
||||
|
||||
export type Schema = SchemaWithBrowserTarget | SchemaWithBuildTarget;
|
||||
|
||||
export type NormalizedSchema = SchemaWithBuildTarget & {
|
||||
export type NormalizedSchema = Schema & {
|
||||
devRemotes: DevRemoteDefinition[];
|
||||
liveReload: boolean;
|
||||
open: boolean;
|
||||
|
||||
@ -12,12 +12,6 @@
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"browserTarget": {
|
||||
"type": "string",
|
||||
"description": "A browser builder target to serve in the format of `project:target[:configuration]`.",
|
||||
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$",
|
||||
"x-deprecated": "Use 'buildTarget' instead. It will be removed when Angular v20 is released."
|
||||
},
|
||||
"buildTarget": {
|
||||
"type": "string",
|
||||
"description": "A build builder target to serve in the format of `project:target[:configuration]`.",
|
||||
@ -166,18 +160,11 @@
|
||||
},
|
||||
"buildLibsFromSource": {
|
||||
"type": "boolean",
|
||||
"description": "Read buildable libraries from source instead of building them separately. If not set, it will take the value specified in the `browserTarget` options, or it will default to `true` if it's also not set in the `browserTarget` options.",
|
||||
"description": "Read buildable libraries from source instead of building them separately. If not set, it will take the value specified in the `buildTarget` options, or it will default to `true` if it's also not set in the `buildTarget` options.",
|
||||
"x-priority": "important"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"anyOf": [
|
||||
{
|
||||
"required": ["buildTarget"]
|
||||
},
|
||||
{
|
||||
"required": ["browserTarget"]
|
||||
}
|
||||
],
|
||||
"required": ["buildTarget"],
|
||||
"examplesFile": "../../../docs/module-federation-dev-server-examples.md"
|
||||
}
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
import { executeSSRDevServerBuilder } from '@angular-devkit/build-angular';
|
||||
import { type ExecutorContext, logger } from '@nx/devkit';
|
||||
import { existsSync } from 'fs';
|
||||
import { readProjectsConfigurationFromProjectGraph } from 'nx/src/project-graph/project-graph';
|
||||
import { extname, join } from 'path';
|
||||
import {
|
||||
getDynamicMfManifestFile,
|
||||
validateDevRemotes,
|
||||
} from '../../builders/utilities/module-federation';
|
||||
import type { Schema } from './schema';
|
||||
import { startRemoteIterators } from '@nx/module-federation/src/executors/utils';
|
||||
import { startRemotes } from './lib/start-dev-remotes';
|
||||
import {
|
||||
combineAsyncIterables,
|
||||
createAsyncIterable,
|
||||
mapAsyncIterable,
|
||||
} from '@nx/devkit/src/utils/async-iterable';
|
||||
import { eachValueFrom } from '@nx/devkit/src/utils/rxjs-for-await';
|
||||
import { createBuilderContext } from 'nx/src/adapter/ngcli-adapter';
|
||||
import { normalizeOptions } from './lib/normalize-options';
|
||||
import { startRemoteIterators } from '@nx/module-federation/src/executors/utils';
|
||||
import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open';
|
||||
import { existsSync } from 'fs';
|
||||
import { createBuilderContext } from 'nx/src/adapter/ngcli-adapter';
|
||||
import { readProjectsConfigurationFromProjectGraph } from 'nx/src/project-graph/project-graph';
|
||||
import { extname, join } from 'path';
|
||||
import {
|
||||
getDynamicMfManifestFile,
|
||||
validateDevRemotes,
|
||||
} from '../../builders/utilities/module-federation';
|
||||
import { assertBuilderPackageIsInstalled } from '../utilities/builder-package';
|
||||
import { normalizeOptions } from './lib/normalize-options';
|
||||
import { startRemotes } from './lib/start-dev-remotes';
|
||||
import type { Schema } from './schema';
|
||||
|
||||
export async function* moduleFederationSsrDevServerExecutor(
|
||||
schema: Schema,
|
||||
@ -26,6 +26,11 @@ export async function* moduleFederationSsrDevServerExecutor(
|
||||
) {
|
||||
const options = normalizeOptions(schema);
|
||||
|
||||
assertBuilderPackageIsInstalled('@angular-devkit/build-angular');
|
||||
const { executeSSRDevServerBuilder } = await import(
|
||||
'@angular-devkit/build-angular'
|
||||
);
|
||||
|
||||
const currIter = eachValueFrom(
|
||||
executeSSRDevServerBuilder(
|
||||
options,
|
||||
|
||||
@ -1,34 +1,117 @@
|
||||
import type {
|
||||
DestinationFiles,
|
||||
NgEntryPoint as NgEntryPointBase,
|
||||
} from 'ng-packagr/lib/ng-package/entry-point/entry-point';
|
||||
import type { NgPackageConfig } from 'ng-packagr/ng-package.schema';
|
||||
import { dirname } from 'node:path';
|
||||
} from 'ng-packagr/src/lib/ng-package/entry-point/entry-point';
|
||||
import type { NgPackageConfig } from 'ng-packagr/src/ng-package.schema';
|
||||
import { dirname, join, relative } from 'node:path';
|
||||
import { getNgPackagrVersionInfo } from '../../../../utilities/ng-packagr/ng-packagr-version';
|
||||
import { importNgPackagrPath } from '../../../../utilities/ng-packagr/package-imports';
|
||||
|
||||
export type NgEntryPointType = NgEntryPointBase & {
|
||||
primaryDestinationPath?: string;
|
||||
};
|
||||
|
||||
export function createNgEntryPoint(
|
||||
packageJson: Record<string, any>,
|
||||
ngPackageJson: NgPackageConfig,
|
||||
basePath: string,
|
||||
secondaryData?: Record<string, any>
|
||||
): NgEntryPointBase {
|
||||
): NgEntryPointType {
|
||||
const { major: ngPackagrMajorVersion } = getNgPackagrVersionInfo();
|
||||
|
||||
const { NgEntryPoint: NgEntryPointBase } = importNgPackagrPath<
|
||||
typeof import('ng-packagr/lib/ng-package/entry-point/entry-point')
|
||||
>('ng-packagr/lib/ng-package/entry-point/entry-point', ngPackagrMajorVersion);
|
||||
typeof import('ng-packagr/src/lib/ng-package/entry-point/entry-point')
|
||||
>(
|
||||
'ng-packagr/src/lib/ng-package/entry-point/entry-point',
|
||||
ngPackagrMajorVersion
|
||||
);
|
||||
|
||||
if (ngPackagrMajorVersion < 20) {
|
||||
class NgEntryPoint extends NgEntryPointBase {
|
||||
/**
|
||||
* Point the FESM2022 files to the ESM2022 files.
|
||||
*/
|
||||
public override get destinationFiles(): DestinationFiles {
|
||||
const result = super.destinationFiles;
|
||||
result.fesm2022 = result.esm2022;
|
||||
result.fesm2022Dir = dirname(result.esm2022);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return new NgEntryPoint(
|
||||
packageJson,
|
||||
ngPackageJson,
|
||||
basePath,
|
||||
secondaryData
|
||||
);
|
||||
}
|
||||
|
||||
const { ensureUnixPath } = importNgPackagrPath<
|
||||
typeof import('ng-packagr/src/lib/utils/path')
|
||||
>('ng-packagr/src/lib/utils/path', ngPackagrMajorVersion);
|
||||
|
||||
class NgEntryPoint extends NgEntryPointBase {
|
||||
/**
|
||||
* Point the FESM2022 files to the ESM2022 files.
|
||||
*/
|
||||
public override get destinationFiles(): DestinationFiles {
|
||||
const result = super.destinationFiles;
|
||||
result.fesm2022 = result.esm2022;
|
||||
result.fesm2022Dir = dirname(result.esm2022);
|
||||
constructor(
|
||||
public readonly packageJson: Record<string, any>,
|
||||
public readonly ngPackageJson: NgPackageConfig,
|
||||
public readonly basePath: string,
|
||||
private readonly _secondaryData?: Record<string, any>
|
||||
) {
|
||||
super(packageJson, ngPackageJson, basePath, _secondaryData);
|
||||
}
|
||||
|
||||
return result;
|
||||
public get primaryDestinationPath(): string {
|
||||
return (
|
||||
this._secondaryData?.primaryDestinationPath ?? this.destinationPath
|
||||
);
|
||||
}
|
||||
|
||||
public get destinationFiles(): DestinationFiles {
|
||||
let primaryDestPath = this.destinationPath;
|
||||
let secondaryDir = '';
|
||||
|
||||
if (this._secondaryData) {
|
||||
primaryDestPath = this._secondaryData.primaryDestinationPath;
|
||||
secondaryDir = relative(
|
||||
primaryDestPath,
|
||||
this._secondaryData.destinationPath
|
||||
);
|
||||
}
|
||||
|
||||
const flatModuleFile = this.flatModuleFile;
|
||||
const pathJoinWithDest = (...paths: string[]) =>
|
||||
join(primaryDestPath, ...paths);
|
||||
|
||||
return {
|
||||
directory: ensureUnixPath(secondaryDir),
|
||||
declarations: pathJoinWithDest(
|
||||
'tmp-typings',
|
||||
secondaryDir,
|
||||
`${flatModuleFile}.d.ts`
|
||||
),
|
||||
// changed to use esm2022
|
||||
declarationsBundled: pathJoinWithDest(
|
||||
'esm2022',
|
||||
secondaryDir,
|
||||
`${flatModuleFile}.d.ts`
|
||||
),
|
||||
declarationsDir: pathJoinWithDest(secondaryDir),
|
||||
esm2022: pathJoinWithDest(
|
||||
'tmp-esm2022',
|
||||
secondaryDir,
|
||||
`${flatModuleFile}.js`
|
||||
),
|
||||
// changed to use esm2022
|
||||
fesm2022: pathJoinWithDest(
|
||||
'esm2022',
|
||||
secondaryDir,
|
||||
`${flatModuleFile}.js`
|
||||
),
|
||||
// changed to use esm2022
|
||||
fesm2022Dir: pathJoinWithDest('esm2022'),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { TransformProvider } from 'ng-packagr/lib/graph/transform.di';
|
||||
import type { TransformProvider } from 'ng-packagr/src/lib/graph/transform.di';
|
||||
import { getNgPackagrVersionInfo } from '../../../../utilities/ng-packagr/ng-packagr-version';
|
||||
import { importNgPackagrPath } from '../../../../utilities/ng-packagr/package-imports';
|
||||
import { writeBundlesTransform } from './write-bundles.transform';
|
||||
@ -7,17 +7,17 @@ export function getWriteBundlesTransformProvider(): TransformProvider {
|
||||
const { major: ngPackagrMajorVersion } = getNgPackagrVersionInfo();
|
||||
|
||||
const { provideTransform } = importNgPackagrPath<
|
||||
typeof import('ng-packagr/lib/graph/transform.di')
|
||||
>('ng-packagr/lib/graph/transform.di', ngPackagrMajorVersion);
|
||||
typeof import('ng-packagr/src/lib/graph/transform.di')
|
||||
>('ng-packagr/src/lib/graph/transform.di', ngPackagrMajorVersion);
|
||||
const { WRITE_BUNDLES_TRANSFORM_TOKEN } = importNgPackagrPath<
|
||||
typeof import('ng-packagr/lib/ng-package/entry-point/write-bundles.di')
|
||||
typeof import('ng-packagr/src/lib/ng-package/entry-point/write-bundles.di')
|
||||
>(
|
||||
'ng-packagr/lib/ng-package/entry-point/write-bundles.di',
|
||||
'ng-packagr/src/lib/ng-package/entry-point/write-bundles.di',
|
||||
ngPackagrMajorVersion
|
||||
);
|
||||
const { OPTIONS_TOKEN } = importNgPackagrPath<
|
||||
typeof import('ng-packagr/lib/ng-package/options.di')
|
||||
>('ng-packagr/lib/ng-package/options.di', ngPackagrMajorVersion);
|
||||
typeof import('ng-packagr/src/lib/ng-package/options.di')
|
||||
>('ng-packagr/src/lib/ng-package/options.di', ngPackagrMajorVersion);
|
||||
|
||||
return provideTransform({
|
||||
provide: WRITE_BUNDLES_TRANSFORM_TOKEN,
|
||||
|
||||
@ -7,29 +7,29 @@
|
||||
* - Fake the FESM2022 outputs pointing them to the ESM2022 outputs.
|
||||
*/
|
||||
|
||||
import type { NgEntryPoint } from 'ng-packagr/lib/ng-package/entry-point/entry-point';
|
||||
import type { NgPackagrOptions } from 'ng-packagr/lib/ng-package/options.di';
|
||||
import type { NgEntryPoint } from 'ng-packagr/src/lib/ng-package/entry-point/entry-point';
|
||||
import type { NgPackagrOptions } from 'ng-packagr/src/lib/ng-package/options.di';
|
||||
import { mkdir, writeFile } from 'node:fs/promises';
|
||||
import { dirname } from 'node:path';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { getNgPackagrVersionInfo } from '../../../../utilities/ng-packagr/ng-packagr-version';
|
||||
import { importNgPackagrPath } from '../../../../utilities/ng-packagr/package-imports';
|
||||
import { createNgEntryPoint } from './entry-point';
|
||||
import { createNgEntryPoint, type NgEntryPointType } from './entry-point';
|
||||
|
||||
export const writeBundlesTransform = (_options: NgPackagrOptions) => {
|
||||
const { major: ngPackagrMajorVersion } = getNgPackagrVersionInfo();
|
||||
|
||||
const { BuildGraph } = importNgPackagrPath<
|
||||
typeof import('ng-packagr/lib/graph/build-graph')
|
||||
>('ng-packagr/lib/graph/build-graph', ngPackagrMajorVersion);
|
||||
typeof import('ng-packagr/src/lib/graph/build-graph')
|
||||
>('ng-packagr/src/lib/graph/build-graph', ngPackagrMajorVersion);
|
||||
const { transformFromPromise } = importNgPackagrPath<
|
||||
typeof import('ng-packagr/lib/graph/transform')
|
||||
>('ng-packagr/lib/graph/transform', ngPackagrMajorVersion);
|
||||
typeof import('ng-packagr/src/lib/graph/transform')
|
||||
>('ng-packagr/src/lib/graph/transform', ngPackagrMajorVersion);
|
||||
const { isEntryPoint, isPackage } = importNgPackagrPath<
|
||||
typeof import('ng-packagr/lib/ng-package/nodes')
|
||||
>('ng-packagr/lib/ng-package/nodes', ngPackagrMajorVersion);
|
||||
typeof import('ng-packagr/src/lib/ng-package/nodes')
|
||||
>('ng-packagr/src/lib/ng-package/nodes', ngPackagrMajorVersion);
|
||||
const { NgPackage } = importNgPackagrPath<
|
||||
typeof import('ng-packagr/lib/ng-package/package')
|
||||
>('ng-packagr/lib/ng-package/package', ngPackagrMajorVersion);
|
||||
typeof import('ng-packagr/src/lib/ng-package/package')
|
||||
>('ng-packagr/src/lib/ng-package/package', ngPackagrMajorVersion);
|
||||
|
||||
return transformFromPromise(async (graph) => {
|
||||
const updatedGraph = new BuildGraph();
|
||||
@ -41,9 +41,13 @@ export const writeBundlesTransform = (_options: NgPackagrOptions) => {
|
||||
entry.data.destinationFiles = entryPoint.destinationFiles;
|
||||
|
||||
for (const [path, outputCache] of entry.cache.outputCache.entries()) {
|
||||
const normalizedPath = normalizeEsm2022Path(path, entryPoint);
|
||||
// write the outputs to the file system
|
||||
await mkdir(dirname(path), { recursive: true });
|
||||
await writeFile(path, outputCache.content);
|
||||
await mkdir(dirname(normalizedPath), { recursive: true });
|
||||
await writeFile(normalizedPath, outputCache.content);
|
||||
}
|
||||
if (!entry.cache.outputCache.size && entryPoint.isSecondaryEntryPoint) {
|
||||
await mkdir(entryPoint.destinationPath, { recursive: true });
|
||||
}
|
||||
} else if (isPackage(entry)) {
|
||||
entry.data = new NgPackage(
|
||||
@ -61,7 +65,26 @@ export const writeBundlesTransform = (_options: NgPackagrOptions) => {
|
||||
});
|
||||
};
|
||||
|
||||
function toCustomNgEntryPoint(entryPoint: NgEntryPoint): NgEntryPoint {
|
||||
function normalizeEsm2022Path(
|
||||
path: string,
|
||||
entryPoint: NgEntryPointType
|
||||
): string {
|
||||
if (!entryPoint.primaryDestinationPath) {
|
||||
return path;
|
||||
}
|
||||
|
||||
if (path.startsWith(join(entryPoint.primaryDestinationPath, 'tmp-esm2022'))) {
|
||||
return path.replace('tmp-esm2022', 'esm2022');
|
||||
}
|
||||
|
||||
if (path.startsWith(join(entryPoint.primaryDestinationPath, 'tmp-typings'))) {
|
||||
return path.replace('tmp-typings', 'esm2022');
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
function toCustomNgEntryPoint(entryPoint: NgEntryPoint): NgEntryPointType {
|
||||
return createNgEntryPoint(
|
||||
entryPoint.packageJson,
|
||||
entryPoint.ngPackageJson,
|
||||
|
||||
@ -31,9 +31,8 @@
|
||||
},
|
||||
"poll": {
|
||||
"type": "number",
|
||||
"description": "Enable and define the file watching poll time period in milliseconds. _Note: this is only supported in Angular versions >= 18.0.0_."
|
||||
"description": "Enable and define the file watching poll time period in milliseconds."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["project"]
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ import type { NgPackagr } from 'ng-packagr';
|
||||
import { join, resolve } from 'path';
|
||||
import { from } from 'rxjs';
|
||||
import { mapTo, switchMap } from 'rxjs/operators';
|
||||
import { getInstalledAngularVersionInfo } from '../utilities/angular-version-utils';
|
||||
import { parseRemappedTsConfigAndMergeDefaults } from '../utilities/typescript';
|
||||
import { getNgPackagrInstance } from './ng-packagr-adjustments/ng-packagr';
|
||||
import type { BuildAngularLibraryExecutorOptions } from './schema';
|
||||
@ -56,13 +55,10 @@ export function createLibraryExecutor(
|
||||
options: BuildAngularLibraryExecutorOptions,
|
||||
context: ExecutorContext
|
||||
) {
|
||||
const { major: angularMajorVersion, version: angularVersion } =
|
||||
getInstalledAngularVersionInfo();
|
||||
if (angularMajorVersion < 18 && options.poll !== undefined) {
|
||||
throw new Error(
|
||||
`The "poll" option requires Angular version 18.0.0 or greater. You are currently using version ${angularVersion}.`
|
||||
);
|
||||
}
|
||||
options.project ??= join(
|
||||
context.projectsConfigurations.projects[context.projectName].root,
|
||||
'ng-package.json'
|
||||
);
|
||||
|
||||
const { dependencies } = calculateProjectBuildableDependencies(
|
||||
context.taskGraph,
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import type { NgPackagrBuilderOptions } from '@angular-devkit/build-angular';
|
||||
|
||||
export interface BuildAngularLibraryExecutorOptions
|
||||
extends NgPackagrBuilderOptions {}
|
||||
extends NgPackagrBuilderOptions {
|
||||
project?: string;
|
||||
}
|
||||
|
||||
@ -31,9 +31,8 @@
|
||||
},
|
||||
"poll": {
|
||||
"type": "number",
|
||||
"description": "Enable and define the file watching poll time period in milliseconds. _Note: this is only supported in Angular versions >= 18.0.0_."
|
||||
"description": "Enable and define the file watching poll time period in milliseconds."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["project"]
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
export function assertBuilderPackageIsInstalled(packageName: string): void {
|
||||
try {
|
||||
require.resolve(packageName);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`This executor requires the package ${packageName} to be installed. Please make sure it is installed and try again.`
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,11 @@
|
||||
import type { buildApplication } from '@angular/build';
|
||||
import { registerTsProject } from '@nx/js/src/internal';
|
||||
import { loadModule } from './module-loader';
|
||||
|
||||
// This is a workaround to make sure we use the same esbuild version as the
|
||||
// Angular DevKit uses. This is only used internally to load the plugins and
|
||||
// forward them to the Angular DevKit builders.
|
||||
type Plugin = Parameters<
|
||||
typeof import('@angular-devkit/build-angular').buildApplication
|
||||
>[2]['codePlugins'][number];
|
||||
type Plugin = Parameters<typeof buildApplication>[2]['codePlugins'][number];
|
||||
|
||||
export type PluginSpec = {
|
||||
path: string;
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
type NgPackagrImportPath = `ng-packagr/src/${string}`;
|
||||
|
||||
export function importNgPackagrPath<T>(
|
||||
path: string,
|
||||
path: NgPackagrImportPath,
|
||||
ngPackagrMajorVersion: number
|
||||
): T {
|
||||
let finalPath = path;
|
||||
let finalPath: string = path;
|
||||
|
||||
if (ngPackagrMajorVersion >= 20 && !path.startsWith('ng-packagr/src/')) {
|
||||
finalPath = path.replace(/^ng-packagr\//, 'ng-packagr/src/');
|
||||
if (ngPackagrMajorVersion < 20 && path.startsWith('ng-packagr/src/')) {
|
||||
finalPath = path.replace(/^ng-packagr\/src\//, 'ng-packagr/');
|
||||
}
|
||||
|
||||
return require(finalPath);
|
||||
|
||||
@ -2,21 +2,15 @@
|
||||
* Adapted from the original ng-packagr source.
|
||||
*
|
||||
* Changes made:
|
||||
* - Use our own function to get the TailwindCSS config path to support a
|
||||
* config at the root of the workspace.
|
||||
* - Resolve `piscina` from the installed `ng-packagr` package.
|
||||
* - Additionally search for the TailwindCSS config in the workspace root.
|
||||
*/
|
||||
|
||||
import { workspaceRoot } from '@nx/devkit';
|
||||
import browserslist from 'browserslist';
|
||||
import { existsSync } from 'fs';
|
||||
import { colors } from 'ng-packagr/src/lib/utils/color';
|
||||
import { dirname, join } from 'path';
|
||||
const Piscina = require('piscina');
|
||||
import { colors } from 'ng-packagr/lib/utils/color';
|
||||
// using this instead of the one from ng-packagr
|
||||
import { getTailwindConfigPath } from '../tailwindcss';
|
||||
import { workspaceRoot } from '@nx/devkit';
|
||||
import type { PostcssConfiguration } from 'ng-packagr/lib/styles/postcss-configuration';
|
||||
import { gt, gte } from 'semver';
|
||||
import { getNgPackagrVersionInfo } from '../ng-packagr-version';
|
||||
|
||||
const maxWorkersVariable = process.env['NG_BUILD_MAX_WORKERS'];
|
||||
const maxThreads =
|
||||
@ -30,7 +24,7 @@ export enum CssUrl {
|
||||
}
|
||||
|
||||
export class StylesheetProcessor {
|
||||
private renderWorker: typeof Piscina | undefined;
|
||||
private renderWorker: any | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly projectBasePath: string,
|
||||
@ -91,33 +85,22 @@ export class StylesheetProcessor {
|
||||
|
||||
const browserslistData = browserslist(undefined, { path: this.basePath });
|
||||
|
||||
const { version: ngPackagrVersion } = getNgPackagrVersionInfo();
|
||||
let tailwindConfigPath: string | undefined;
|
||||
let postcssConfiguration: PostcssConfiguration | undefined;
|
||||
if (gte(ngPackagrVersion, '18.0.0')) {
|
||||
const {
|
||||
findTailwindConfiguration,
|
||||
generateSearchDirectories,
|
||||
loadPostcssConfiguration,
|
||||
} = require('ng-packagr/lib/styles/postcss-configuration');
|
||||
let searchDirs = generateSearchDirectories([this.projectBasePath]);
|
||||
postcssConfiguration = loadPostcssConfiguration(searchDirs);
|
||||
// (nx-specific): we support loading the TailwindCSS config from the root of the workspace
|
||||
searchDirs = generateSearchDirectories([
|
||||
this.projectBasePath,
|
||||
workspaceRoot,
|
||||
]);
|
||||
tailwindConfigPath = findTailwindConfiguration(searchDirs);
|
||||
} else if (gt(ngPackagrVersion, '17.2.0')) {
|
||||
const {
|
||||
loadPostcssConfiguration,
|
||||
} = require('ng-packagr/lib/styles/postcss-configuration');
|
||||
postcssConfiguration = loadPostcssConfiguration(this.projectBasePath);
|
||||
tailwindConfigPath = getTailwindConfigPath(
|
||||
this.projectBasePath,
|
||||
workspaceRoot
|
||||
);
|
||||
}
|
||||
const {
|
||||
findTailwindConfiguration,
|
||||
generateSearchDirectories,
|
||||
loadPostcssConfiguration,
|
||||
} = require('ng-packagr/lib/styles/postcss-configuration');
|
||||
|
||||
let searchDirs = generateSearchDirectories([this.projectBasePath]);
|
||||
const postcssConfiguration = loadPostcssConfiguration(searchDirs);
|
||||
// (nx-specific): we support loading the TailwindCSS config from the root of the workspace
|
||||
searchDirs = generateSearchDirectories([
|
||||
this.projectBasePath,
|
||||
workspaceRoot,
|
||||
]);
|
||||
const tailwindConfigPath = findTailwindConfiguration(searchDirs);
|
||||
|
||||
const Piscina = getPiscina();
|
||||
|
||||
this.renderWorker = new Piscina({
|
||||
filename: require.resolve(
|
||||
@ -143,112 +126,6 @@ export class StylesheetProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used when ng-packagr version is 17.2.0. The async `loadPostcssConfiguration` function
|
||||
* introduced in ng-packagr 17.2.0 causes a memory leak due to multiple workers being created. We must
|
||||
* keep this class to support any workspace that might be using ng-packagr 17.2.0 where that function
|
||||
* need to be awaited.
|
||||
*/
|
||||
export class AsyncStylesheetProcessor {
|
||||
private renderWorker: typeof Piscina | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly projectBasePath: string,
|
||||
private readonly basePath: string,
|
||||
private readonly cssUrl?: CssUrl,
|
||||
private readonly includePaths?: string[],
|
||||
private readonly cacheDirectory?: string | false
|
||||
) {
|
||||
// By default, browserslist defaults are too inclusive
|
||||
// https://github.com/browserslist/browserslist/blob/83764ea81ffaa39111c204b02c371afa44a4ff07/index.js#L516-L522
|
||||
// We change the default query to browsers that Angular support.
|
||||
// https://angular.io/guide/browser-support
|
||||
(browserslist.defaults as string[]) = [
|
||||
'last 2 Chrome versions',
|
||||
'last 1 Firefox version',
|
||||
'last 2 Edge major versions',
|
||||
'last 2 Safari major versions',
|
||||
'last 2 iOS major versions',
|
||||
'Firefox ESR',
|
||||
];
|
||||
}
|
||||
|
||||
async process({
|
||||
filePath,
|
||||
content,
|
||||
}: {
|
||||
filePath: string;
|
||||
content: string;
|
||||
}): Promise<string> {
|
||||
await this.createRenderWorker();
|
||||
|
||||
return this.renderWorker.run({ content, filePath });
|
||||
}
|
||||
|
||||
/** Destory workers in pool. */
|
||||
destroy(): void {
|
||||
void this.renderWorker?.destroy();
|
||||
}
|
||||
|
||||
private async createRenderWorker(): Promise<void> {
|
||||
if (this.renderWorker) {
|
||||
return;
|
||||
}
|
||||
|
||||
const styleIncludePaths = [...this.includePaths];
|
||||
let prevDir = null;
|
||||
let currentDir = this.basePath;
|
||||
|
||||
while (currentDir !== prevDir) {
|
||||
const p = join(currentDir, 'node_modules');
|
||||
if (existsSync(p)) {
|
||||
styleIncludePaths.push(p);
|
||||
}
|
||||
|
||||
prevDir = currentDir;
|
||||
currentDir = dirname(prevDir);
|
||||
}
|
||||
|
||||
const browserslistData = browserslist(undefined, { path: this.basePath });
|
||||
|
||||
const { version: ngPackagrVersion } = getNgPackagrVersionInfo();
|
||||
let postcssConfiguration: PostcssConfiguration | undefined;
|
||||
if (ngPackagrVersion === '17.2.0') {
|
||||
const {
|
||||
loadPostcssConfiguration,
|
||||
} = require('ng-packagr/lib/styles/postcss-configuration');
|
||||
postcssConfiguration = await loadPostcssConfiguration(
|
||||
this.projectBasePath
|
||||
);
|
||||
}
|
||||
|
||||
this.renderWorker = new Piscina({
|
||||
filename: require.resolve(
|
||||
'ng-packagr/lib/styles/stylesheet-processor-worker'
|
||||
),
|
||||
maxThreads,
|
||||
recordTiming: false,
|
||||
env: {
|
||||
...process.env,
|
||||
FORCE_COLOR: '' + colors.enabled,
|
||||
},
|
||||
workerData: {
|
||||
postcssConfiguration,
|
||||
tailwindConfigPath: getTailwindConfigPath(
|
||||
this.projectBasePath,
|
||||
workspaceRoot
|
||||
),
|
||||
projectBasePath: this.projectBasePath,
|
||||
browserslistData,
|
||||
targets: transformSupportedBrowsersToTargets(browserslistData),
|
||||
cacheDirectory: this.cacheDirectory,
|
||||
cssUrl: this.cssUrl,
|
||||
styleIncludePaths,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function transformSupportedBrowsersToTargets(
|
||||
supportedBrowsers: string[]
|
||||
): string[] {
|
||||
@ -288,3 +165,34 @@ function transformSupportedBrowsersToTargets(
|
||||
|
||||
return transformed.length ? transformed : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the `piscina` package from the installed `ng-packagr` package.
|
||||
*/
|
||||
function getPiscina() {
|
||||
const ngPackagrPath = getInstalledNgPackagrPath();
|
||||
|
||||
try {
|
||||
// Resolve the main piscina module entry point
|
||||
const piscinaModulePath = require.resolve('piscina', {
|
||||
paths: [ngPackagrPath],
|
||||
});
|
||||
|
||||
return require(piscinaModulePath);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Failed to load the \`piscina\` package from \`ng-packagr\` dependencies: ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getInstalledNgPackagrPath(): string {
|
||||
try {
|
||||
const ngPackagrPackageJsonPath = require.resolve('ng-packagr/package.json');
|
||||
return dirname(ngPackagrPackageJsonPath);
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
'The `ng-packagr` package is not installed. The package is required to use this executor. Please install it in your workspace.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,12 +3,11 @@ import { getNgPackagrVersionInfo } from './ng-packagr-version';
|
||||
import { importNgPackagrPath } from './package-imports';
|
||||
|
||||
export function getStylesheetProcessorFactoryProvider(): FactoryProvider {
|
||||
const { major: ngPackagrMajorVersion, version: ngPackagrVersion } =
|
||||
getNgPackagrVersionInfo();
|
||||
const { major: ngPackagrMajorVersion } = getNgPackagrVersionInfo();
|
||||
|
||||
const { STYLESHEET_PROCESSOR_TOKEN } = importNgPackagrPath<
|
||||
typeof import('ng-packagr/lib/styles/stylesheet-processor.di')
|
||||
>('ng-packagr/lib/styles/stylesheet-processor.di', ngPackagrMajorVersion);
|
||||
typeof import('ng-packagr/src/lib/styles/stylesheet-processor.di')
|
||||
>('ng-packagr/src/lib/styles/stylesheet-processor.di', ngPackagrMajorVersion);
|
||||
|
||||
return {
|
||||
provide: STYLESHEET_PROCESSOR_TOKEN,
|
||||
@ -20,17 +19,8 @@ export function getStylesheetProcessorFactoryProvider(): FactoryProvider {
|
||||
return getStylesheetProcessor();
|
||||
}
|
||||
|
||||
if (ngPackagrVersion !== '17.2.0') {
|
||||
const {
|
||||
StylesheetProcessor,
|
||||
} = require('./pre-v19/stylesheet-processor');
|
||||
return StylesheetProcessor;
|
||||
}
|
||||
|
||||
const {
|
||||
AsyncStylesheetProcessor,
|
||||
} = require('./pre-v19/stylesheet-processor');
|
||||
return AsyncStylesheetProcessor;
|
||||
const { StylesheetProcessor } = require('./pre-v19/stylesheet-processor');
|
||||
return StylesheetProcessor;
|
||||
},
|
||||
deps: [],
|
||||
};
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
import { workspaceRoot } from '@nx/devkit';
|
||||
import browserslist from 'browserslist';
|
||||
import type { NgPackageEntryConfig } from 'ng-packagr/ng-entrypoint.schema';
|
||||
import type { NgPackageEntryConfig } from 'ng-packagr/src/ng-entrypoint.schema';
|
||||
import { getNgPackagrVersionInfo } from '../ng-packagr-version';
|
||||
import { importNgPackagrPath } from '../package-imports';
|
||||
|
||||
@ -30,15 +30,15 @@ export function getStylesheetProcessor(): new (
|
||||
const { major: ngPackagrMajorVersion } = getNgPackagrVersionInfo();
|
||||
|
||||
const { ComponentStylesheetBundler } = importNgPackagrPath<
|
||||
typeof import('ng-packagr/lib/styles/component-stylesheets')
|
||||
>('ng-packagr/lib/styles/component-stylesheets', ngPackagrMajorVersion);
|
||||
typeof import('ng-packagr/src/lib/styles/component-stylesheets')
|
||||
>('ng-packagr/src/lib/styles/component-stylesheets', ngPackagrMajorVersion);
|
||||
const {
|
||||
generateSearchDirectories,
|
||||
getTailwindConfig,
|
||||
loadPostcssConfiguration,
|
||||
} = importNgPackagrPath<
|
||||
typeof import('ng-packagr/lib/styles/postcss-configuration')
|
||||
>('ng-packagr/lib/styles/postcss-configuration', ngPackagrMajorVersion);
|
||||
typeof import('ng-packagr/src/lib/styles/postcss-configuration')
|
||||
>('ng-packagr/src/lib/styles/postcss-configuration', ngPackagrMajorVersion);
|
||||
|
||||
class StylesheetProcessor extends ComponentStylesheetBundler {
|
||||
constructor(
|
||||
@ -53,15 +53,21 @@ export function getStylesheetProcessor(): new (
|
||||
// By default, browserslist defaults are too inclusive
|
||||
// https://github.com/browserslist/browserslist/blob/83764ea81ffaa39111c204b02c371afa44a4ff07/index.js#L516-L522
|
||||
// We change the default query to browsers that Angular support.
|
||||
// https://angular.io/guide/browser-support
|
||||
(browserslist.defaults as string[]) = [
|
||||
'last 2 Chrome versions',
|
||||
'last 1 Firefox version',
|
||||
'last 2 Edge major versions',
|
||||
'last 2 Safari major versions',
|
||||
'last 2 iOS major versions',
|
||||
'Firefox ESR',
|
||||
];
|
||||
// https://angular.dev/reference/versions#browser-support
|
||||
if (ngPackagrMajorVersion >= 20) {
|
||||
(browserslist.defaults as string[]) = browserslist(undefined, {
|
||||
path: require.resolve('ng-packagr/.browserslistrc'),
|
||||
});
|
||||
} else {
|
||||
(browserslist.defaults as string[]) = [
|
||||
'last 2 Chrome versions',
|
||||
'last 1 Firefox version',
|
||||
'last 2 Edge major versions',
|
||||
'last 2 Safari major versions',
|
||||
'last 2 iOS major versions',
|
||||
'Firefox ESR',
|
||||
];
|
||||
}
|
||||
|
||||
const browserslistData = browserslist(undefined, { path: basePath });
|
||||
let searchDirs = generateSearchDirectories([projectBasePath]);
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
import type { BuilderContext } from '@angular-devkit/architect';
|
||||
import type {
|
||||
ApplicationBuilderOptions,
|
||||
BrowserBuilderOptions,
|
||||
} from '@angular-devkit/build-angular';
|
||||
import type { BrowserBuilderOptions } from '@angular-devkit/build-angular';
|
||||
import type { Schema as BrowserEsbuildBuilderOptions } from '@angular-devkit/build-angular/src/builders/browser-esbuild/schema';
|
||||
import type { ApplicationBuilderOptions } from '@angular/build';
|
||||
import type { Target } from '@nx/devkit';
|
||||
|
||||
const executorToBuilderMap = new Map<string, string>([
|
||||
|
||||
@ -18,6 +18,7 @@ exports[`addLinting generator should correctly generate the .eslintrc.json file
|
||||
"*.ts",
|
||||
],
|
||||
"rules": {
|
||||
"@angular-eslint/component-class-suffix": "off",
|
||||
"@angular-eslint/component-selector": [
|
||||
"error",
|
||||
{
|
||||
@ -26,6 +27,7 @@ exports[`addLinting generator should correctly generate the .eslintrc.json file
|
||||
"type": "element",
|
||||
},
|
||||
],
|
||||
"@angular-eslint/directive-class-suffix": "off",
|
||||
"@angular-eslint/directive-selector": [
|
||||
"error",
|
||||
{
|
||||
|
||||
@ -66,7 +66,7 @@ describe('addLinting generator', () => {
|
||||
|
||||
const { devDependencies } = readJson(tree, 'package.json');
|
||||
expect(devDependencies['@typescript-eslint/utils']).toMatchInlineSnapshot(
|
||||
`"^8.19.0"`
|
||||
`"^8.29.0"`
|
||||
);
|
||||
delete process.env.ESLINT_USE_FLAT_CONFIG;
|
||||
});
|
||||
@ -168,7 +168,9 @@ describe('addLinting generator', () => {
|
||||
prefix: "my-org",
|
||||
style: "kebab-case"
|
||||
}
|
||||
]
|
||||
],
|
||||
"@angular-eslint/component-class-suffix": "off",
|
||||
"@angular-eslint/directive-class-suffix": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -289,7 +291,9 @@ describe('addLinting generator', () => {
|
||||
"prefix": "my-org",
|
||||
"style": "kebab-case"
|
||||
}
|
||||
]
|
||||
],
|
||||
"@angular-eslint/component-class-suffix": "off",
|
||||
"@angular-eslint/directive-class-suffix": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -82,6 +82,10 @@ export async function addLintingGenerator(
|
||||
style: 'kebab-case',
|
||||
},
|
||||
],
|
||||
// Temporary disable these rules until Angular ESLint recommended
|
||||
// rules are updated with the new Style Guide
|
||||
'@angular-eslint/component-class-suffix': 'off',
|
||||
'@angular-eslint/directive-class-suffix': 'off',
|
||||
},
|
||||
});
|
||||
addOverrideToLintConfig(tree, options.projectRoot, {
|
||||
@ -121,6 +125,10 @@ export async function addLintingGenerator(
|
||||
style: 'kebab-case',
|
||||
},
|
||||
],
|
||||
// Temporary disable these rules until Angular ESLint recommended
|
||||
// rules are updated with the new Style Guide
|
||||
'@angular-eslint/component-class-suffix': 'off',
|
||||
'@angular-eslint/directive-class-suffix': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@ -27,7 +27,6 @@ exports[`app --minimal should generate a correct setup when --bundler=rspack and
|
||||
"styles": [
|
||||
"./src/styles.css"
|
||||
],
|
||||
"scripts": [],
|
||||
"devServer": {},
|
||||
"ssr": {
|
||||
"entry": "./src/server.ts"
|
||||
@ -188,7 +187,6 @@ exports[`app --minimal should generate a correct setup when --bundler=rspack inc
|
||||
"styles": [
|
||||
"./src/styles.css"
|
||||
],
|
||||
"scripts": [],
|
||||
"devServer": {}
|
||||
|
||||
}
|
||||
@ -228,54 +226,54 @@ exports[`app --minimal should generate a correct setup when --bundler=rspack inc
|
||||
}});"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for non-standalone apps with routing 1`] = `
|
||||
"import { NgModule } from '@angular/core';
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for non-standalone apps with routing 1`] = `
|
||||
"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AppComponent } from './app.component';
|
||||
import { App } from './app';
|
||||
import { appRoutes } from './app.routes';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent],
|
||||
declarations: [App],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
RouterModule.forRoot(appRoutes),
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
providers: [provideBrowserGlobalErrorListeners()],
|
||||
bootstrap: [App],
|
||||
})
|
||||
export class AppModule {}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for non-standalone apps with routing 2`] = `
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for non-standalone apps with routing 2`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
standalone: false,
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.css',
|
||||
templateUrl: './app.html',
|
||||
styleUrl: './app.css',
|
||||
})
|
||||
export class AppComponent {}
|
||||
export class App {}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for non-standalone apps with routing 3`] = `
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for non-standalone apps with routing 3`] = `
|
||||
"import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { App } from './app';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
describe('App', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [RouterModule.forRoot([])],
|
||||
declarations: [AppComponent]
|
||||
declarations: [App]
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||
@ -286,56 +284,56 @@ describe('AppComponent', () => {
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for non-standalone apps with routing 4`] = `
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for non-standalone apps with routing 4`] = `
|
||||
"<h1>Welcome plain</h1>
|
||||
<router-outlet></router-outlet>
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for non-standalone apps without routing 1`] = `
|
||||
"import { NgModule } from '@angular/core';
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for non-standalone apps without routing 1`] = `
|
||||
"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { AppComponent } from './app.component';
|
||||
import { App } from './app';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent],
|
||||
declarations: [App],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
providers: [provideBrowserGlobalErrorListeners()],
|
||||
bootstrap: [App],
|
||||
})
|
||||
export class AppModule {}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for non-standalone apps without routing 2`] = `
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for non-standalone apps without routing 2`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
standalone: false,
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.css',
|
||||
templateUrl: './app.html',
|
||||
styleUrl: './app.css',
|
||||
})
|
||||
export class AppComponent {}
|
||||
export class App {}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for non-standalone apps without routing 3`] = `
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for non-standalone apps without routing 3`] = `
|
||||
"import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { App } from './app';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
describe('App', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [],
|
||||
declarations: [AppComponent]
|
||||
declarations: [App]
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||
@ -346,39 +344,39 @@ describe('AppComponent', () => {
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for non-standalone apps without routing 4`] = `
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for non-standalone apps without routing 4`] = `
|
||||
"<h1>Welcome plain</h1>
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for standalone apps with routing 1`] = `
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for standalone apps with routing 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
imports: [RouterModule],
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.css',
|
||||
templateUrl: './app.html',
|
||||
styleUrl: './app.css',
|
||||
})
|
||||
export class AppComponent {}
|
||||
export class App {}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for standalone apps with routing 2`] = `
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for standalone apps with routing 2`] = `
|
||||
"import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { App } from './app';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
describe('App', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AppComponent, RouterModule.forRoot([])],
|
||||
imports: [App, RouterModule.forRoot([])],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||
@ -389,38 +387,38 @@ describe('AppComponent', () => {
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for standalone apps with routing 3`] = `
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for standalone apps with routing 3`] = `
|
||||
"<h1>Welcome plain</h1>
|
||||
<router-outlet></router-outlet>
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for standalone apps without routing 1`] = `
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for standalone apps without routing 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
imports: [],
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.css',
|
||||
templateUrl: './app.html',
|
||||
styleUrl: './app.css',
|
||||
})
|
||||
export class AppComponent {}
|
||||
export class App {}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for standalone apps without routing 2`] = `
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for standalone apps without routing 2`] = `
|
||||
"import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { App } from './app';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
describe('App', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AppComponent],
|
||||
imports: [App],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||
@ -431,7 +429,7 @@ describe('AppComponent', () => {
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for standalone apps without routing 3`] = `
|
||||
exports[`app --minimal should skip "nx-welcome.ts" file and references for standalone apps without routing 3`] = `
|
||||
"<h1>Welcome plain</h1>
|
||||
"
|
||||
`;
|
||||
@ -439,21 +437,25 @@ exports[`app --minimal should skip "nx-welcome.component.ts" file and references
|
||||
exports[`app --standalone should generate a standalone app correctly with routing 1`] = `
|
||||
"import { bootstrapApplication } from '@angular/platform-browser';
|
||||
import { appConfig } from './app/app.config';
|
||||
import { AppComponent } from './app/app.component';
|
||||
import { App } from './app/app';
|
||||
|
||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||
bootstrapApplication(App, appConfig).catch((err) =>
|
||||
console.error(err)
|
||||
);
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --standalone should generate a standalone app correctly with routing 2`] = `
|
||||
"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
|
||||
"import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { appRoutes } from './app.routes';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ]
|
||||
providers: [
|
||||
provideBrowserGlobalErrorListeners(),
|
||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||
provideRouter(appRoutes)
|
||||
]
|
||||
};
|
||||
"
|
||||
`;
|
||||
@ -468,47 +470,41 @@ export const appRoutes: Route[] = [];
|
||||
exports[`app --standalone should generate a standalone app correctly with routing 4`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
|
||||
@Component({
|
||||
imports: [NxWelcomeComponent, RouterModule],
|
||||
imports: [NxWelcome, RouterModule],
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.css',
|
||||
templateUrl: './app.html',
|
||||
styleUrl: './app.css',
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'standalone';
|
||||
export class App {
|
||||
protected title = 'standalone';
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --standalone should generate a standalone app correctly with routing 5`] = `
|
||||
"import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { App } from './app';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
describe('App', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AppComponent, NxWelcomeComponent, RouterModule.forRoot([])],
|
||||
imports: [App, NxWelcome, RouterModule.forRoot([])],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||
'Welcome standalone'
|
||||
);
|
||||
});
|
||||
|
||||
it(\`should have as title 'standalone'\`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('standalone');
|
||||
});
|
||||
});
|
||||
"
|
||||
`;
|
||||
@ -516,80 +512,66 @@ describe('AppComponent', () => {
|
||||
exports[`app --standalone should generate a standalone app correctly without routing 1`] = `
|
||||
"import { bootstrapApplication } from '@angular/platform-browser';
|
||||
import { appConfig } from './app/app.config';
|
||||
import { AppComponent } from './app/app.component';
|
||||
import { App } from './app/app';
|
||||
|
||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||
bootstrapApplication(App, appConfig).catch((err) =>
|
||||
console.error(err)
|
||||
);
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --standalone should generate a standalone app correctly without routing 2`] = `
|
||||
"import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
|
||||
"import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [provideZoneChangeDetection({ eventCoalescing: true }), ]
|
||||
providers: [
|
||||
provideBrowserGlobalErrorListeners(),
|
||||
provideZoneChangeDetection({ eventCoalescing: true })
|
||||
]
|
||||
};
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --standalone should generate a standalone app correctly without routing 3`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
|
||||
@Component({
|
||||
imports: [NxWelcomeComponent, ],
|
||||
imports: [NxWelcome, ],
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.css',
|
||||
templateUrl: './app.html',
|
||||
styleUrl: './app.css',
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'standalone';
|
||||
export class App {
|
||||
protected title = 'standalone';
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --standalone should generate a standalone app correctly without routing 4`] = `
|
||||
"import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { App } from './app';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
describe('App', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AppComponent, NxWelcomeComponent],
|
||||
imports: [App, NxWelcome],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||
'Welcome standalone'
|
||||
);
|
||||
});
|
||||
|
||||
it(\`should have as title 'standalone'\`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('standalone');
|
||||
});
|
||||
});
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --standalone should should not use event coalescing in versions lower than v18 1`] = `
|
||||
"import { ApplicationConfig } from '@angular/core';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { appRoutes } from './app.routes';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [provideRouter(appRoutes) ]
|
||||
};
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app --strict should enable strict type checking: app tsconfig.json 1`] = `
|
||||
{
|
||||
"angularCompilerOptions": {
|
||||
@ -597,14 +579,19 @@ exports[`app --strict should enable strict type checking: app tsconfig.json 1`]
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"strictTemplates": true,
|
||||
"typeCheckHostBindings": true,
|
||||
},
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"module": "preserve",
|
||||
"moduleResolution": "bundler",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"target": "es2022",
|
||||
},
|
||||
@ -629,7 +616,6 @@ exports[`app --strict should enable strict type checking: e2e tsconfig.json 1`]
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "commonjs",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
@ -689,17 +675,18 @@ exports[`app --unit-test-runner vitest should add tsconfig.spec.json 1`] = `
|
||||
`;
|
||||
|
||||
exports[`app --unit-test-runner vitest should generate src/test-setup.ts 1`] = `
|
||||
"import '@analogjs/vitest-angular/setup-zone';
|
||||
"import '@angular/compiler';
|
||||
import '@analogjs/vitest-angular/setup-zone';
|
||||
|
||||
import {
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting,
|
||||
} from '@angular/platform-browser-dynamic/testing';
|
||||
BrowserTestingModule,
|
||||
platformBrowserTesting,
|
||||
} from '@angular/platform-browser/testing';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
|
||||
getTestBed().initTestEnvironment(
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting()
|
||||
BrowserTestingModule,
|
||||
platformBrowserTesting()
|
||||
);
|
||||
"
|
||||
`;
|
||||
@ -735,32 +722,86 @@ export default defineConfig(() => ({
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app angular compat support should import "ApplicationConfig" from "@angular/platform-browser" 1`] = `
|
||||
"import { ApplicationConfig } from '@angular/core';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { appRoutes } from './app.routes';
|
||||
exports[`app angular compat support should generate components with the "component" type for versions lower than v20 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [provideRouter(appRoutes) ]
|
||||
};
|
||||
@Component({
|
||||
imports: [NxWelcomeComponent, RouterModule],
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.css',
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'myapp';
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app angular compat support should generate components with the "component" type for versions lower than v20 2`] = `
|
||||
"<app-nx-welcome></app-nx-welcome>
|
||||
<router-outlet></router-outlet>
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app angular compat support should generate components with the "component" type for versions lower than v20 3`] = `
|
||||
"import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AppComponent, NxWelcomeComponent, RouterModule.forRoot([])],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||
'Welcome myapp'
|
||||
);
|
||||
});
|
||||
|
||||
it(\`should have as title 'myapp'\`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('myapp');
|
||||
});
|
||||
});
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app angular compat support should generate components with the "component" type for versions lower than v20 4`] = `
|
||||
"import { bootstrapApplication } from '@angular/platform-browser';
|
||||
import { appConfig } from './app/app.config';
|
||||
import { AppComponent } from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||
console.error(err)
|
||||
);
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app at the root should accept numbers in the path 1`] = `"src/9-websites/my-app"`;
|
||||
|
||||
exports[`app format files should format files 1`] = `
|
||||
"import { NgModule } from '@angular/core';
|
||||
"import { NgModule, provideBrowserGlobalErrorListeners } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AppComponent } from './app.component';
|
||||
import { App } from './app';
|
||||
import { appRoutes } from './app.routes';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, NxWelcomeComponent],
|
||||
declarations: [App, NxWelcome],
|
||||
imports: [BrowserModule, RouterModule.forRoot(appRoutes)],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
providers: [provideBrowserGlobalErrorListeners()],
|
||||
bootstrap: [App],
|
||||
})
|
||||
export class AppModule {}
|
||||
"
|
||||
@ -772,43 +813,37 @@ exports[`app format files should format files 2`] = `
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
standalone: false,
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.css',
|
||||
templateUrl: './app.html',
|
||||
styleUrl: './app.css',
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'my-app';
|
||||
export class App {
|
||||
protected title = 'my-app';
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app format files should format files 3`] = `
|
||||
"import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { App } from './app';
|
||||
import { NxWelcome } from './nx-welcome';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
describe('App', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [RouterModule.forRoot([])],
|
||||
declarations: [AppComponent, NxWelcomeComponent],
|
||||
declarations: [App, NxWelcome],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||
'Welcome my-app'
|
||||
);
|
||||
});
|
||||
|
||||
it(\`should have as title 'my-app'\`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('my-app');
|
||||
});
|
||||
});
|
||||
"
|
||||
`;
|
||||
@ -854,7 +889,7 @@ exports[`app nested should create project configs 1`] = `
|
||||
},
|
||||
},
|
||||
"defaultConfiguration": "production",
|
||||
"executor": "@angular-devkit/build-angular:application",
|
||||
"executor": "@angular/build:application",
|
||||
"options": {
|
||||
"assets": [
|
||||
{
|
||||
@ -863,12 +898,10 @@ exports[`app nested should create project configs 1`] = `
|
||||
},
|
||||
],
|
||||
"browser": "my-dir/my-app/src/main.ts",
|
||||
"index": "my-dir/my-app/src/index.html",
|
||||
"outputPath": "dist/my-dir/my-app",
|
||||
"polyfills": [
|
||||
"zone.js",
|
||||
],
|
||||
"scripts": [],
|
||||
"styles": [
|
||||
"my-dir/my-app/src/styles.css",
|
||||
],
|
||||
@ -879,7 +912,7 @@ exports[`app nested should create project configs 1`] = `
|
||||
],
|
||||
},
|
||||
"extract-i18n": {
|
||||
"executor": "@angular-devkit/build-angular:extract-i18n",
|
||||
"executor": "@angular/build:extract-i18n",
|
||||
"options": {
|
||||
"buildTarget": "my-app:build",
|
||||
},
|
||||
@ -898,7 +931,7 @@ exports[`app nested should create project configs 1`] = `
|
||||
},
|
||||
"continuous": true,
|
||||
"defaultConfiguration": "development",
|
||||
"executor": "@angular-devkit/build-angular:dev-server",
|
||||
"executor": "@angular/build:dev-server",
|
||||
},
|
||||
"serve-static": {
|
||||
"continuous": true,
|
||||
@ -972,7 +1005,7 @@ exports[`app not nested should create project configs 1`] = `
|
||||
},
|
||||
},
|
||||
"defaultConfiguration": "production",
|
||||
"executor": "@angular-devkit/build-angular:application",
|
||||
"executor": "@angular/build:application",
|
||||
"options": {
|
||||
"assets": [
|
||||
{
|
||||
@ -981,12 +1014,10 @@ exports[`app not nested should create project configs 1`] = `
|
||||
},
|
||||
],
|
||||
"browser": "my-app/src/main.ts",
|
||||
"index": "my-app/src/index.html",
|
||||
"outputPath": "dist/my-app",
|
||||
"polyfills": [
|
||||
"zone.js",
|
||||
],
|
||||
"scripts": [],
|
||||
"styles": [
|
||||
"my-app/src/styles.css",
|
||||
],
|
||||
@ -997,7 +1028,7 @@ exports[`app not nested should create project configs 1`] = `
|
||||
],
|
||||
},
|
||||
"extract-i18n": {
|
||||
"executor": "@angular-devkit/build-angular:extract-i18n",
|
||||
"executor": "@angular/build:extract-i18n",
|
||||
"options": {
|
||||
"buildTarget": "my-app:build",
|
||||
},
|
||||
@ -1016,7 +1047,7 @@ exports[`app not nested should create project configs 1`] = `
|
||||
},
|
||||
"continuous": true,
|
||||
"defaultConfiguration": "development",
|
||||
"executor": "@angular-devkit/build-angular:dev-server",
|
||||
"executor": "@angular/build:dev-server",
|
||||
},
|
||||
"serve-static": {
|
||||
"continuous": true,
|
||||
@ -1060,7 +1091,6 @@ exports[`app not nested should generate files: e2e tsconfig.json 1`] = `
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "commonjs",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
@ -1094,15 +1124,13 @@ exports[`app not nested should generate files: tsconfig.app.json 1`] = `
|
||||
},
|
||||
"exclude": [
|
||||
"jest.config.ts",
|
||||
"src/test-setup.ts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
],
|
||||
"extends": "./tsconfig.json",
|
||||
"files": [
|
||||
"src/main.ts",
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.ts",
|
||||
],
|
||||
}
|
||||
`;
|
||||
@ -1114,14 +1142,19 @@ exports[`app not nested should generate files: tsconfig.json 1`] = `
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"strictTemplates": true,
|
||||
"typeCheckHostBindings": true,
|
||||
},
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"module": "preserve",
|
||||
"moduleResolution": "bundler",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"target": "es2022",
|
||||
},
|
||||
@ -1142,17 +1175,61 @@ exports[`app not nested should generate files: tsconfig.json 1`] = `
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`app should generate correct tsconfig.editor.json 1`] = `
|
||||
{
|
||||
"compilerOptions": {},
|
||||
"exclude": [
|
||||
"jest.config.ts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
],
|
||||
"extends": "./tsconfig.json",
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
],
|
||||
exports[`app template generation mode should respect the "type" configured in the component generator defaults 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
|
||||
@Component({
|
||||
imports: [NxWelcomeComponent, RouterModule],
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.css',
|
||||
})
|
||||
export class AppComponent {
|
||||
protected title = 'myapp';
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app template generation mode should respect the "type" configured in the component generator defaults 2`] = `
|
||||
"<app-nx-welcome></app-nx-welcome>
|
||||
<router-outlet></router-outlet>
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app template generation mode should respect the "type" configured in the component generator defaults 3`] = `
|
||||
"import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AppComponent, NxWelcomeComponent, RouterModule.forRoot([])],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||
'Welcome myapp'
|
||||
);
|
||||
});
|
||||
});
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`app template generation mode should respect the "type" configured in the component generator defaults 4`] = `
|
||||
"import { bootstrapApplication } from '@angular/platform-browser';
|
||||
import { appConfig } from './app/app.config';
|
||||
import { AppComponent } from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||
console.error(err)
|
||||
);
|
||||
"
|
||||
`;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
formatFiles,
|
||||
generateFiles,
|
||||
GeneratorCallback,
|
||||
@ -12,11 +13,16 @@ import {
|
||||
import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
|
||||
import { initGenerator as jsInitGenerator } from '@nx/js';
|
||||
import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||
import { angularInitGenerator } from '../init/init';
|
||||
import { convertToRspack } from '../convert-to-rspack/convert-to-rspack';
|
||||
import { angularInitGenerator } from '../init/init';
|
||||
import { setupSsr } from '../setup-ssr/setup-ssr';
|
||||
import { setupTailwindGenerator } from '../setup-tailwind/setup-tailwind';
|
||||
import { ensureAngularDependencies } from '../utils/ensure-angular-dependencies';
|
||||
import {
|
||||
getInstalledAngularDevkitVersion,
|
||||
getInstalledAngularVersionInfo,
|
||||
versions,
|
||||
} from '../utils/version-utils';
|
||||
import {
|
||||
addE2e,
|
||||
addLinting,
|
||||
@ -25,11 +31,9 @@ import {
|
||||
addUnitTestRunner,
|
||||
createFiles,
|
||||
createProject,
|
||||
enableStrictTypeChecking,
|
||||
normalizeOptions,
|
||||
setApplicationStrictDefault,
|
||||
setGeneratorDefaults,
|
||||
updateEditorTsConfig,
|
||||
updateTsconfigFiles,
|
||||
} from './lib';
|
||||
import type { Schema } from './schema';
|
||||
|
||||
@ -82,7 +86,7 @@ export async function applicationGenerator(
|
||||
options,
|
||||
options.e2eTestRunner !== 'none' ? e2ePort : options.port
|
||||
);
|
||||
updateEditorTsConfig(tree, options);
|
||||
updateTsconfigFiles(tree, options);
|
||||
setGeneratorDefaults(tree, options);
|
||||
|
||||
if (options.rootProject) {
|
||||
@ -95,12 +99,6 @@ export async function applicationGenerator(
|
||||
addProxyConfig(tree, options);
|
||||
}
|
||||
|
||||
if (options.strict) {
|
||||
enableStrictTypeChecking(tree, options);
|
||||
} else {
|
||||
setApplicationStrictDefault(tree, false);
|
||||
}
|
||||
|
||||
if (options.ssr) {
|
||||
await setupSsr(tree, {
|
||||
project: options.name,
|
||||
@ -134,6 +132,27 @@ export async function applicationGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
if (!options.skipPackageJson) {
|
||||
const { major: angularMajorVersion } = getInstalledAngularVersionInfo(tree);
|
||||
if (angularMajorVersion >= 20) {
|
||||
const angularDevkitVersion =
|
||||
getInstalledAngularDevkitVersion(tree) ??
|
||||
versions(tree).angularDevkitVersion;
|
||||
|
||||
const devDependencies: Record<string, string> = {};
|
||||
if (options.bundler === 'esbuild') {
|
||||
devDependencies['@angular/build'] = angularDevkitVersion;
|
||||
} else if (isRspack) {
|
||||
devDependencies['@angular/build'] = angularDevkitVersion;
|
||||
devDependencies['@angular-devkit/build-angular'] = angularDevkitVersion;
|
||||
} else {
|
||||
devDependencies['@angular-devkit/build-angular'] = angularDevkitVersion;
|
||||
}
|
||||
|
||||
addDependenciesToPackageJson(tree, {}, devDependencies, undefined, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!options.skipFormat) {
|
||||
await formatFiles(tree);
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@ -4,7 +4,16 @@
|
||||
"outDir": "<%= rootOffset %>dist/out-tsc",
|
||||
"types": []
|
||||
},
|
||||
<%_ if (angularMajorVersion < 20) { _%>
|
||||
"files": ["src/main.ts"],
|
||||
"include": ["src/**/*.d.ts"],
|
||||
"exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
|
||||
<%_ } else { _%>
|
||||
"include": ["src/**/*.ts"],
|
||||
<%_ } _%>
|
||||
"exclude": [
|
||||
"jest.config.ts",
|
||||
"src/test-setup.ts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2022"<% if (disableModernClassFieldsBehavior) { %>,
|
||||
"useDefineForClassFields": false<% } %><% if (isUsingApplicationBuilder) { %>,
|
||||
"esModuleInterop": true<% } %>
|
||||
"extends": "<%= rootTsConfig %>",
|
||||
"compilerOptions": {},
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
@ -13,6 +13,5 @@
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
],
|
||||
"extends": "<%= rootTsConfig %>"
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';<% if(!minimal) { %>
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';<% } %><% if(routing && useRouterTestingModule) { %>
|
||||
import { RouterTestingModule } from '@angular/router/testing';<% } %><% if(routing && !useRouterTestingModule) { %>
|
||||
import { RouterModule } from '@angular/router';<% } %>
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [<% if(routing && useRouterTestingModule) { %>RouterTestingModule<% } %><% if(routing && !useRouterTestingModule) { %>RouterModule.forRoot([])<% } %>],
|
||||
declarations: [AppComponent<% if(!minimal) { %>, NxWelcomeComponent<% } %>]
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||
'Welcome <%= appName %>'
|
||||
);
|
||||
});<% if(!minimal) { %>
|
||||
|
||||
it(`should have as title '<%= appName %>'`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('<%= appName %>');
|
||||
});<% } %>
|
||||
});
|
||||
@ -1,17 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';<% if(routing) { %>
|
||||
import { RouterModule } from '@angular/router';<% } %>
|
||||
import { AppComponent } from './app.component';<% if(routing) { %>
|
||||
import { appRoutes } from './app.routes';<% } %><% if(!minimal) { %>
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';<% } %>
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent<% if(!minimal) { %>, NxWelcomeComponent<% } %>],
|
||||
imports: [
|
||||
BrowserModule,<% if(routing) { %>
|
||||
RouterModule.forRoot(appRoutes),<% } %>
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule {}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user