@nx/web 17.0.3 → 17.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +9 -4
  3. package/migrations.json +11 -1
  4. package/package.json +4 -4
  5. package/src/executors/file-server/file-server.impl.js +67 -30
  6. package/src/executors/file-server/schema.d.ts +4 -4
  7. package/src/executors/file-server/schema.json +2 -3
  8. package/src/generators/application/application.js +128 -46
  9. package/src/generators/application/files/app-vite/src/app/app.element.__style__ +9 -1
  10. package/src/generators/application/files/app-vite/src/app/app.element.ts__tmpl__ +39 -5
  11. package/src/generators/application/files/app-webpack/src/app/app.element.__style__ +9 -1
  12. package/src/generators/application/files/app-webpack/src/app/app.element.ts__tmpl__ +39 -5
  13. package/src/generators/application/files/app-webpack/webpack.config.js__tmpl__ +36 -5
  14. package/src/generators/application/schema.d.ts +1 -0
  15. package/src/generators/application/schema.json +3 -3
  16. package/src/generators/init/init.js +7 -40
  17. package/src/generators/init/schema.d.ts +1 -3
  18. package/src/generators/init/schema.json +7 -20
  19. package/src/generators/static-serve/schema.json +6 -1
  20. package/src/generators/static-serve/static-serve-configuration.d.ts +3 -2
  21. package/src/generators/static-serve/static-serve-configuration.js +14 -5
  22. package/src/migrations/update-15-9-1/add-dropped-dependencies.js +2 -2
  23. package/src/utils/has-webpack-plugin.d.ts +2 -0
  24. package/src/utils/has-webpack-plugin.js +11 -0
  25. package/src/utils/versions.d.ts +1 -1
  26. package/src/utils/versions.js +1 -1
  27. package/src/utils/wait-for-port-open.js +10 -2
  28. package/src/generators/application/files/app-webpack/src/environments/environment.prod.ts__tmpl__ +0 -3
  29. package/src/generators/application/files/app-webpack/src/environments/environment.ts__tmpl__ +0 -6
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2017-2023 Narwhal Technologies Inc.
3
+ Copyright (c) 2017-2024 Narwhal Technologies Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
package/README.md CHANGED
@@ -1,4 +1,9 @@
1
- <p style="text-align: center;"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx.png" width="600" alt="Nx - Smart, Fast and Extensible Build System"></p>
1
+ <p style="text-align: center;">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-dark.svg">
4
+ <img alt="Nx - Smart Monorepos · Fast CI" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-light.svg" width="100%">
5
+ </picture>
6
+ </p>
2
7
 
3
8
  <div style="text-align: center;">
4
9
 
@@ -15,9 +20,9 @@
15
20
 
16
21
  <hr>
17
22
 
18
- # Nx: Smart, Fast and Extensible Build System
23
+ # Nx: Smart Monorepos · Fast CI
19
24
 
20
- Nx is a next generation build system with first class monorepo support and powerful integrations.
25
+ Nx is a build system with built-in tooling and advanced CI capabilities. It helps you maintain and scale monorepos, both locally and on CI.
21
26
 
22
27
  This package is a [Web plugin for Nx](https://nx.dev/packages/web).
23
28
 
@@ -59,5 +64,5 @@ npx nx@latest init
59
64
  - [Blog Posts About Nx](https://blog.nrwl.io/nx/home)
60
65
 
61
66
  <p style="text-align: center;"><a href="https://nx.dev/#learning-materials" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-courses-and-videos.svg"
62
- width="100%" alt="Nx - Smart, Fast and Extensible Build System"></a></p>
67
+ width="100%" alt="Nx - Smart Monorepos · Fast CI"></a></p>
63
68
 
package/migrations.json CHANGED
@@ -37,5 +37,15 @@
37
37
  "implementation": "./src/migrations/update-16-0-0-update-executors/update-16-0-0-update-executors"
38
38
  }
39
39
  },
40
- "packageJsonUpdates": {}
40
+ "packageJsonUpdates": {
41
+ "17.3.0": {
42
+ "version": "17.3.0-beta.3",
43
+ "packages": {
44
+ "@types/node": {
45
+ "version": "18.16.9",
46
+ "alwaysAddToPackageJson": false
47
+ }
48
+ }
49
+ }
50
+ }
41
51
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/web",
3
- "version": "17.0.3",
3
+ "version": "17.0.5",
4
4
  "private": false,
5
5
  "description": "The Nx Plugin for Web Components contains generators for managing Web Component applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Jest, Cypress, and Storybook.\n\n- Scaffolding for creating buildable libraries that can be published to npm.\n\n- Utilities for automatic workspace refactoring.",
6
6
  "repository": {
@@ -34,9 +34,9 @@
34
34
  "detect-port": "^1.5.1",
35
35
  "http-server": "^14.1.0",
36
36
  "tslib": "^2.3.0",
37
- "@nx/devkit": "17.0.3",
38
- "@nx/js": "17.0.3",
39
- "@nrwl/web": "17.0.3"
37
+ "@nx/devkit": "17.0.5",
38
+ "@nx/js": "17.0.5",
39
+ "@nrwl/web": "17.0.5"
40
40
  },
