@nx/webpack 19.4.0-beta.0 → 19.4.0-beta.2

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 (39) hide show
  1. package/generators.json +11 -1
  2. package/index.d.ts +3 -1
  3. package/index.js +5 -1
  4. package/package.json +5 -4
  5. package/plugin.d.ts +1 -1
  6. package/plugin.js +2 -1
  7. package/src/executors/dev-server/dev-server.impl.js +7 -1
  8. package/src/executors/webpack/webpack.impl.js +5 -0
  9. package/src/generators/convert-config-to-webpack-plugin/convert-config-to-webpack-plugin.d.ts +7 -0
  10. package/src/generators/convert-config-to-webpack-plugin/convert-config-to-webpack-plugin.js +93 -0
  11. package/src/generators/convert-config-to-webpack-plugin/lib/extract-webpack-options.d.ts +6 -0
  12. package/src/generators/convert-config-to-webpack-plugin/lib/extract-webpack-options.js +106 -0
  13. package/src/generators/convert-config-to-webpack-plugin/lib/normalize-path-options.d.ts +2 -0
  14. package/src/generators/convert-config-to-webpack-plugin/lib/normalize-path-options.js +75 -0
  15. package/src/generators/convert-config-to-webpack-plugin/lib/utils.d.ts +1 -0
  16. package/src/generators/convert-config-to-webpack-plugin/lib/utils.js +14 -0
  17. package/src/generators/convert-config-to-webpack-plugin/lib/validate-project.d.ts +9 -0
  18. package/src/generators/convert-config-to-webpack-plugin/lib/validate-project.js +44 -0
  19. package/src/generators/convert-config-to-webpack-plugin/schema.json +19 -0
  20. package/src/generators/convert-to-inferred/convert-to-inferred.d.ts +7 -0
  21. package/src/generators/convert-to-inferred/convert-to-inferred.js +71 -0
  22. package/src/generators/convert-to-inferred/schema.json +19 -0
  23. package/src/generators/convert-to-inferred/utils/ast.d.ts +3 -0
  24. package/src/generators/convert-to-inferred/utils/ast.js +40 -0
  25. package/src/generators/convert-to-inferred/utils/build-post-target-transformer.d.ts +6 -0
  26. package/src/generators/convert-to-inferred/utils/build-post-target-transformer.js +219 -0
  27. package/src/generators/convert-to-inferred/utils/index.d.ts +3 -0
  28. package/src/generators/convert-to-inferred/utils/index.js +6 -0
  29. package/src/generators/convert-to-inferred/utils/serve-post-target-transformer.d.ts +6 -0
  30. package/src/generators/convert-to-inferred/utils/serve-post-target-transformer.js +250 -0
  31. package/src/generators/convert-to-inferred/utils/types.d.ts +11 -0
  32. package/src/generators/convert-to-inferred/utils/types.js +2 -0
  33. package/src/plugins/nx-webpack-plugin/lib/apply-base-config.js +5 -1
  34. package/src/plugins/nx-webpack-plugin/lib/normalize-options.js +1 -1
  35. package/src/plugins/plugin.d.ts +5 -1
  36. package/src/plugins/plugin.js +62 -41
  37. package/src/plugins/use-legacy-nx-plugin/use-legacy-nx-plugin.d.ts +29 -0
  38. package/src/plugins/use-legacy-nx-plugin/use-legacy-nx-plugin.js +59 -0
  39. package/src/utils/module-federation/get-remotes-for-host.js +1 -1
package/generators.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "init": {
6
6
  "factory": "./src/generators/init/init#webpackInitGeneratorInternal",
7
7
  "schema": "./src/generators/init/schema.json",
8
- "description": "Initialize the `@nrwl/webpack` plugin.",
8
+ "description": "Initialize the `@nx/webpack` plugin.",
9
9
  "aliases": ["ng-add"],
10
10
  "hidden": true
11
11
  },
@@ -15,6 +15,16 @@
15
15
  "schema": "./src/generators/configuration/schema.json",
16
16
  "description": "Add webpack configuration to a project.",
17
17
  "hidden": true