41
41
  "publishConfig": {
42
42
  "access": "public"
@@ -9,6 +9,7 @@ const path_1 = require("path");
9
9
  const package_json_1 = require("nx/src/utils/package-json");
10
10
  const detectPort = require("detect-port");
11
11
  const client_1 = require("nx/src/daemon/client/client");
12
+ const utils_1 = require("nx/src/tasks-runner/utils");
12
13
  // platform specific command name
13
14
  const pmCmd = (0, os_1.platform)() === 'win32' ? `npx.cmd` : 'npx';
14
15
  function getHttpServerArgs(options) {
@@ -44,8 +45,15 @@ function getHttpServerArgs(options) {
44
45
  }
45
46
  return args;
46
47
  }
47
- function getBuildTargetCommand(options) {
48
- const cmd = ['nx', 'run', options.buildTarget];
48
+ function getBuildTargetCommand(options, context) {
49
+ const target = (0, devkit_1.parseTargetString)(options.buildTarget, context);
50
+ const cmd = ['nx', 'run'];
51
+ if (target.configuration) {
52
+ cmd.push(`${target.project}:${target.target}:${target.configuration}`);
53
+ }
54
+ else {
55
+ cmd.push(`${target.project}:${target.target}`);
56
+ }
49
57
  if (options.parallel) {
50
58
  cmd.push(`--parallel`);
51
59
  }
@@ -58,16 +66,27 @@ function getBuildTargetOutputPath(options, context) {
58
66
  if (options.staticFilePath) {
59
67
  return options.staticFilePath;
60
68
  }
61
- let buildOptions;
69
+ let outputPath;
62
70
  try {
63
71
  const target = (0, devkit_1.parseTargetString)(options.buildTarget, context);
64
- buildOptions = (0, devkit_1.readTargetOptions)(target, context);
72
+ const buildOptions = (0, devkit_1.readTargetOptions)(target, context);
73
+ if (buildOptions?.outputPath) {
74
+ outputPath = buildOptions.outputPath;
75
+ }
76
+ else {
77
+ const project = context.projectGraph.nodes[context.projectName];
78
+ const buildTarget = project.data.targets[target.target];
79
+ outputPath = buildTarget.outputs?.[0];
80
+ if (outputPath)
81
+ outputPath = (0, utils_1.interpolate)(outputPath, {
82
+ projectName: project.data.name,
83
+ projectRoot: project.data.root,
84
+ });
85
+ }
65
86
  }
66
87
  catch (e) {
67
88
  throw new Error(`Invalid buildTarget: ${options.buildTarget}`);
68
89
  }
69
- // TODO: vsavkin we should also check outputs
70
- const outputPath = buildOptions.outputPath;
71
90
  if (!outputPath) {
72
91
  throw new Error(`Unable to get the outputPath from buildTarget ${options.buildTarget}. Make sure ${options.buildTarget} has an outputPath property or manually provide an staticFilePath property`);
73
92
  }
@@ -78,50 +97,69 @@ function createFileWatcher(project, changeHandler) {
78
97
  watchProjects: project ? [project] : 'all',
79
98
  includeGlobalWorkspaceFiles: true,
80
99
  includeDependentProjects: true,
81
- }, async (error, { changedFiles }) => {
100
+ }, async (error, val) => {
82
101
  if (error === 'closed') {
83
102
  throw new Error('Watch error: Daemon closed the connection');
84
103
  }
85
104
  else if (error) {
86
105
  throw new Error(`Watch error: ${error?.message ?? 'Unknown'}`);
87
106
  }
88
- else if (changedFiles.length > 0) {
107
+ else if (val?.changedFiles.length > 0) {
89
108
  changeHandler();
90
109
  }
91
110
  });
92
111
  }
93
112
  async function* fileServerExecutor(options, context) {
113
+ if (!options.buildTarget && !options.staticFilePath) {
114
+ throw new Error("You must set either 'buildTarget' or 'staticFilePath'.");
115
+ }
116
+ if (options.watch && !options.buildTarget) {
117
+ throw new Error("Watch error: You can only specify 'watch' when 'buildTarget' is set.");
118
+ }
94
119
  let running = false;
95
- const run = () => {
96
- if (!running) {
97
- running = true;
98
- try {
99
- const args = getBuildTargetCommand(options);
100
- (0, child_process_1.execFileSync)(pmCmd, args, {
101
- stdio: [0, 1, 2],
102
- });
103
- }
104
- catch {
105
- throw new Error(`Build target failed: ${chalk.bold(options.buildTarget)}`);
106
- }
107
- finally {
108
- running = false;
120
+ let disposeWatch;
121
+ if (options.buildTarget) {
122
+ const run = () => {
123
+ if (!running) {
124
+ running = true;
125
+ /**
126
+ * Expose a variable to the build target to know if it's being run by the serve-static executor
127
+ * This is useful because a config might need to change if it's being run by serve-static without the user's input
128
+ * or if being ran by another executor (eg. E2E tests)
129
+ * */
130
+ process.env.NX_SERVE_STATIC_BUILD_RUNNING = 'true';
131
+ try {
132
+ const args = getBuildTargetCommand(options, context);
133
+ (0, child_process_1.execFileSync)(pmCmd, args, {
134
+ stdio: [0, 1, 2],
135
+ });
136
+ }
137
+ catch {
138
+ throw new Error(`Build target failed: ${chalk.bold(options.buildTarget)}`);
139
+ }
140
+ finally {
141
+ process.env.NX_SERVE_STATIC_BUILD_RUNNING = undefined;
142
+ running = false;
143
+ }
109
144
  }
145
+ };
146
+ if (options.watch) {
147
+ const projectRoot = context.projectsConfigurations.projects[context.projectName].root;
148
+ disposeWatch = await createFileWatcher(context.projectName, run);
110
149
  }
111
- };
112
- let disposeWatch;
113
- if (options.watch) {
114
- const projectRoot = context.projectsConfigurations.projects[context.projectName].root;
115
- disposeWatch = await createFileWatcher(context.projectName, run);
150
+ // perform initial run
151
+ run();
116
152
  }
117
- // perform initial run
118
- run();
153
+ const port = await detectPort(options.port || 8080);
119
154
  const outputPath = getBuildTargetOutputPath(options, context);
120
155
  if (options.spa) {
121
156
  const src = (0, path_1.join)(outputPath, 'index.html');
122
157
  const dst = (0, path_1.join)(outputPath, '404.html');
123
158
  // See: https://github.com/http-party/http-server#magic-files
124
159
  (0, fs_1.copyFileSync)(src, dst);
160
+ // We also need to ensure the proxyUrl is set, otherwise the browser will continue to throw a 404 error
161
+ // This can cause unexpected behaviors and failures especially in automated test suites
162
+ options.proxyUrl ??= `http${options.ssl ? 's' : ''}://localhost:${port}?`;
125
163
  }
126
164
  const args = getHttpServerArgs(options);
127
165
  const { path: pathToHttpServerPkgJson, packageJson } = (0, package_json_1.readModulePackageJson)('http-server', module.paths);
@@ -129,7 +167,6 @@ async function* fileServerExecutor(options, context) {
129
167
  const pathToHttpServer = (0, path_1.resolve)(pathToHttpServerPkgJson.replace('package.json', ''), pathToHttpServerBin);
130
168
  // detect port as close to when used to prevent port being used by another process
131
169
  // when running in parallel
132
- const port = await detectPort(options.port || 8080);
133
170
  args.push(`-p=${port}`);
134
171
  const serve = (0, child_process_1.fork)(pathToHttpServer, [outputPath, ...args], {
135
172
  stdio: 'pipe',
@@ -1,11 +1,11 @@
1
1
  export interface Schema {
2
- host: string;
3
- port: number;
4
- ssl: boolean;
2
+ host?: string;
3
+ port?: number;
4
+ ssl?: boolean;
5
5
  sslKey?: string;
6
6
  sslCert?: string;
7
7
  proxyUrl?: string;
8
- buildTarget: string;
8
+ buildTarget?: string;
9
9
  parallel: boolean;
10
10
  maxParallel?: number;
11
11
  withDeps: boolean;
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "proxyUrl": {
46
46
  "type": "string",
47
- "description": "URL to proxy unhandled requests to."
47
+ "description": "URL to proxy unhandled requests to. _Note: If the 'spa' flag is set to true, manually setting this value will override the catch-all redirect functionality from http-server which may lead to unexpected behavior._"
48
48
  },
49
49
  "proxyOptions": {
50
50
  "type": "object",
@@ -94,6 +94,5 @@
94
94
  "default": -1
95
95
  }
96
96
  },
97
- "additionalProperties": false,
98
- "required": ["buildTarget"]
97
+ "additionalProperties": false
99
98
  }
@@ -9,16 +9,45 @@ const path_1 = require("path");
9
9
  const versions_2 = require("../../utils/versions");
10
10
  const init_1 = require("../init/init");
11
11
  const get_npm_scope_1 = require("@nx/js/src/utils/package-json/get-npm-scope");
12
+ const has_webpack_plugin_1 = require("../../utils/has-webpack-plugin");
13
+ const add_build_target_defaults_1 = require("@nx/devkit/src/generators/add-build-target-defaults");
14
+ const log_show_project_command_1 = require("@nx/devkit/src/utils/log-show-project-command");
12
15
  function createApplicationFiles(tree, options) {
13
- (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, options.bundler === 'vite' ? './files/app-vite' : './files/app-webpack'), options.appProjectRoot, {
14
- ...options,
15
- ...(0, devkit_1.names)(options.name),
16
- tmpl: '',
17
- offsetFromRoot: (0, devkit_1.offsetFromRoot)(options.appProjectRoot),
18
- rootTsConfigPath: (0, js_1.getRelativePathToRootTsConfig)(tree, options.appProjectRoot),
19
- });
20
- if (options.unitTestRunner === 'none') {
21
- tree.delete((0, path_1.join)(options.appProjectRoot, './src/app/app.element.spec.ts'));
16
+ if (options.bundler === 'vite') {
17
+ (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, './files/app-vite'), options.appProjectRoot, {
18
+ ...options,
19
+ ...(0, devkit_1.names)(options.name),
20
+ tmpl: '',
21
+ offsetFromRoot: (0, devkit_1.offsetFromRoot)(options.appProjectRoot),
22
+ rootTsConfigPath: (0, js_1.getRelativePathToRootTsConfig)(tree, options.appProjectRoot),
23
+ });
24
+ }
25
+ else {
26
+ (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, './files/app-webpack'), options.appProjectRoot, {
27
+ ...options,
28
+ ...(0, devkit_1.names)(options.name),
29
+ tmpl: '',
30
+ offsetFromRoot: (0, devkit_1.offsetFromRoot)(options.appProjectRoot),
31
+ rootTsConfigPath: (0, js_1.getRelativePathToRootTsConfig)(tree, options.appProjectRoot),
32
+ webpackPluginOptions: (0, has_webpack_plugin_1.hasWebpackPlugin)(tree)
33
+ ? {
34
+ compiler: options.compiler,
35
+ target: 'web',
36
+ outputPath: (0, devkit_1.joinPathFragments)('dist', options.appProjectRoot != '.'
37
+ ? options.appProjectRoot
38
+ : options.projectName),
39
+ tsConfig: './tsconfig.app.json',
40
+ main: './src/main.ts',
41
+ assets: ['./src/favicon.ico', './src/assets'],
42
+ index: './src/index.html',
43
+ baseHref: '/',
44
+ styles: [`./src/styles.${options.style}`],
45
+ }
46
+ : null,
47
+ });
48
+ if (options.unitTestRunner === 'none') {
49
+ tree.delete((0, path_1.join)(options.appProjectRoot, './src/app/app.element.spec.ts'));
50
+ }
22
51
  }
23
52
  }
24
53
  async function setupBundler(tree, options) {
@@ -31,6 +60,7 @@ async function setupBundler(tree, options) {
31
60
  if (options.bundler === 'webpack') {
32
61
  const { configurationGenerator } = (0, devkit_1.ensurePackage)('@nx/webpack', versions_2.nxVersion);
33
62
  await configurationGenerator(tree, {
63
+ target: 'web',
34
64
  project: options.projectName,
35
65
  main,
36
66
  tsConfig,
@@ -38,38 +68,42 @@ async function setupBundler(tree, options) {
38
68
  devServer: true,
39
69
  webpackConfig: (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'webpack.config.js'),
40
70
  skipFormat: true,
71
+ addPlugin: options.addPlugin,
41
72
  });
42
73
  const project = (0, devkit_1.readProjectConfiguration)(tree, options.projectName);
43
- const prodConfig = project.targets.build.configurations.production;
44
- const buildOptions = project.targets.build.options;
45
- buildOptions.assets = assets;
46
- buildOptions.index = (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'src/index.html');
47
- buildOptions.baseHref = '/';
48
- buildOptions.styles = [
49
- (0, devkit_1.joinPathFragments)(options.appProjectRoot, `src/styles.${options.style}`),
50
- ];
51
- // We can delete that, because this projest is an application
52
- // and applications have a .babelrc file in their root dir.
53
- // So Nx will find it and use it
54
- delete buildOptions.babelUpwardRootMode;
55
- buildOptions.scripts = [];
56
- prodConfig.fileReplacements = [
57
- {
58
- replace: (0, devkit_1.joinPathFragments)(options.appProjectRoot, `src/environments/environment.ts`),
59
- with: (0, devkit_1.joinPathFragments)(options.appProjectRoot, `src/environments/environment.prod.ts`),
60
- },
61
- ];
62
- prodConfig.optimization = true;
63
- prodConfig.outputHashing = 'all';
64
- prodConfig.sourceMap = false;
65
- prodConfig.namedChunks = false;
66
- prodConfig.extractLicenses = true;
67
- prodConfig.vendorChunk = false;
68
- (0, devkit_1.updateProjectConfiguration)(tree, options.projectName, project);
74
+ if (project.targets.build) {
75
+ const prodConfig = project.targets.build.configurations.production;
76
+ const buildOptions = project.targets.build.options;
77
+ buildOptions.assets = assets;
78
+ buildOptions.index = (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'src/index.html');
79
+ buildOptions.baseHref = '/';
80
+ buildOptions.styles = [
81
+ (0, devkit_1.joinPathFragments)(options.appProjectRoot, `src/styles.${options.style}`),
82
+ ];
83
+ // We can delete that, because this projest is an application
84
+ // and applications have a .babelrc file in their root dir.
85
+ // So Nx will find it and use it
86
+ delete buildOptions.babelUpwardRootMode;
87
+ buildOptions.scripts = [];
88
+ prodConfig.fileReplacements = [
89
+ {
90
+ replace: (0, devkit_1.joinPathFragments)(options.appProjectRoot, `src/environments/environment.ts`),
91
+ with: (0, devkit_1.joinPathFragments)(options.appProjectRoot, `src/environments/environment.prod.ts`),
92
+ },
93
+ ];
94
+ prodConfig.optimization = true;
95
+ prodConfig.outputHashing = 'all';
96
+ prodConfig.sourceMap = false;
97
+ prodConfig.namedChunks = false;
98
+ prodConfig.extractLicenses = true;
99
+ prodConfig.vendorChunk = false;
100
+ (0, devkit_1.updateProjectConfiguration)(tree, options.projectName, project);
101
+ }
102
+ // TODO(jack): Flush this out... no bundler should be possible for web but the experience isn't holistic due to missing features (e.g. writing index.html).
69
103
  }
70
104
  else if (options.bundler === 'none') {
71
- // TODO(jack): Flush this out... no bundler should be possible for web but the experience isn't holistic due to missing features (e.g. writing index.html).
72
105
  const project = (0, devkit_1.readProjectConfiguration)(tree, options.projectName);
106
+ (0, add_build_target_defaults_1.addBuildTargetDefaults)(tree, `@nx/js:${options.compiler}`);
73
107
  project.targets.build = {
74
108
  executor: `@nx/js:${options.compiler}`,
75
109
  outputs: ['{options.outputPath}'],
@@ -77,7 +111,6 @@ async function setupBundler(tree, options) {
77
111
  main,
78
112
  outputPath: (0, devkit_1.joinPathFragments)('dist', options.appProjectRoot),
79
113
  tsConfig,
80
- assets,
81
114
  },
82
115
  };
83
116
  (0, devkit_1.updateProjectConfiguration)(tree, options.projectName, project);
@@ -95,9 +128,6 @@ async function addProject(tree, options) {
95
128
  tags: options.parsedTags,
96
129
  targets,
97
130
  }, options.standaloneConfig);
98
- if (options.bundler !== 'vite') {
99
- await setupBundler(tree, options);
100
- }
101
131
  }
102
132
  function setDefaults(tree, options) {
103
133
  const nxJson = (0, devkit_1.readNxJson)(tree);
@@ -113,6 +143,7 @@ function setDefaults(tree, options) {
113
143
  }
114
144
  async function applicationGenerator(host, schema) {
115
145
  return await applicationGeneratorInternal(host, {
146
+ addPlugin: false,
116
147
  projectNameAndRootFormat: 'derived',
117
148
  ...schema,
118
149
  });
@@ -121,13 +152,21 @@ exports.applicationGenerator = applicationGenerator;
121
152
  async function applicationGeneratorInternal(host, schema) {
122
153
  const options = await normalizeOptions(host, schema);
123
154
  const tasks = [];
155
+ const jsInitTask = await (0, js_1.initGenerator)(host, {
156
+ js: false,
157
+ skipFormat: true,
158
+ });
159
+ tasks.push(jsInitTask);
124
160
  const webTask = await (0, init_1.webInitGenerator)(host, {
125
161
  ...options,
126
162
  skipFormat: true,
127
163
  });
128
164
  tasks.push(webTask);
129
- createApplicationFiles(host, options);
130
165
  await addProject(host, options);
166
+ if (options.bundler !== 'vite') {
167
+ await setupBundler(host, options);
168
+ }
169
+ createApplicationFiles(host, options);
131
170
  if (options.bundler === 'vite') {
132
171
  const { viteConfigurationGenerator, createOrEditViteConfig } = (0, devkit_1.ensurePackage)('@nx/vite', versions_2.nxVersion);
133
172
  // We recommend users use `import.meta.env.MODE` and other variables in their code to differentiate between production and development.
@@ -142,6 +181,7 @@ async function applicationGeneratorInternal(host, schema) {
142
181
  includeVitest: options.unitTestRunner === 'vitest',
143
182
  inSourceTests: options.inSourceTests,
144
183
  skipFormat: true,
184
+ addPlugin: options.addPlugin,
145
185
  });
146
186
  tasks.push(viteTask);
147
187
  createOrEditViteConfig(host, {
@@ -156,9 +196,10 @@ async function applicationGeneratorInternal(host, schema) {
156
196
  const vitestTask = await vitestGenerator(host, {
157
197
  uiFramework: 'none',
158
198
  project: options.projectName,
159
- coverageProvider: 'c8',
199
+ coverageProvider: 'v8',
160
200
  inSourceTests: options.inSourceTests,
161
201
  skipFormat: true,
202
+ addPlugin: options.addPlugin,
162
203
  });
163
204
  tasks.push(vitestTask);
164
205
  createOrEditViteConfig(host, {
@@ -181,9 +222,9 @@ async function applicationGeneratorInternal(host, schema) {
181
222
  (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'tsconfig.app.json'),
182
223
  ],
183
224
  unitTestRunner: options.unitTestRunner,
184
- eslintFilePatterns: [`${options.appProjectRoot}/**/*.ts`],
185
225
  skipFormat: true,
186
226
  setParserOptionsProject: options.setParserOptionsProject,
227
+ addPlugin: options.addPlugin,
187
228
  });
188
229
  tasks.push(lintTask);
189
230
  }
@@ -200,7 +241,8 @@ async function applicationGeneratorInternal(host, schema) {
200
241
  const cypressTask = await configurationGenerator(host, {
201
242
  ...options,
202
243
  project: options.e2eProjectName,
203
- devServerTarget: `${options.projectName}:serve`,
244
+ devServerTarget: `${options.projectName}:${options.e2eWebServerTarget}`,
245
+ baseUrl: options.e2eWebServerAddress,
204
246
  directory: 'src',
205
247
  skipFormat: true,
206
248
  });
@@ -223,8 +265,9 @@ async function applicationGeneratorInternal(host, schema) {
223
265
  js: false,
224
266
  linter: options.linter,
225
267
  setParserOptionsProject: options.setParserOptionsProject,
226
- webServerCommand: `${(0, devkit_1.getPackageManagerCommand)().exec} nx serve ${options.name}`,
227
- webServerAddress: 'http://localhost:4200',
268
+ webServerCommand: `${(0, devkit_1.getPackageManagerCommand)().exec} nx ${options.e2eWebServerTarget} ${options.name}`,
269
+ webServerAddress: options.e2eWebServerAddress,
270
+ addPlugin: options.addPlugin,
228
271
  });
229
272
  tasks.push(playwrightTask);
230
273
  }
@@ -236,6 +279,7 @@ async function applicationGeneratorInternal(host, schema) {
236
279
  setupFile: 'web-components',
237
280
  compiler: options.compiler,
238
281
  skipFormat: true,
282
+ addPlugin: options.addPlugin,
239
283
  });
240
284
  tasks.push(jestTask);
241
285
  }
@@ -257,9 +301,13 @@ async function applicationGeneratorInternal(host, schema) {
257
301
  });
258
302
  }
259
303
  setDefaults(host, options);
304
+ tasks.push((0, devkit_1.addDependenciesToPackageJson)(host, { tslib: versions_2.tsLibVersion }, { '@types/node': versions_2.typesNodeVersion }));
260
305
  if (!schema.skipFormat) {
261
306
  await (0, devkit_1.formatFiles)(host);
262
307
  }
308
+ tasks.push(() => {
309
+ (0, log_show_project_command_1.logShowProjectCommand)(options.projectName);
310
+ });
263
311
  return (0, devkit_1.runTasksInSerial)(...tasks);
264
312
  }
265
313
  exports.applicationGeneratorInternal = applicationGeneratorInternal;
@@ -272,8 +320,39 @@ async function normalizeOptions(host, options) {
272
320
  callingGenerator: '@nx/web:application',
273
321
  });
274
322
  options.projectNameAndRootFormat = projectNameAndRootFormat;
323
+ const nxJson = (0, devkit_1.readNxJson)(host);
324
+ const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
325
+ nxJson.useInferencePlugins !== false;
326
+ options.addPlugin ??= addPluginDefault;
327
+ let e2eWebServerTarget = 'serve';
328
+ if (options.addPlugin) {
329
+ if (nxJson.plugins) {
330
+ for (const plugin of nxJson.plugins) {
331
+ if (options.bundler === 'vite' &&
332
+ typeof plugin === 'object' &&
333
+ plugin.plugin === '@nx/vite/plugin' &&
334
+ plugin.options.serveTargetName) {
335
+ e2eWebServerTarget = plugin.options
336
+ .serveTargetName;
337
+ }
338
+ else if (options.bundler === 'webpack' &&
339
+ typeof plugin === 'object' &&
340
+ plugin.plugin === '@nx/webpack/plugin' &&
341
+ plugin.options.serveTargetName) {
342
+ e2eWebServerTarget = plugin.options
343
+ .serveTargetName;
344
+ }
345
+ }
346
+ }
347
+ }
348
+ let e2ePort = 4200;
349
+ if (nxJson.targetDefaults?.[e2eWebServerTarget] &&
350
+ nxJson.targetDefaults?.[e2eWebServerTarget].options?.port) {
351
+ e2ePort = nxJson.targetDefaults?.[e2eWebServerTarget].options?.port;
352
+ }
275
353
  const e2eProjectName = `${appProjectName}-e2e`;
276
354
  const e2eProjectRoot = `${appProjectRoot}-e2e`;
355
+ const e2eWebServerAddress = `http://localhost:${e2ePort}`;
277
356
  const npmScope = (0, get_npm_scope_1.getNpmScope)(host);
278
357
  const parsedTags = options.tags
279
358
  ? options.tags.split(',').map((s) => s.trim())
@@ -295,6 +374,9 @@ async function normalizeOptions(host, options) {
295
374
  appProjectRoot,
296
375
  e2eProjectRoot,
297
376
  e2eProjectName,
377
+ e2eWebServerAddress,
378
+ e2eWebServerTarget,
379
+ e2ePort,
298
380
  parsedTags,
299
381
  };
300
382
  }
@@ -278,7 +278,15 @@
278
278
  #nx-console svg {
279
279
  color: rgba(0, 122, 204, 1);
280
280
  }
281
-
281
+ #nx-console-jetbrains {
282
+ margin-top: 2rem;
283
+ }
284
+ #nx-console-jetbrains:hover {
285
+ background-color: rgba(255, 49, 140, 1);
286
+ }
287
+ #nx-console-jetbrains svg {
288
+ color: rgba(255, 49, 140, 1);
289
+ }
282
290
  #nx-repo:hover {
283
291
  background-color: rgba(24, 23, 23, 1);
284
292
  }
@@ -234,10 +234,44 @@ export class AppElement extends HTMLElement {
234
234
  />
235
235
  </svg>
236
236
  <span>
237
- Install Nx Console
238
- <span>Plugin for VSCode</span>
237
+ Install Nx Console for VSCode
238
+ <span>The official VSCode extension for Nx.</span>
239
239
  </span>
240
240
  </a>
241
+ <a
242
+ id="nx-console-jetbrains"
243
+ class="button-pill rounded shadow"
244
+ href="https://plugins.jetbrains.com/plugin/21060-nx-console"
245
+ target="_blank"
246
+ rel="noreferrer"
247
+ >
248
+ <svg
249
+ height="48"
250
+ width="48"
251
+ viewBox="20 20 60 60"
252
+ xmlns="http://www.w3.org/2000/svg"
253
+ >
254
+ <path d="m22.5 22.5h60v60h-60z" />
255
+ <g fill="#fff">
256
+ <path d="m29.03 71.25h22.5v3.75h-22.5z" />
257
+ <path d="m28.09 38 1.67-1.58a1.88 1.88 0 0 0 1.47.87c.64 0 1.06-.44 1.06-1.31v-5.98h2.58v6a3.48 3.48 0 0 1 -.87 2.6 3.56 3.56 0 0 1 -2.57.95 3.84 3.84 0 0 1 -3.34-1.55z" />
258
+ <path d="m36 30h7.53v2.19h-5v1.44h4.49v2h-4.42v1.49h5v2.21h-7.6z" />
259
+ <path d="m47.23 32.29h-2.8v-2.29h8.21v2.27h-2.81v7.1h-2.6z" />
260
+ <path d="m29.13 43.08h4.42a3.53 3.53 0 0 1 2.55.83 2.09 2.09 0 0 1 .6 1.53 2.16 2.16 0 0 1 -1.44 2.09 2.27 2.27 0 0 1 1.86 2.29c0 1.61-1.31 2.59-3.55 2.59h-4.44zm5 2.89c0-.52-.42-.8-1.18-.8h-1.29v1.64h1.24c.79 0 1.25-.26 1.25-.81zm-.9 2.66h-1.57v1.73h1.62c.8 0 1.24-.31 1.24-.86 0-.5-.4-.87-1.27-.87z" />
261
+ <path d="m38 43.08h4.1a4.19 4.19 0 0 1 3 1 2.93 2.93 0 0 1 .9 2.19 3 3 0 0 1 -1.93 2.89l2.24 3.27h-3l-1.88-2.84h-.87v2.84h-2.56zm4 4.5c.87 0 1.39-.43 1.39-1.11 0-.75-.54-1.12-1.4-1.12h-1.44v2.26z" />
262
+ <path d="m49.59 43h2.5l4 9.44h-2.79l-.67-1.69h-3.63l-.67 1.69h-2.71zm2.27 5.73-1-2.65-1.06 2.65z" />
263
+ <path d="m56.46 43.05h2.6v9.37h-2.6z" />
264
+ <path d="m60.06 43.05h2.42l3.37 5v-5h2.57v9.37h-2.26l-3.53-5.14v5.14h-2.57z" />
265
+ <path d="m68.86 51 1.45-1.73a4.84 4.84 0 0 0 3 1.13c.71 0 1.08-.24 1.08-.65 0-.4-.31-.6-1.59-.91-2-.46-3.53-1-3.53-2.93 0-1.74 1.37-3 3.62-3a5.89 5.89 0 0 1 3.86 1.25l-1.26 1.84a4.63 4.63 0 0 0 -2.62-.92c-.63 0-.94.25-.94.6 0 .42.32.61 1.63.91 2.14.46 3.44 1.16 3.44 2.91 0 1.91-1.51 3-3.79 3a6.58 6.58 0 0 1 -4.35-1.5z" />
266
+ </g>
267
+ </svg>
268
+ <span>
269
+ Install Nx Console for JetBrains
270
+ <span>
271
+ Available for WebStorm, Intellij IDEA Ultimate and more!
272
+ </span>
273
+ </span>
274
+ </a>
241
275
  <div id="nx-cloud" class="rounded shadow">
242
276
  <div>
243
277
  <svg id="nx-cloud-logo" role="img" xmlns="http://www.w3.org/2000/svg" stroke="currentColor" fill="transparent" viewBox="0 0 24 24">
@@ -245,7 +279,7 @@ export class AppElement extends HTMLElement {
245
279
  <path stroke-width="2" d="M23 6v14.1667C23 21.7307 21.7307 23 20.1667 23H6c0-3.128 2.53867-5.6667 5.6667-5.6667 3.128 0 5.6666-2.5386 5.6666-5.6666C17.3333 8.53867 19.872 6 23 6Z" />
246
280
  </svg>
247
281
  <h2>
248
- NxCloud
282
+ Nx Cloud
249
283
  <span>
250
284
  Enable faster CI & better DX
251
285
  </span>
@@ -255,7 +289,7 @@ export class AppElement extends HTMLElement {
255
289
  You can activate distributed tasks executions and caching by
256
290
  running:
257
291
  </p>
258
- <pre>nx connect-to-nx-cloud</pre>
292
+ <pre>nx connect</pre>
259
293
  <a href="https://nx.app/?utm_source=nx-project" target="_blank" rel="noreferrer"> What is Nx Cloud? </a>
260
294
  </div>
261
295
  <a id="nx-repo" class="button-pill rounded shadow" href="https://github.com/nrwl/nx?utm_source=nx-project" target="_blank" rel="noreferrer">
@@ -302,7 +336,7 @@ export class AppElement extends HTMLElement {
302
336
  nx g @nx/angular:lib ui
303
337
 
304
338
  <span># Add a component</span>
305
- nx g @nx/angular:component button --project ui</pre>
339
+ nx g @nx/angular:component ui/src/lib/button</pre>
306
340
  </details>
307
341
  <details>
308
342
  <summary>
@@ -278,7 +278,15 @@
278
278
  #nx-console svg {
279
279
  color: rgba(0, 122, 204, 1);
280
280
  }
281
-
281
+ #nx-console-jetbrains {
282
+ margin-top: 2rem;
283
+ }
284
+ #nx-console-jetbrains:hover {
285
+ background-color: rgba(255, 49, 140, 1);
286
+ }
287
+ #nx-console-jetbrains svg {
288
+ color: rgba(255, 49, 140, 1);
289
+ }
282
290
  #nx-repo:hover {
283
291
  background-color: rgba(24, 23, 23, 1);
284
292
  }