18
+ },
19
+ "convert-config-to-webpack-plugin": {
20
+ "factory": "./src/generators/convert-config-to-webpack-plugin/convert-config-to-webpack-plugin",
21
+ "schema": "./src/generators/convert-config-to-webpack-plugin/schema.json",
22
+ "description": "Convert the project to use the `NxAppWebpackPlugin` and `NxReactWebpackPlugin`."
23
+ },
24
+ "convert-to-inferred": {
25
+ "factory": "./src/generators/convert-to-inferred/convert-to-inferred#convertToInferred",
26
+ "schema": "./src/generators/convert-to-inferred/schema.json",
27
+ "description": "Convert existing Webpack project(s) using `@nx/webpack:wepack` executor to use `@nx/webpack/plugin`."
18
28
  }
19
29
  }
20
30
  }
package/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import { configurationGenerator } from './src/generators/configuration/configuration';
2
2
  import { NxAppWebpackPlugin } from './src/plugins/nx-webpack-plugin/nx-app-webpack-plugin';
3
3
  import { NxTsconfigPathsWebpackPlugin as _NxTsconfigPathsWebpackPlugin } from './src/plugins/nx-typescript-webpack-plugin/nx-tsconfig-paths-webpack-plugin';
4
- export { configurationGenerator };
4
+ import { convertConfigToWebpackPluginGenerator } from './src/generators/convert-config-to-webpack-plugin/convert-config-to-webpack-plugin';
5
+ import { useLegacyNxPlugin } from './src/plugins/use-legacy-nx-plugin/use-legacy-nx-plugin';
6
+ export { configurationGenerator, convertConfigToWebpackPluginGenerator, useLegacyNxPlugin, };
5
7
  /** @deprecated Use `configurationGenerator` instead. */
6
8
  export declare const webpackProjectGenerator: typeof configurationGenerator;
7
9
  /** @deprecated Use NxAppWebpackPlugin from `@nx/webpack/app-plugin` instead. */
package/index.js CHANGED
@@ -1,11 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.webpackInitGenerator = exports.NxTsconfigPathsWebpackPlugin = exports.NxWebpackPlugin = exports.webpackProjectGenerator = exports.configurationGenerator = void 0;
3
+ exports.webpackInitGenerator = exports.NxTsconfigPathsWebpackPlugin = exports.NxWebpackPlugin = exports.webpackProjectGenerator = exports.useLegacyNxPlugin = exports.convertConfigToWebpackPluginGenerator = exports.configurationGenerator = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const configuration_1 = require("./src/generators/configuration/configuration");
6
6
  Object.defineProperty(exports, "configurationGenerator", { enumerable: true, get: function () { return configuration_1.configurationGenerator; } });
7
7
  const nx_app_webpack_plugin_1 = require("./src/plugins/nx-webpack-plugin/nx-app-webpack-plugin");
8
8
  const nx_tsconfig_paths_webpack_plugin_1 = require("./src/plugins/nx-typescript-webpack-plugin/nx-tsconfig-paths-webpack-plugin");
9
+ const convert_config_to_webpack_plugin_1 = require("./src/generators/convert-config-to-webpack-plugin/convert-config-to-webpack-plugin");
10
+ Object.defineProperty(exports, "convertConfigToWebpackPluginGenerator", { enumerable: true, get: function () { return convert_config_to_webpack_plugin_1.convertConfigToWebpackPluginGenerator; } });
11
+ const use_legacy_nx_plugin_1 = require("./src/plugins/use-legacy-nx-plugin/use-legacy-nx-plugin");
12
+ Object.defineProperty(exports, "useLegacyNxPlugin", { enumerable: true, get: function () { return use_legacy_nx_plugin_1.useLegacyNxPlugin; } });
9
13
  // Exported for backwards compatibility in case a plugin is using the old name.
10
14
  /** @deprecated Use `configurationGenerator` instead. */
11
15
  exports.webpackProjectGenerator = configuration_1.configurationGenerator;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/webpack",
3
- "version": "19.4.0-beta.0",
3
+ "version": "19.4.0-beta.2",
4
4
  "private": false,
5
5
  "description": "The Nx Plugin for Webpack contains executors and generators that support building applications using Webpack.",
6
6
  "repository": {
@@ -31,6 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@babel/core": "^7.23.2",
34
+ "@phenomnomnominal/tsquery": "~5.0.1",
34
35
  "ajv": "^8.12.0",
35
36
  "autoprefixer": "^10.4.9",
36
37
  "babel-loader": "^9.1.2",
@@ -64,9 +65,9 @@
64
65
  "webpack-dev-server": "^4.9.3",
65
66
  "webpack-node-externals": "^3.0.0",
66
67
  "webpack-subresource-integrity": "^5.1.0",
67
- "@nx/devkit": "19.4.0-beta.0",
68
- "@nx/js": "19.4.0-beta.0",
69
- "@nrwl/webpack": "19.4.0-beta.0"
68
+ "@nx/devkit": "19.4.0-beta.2",
69
+ "@nx/js": "19.4.0-beta.2",
70
+ "@nrwl/webpack": "19.4.0-beta.2"
70
71
  },
71
72
  "publishConfig": {
72
73
  "access": "public"
package/plugin.d.ts CHANGED
@@ -1 +1 @@
1
- export { createNodes } from './src/plugins/plugin';
1
+ export { createNodes, createNodesV2, type WebpackPluginOptions, } from './src/plugins/plugin';
package/plugin.js CHANGED
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createNodes = void 0;
3
+ exports.createNodesV2 = exports.createNodes = void 0;
4
4
  var plugin_1 = require("./src/plugins/plugin");
5
5
  Object.defineProperty(exports, "createNodes", { enumerable: true, get: function () { return plugin_1.createNodes; } });
6
+ Object.defineProperty(exports, "createNodesV2", { enumerable: true, get: function () { return plugin_1.createNodesV2; } });
@@ -50,7 +50,13 @@ async function* devServerExecutor(serveOptions, context) {
50
50
  }
51
51
  else if (userDefinedWebpackConfig) {
52
52
  // New behavior, we want the webpack config to export object
53
- config = userDefinedWebpackConfig;
53
+ // If the config is a function, we assume it's a standard webpack config function and it's async
54
+ if (typeof userDefinedWebpackConfig === 'function') {
55
+ config = await userDefinedWebpackConfig(process.env.NODE_ENV, {});
56
+ }
57
+ else {
58
+ config = userDefinedWebpackConfig;
59
+ }
54
60
  config.devServer ??= devServer;
55
61
  }
56
62
  }
@@ -41,6 +41,11 @@ async function getWebpackConfigs(options, context) {
41
41
  });
42
42
  }
43
43
  else if (userDefinedWebpackConfig) {
44
+ if (typeof userDefinedWebpackConfig === 'function') {
45
+ // assume it's an async standard webpack config function
46
+ // https://webpack.js.org/configuration/configuration-types/#exporting-a-promise
47
+ return await userDefinedWebpackConfig(process.env.NODE_ENV, {});
48
+ }
44
49
  // New behavior, we want the webpack config to export object
45
50
  return userDefinedWebpackConfig;
46
51
  }