@@ -234,10 +234,44 @@ export class AppElement extends HTMLElement {
234
234
  />
235
235
  </svg>
236
236
  <span>
237
- Install Nx Console
238
- <span>Plugin for VSCode</span>
237
+ Install Nx Console for VSCode
238
+ <span>The official VSCode extension for Nx.</span>
239
239
  </span>
240
240
  </a>
241
+ <a
242
+ id="nx-console-jetbrains"
243
+ class="button-pill rounded shadow"
244
+ href="https://plugins.jetbrains.com/plugin/21060-nx-console"
245
+ target="_blank"
246
+ rel="noreferrer"
247
+ >
248
+ <svg
249
+ height="48"
250
+ width="48"
251
+ viewBox="20 20 60 60"
252
+ xmlns="http://www.w3.org/2000/svg"
253
+ >
254
+ <path d="m22.5 22.5h60v60h-60z" />
255
+ <g fill="#fff">
256
+ <path d="m29.03 71.25h22.5v3.75h-22.5z" />
257
+ <path d="m28.09 38 1.67-1.58a1.88 1.88 0 0 0 1.47.87c.64 0 1.06-.44 1.06-1.31v-5.98h2.58v6a3.48 3.48 0 0 1 -.87 2.6 3.56 3.56 0 0 1 -2.57.95 3.84 3.84 0 0 1 -3.34-1.55z" />
258
+ <path d="m36 30h7.53v2.19h-5v1.44h4.49v2h-4.42v1.49h5v2.21h-7.6z" />
259
+ <path d="m47.23 32.29h-2.8v-2.29h8.21v2.27h-2.81v7.1h-2.6z" />
260
+ <path d="m29.13 43.08h4.42a3.53 3.53 0 0 1 2.55.83 2.09 2.09 0 0 1 .6 1.53 2.16 2.16 0 0 1 -1.44 2.09 2.27 2.27 0 0 1 1.86 2.29c0 1.61-1.31 2.59-3.55 2.59h-4.44zm5 2.89c0-.52-.42-.8-1.18-.8h-1.29v1.64h1.24c.79 0 1.25-.26 1.25-.81zm-.9 2.66h-1.57v1.73h1.62c.8 0 1.24-.31 1.24-.86 0-.5-.4-.87-1.27-.87z" />
261
+ <path d="m38 43.08h4.1a4.19 4.19 0 0 1 3 1 2.93 2.93 0 0 1 .9 2.19 3 3 0 0 1 -1.93 2.89l2.24 3.27h-3l-1.88-2.84h-.87v2.84h-2.56zm4 4.5c.87 0 1.39-.43 1.39-1.11 0-.75-.54-1.12-1.4-1.12h-1.44v2.26z" />
262
+ <path d="m49.59 43h2.5l4 9.44h-2.79l-.67-1.69h-3.63l-.67 1.69h-2.71zm2.27 5.73-1-2.65-1.06 2.65z" />
263
+ <path d="m56.46 43.05h2.6v9.37h-2.6z" />
264
+ <path d="m60.06 43.05h2.42l3.37 5v-5h2.57v9.37h-2.26l-3.53-5.14v5.14h-2.57z" />
265
+ <path d="m68.86 51 1.45-1.73a4.84 4.84 0 0 0 3 1.13c.71 0 1.08-.24 1.08-.65 0-.4-.31-.6-1.59-.91-2-.46-3.53-1-3.53-2.93 0-1.74 1.37-3 3.62-3a5.89 5.89 0 0 1 3.86 1.25l-1.26 1.84a4.63 4.63 0 0 0 -2.62-.92c-.63 0-.94.25-.94.6 0 .42.32.61 1.63.91 2.14.46 3.44 1.16 3.44 2.91 0 1.91-1.51 3-3.79 3a6.58 6.58 0 0 1 -4.35-1.5z" />
266
+ </g>
267
+ </svg>
268
+ <span>
269
+ Install Nx Console for JetBrains
270
+ <span>
271
+ Available for WebStorm, Intellij IDEA Ultimate and more!
272
+ </span>
273
+ </span>
274
+ </a>
241
275
  <div id="nx-cloud" class="rounded shadow">
242
276
  <div>
243
277
  <svg id="nx-cloud-logo" role="img" xmlns="http://www.w3.org/2000/svg" stroke="currentColor" fill="transparent" viewBox="0 0 24 24">
@@ -245,7 +279,7 @@ export class AppElement extends HTMLElement {
245
279
  <path stroke-width="2" d="M23 6v14.1667C23 21.7307 21.7307 23 20.1667 23H6c0-3.128 2.53867-5.6667 5.6667-5.6667 3.128 0 5.6666-2.5386 5.6666-5.6666C17.3333 8.53867 19.872 6 23 6Z" />
246
280
  </svg>
247
281
  <h2>
248
- NxCloud
282
+ Nx Cloud
249
283
  <span>
250
284
  Enable faster CI & better DX
251
285
  </span>
@@ -255,7 +289,7 @@ export class AppElement extends HTMLElement {
255
289
  You can activate distributed tasks executions and caching by
256
290
  running:
257
291
  </p>
258
- <pre>nx connect-to-nx-cloud</pre>
292
+ <pre>nx connect</pre>
259
293
  <a href="https://nx.app/?utm_source=nx-project" target="_blank" rel="noreferrer"> What is Nx Cloud? </a>
260
294
  </div>
261
295
  <a id="nx-repo" class="button-pill rounded shadow" href="https://github.com/nrwl/nx?utm_source=nx-project" target="_blank" rel="noreferrer">
@@ -302,7 +336,7 @@ export class AppElement extends HTMLElement {
302
336
  nx g @nx/angular:lib ui
303
337
 
304
338
  <span># Add a component</span>
305
- nx g @nx/angular:component button --project ui</pre>
339
+ nx g @nx/angular:component ui/src/lib/button</pre>
306
340
  </details>
307
341
  <details>
308
342
  <summary>
@@ -1,8 +1,39 @@
1
+ <% if (webpackPluginOptions) { %>
2
+ const { NxWebpackPlugin } = require('@nx/webpack');
3
+ const { join } = require('path');
4
+
5
+ module.exports = {
6
+ output: {
7
+ path: join(__dirname, '<%= offsetFromRoot %><%= webpackPluginOptions.outputPath %>'),
8
+ },
9
+ devServer: {
10
+ port: 4200
11
+ },
12
+ plugins: [
13
+ new NxWebpackPlugin({
14
+ tsConfig: '<%= webpackPluginOptions.tsConfig %>',
15
+ compiler: '<%= webpackPluginOptions.compiler %>',
16
+ main: '<%= webpackPluginOptions.main %>',
17
+ index: '<%= webpackPluginOptions.index %>',
18
+ baseHref: '<%= webpackPluginOptions.baseHref %>',
19
+ assets: <%- JSON.stringify(webpackPluginOptions.assets) %>,
20
+ styles: <%- JSON.stringify(webpackPluginOptions.styles) %>,
21
+ outputHashing: process.env['NODE_ENV'] === 'production' ? 'all' : 'none',
22
+ optimization: process.env['NODE_ENV'] === 'production',
23
+ })
24
+ ],
25
+ };
26
+ <% } else { %>
1
27
  const { composePlugins, withNx, withWeb } = require('@nx/webpack');
2
28
 
3
29
  // Nx plugins for webpack.
4
- module.exports = composePlugins(withNx(), withWeb(), (config) => {
5
- // Update the webpack config as needed here.
6
- // e.g. `config.plugins.push(new MyPlugin())`
7
- return config;
8
- });
30
+ module.exports = composePlugins(
31
+ withNx(),
32
+ withWeb(),
33
+ (config) => {
34
+ // Update the webpack config as needed here.
35
+ // e.g. `config.plugins.push(new MyPlugin())`
36
+ return config;
37
+ }
38
+ );
39
+ <% } %>
@@ -17,4 +17,5 @@ export interface Schema {
17
17
  linter?: Linter;
18
18
  standaloneConfig?: boolean;
19
19
  setParserOptionsProject?: boolean;
20
+ addPlugin?: boolean;
20
21
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "cli": "nx",
4
4
  "$id": "NxWebApp",
5
5
  "title": "Create a Web Application for Nx",
@@ -39,11 +39,11 @@
39
39
  },
40
40
  {
41
41
  "value": "scss",
42
- "label": "SASS(.scss) [ http://sass-lang.com ]"
42
+ "label": "SASS(.scss) [ https://sass-lang.com ]"
43
43
  },
44
44
  {
45
45
  "value": "less",
46
- "label": "LESS [ http://lesscss.org ]"
46
+ "label": "LESS [ https://lesscss.org ]"
47
47
  }
48
48
  ]
49
49
  }
@@ -2,55 +2,22 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.webInitGenerator = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
- const js_1 = require("@nx/js");
6
5
  const versions_1 = require("../../utils/versions");
7
6
  function updateDependencies(tree, schema) {
8
- (0, devkit_1.removeDependenciesFromPackageJson)(tree, ['@nx/web'], []);
9
- const devDependencies = {
10
- '@nx/web': versions_1.nxVersion,
11
- '@types/node': versions_1.typesNodeVersion,
12
- };
13
- return (0, devkit_1.addDependenciesToPackageJson)(tree, {
14
- tslib: versions_1.tsLibVersion,
15
- }, devDependencies);
7
+ const tasks = [];
8
+ tasks.push((0, devkit_1.removeDependenciesFromPackageJson)(tree, ['@nx/web'], []));
9
+ tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@nx/web': versions_1.nxVersion }, undefined, schema.keepExistingVersions));
10
+ return (0, devkit_1.runTasksInSerial)(...tasks);
16
11
  }
17
12
  async function webInitGenerator(tree, schema) {
18
- const tasks = [];
19
- const jsInitTask = await (0, js_1.initGenerator)(tree, {
20
- js: false,
21
- skipFormat: true,
22
- });
23
- tasks.push(jsInitTask);
24
- if (!schema.unitTestRunner || schema.unitTestRunner === 'jest') {
25
- const { jestInitGenerator } = (0, devkit_1.ensurePackage)('@nx/jest', versions_1.nxVersion);
26
- const jestTask = await jestInitGenerator(tree, {
27
- skipPackageJson: schema.skipPackageJson,
28
- });
29
- tasks.push(jestTask);
30
- }
31
- if (!schema.e2eTestRunner || schema.e2eTestRunner === 'cypress') {
32
- const { cypressInitGenerator } = (0, devkit_1.ensurePackage)('@nx/cypress', versions_1.nxVersion);
33
- const cypressTask = await cypressInitGenerator(tree, {
34
- skipPackageJson: schema.skipPackageJson,
35
- });
36
- tasks.push(cypressTask);
37
- }
38
- else if (schema.e2eTestRunner === 'playwright') {
39
- const { initGenerator: playwrightInitGenerator } = (0, devkit_1.ensurePackage)('@nx/playwright', versions_1.nxVersion);
40
- const playwrightConfigTask = await playwrightInitGenerator(tree, {
41
- skipFormat: true,
42
- skipPackageJson: schema.skipPackageJson,
43
- });
44
- tasks.push(playwrightConfigTask);
45
- }
13
+ let installTask = () => { };
46
14
  if (!schema.skipPackageJson) {
47
- const installTask = updateDependencies(tree, schema);
48
- tasks.push(installTask);
15
+ installTask = updateDependencies(tree, schema);
49
16
  }
50
17
  if (!schema.skipFormat) {
51
18
  await (0, devkit_1.formatFiles)(tree);
52
19
  }
53
- return (0, devkit_1.runTasksInSerial)(...tasks);
20
+ return installTask;
54
21
  }
55
22
  exports.webInitGenerator = webInitGenerator;
56
23
  exports.default = webInitGenerator;
@@ -1,7 +1,5 @@
1
1
  export interface Schema {
2
- bundler?: 'webpack' | 'none' | 'vite';
3
- unitTestRunner?: 'jest' | 'vitest' | 'none';
4
- e2eTestRunner?: 'cypress' | 'playwright' | 'none';
5
2
  skipFormat?: boolean;
6
3
  skipPackageJson?: boolean;
4
+ keepExistingVersions?: boolean;
7
5
  }
@@ -1,30 +1,11 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "$id": "NxWebInit",
4
4
  "cli": "nx",
5
5
  "title": "Init Web Plugin",
6
6
  "description": "Init Web Plugin.",
7
7
  "type": "object",
8
8
  "properties": {
9
- "bundler": {
10
- "type": "string",
11
- "description": "The bundler to use.",
12
- "enum": ["webpack", "none", "vite"],
13
- "default": "webpack"
14
- },
15
- "unitTestRunner": {
16
- "description": "Adds the specified unit test runner",
17
- "type": "string",
18
- "enum": ["jest", "none"],
19
- "default": "jest"
20
- },
21
- "e2eTestRunner": {
22
- "description": "Adds the specified e2e test runner",
23
- "type": "string",
24
- "enum": ["cypress", "playwright", "none"],
25
- "x-prompt": "Which E2E test runner would you like to use?",
26
- "default": "cypress"
27
- },
28
9
  "skipFormat": {
29
10
  "description": "Skip formatting files",
30
11
  "type": "boolean",
@@ -35,6 +16,12 @@
35
16
  "type": "boolean",
36
17
  "default": false,
37
18
  "x-priority": "internal"
19
+ },
20
+ "keepExistingVersions": {
21
+ "type": "boolean",
22
+ "x-priority": "internal",
23
+ "description": "Keep existing dependencies versions",
24
+ "default": false
38
25
  }
39
26
  },
40
27
  "required": []
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "$id": "NxWebStaticServe",
4
4
  "cli": "nx",
5
5
  "title": "Static Serve Configuration",
@@ -18,6 +18,11 @@
18
18
  "type": "string",
19
19
  "description": "Name of the serve target to add. Defaults to 'serve-static'.",
20
20
  "default": "serve-static"
21
+ },
22
+ "spa": {
23
+ "type": "boolean",
24
+ "description": "Whether to set the 'spa' flag on the generated target.",
25
+ "default": true
21
26
  }
22
27
  },