@@ -0,0 +1,7 @@
1
+ import { Tree } from '@nx/devkit';
2
+ interface Schema {
3
+ project?: string;
4
+ skipFormat?: boolean;
5
+ }
6
+ export declare function convertConfigToWebpackPluginGenerator(tree: Tree, options: Schema): Promise<void>;
7
+ export default convertConfigToWebpackPluginGenerator;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertConfigToWebpackPluginGenerator = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
6
+ const extract_webpack_options_1 = require("./lib/extract-webpack-options");
7
+ const normalize_path_options_1 = require("./lib/normalize-path-options");
8
+ const path_1 = require("path");
9
+ const validate_project_1 = require("./lib/validate-project");
10
+ // Make text JSON compatible
11
+ const preprocessText = (text) => {
12
+ return text
13
+ .replace(/(\w+):/g, '"$1":') // Quote property names
14
+ .replace(/'/g, '"') // Convert single quotes to double quotes
15
+ .replace(/,(\s*[}\]])/g, '$1') // Remove trailing commas
16
+ .replace(/(\r\n|\n|\r|\t)/gm, ''); // Remove newlines and tabs
17
+ };
18
+ async function convertConfigToWebpackPluginGenerator(tree, options) {
19
+ let migrated = 0;
20
+ const projects = (0, devkit_1.getProjects)(tree);
21
+ (0, executor_options_utils_1.forEachExecutorOptions)(tree, '@nx/webpack:webpack', (currentTargetOptions, projectName, targetName, configurationName) => {
22
+ if (options.project && projectName !== options.project) {
23
+ return;
24
+ }
25
+ if (!configurationName) {
26
+ const project = projects.get(projectName);
27
+ const target = project.targets[targetName];
28
+ const hasError = (0, validate_project_1.validateProject)(tree, project);
29
+ if (hasError) {
30
+ throw new Error(hasError);
31
+ }
32
+ const webpackConfigPath = currentTargetOptions?.webpackConfig || '';
33
+ if (webpackConfigPath && tree.exists(webpackConfigPath)) {
34
+ let { withNxConfig: webpackOptions, withReactConfig } = (0, extract_webpack_options_1.extractWebpackOptions)(tree, webpackConfigPath);
35
+ // if webpackOptions === undefined
36
+ // withNx was not found in the webpack.config.js file so we should skip this project
37
+ if (webpackOptions !== undefined) {
38
+ let parsedOptions = {};
39
+ if (webpackOptions) {
40
+ parsedOptions = JSON.parse(preprocessText(webpackOptions.getText()));
41
+ parsedOptions = (0, normalize_path_options_1.normalizePathOptions)(project.root, parsedOptions);
42
+ }
43
+ target.options.standardWebpackConfigFunction = true;
44
+ (0, devkit_1.updateProjectConfiguration)(tree, projectName, project);
45
+ const { dir, name, ext } = (0, path_1.parse)(webpackConfigPath);
46
+ tree.rename(webpackConfigPath, `${(0, devkit_1.joinPathFragments)(dir, `${name}.old${ext}`)}`);
47
+ tree.write(webpackConfigPath, (0, devkit_1.stripIndents) `
48
+ const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin');
49
+ const { NxReactWebpackPlugin } = require('@nx/react/webpack-plugin');
50
+ const { useLegacyNxPlugin } = require('@nx/webpack');
51
+
52
+ // This file was migrated using @nx/webpack:convert-config-to-webpack-plugin from your './webpack.config.old.js'
53
+ // Please check that the options here are correct as they were moved from the old webpack.config.js to this file.
54
+ const options = ${webpackOptions ? JSON.stringify(parsedOptions, null, 2) : '{}'};
55
+
56
+ /**
57
+ * @type{import('webpack').WebpackOptionsNormalized}
58
+ */
59
+ module.exports = async () => ({
60
+ plugins: [
61
+ ${webpackOptions
62
+ ? 'new NxAppWebpackPlugin(options)'
63
+ : 'new NxAppWebpackPlugin()'},
64
+ ${withReactConfig
65
+ ? `new NxReactWebpackPlugin(${withReactConfig.getText()})`
66
+ : `new NxReactWebpackPlugin({
67
+ // Uncomment this line if you don't want to use SVGR
68
+ // See: https://react-svgr.com/
69
+ // svgr: false
70
+ })`},
71
+ // NOTE: useLegacyNxPlugin ensures that the non-standard Webpack configuration file previously used still works.
72
+ // To remove its usage, move options such as "plugins" into this file as standard Webpack configuration options.
73
+ // To enhance configurations after Nx plugins have applied, you can add a new plugin with the \`apply\` method.
74
+ // e.g. \`{ apply: (compiler) => { /* modify compiler.options */ }\`
75
+ // eslint-disable-next-line react-hooks/rules-of-hooks
76
+ await useLegacyNxPlugin(require('./webpack.config.old'), options),
77
+ ],
78
+ });
79
+ `);
80
+ migrated++;
81
+ }
82
+ }
83
+ }
84
+ });
85
+ if (migrated === 0) {
86
+ throw new Error('Could not find any projects to migrate.');
87
+ }
88
+ if (!options.skipFormat) {
89
+ await (0, devkit_1.formatFiles)(tree);
90
+ }
91
+ }
92
+ exports.convertConfigToWebpackPluginGenerator = convertConfigToWebpackPluginGenerator;
93
+ exports.default = convertConfigToWebpackPluginGenerator;
@@ -0,0 +1,6 @@
1
+ import { Tree } from '@nx/devkit';
2
+ import * as ts from 'typescript';
3
+ export declare function extractWebpackOptions(tree: Tree, webpackConfigPath: string): {
4
+ withNxConfig: "" | ts.Node;
5
+ withReactConfig: "" | ts.Node;
6
+ };
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractWebpackOptions = void 0;
4
+ const tsquery_1 = require("@phenomnomnominal/tsquery");
5
+ const ts = require("typescript");
6
+ function extractWebpackOptions(tree, webpackConfigPath) {
7
+ const source = tree.read(webpackConfigPath).toString('utf-8');
8
+ const ast = tsquery_1.tsquery.ast(source);
9
+ const withNxQuery = 'CallExpression:has(Identifier[name="withNx"])';
10
+ const withReactQuery = 'CallExpression:has(Identifier[name="withReact"])';
11
+ const withWebQuery = 'CallExpression:has(Identifier[name="withWeb"])';
12
+ const withNxCall = (0, tsquery_1.tsquery)(ast, withNxQuery);
13
+ const withReactCall = (0, tsquery_1.tsquery)(ast, withReactQuery);
14
+ const withWebCall = (0, tsquery_1.tsquery)(ast, withWebQuery);
15
+ // If the config is empty set to empty string to avoid undefined. Undefined is used to check if the withNx exists inside of the config file.
16
+ let withNxConfig, withReactConfig;
17
+ withWebCall.forEach((node) => {
18
+ const argument = node.arguments[0] || '';
19
+ withNxConfig = argument; // Since withWeb and withNx use the same config object and both should not exist in the same file, we can reuse the withNxConfig variable.
20
+ });
21
+ withNxCall.forEach((node) => {
22
+ const argument = node.arguments[0] || ''; // The first argument is the config object
23
+ withNxConfig = argument;
24
+ });
25
+ withReactCall.forEach((node) => {
26
+ const argument = node.arguments[0] || '';
27
+ withReactConfig = argument;
28
+ });
29
+ if (withNxConfig !== undefined) {
30
+ // Only remove the withNx and withReact calls if they exist
31
+ let updatedSource = removeCallExpressions(source, [
32
+ 'withNx',
33
+ 'withReact',
34
+ 'withWeb',
35
+ ]);
36
+ updatedSource = removeImportDeclarations(updatedSource, 'withNx', '@nx/webpack');
37
+ updatedSource = removeImportDeclarations(updatedSource, 'withWeb', '@nx/webpack');
38
+ updatedSource = removeImportDeclarations(updatedSource, 'withReact', '@nx/react');
39
+ tree.write(webpackConfigPath, updatedSource);
40
+ }
41
+ return { withNxConfig, withReactConfig };
42
+ }
43
+ exports.extractWebpackOptions = extractWebpackOptions;
44
+ function removeCallExpressions(source, functionNames) {
45
+ let modifiedSource = source;
46
+ functionNames.forEach((functionName) => {
47
+ const callExpressionQuery = `CallExpression:has(Identifier[name="composePlugins"]) > CallExpression:has(Identifier[name="${functionName}"])`;
48
+ modifiedSource = tsquery_1.tsquery.replace(modifiedSource, callExpressionQuery, () => {
49
+ return ''; // Removes the entire CallExpression
50
+ });
51
+ });
52
+ return modifiedSource;
53
+ }
54
+ function removeImportDeclarations(source, importName, moduleName) {
55
+ const sourceFile = tsquery_1.tsquery.ast(source);
56
+ const modifiedStatements = sourceFile.statements
57
+ .map((statement) => {
58
+ if (!ts.isVariableStatement(statement))
59
+ return statement;
60
+ const declarationList = statement.declarationList;
61
+ const newDeclarations = declarationList.declarations
62
+ .map((declaration) => {
63
+ if (!ts.isVariableDeclaration(declaration) ||
64
+ !declaration.initializer)
65
+ return declaration;
66
+ if (ts.isCallExpression(declaration.initializer) &&
67
+ ts.isIdentifier(declaration.initializer.expression)) {
68
+ const callExpr = declaration.initializer.expression;
69
+ if (callExpr.text === 'require' &&
70
+ declaration.initializer.arguments[0]
71
+ ?.getText()
72
+ .replace(/['"]/g, '') === moduleName) {
73
+ if (ts.isObjectBindingPattern(declaration.name)) {
74
+ const bindingElements = declaration.name.elements.filter((element) => {
75
+ const elementName = element.name.getText();
76
+ return elementName !== importName;
77
+ });
78
+ if (bindingElements.length > 0) {
79
+ const newBindingPattern = ts.factory.updateObjectBindingPattern(declaration.name, bindingElements);
80
+ // Update the variable declaration with the new binding pattern without the specified import name
81
+ return ts.factory.updateVariableDeclaration(declaration, newBindingPattern, declaration.exclamationToken, declaration.type, declaration.initializer);
82
+ }
83
+ else {
84
+ return null; // Remove this declaration entirely if no bindings remain
85
+ }
86
+ }
87
+ }
88
+ }
89
+ return declaration;
90
+ })
91
+ .filter(Boolean);
92
+ if (newDeclarations.length > 0) {
93
+ const newDeclarationList = ts.factory.updateVariableDeclarationList(declarationList, newDeclarations);
94
+ return ts.factory.updateVariableStatement(statement, statement.modifiers, newDeclarationList);
95
+ }
96
+ else {
97
+ return null; // Remove the entire statement
98
+ }
99
+ })
100
+ .filter(Boolean);
101
+ // Use printer to format the source code and rewrite the modified
102
+ const newSourceFile = ts.factory.updateSourceFile(sourceFile, modifiedStatements);
103
+ const printer = ts.createPrinter();
104
+ const formattedSource = printer.printFile(newSourceFile);
105
+ return formattedSource;
106
+ }
@@ -0,0 +1,2 @@
1
+ import { WebpackExecutorOptions } from '../../../executors/webpack/schema';
2
+ export declare function normalizePathOptions(projectRoot: string, options: Partial<WebpackExecutorOptions>): Partial<WebpackExecutorOptions>;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizePathOptions = void 0;
4
+ const utils_1 = require("./utils");
5
+ const executorFieldsToNormalize = [
6
+ 'outputPath',
7
+ 'index',
8
+ 'main',
9
+ 'assets',
10
+ 'tsConfig',
11
+ 'styles',
12
+ 'babelConfig',
13
+ 'additionalEntryPoints',
14
+ 'scripts',
15
+ 'fileReplacements',
16
+ 'postcssConfig',
17
+ 'stylePreprocessorOptions',
18
+ 'publicPath',
19
+ ];
20
+ function normalizePathOptions(projectRoot, options) {
21
+ for (const [key, value] of Object.entries(options)) {
22
+ if (!executorFieldsToNormalize.includes(key)) {
23
+ continue;
24
+ }
25
+ options[key] = normalizePath(projectRoot, key, value);
26
+ }
27
+ return options;
28
+ }
29
+ exports.normalizePathOptions = normalizePathOptions;
30
+ function normalizePath(projectRoot, key, value) {
31
+ if (!value)
32
+ return value;
33
+ switch (key) {
34
+ case 'assets':
35
+ return value.map((asset) => {
36
+ if (typeof asset === 'string') {
37
+ return (0, utils_1.toProjectRelativePath)(asset, projectRoot);
38
+ }
39
+ return {
40
+ ...asset,
41
+ input: (0, utils_1.toProjectRelativePath)(asset.input, projectRoot),
42
+ output: (0, utils_1.toProjectRelativePath)(asset.output, projectRoot),
43
+ };
44
+ });
45
+ case 'styles':
46
+ case 'scripts':
47
+ return value.map((item) => {
48
+ if (typeof item === 'string') {
49
+ return (0, utils_1.toProjectRelativePath)(item, projectRoot);
50
+ }
51
+ return {
52
+ ...item,
53
+ input: (0, utils_1.toProjectRelativePath)(item.input, projectRoot),
54
+ };
55
+ });
56
+ case 'additionalEntryPoints':
57
+ return value.map((entry) => {
58
+ return {
59
+ ...entry,
60
+ entryPath: (0, utils_1.toProjectRelativePath)(entry.entryPath, projectRoot),
61
+ };
62
+ });
63
+ case 'fileReplacements':
64
+ return value.map((replacement) => {
65
+ return {
66
+ replace: (0, utils_1.toProjectRelativePath)(replacement.replace, projectRoot),
67
+ with: (0, utils_1.toProjectRelativePath)(replacement.with, projectRoot),
68
+ };
69
+ });
70
+ default:
71
+ return Array.isArray(value)
72
+ ? value.map((item) => (0, utils_1.toProjectRelativePath)(item, projectRoot))
73
+ : (0, utils_1.toProjectRelativePath)(value, projectRoot);
74
+ }
75
+ }
@@ -0,0 +1 @@
1
+ export declare function toProjectRelativePath(path: string, projectRoot: string): string;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toProjectRelativePath = void 0;
4
+ const posix_1 = require("path/posix");
5
+ const devkit_1 = require("@nx/devkit");
6
+ function toProjectRelativePath(path, projectRoot) {
7
+ if (projectRoot === '.') {
8
+ // workspace and project root are the same, we normalize it to ensure it
9
+ return path.startsWith('.') ? path : `./${path}`;
10
+ }
11
+ const relativePath = (0, posix_1.relative)((0, posix_1.resolve)(devkit_1.workspaceRoot, projectRoot), (0, posix_1.resolve)(devkit_1.workspaceRoot, path));
12
+ return relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
13
+ }
14
+ exports.toProjectRelativePath = toProjectRelativePath;
@@ -0,0 +1,9 @@
1
+ import { ProjectConfiguration, Tree } from '@nx/devkit';
2
+ /**
3
+ * Validates the project to ensure it can be migrated
4
+ *
5
+ * @param tree The virtaul file system
6
+ * @param project the project configuration object for the project
7
+ * @returns A string if there is an error, otherwise undefined
8
+ */
9
+ export declare function validateProject(tree: Tree, project: ProjectConfiguration): string;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateProject = void 0;
4
+ function hasAnotherWebpackConfig(tree, projectRoot) {
5
+ const files = tree.children(projectRoot);
6
+ const projectJsonString = tree.read(`${projectRoot}/project.json`, 'utf-8');
7
+ for (const file of files) {
8
+ if (file !== 'webpack.config.js' &&
9
+ file.endsWith('.js') &&
10
+ file.includes('webpack.config') &&
11
+ projectJsonString.includes(file) &&
12
+ tree.exists(`${projectRoot}/webpack.config.js`)) {
13
+ return 'Cannot convert a project with multiple webpack config files. Please consolidate them into a single webpack.config.js file.';
14
+ }
15
+ }
16
+ }
17
+ function isNestProject(project) {
18
+ for (const target in project.targets) {
19
+ if (project.targets[target].executor === '@nx/js:node') {
20
+ return `The project ${project.name} is using the '@nx/js:node' executor. At the moment, we do not support migrating such projects.`;
21
+ }
22
+ }
23
+ }
24
+ /**
25
+ * Validates the project to ensure it can be migrated
26
+ *
27
+ * @param tree The virtaul file system
28
+ * @param project the project configuration object for the project
29
+ * @returns A string if there is an error, otherwise undefined
30
+ */
31
+ function validateProject(tree, project) {
32
+ const containsMfeExecutor = Object.keys(project.targets).some((target) => {
33
+ return [
34
+ '@nx/react:module-federation-dev-server',
35
+ '@nx/angular:module-federation-dev-server',
36
+ ].includes(project.targets[target].executor);
37
+ });
38
+ if (containsMfeExecutor) {
39
+ return `The project ${project.name} is using Module Federation. At the moment, we don't support migrating projects that use Module Federation.`;
40
+ }
41
+ const hasAnotherConfig = hasAnotherWebpackConfig(tree, project.root);
42
+ return hasAnotherConfig || isNestProject(project);
43
+ }
44
+ exports.validateProject = validateProject;
@@ -0,0 +1,19 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "NxWebpackConvertConfigToWebpackPlugin",
4
+ "description": "Convert existing Webpack project(s) using `@nx/webpack:webpack` executor that uses `withNx` to use `NxAppWebpackPlugin`. Defaults to migrating all projects. Pass '--project' to migrate only one target.",
5
+ "title": "Convert Webpack project using withNx to NxAppWebpackPlugin",
6
+ "type": "object",
7
+ "properties": {
8
+ "project": {
9
+ "type": "string",
10
+ "description": "The project to convert from using the `@nx/webpack:webpack` executor and `withNx` plugin to use `NxAppWebpackPlugin`.",
11
+ "x-priority": "important"
12
+ },
13
+ "skipFormat": {
14
+ "type": "boolean",
15
+ "description": "Whether to format files at the end of the migration.",
16
+ "default": false
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,7 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ interface Schema {
3
+ project?: string;
4
+ skipFormat?: boolean;
5
+ }
6
+ export declare function convertToInferred(tree: Tree, options: Schema): Promise<import("@nx/devkit").GeneratorCallback>;
7
+ export {};
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertToInferred = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const aggregate_log_util_1 = require("@nx/devkit/src/generators/plugin-migrations/aggregate-log-util");
6
+ const executor_to_plugin_migrator_1 = require("@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator");
7
+ const tsquery_1 = require("@phenomnomnominal/tsquery");
8
+ const plugin_1 = require("../../plugins/plugin");
9
+ const versions_1 = require("../../utils/versions");
10
+ const utils_1 = require("./utils");
11
+ async function convertToInferred(tree, options) {
12
+ const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
13
+ const migrationContext = {
14
+ logger: new aggregate_log_util_1.AggregatedLog(),
15
+ projectGraph,
16
+ workspaceRoot: tree.root,
17
+ };
18
+ const migratedProjects = await (0, executor_to_plugin_migrator_1.migrateProjectExecutorsToPlugin)(tree, projectGraph, '@nx/webpack/plugin', plugin_1.createNodesV2, {
19
+ buildTargetName: 'build',
20
+ previewTargetName: 'preview',
21
+ serveStaticTargetName: 'serve-static',
22
+ serveTargetName: 'serve',
23
+ }, [
24
+ {
25
+ executors: ['@nx/webpack:webpack', '@nrwl/webpack:webpack'],
26
+ postTargetTransformer: (0, utils_1.buildPostTargetTransformerFactory)(migrationContext),
27
+ targetPluginOptionMapper: (target) => ({ buildTargetName: target }),
28
+ skipProjectFilter: skipProjectFilterFactory(tree),
29
+ },
30
+ {
31
+ executors: ['@nx/webpack:dev-server', '@nrwl/webpack:dev-server'],
32
+ postTargetTransformer: (0, utils_1.servePostTargetTransformerFactory)(migrationContext),
33
+ targetPluginOptionMapper: (target) => ({ serveTargetName: target }),
34
+ skipProjectFilter: skipProjectFilterFactory(tree),
35
+ },
36
+ ], options.project);
37
+ if (migratedProjects.size === 0) {
38
+ throw new Error('Could not find any targets to migrate.');
39
+ }
40
+ const installCallback = (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { 'webpack-cli': versions_1.webpackCliVersion }, undefined, true);
41
+ if (!options.skipFormat) {
42
+ await (0, devkit_1.formatFiles)(tree);
43
+ }
44
+ return (0, devkit_1.runTasksInSerial)(installCallback, () => {
45
+ migrationContext.logger.flushLogs();
46
+ });
47
+ }
48
+ exports.convertToInferred = convertToInferred;
49
+ function skipProjectFilterFactory(tree) {
50
+ return function skipProjectFilter(projectConfiguration) {
51
+ const buildTarget = Object.values(projectConfiguration.targets).find((target) => target.executor === '@nx/webpack:webpack' ||
52
+ target.executor === '@nrwl/webpack:webpack');
53
+ // the projects for which this is called are guaranteed to have a build target
54
+ const webpackConfigPath = buildTarget.options.webpackConfig;
55
+ if (!webpackConfigPath) {
56
+ return `The webpack config path is missing in the project configuration (${projectConfiguration.root}).`;
57
+ }
58
+ const sourceFile = tsquery_1.tsquery.ast(tree.read(webpackConfigPath, 'utf-8'));
59
+ const composePluginsSelector = 'CallExpression:has(Identifier[name=composePlugins])';
60
+ const composePlugins = (0, tsquery_1.tsquery)(sourceFile, composePluginsSelector)[0];
61
+ if (composePlugins) {
62
+ return `The webpack config (${webpackConfigPath}) can only work with the "@nx/webpack:webpack" executor. Run the "@nx/webpack:convert-config-to-webpack-plugin" generator first.`;
63
+ }
64
+ const nxAppWebpackPluginSelector = 'PropertyAssignment:has(Identifier[name=plugins]) NewExpression:has(Identifier[name=NxAppWebpackPlugin])';
65
+ const nxAppWebpackPlugin = (0, tsquery_1.tsquery)(sourceFile, nxAppWebpackPluginSelector)[0];
66
+ if (!nxAppWebpackPlugin) {
67
+ return `No "NxAppWebpackPlugin" found in the webpack config (${webpackConfigPath}). Its usage is required for the migration to work.`;
68
+ }
69
+ return false;
70
+ };
71
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "NxWebpackConvertToInferred",
4
+ "description": "Convert existing Webpack project(s) using `@nx/webpack:wepack` executor to use `@nx/webpack/plugin`.",
5
+ "title": "Convert a Webpack project from executor to plugin",
6
+ "type": "object",
7
+ "properties": {
8
+ "project": {
9
+ "type": "string",
10
+ "description": "The project to convert from using the `@nx/webpack:webpack` executor to use `@nx/webpack/plugin`. If not provided, all projects using the `@nx/webpack:webpack` executor will be converted.",
11
+ "x-priority": "important"
12
+ },
13
+ "skipFormat": {
14
+ "type": "boolean",
15
+ "description": "Whether to format files.",
16
+ "default": false
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,3 @@
1
+ import * as ts from 'typescript';
2
+ export declare function toPropertyAssignment(key: string, value: unknown): ts.PropertyAssignment;
3
+ export declare function toExpression(value: unknown): ts.Expression;