23
28
  "required": ["buildTarget"]
@@ -1,8 +1,9 @@
1
- import { Tree } from '@nx/devkit';
1
+ import { type Tree } from '@nx/devkit';
2
2
  interface WebStaticServeSchema {
3
3
  buildTarget: string;
4
4
  outputPath?: string;
5
5
  targetName?: string;
6
+ spa?: boolean;
6
7
  }
7
- export declare function webStaticServeGenerator(tree: Tree, options: WebStaticServeSchema): void;
8
+ export declare function webStaticServeGenerator(tree: Tree, options: WebStaticServeSchema): Promise<void>;
8
9
  export default webStaticServeGenerator;
@@ -2,17 +2,25 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.webStaticServeGenerator = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
- function webStaticServeGenerator(tree, options) {
6
- const opts = normalizeOptions(tree, options);
5
+ async function webStaticServeGenerator(tree, options) {
6
+ const opts = await normalizeOptions(tree, options);
7
7
  addStaticConfig(tree, opts);
8
8
  }
9
9
  exports.webStaticServeGenerator = webStaticServeGenerator;
10
- function normalizeOptions(tree, options) {
11
- const target = (0, devkit_1.parseTargetString)(options.buildTarget);
10
+ async function normalizeOptions(tree, options) {
11
+ let projectGraph;
12
+ try {
13
+ projectGraph = (0, devkit_1.readCachedProjectGraph)();
14
+ }
15
+ catch (e) {
16
+ projectGraph = await (0, devkit_1.createProjectGraphAsync)();
17
+ }
18
+ const target = (0, devkit_1.parseTargetString)(options.buildTarget, projectGraph);
12
19
  const opts = {
13
20
  ...options,
14
21
  targetName: options.targetName || 'serve-static',
15
22
  projectName: target.project,
23
+ spa: options.spa ?? true,
16
24
  };
17
25
  const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, target.project);
18
26
  const buildTargetConfig = projectConfig?.targets?.[target.target];
@@ -27,7 +35,7 @@ Optionally, you can provide a different name with the --target-name option other
27
35
  }
28
36
  // NOTE: @nx/web:file-server only looks for the outputPath option
29
37
  if (!buildTargetConfig.options?.outputPath && !opts.outputPath) {
30
- // attempt to find the suiteable path from the outputs
38
+ // attempt to find the suitable path from the outputs
31
39
  let maybeOutputValue;
32
40
  for (const o of buildTargetConfig?.outputs || []) {
33
41
  const isInterpolatedOutput = o.trim().startsWith('{options.');
@@ -65,6 +73,7 @@ function addStaticConfig(tree, opts) {
65
73
  options: {
66
74
  buildTarget: opts.buildTarget,
67
75
  staticFilePath: opts.outputPath,
76
+ spa: opts.spa,
68
77
  },
69
78
  };
70
79
  projectConfig.targets[opts.targetName] = staticServeOptions;
@@ -13,7 +13,7 @@ async function addDroppedDependencies(tree) {
13
13
  for (const [_, projectConfiguration] of projects) {
14
14
  for (const [_, targetConfiguration] of Object.entries(projectConfiguration.targets ?? {})) {
15
15
  for (const droppedDependency of droppedDependencies) {
16
- if (targetConfiguration.executor?.startsWith(droppedDependency + ':')) {
16
+ if (targetConfiguration?.['executor']?.startsWith(droppedDependency + ':')) {
17
17
  devDependencies[droppedDependency] = devkit_1.NX_VERSION;
18
18
  }
19
19
  }
@@ -22,7 +22,7 @@ async function addDroppedDependencies(tree) {
22
22
  const nxJson = (0, devkit_1.readNxJson)(tree);
23
23
  for (const [_, targetConfiguration] of Object.entries(nxJson?.targetDefaults ?? {})) {
24
24
  for (const droppedDependency of droppedDependencies) {
25
- if (targetConfiguration.executor?.startsWith(droppedDependency + ':')) {
25
+ if (targetConfiguration?.['executor']?.startsWith(droppedDependency + ':')) {
26
26
  devDependencies[droppedDependency] = devkit_1.NX_VERSION;
27
27
  }
28
28
  }
@@ -0,0 +1,2 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export declare function hasWebpackPlugin(tree: Tree): boolean;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasWebpackPlugin = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ function hasWebpackPlugin(tree) {
6
+ const nxJson = (0, devkit_1.readNxJson)(tree);
7
+ return !!nxJson.plugins?.some((p) => typeof p === 'string'
8
+ ? p === '@nx/webpack/plugin'
9
+ : p.plugin === '@nx/webpack/plugin');
10
+ }
11
+ exports.hasWebpackPlugin = hasWebpackPlugin;
@@ -1,4 +1,4 @@
1
1
  export declare const nxVersion: any;
2
2
  export declare const swcLoaderVersion = "0.1.15";
3
- export declare const typesNodeVersion = "18.7.1";
3
+ export declare const typesNodeVersion = "18.16.9";
4
4
  export declare const tsLibVersion = "^2.3.0";
@@ -3,5 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.tsLibVersion = exports.typesNodeVersion = exports.swcLoaderVersion = exports.nxVersion = void 0;
4
4
  exports.nxVersion = require('../../package.json').version;
5
5
  exports.swcLoaderVersion = '0.1.15';
6
- exports.typesNodeVersion = '18.7.1';
6
+ exports.typesNodeVersion = '18.16.9';
7
7
  exports.tsLibVersion = '^2.3.0';
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.waitForPortOpen = void 0;
4
+ const devkit_1 = require("@nx/devkit");
4
5
  const net = require("net");
5
6
  function waitForPortOpen(port, options = {}) {
6
- const allowedErrorCodes = ['ECONNREFUSED', 'ECONNRESET'];
7
+ const host = options.host ?? '127.0.0.1';
8
+ const allowedErrorCodes = ['ECONNREFUSED', 'ECONNRESET', 'ETIMEDOUT'];
7
9
  return new Promise((resolve, reject) => {
8
10
  const checkPort = (retries = options.retries ?? 120) => {
9
11
  const client = new net.Socket();
@@ -20,6 +22,9 @@ function waitForPortOpen(port, options = {}) {
20
22
  });
21
23
  client.once('error', (err) => {
22
24
  if (retries === 0 || !allowedErrorCodes.includes(err['code'])) {
25
+ if (process.env['NX_VERBOSE_LOGGING'] === 'true') {
26
+ devkit_1.logger.info(`Error connecting on ${host}:${port}: ${err['code'] || err}`);
27
+ }
23
28
  cleanupClient();
24
29
  reject(err);
25
30
  }
@@ -29,7 +34,10 @@ function waitForPortOpen(port, options = {}) {
29
34
  });
30
35
  // Node will use IPv6 if it is available, but this can cause issues if the server is only listening on IPv4.
31
36
  // Hard-coding to look on 127.0.0.1 to avoid using the IPv6 loopback address "::1".
32
- client.connect({ port, host: options.host ?? '127.0.0.1' });
37
+ if (process.env['NX_VERBOSE_LOGGING'] === 'true') {
38
+ devkit_1.logger.info(`Connecting on ${host}:${port}`);
39
+ }
40
+ client.connect({ port, host });
33
41
  };
34
42
  checkPort();
35
43
  });
@@ -1,3 +0,0 @@
1
- export const environment = {
2
- production: true
3
- };
@@ -1,6 +0,0 @@
1
- // This file can be replaced during build by using the `fileReplacements` array.
2
- // When building for production, this file is replaced with `environment.prod.ts`.
3
-
4
- export const environment = {
5
- production: false
6
- };