@nx/angular 17.2.0-beta.10 → 17.2.0-beta.12

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 (24) hide show
  1. package/executors.d.ts +1 -1
  2. package/executors.js +1 -1
  3. package/executors.json +5 -5
  4. package/package.json +10 -10
  5. package/src/builders/dev-server/dev-server.impl.js +38 -24
  6. package/src/builders/utilities/module-federation.js +1 -1
  7. package/src/builders/webpack-browser/webpack-browser.impl.js +2 -1
  8. package/src/builders/webpack-server/webpack-server.impl.js +2 -1
  9. package/src/executors/module-federation-dev-server/lib/build-static-remotes.d.ts +7 -0
  10. package/src/executors/module-federation-dev-server/lib/build-static-remotes.js +49 -0
  11. package/src/executors/module-federation-dev-server/lib/index.d.ts +4 -0
  12. package/src/executors/module-federation-dev-server/lib/index.js +7 -0
  13. package/src/executors/module-federation-dev-server/lib/normalize-options.d.ts +2 -0
  14. package/src/executors/module-federation-dev-server/lib/normalize-options.js +20 -0
  15. package/src/executors/module-federation-dev-server/lib/start-dev-remotes.d.ts +9 -0
  16. package/src/executors/module-federation-dev-server/lib/start-dev-remotes.js +29 -0
  17. package/src/executors/module-federation-dev-server/lib/start-static-remotes-file-server.d.ts +12 -0
  18. package/src/executors/module-federation-dev-server/lib/start-static-remotes-file-server.js +48 -0
  19. package/src/executors/module-federation-dev-server/module-federation-dev-server.impl.d.ts +3 -0
  20. package/src/executors/module-federation-dev-server/module-federation-dev-server.impl.js +110 -0
  21. package/src/{builders → executors}/module-federation-dev-server/schema.json +9 -3
  22. package/src/builders/module-federation-dev-server/module-federation-dev-server.impl.d.ts +0 -5
  23. package/src/builders/module-federation-dev-server/module-federation-dev-server.impl.js +0 -232
  24. /package/src/{builders → executors}/module-federation-dev-server/schema.d.ts +0 -0
package/executors.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export * from './src/builders/module-federation-dev-server/module-federation-dev-server.impl';
2
1
  export * from './src/builders/module-federation-dev-ssr/module-federation-dev-ssr.impl';
3
2
  export * from './src/builders/webpack-browser/webpack-browser.impl';
4
3
  export * from './src/builders/webpack-server/webpack-server.impl';
4
+ export * from './src/executors/module-federation-dev-server/module-federation-dev-server.impl';
5
5
  export * from './src/executors/delegate-build/delegate-build.impl';
6
6
  export * from './src/executors/ng-packagr-lite/ng-packagr-lite.impl';
7
7
  export * from './src/executors/package/package.impl';
package/executors.js CHANGED
@@ -2,10 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.executeDevServerBuilder = exports.executeWebpackDevServerBuilder = void 0;
4
4
  const tslib_1 = require("tslib");
5
- tslib_1.__exportStar(require("./src/builders/module-federation-dev-server/module-federation-dev-server.impl"), exports);
6
5
  tslib_1.__exportStar(require("./src/builders/module-federation-dev-ssr/module-federation-dev-ssr.impl"), exports);
7
6
  tslib_1.__exportStar(require("./src/builders/webpack-browser/webpack-browser.impl"), exports);
8
7
  tslib_1.__exportStar(require("./src/builders/webpack-server/webpack-server.impl"), exports);
8
+ tslib_1.__exportStar(require("./src/executors/module-federation-dev-server/module-federation-dev-server.impl"), exports);
9
9
  tslib_1.__exportStar(require("./src/executors/delegate-build/delegate-build.impl"), exports);
10
10
  tslib_1.__exportStar(require("./src/executors/ng-packagr-lite/ng-packagr-lite.impl"), exports);
11
11
  tslib_1.__exportStar(require("./src/executors/package/package.impl"), exports);
package/executors.json CHANGED
@@ -19,6 +19,11 @@
19
19
  "implementation": "./src/executors/browser-esbuild/browser-esbuild.impl",
20
20
  "schema": "./src/executors/browser-esbuild/schema.json",
21
21
  "description": "Builds your application with esbuild and adds support for incremental builds."
22
+ },
23
+ "module-federation-dev-server": {
24
+ "implementation": "./src/executors/module-federation-dev-server/module-federation-dev-server.impl",
25
+ "schema": "./src/executors/module-federation-dev-server/schema.json",
26
+ "description": "The module-federation-dev-server executor is reserved exclusively for use with host Module Federation applications. It allows the user to specify which remote applications should be served with the host."
22
27
  }
23
28
  },
24
29
  "builders": {
@@ -37,11 +42,6 @@
37
42
  "schema": "./src/builders/webpack-server/schema.json",
38
43
  "description": "The `webpack-server` executor is very similar to the standard `server` builder provided by the Angular Devkit. It is usually used in tandem with `@nrwl/angular:webpack-browser` when your Angular application uses a custom webpack configuration and NgUniversal for SSR."
39
44
  },
40
- "module-federation-dev-server": {
41
- "implementation": "./src/builders/module-federation-dev-server/module-federation-dev-server.impl",
42
- "schema": "./src/builders/module-federation-dev-server/schema.json",
43
- "description": "The module-federation-dev-server executor is reserved exclusively for use with host Module Federation applications. It allows the user to specify which remote applications should be served with the host."
44
- },
45
45
  "module-federation-dev-ssr": {
46
46
  "implementation": "./src/builders/module-federation-dev-ssr/module-federation-dev-ssr.impl",
47
47
  "schema": "./src/builders/module-federation-dev-ssr/schema.json",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/angular",
3
- "version": "17.2.0-beta.10",
3
+ "version": "17.2.0-beta.12",
4
4
  "private": false,
5
5
  "description": "The Nx Plugin for Angular contains executors, generators, and utilities for managing Angular applications and libraries within an Nx workspace. It provides: \n\n- Integration with libraries such as Storybook, Jest, ESLint, Tailwind CSS, and Cypress. \n\n- Generators to help scaffold code quickly (like: Micro Frontends, Libraries, both internal to your codebase and publishable to npm) \n\n- Upgrading AngularJS applications \n\n- Single Component Application Modules (SCAMs) \n\n- NgRx helpers. \n\n- Utilities for automatic workspace refactoring.",
6
6
  "repository": {
@@ -78,15 +78,15 @@
78
78
  "tslib": "^2.3.0",
79
79
  "webpack": "^5.80.0",
80
80
  "webpack-merge": "^5.8.0",
81
- "@nx/devkit": "17.2.0-beta.10",
82
- "@nx/cypress": "17.2.0-beta.10",
83
- "@nx/jest": "17.2.0-beta.10",
84
- "@nx/js": "17.2.0-beta.10",
85
- "@nx/eslint": "17.2.0-beta.10",
86
- "@nx/webpack": "17.2.0-beta.10",
87
- "@nx/web": "17.2.0-beta.10",
88
- "@nx/workspace": "17.2.0-beta.10",
89
- "@nrwl/angular": "17.2.0-beta.10"
81
+ "@nx/devkit": "17.2.0-beta.12",
82
+ "@nx/cypress": "17.2.0-beta.12",
83
+ "@nx/jest": "17.2.0-beta.12",
84
+ "@nx/js": "17.2.0-beta.12",
85
+ "@nx/eslint": "17.2.0-beta.12",
86
+ "@nx/webpack": "17.2.0-beta.12",
87
+ "@nx/web": "17.2.0-beta.12",
88
+ "@nx/workspace": "17.2.0-beta.12",
89
+ "@nrwl/angular": "17.2.0-beta.12"
90
90
  },
91
91
  "peerDependencies": {
92
92
  "@angular-devkit/build-angular": ">= 15.0.0 < 18.0.0",
@@ -7,9 +7,9 @@ const webpack_nx_build_coordination_plugin_1 = require("@nx/webpack/src/plugins/
7
7
  const fs_1 = require("fs");
8
8
  const operators_1 = require("nx/src/project-graph/operators");
9
9
  const project_graph_1 = require("nx/src/project-graph/project-graph");
10
+ const path_1 = require("path");
10
11
  const rxjs_1 = require("rxjs");
11
12
  const operators_2 = require("rxjs/operators");
12
- const semver_1 = require("semver");
13
13
  const angular_version_utils_1 = require("../../executors/utilities/angular-version-utils");
14
14
  const buildable_libs_1 = require("../utilities/buildable-libs");
15
15
  const webpack_1 = require("../utilities/webpack");
@@ -57,6 +57,7 @@ function executeDevServerBuilder(rawOptions, context) {
57
57
  target: parsedBuildTarget.target,
58
58
  });
59
59
  dependencies = foundDependencies;
60
+ const relativeTsConfigPath = (0, devkit_1.normalizePath)((0, path_1.relative)(context.workspaceRoot, tsConfigPath));
60
61
  // We can't just pass the tsconfig path in memory to the angular builder
61
62
  // function because we can't pass the build target options to it, the build
62
63
  // targets options will be retrieved by the builder from the project
@@ -66,21 +67,28 @@ function executeDevServerBuilder(rawOptions, context) {
66
67
  const originalGetTargetOptions = context.getTargetOptions;
67
68
  context.getTargetOptions = async (target) => {
68
69
  const options = await originalGetTargetOptions(target);
69
- options.tsConfig = tsConfigPath;
70
+ options.tsConfig = relativeTsConfigPath;
70
71
  return options;
71
72
  };
72
73
  // The buildTargetConfiguration also needs to use the generated tsconfig path
73
74
  // otherwise the build will fail if customWebpack function/file is referencing
74
75
  // local libs. This synchronize the behavior with webpack-browser and
75
76
  // webpack-server implementation.
76
- buildTargetOptions.tsConfig = tsConfigPath;
77
+ buildTargetOptions.tsConfig = relativeTsConfigPath;
77
78
  }
78
- const delegateBuilderOptions = getDelegateBuilderOptions(options, buildTarget, context);
79
+ const delegateBuilderOptions = getDelegateBuilderOptions(options);
79
80
  const isUsingWebpackBuilder = ![
80
81
  '@angular-devkit/build-angular:application',
81
82
  '@angular-devkit/build-angular:browser-esbuild',
82
83
  '@nx/angular:browser-esbuild',
83
84
  ].includes(buildTarget.executor);
85
+ /**
86
+ * The Angular CLI dev-server builder make some decisions based on the build
87
+ * target builder but it only considers `@angular-devkit/build-angular:*`
88
+ * builders. Since we are using a custom builder, we patch the context to
89
+ * handle `@nx/angular:*` executors.
90
+ */
91
+ patchBuilderContext(context);
84
92
  return (0, rxjs_1.from)(Promise.resolve().then(() => require('@angular-devkit/build-angular'))).pipe((0, operators_2.switchMap)(({ executeDevServerBuilder }) => executeDevServerBuilder(delegateBuilderOptions, context, {
85
93
  webpackConfiguration: isUsingWebpackBuilder
86
94
  ? async (baseWebpackConfig) => {
@@ -113,26 +121,32 @@ function executeDevServerBuilder(rawOptions, context) {
113
121
  }
114
122
  exports.executeDevServerBuilder = executeDevServerBuilder;
115
123
  exports.default = require('@angular-devkit/architect').createBuilder(executeDevServerBuilder);
116
- function getDelegateBuilderOptions(options, buildTarget, context) {
117
- const delegatedBuilderOptions = { ...options };
118
- const { major: angularMajorVersion, version: angularVersion } = (0, angular_version_utils_1.getInstalledAngularVersionInfo)();
119
- // this option was introduced in angular 16.1.0
120
- // https://github.com/angular/angular-cli/commit/3ede1a2cac5005f4dfbd2a62ef528a34c3793b78
121
- if ((0, semver_1.gte)(angularVersion, '16.1.0') &&
122
- buildTarget.executor === '@nx/angular:browser-esbuild') {
123
- delegatedBuilderOptions.forceEsbuild = true;
124
- const originalLoggerWarn = context.logger.warn.bind(context.logger);
125
- context.logger.warn = (...args) => {
126
- // we silence the warning about forcing esbuild from third-party builders
127
- if (args[0].includes('Warning: Forcing the use of the esbuild-based build system with third-party builders may cause unexpected behavior and/or build failures.')) {
128
- return;
129
- }
130
- originalLoggerWarn(...args);
131
- };
132
- }
124
+ function getDelegateBuilderOptions(options) {
125
+ const delegateBuilderOptions = {
126
+ ...options,
127
+ };
128
+ const { major: angularMajorVersion } = (0, angular_version_utils_1.getInstalledAngularVersionInfo)();
133
129
  if (angularMajorVersion <= 17) {
134
- delegatedBuilderOptions.browserTarget = delegatedBuilderOptions.buildTarget;
135
- delete delegatedBuilderOptions.buildTarget;
130
+ delegateBuilderOptions.browserTarget = delegateBuilderOptions.buildTarget;
131
+ delete delegateBuilderOptions.buildTarget;
136
132
  }
137
- return delegatedBuilderOptions;
133
+ // delete extra option not supported by the delegate builder
134
+ delete delegateBuilderOptions.buildLibsFromSource;
135
+ return delegateBuilderOptions;
136
+ }
137
+ const executorToBuilderMap = new Map([
138
+ [
139
+ '@nx/angular:browser-esbuild',
140
+ '@angular-devkit/build-angular:browser-esbuild',
141
+ ],
142
+ ]);
143
+ function patchBuilderContext(context) {
144
+ const originalGetBuilderNameForTarget = context.getBuilderNameForTarget;
145
+ context.getBuilderNameForTarget = async (target) => {
146
+ const builderName = await originalGetBuilderNameForTarget(target);
147
+ if (executorToBuilderMap.has(builderName)) {
148
+ return executorToBuilderMap.get(builderName);
149
+ }
150
+ return builderName;
151
+ };
138
152
  }
@@ -85,7 +85,7 @@ function getStaticRemotes(project, context, workspaceProjects, remotesToSkip) {
85
85
  }
86
86
  exports.getStaticRemotes = getStaticRemotes;
87
87
  function validateDevRemotes(options, workspaceProjects) {
88
- const invalidDevRemotes = options.devRemotes?.filter((remote) => !workspaceProjects[remote]);
88
+ const invalidDevRemotes = options.devRemotes?.filter((remote) => !workspaceProjects[remote]) ?? [];
89
89
  if (invalidDevRemotes.length) {
90
90
  throw new Error(invalidDevRemotes.length === 1
91
91
  ? `Invalid dev remote provided: ${invalidDevRemotes[0]}.`
@@ -7,6 +7,7 @@ const fs_1 = require("fs");
7
7
  const configuration_1 = require("nx/src/config/configuration");
8
8
  const operators_1 = require("nx/src/project-graph/operators");
9
9
  const utils_1 = require("nx/src/tasks-runner/utils");
10
+ const path_1 = require("path");
10
11
  const rxjs_1 = require("rxjs");
11
12
  const operators_2 = require("rxjs/operators");
12
13
  const buildable_libs_1 = require("../utilities/buildable-libs");
@@ -40,7 +41,7 @@ function executeWebpackBrowserBuilder(options, context) {
40
41
  projectGraph = (0, devkit_1.readCachedProjectGraph)();
41
42
  const { tsConfigPath, dependencies: foundDependencies } = (0, buildable_libs_1.createTmpTsConfigForBuildableLibs)(delegateBuilderOptions.tsConfig, context, { projectGraph });
42
43
  dependencies = foundDependencies;
43
- delegateBuilderOptions.tsConfig = tsConfigPath;
44
+ delegateBuilderOptions.tsConfig = (0, devkit_1.normalizePath)((0, path_1.relative)(context.workspaceRoot, tsConfigPath));
44
45
  }
45
46
  return (0, rxjs_1.from)(Promise.resolve().then(() => require('@angular-devkit/build-angular'))).pipe((0, operators_2.switchMap)(({ executeBrowserBuilder }) => executeBrowserBuilder(delegateBuilderOptions, context, {
46
47
  webpackConfiguration: (baseWebpackConfig) => {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.executeWebpackServerBuilder = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const fs_1 = require("fs");
6
+ const path_1 = require("path");
6
7
  const rxjs_1 = require("rxjs");
7
8
  const operators_1 = require("rxjs/operators");
8
9
  const buildable_libs_1 = require("../utilities/buildable-libs");
@@ -50,7 +51,7 @@ function executeWebpackServerBuilder(options, context) {
50
51
  options.buildLibsFromSource ??= true;
51
52
  if (!options.buildLibsFromSource) {
52
53
  const { tsConfigPath } = (0, buildable_libs_1.createTmpTsConfigForBuildableLibs)(options.tsConfig, context);
53
- options.tsConfig = tsConfigPath;
54
+ options.tsConfig = (0, devkit_1.normalizePath)((0, path_1.relative)(context.workspaceRoot, tsConfigPath));
54
55
  }
55
56
  return buildServerApp(options, context);
56
57
  }
@@ -0,0 +1,7 @@
1
+ import { type Schema } from '../schema';
2
+ import { type ExecutorContext } from '@nx/devkit';
3
+ export declare function buildStaticRemotes(remotes: {
4
+ remotePorts: any[];
5
+ staticRemotes: string[];
6
+ devRemotes: string[];
7
+ }, nxBin: any, context: ExecutorContext, options: Schema): Promise<void>;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildStaticRemotes = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const child_process_1 = require("child_process");
6
+ async function buildStaticRemotes(remotes, nxBin, context, options) {
7
+ if (!remotes.staticRemotes ||
8
+ (Array.isArray(remotes.staticRemotes) && !remotes.staticRemotes.length)) {
9
+ return;
10
+ }
11
+ const mappedLocationOfRemotes = {};
12
+ for (const app of remotes.staticRemotes) {
13
+ mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${options.host}:${options.staticRemotesPort}/${app}`;
14
+ }
15
+ process.env.NX_MF_DEV_SERVER_STATIC_REMOTES = JSON.stringify(mappedLocationOfRemotes);
16
+ await new Promise((res) => {
17
+ devkit_1.logger.info(`NX Building ${remotes.staticRemotes.length} static remotes...`);
18
+ const staticProcess = (0, child_process_1.fork)(nxBin, [
19
+ 'run-many',
20
+ `--target=build`,
21
+ `--projects=${remotes.staticRemotes.join(',')}`,
22
+ ...(context.configurationName
23
+ ? [`--configuration=${context.configurationName}`]
24
+ : []),
25
+ ...(options.parallel ? [`--parallel=${options.parallel}`] : []),
26
+ ], {
27
+ cwd: context.root,
28
+ stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
29
+ });
30
+ staticProcess.stdout.on('data', (data) => {
31
+ const ANSII_CODE_REGEX = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
32
+ const stdoutString = data.toString().replace(ANSII_CODE_REGEX, '');
33
+ if (stdoutString.includes('Successfully ran target build')) {
34
+ staticProcess.stdout.removeAllListeners('data');
35
+ devkit_1.logger.info(`NX Built ${remotes.staticRemotes.length} static remotes`);
36
+ res();
37
+ }
38
+ });
39
+ staticProcess.stderr.on('data', (data) => devkit_1.logger.info(data.toString()));
40
+ staticProcess.on('exit', (code) => {
41
+ if (code !== 0) {
42
+ throw new Error(`Remotes failed to build. See above for errors.`);
43
+ }
44
+ });
45
+ process.on('SIGTERM', () => staticProcess.kill('SIGTERM'));
46
+ process.on('exit', () => staticProcess.kill('SIGTERM'));
47
+ });
48
+ }
49
+ exports.buildStaticRemotes = buildStaticRemotes;
@@ -0,0 +1,4 @@
1
+ export * from './build-static-remotes';
2
+ export * from './normalize-options';
3
+ export * from './start-dev-remotes';
4
+ export * from './start-static-remotes-file-server';
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./build-static-remotes"), exports);
5
+ tslib_1.__exportStar(require("./normalize-options"), exports);
6
+ tslib_1.__exportStar(require("./start-dev-remotes"), exports);
7
+ tslib_1.__exportStar(require("./start-static-remotes-file-server"), exports);
@@ -0,0 +1,2 @@
1
+ import type { NormalizedSchema, Schema } from '../schema';
2
+ export declare function normalizeOptions(schema: Schema): NormalizedSchema;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeOptions = void 0;
4
+ function normalizeOptions(schema) {
5
+ let buildTarget = schema.buildTarget;
6
+ if (schema.browserTarget) {
7
+ buildTarget ??= schema.browserTarget;
8
+ delete schema.browserTarget;
9
+ }
10
+ return {
11
+ ...schema,
12
+ buildTarget,
13
+ host: schema.host ?? 'localhost',
14
+ port: schema.port ?? 4200,
15
+ liveReload: schema.liveReload ?? true,
16
+ open: schema.open ?? false,
17
+ ssl: schema.ssl ?? false,
18
+ };
19
+ }
20
+ exports.normalizeOptions = normalizeOptions;
@@ -0,0 +1,9 @@
1
+ import { type Schema } from '../schema';
2
+ import { type ExecutorContext, type ProjectConfiguration } from '@nx/devkit';
3
+ export declare function startDevRemotes(remotes: {
4
+ remotePorts: any[];
5
+ staticRemotes: string[];
6
+ devRemotes: string[];
7
+ }, workspaceProjects: Record<string, ProjectConfiguration>, options: Schema, context: ExecutorContext): Promise<AsyncIterable<{
8
+ success: boolean;
9
+ }>[]>;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startDevRemotes = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ async function startDevRemotes(remotes, workspaceProjects, options, context) {
6
+ const devRemotesIters = [];
7
+ for (const app of remotes.devRemotes) {
8
+ if (!workspaceProjects[app].targets?.['serve']) {
9
+ throw new Error(`Could not find "serve" target in "${app}" project.`);
10
+ }
11
+ else if (!workspaceProjects[app].targets?.['serve'].executor) {
12
+ throw new Error(`Could not find executor for "serve" target in "${app}" project.`);
13
+ }
14
+ const [collection, executor] = workspaceProjects[app].targets['serve'].executor.split(':');
15
+ const isUsingModuleFederationDevServerExecutor = executor.includes('module-federation-dev-server');
16
+ devRemotesIters.push(await (0, devkit_1.runExecutor)({
17
+ project: app,
18
+ target: 'serve',
19
+ configuration: context.configurationName,
20
+ }, {
21
+ verbose: options.verbose ?? false,
22
+ ...(isUsingModuleFederationDevServerExecutor
23
+ ? { isInitialHost: false }
24
+ : {}),
25
+ }, context));
26
+ }
27
+ return devRemotesIters;
28
+ }
29
+ exports.startDevRemotes = startDevRemotes;
@@ -0,0 +1,12 @@
1
+ import { type ExecutorContext } from '@nx/devkit';
2
+ import { type Schema } from '../schema';
3
+ export declare function startStaticRemotesFileServer(remotes: {
4
+ remotePorts: any[];
5
+ staticRemotes: string[];
6
+ devRemotes: string[];
7
+ }, context: ExecutorContext, options: Schema): AsyncGenerator<{
8
+ success: boolean;
9
+ baseUrl: string;
10
+ }, {
11
+ success: boolean;
12
+ }, unknown>;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startStaticRemotesFileServer = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const file_server_impl_1 = require("@nx/web/src/executors/file-server/file-server.impl");
6
+ const path_1 = require("path");
7
+ const fs_1 = require("fs");
8
+ function startStaticRemotesFileServer(remotes, context, options) {
9
+ let shouldMoveToCommonLocation = false;
10
+ let commonOutputDirectory;
11
+ for (const app of remotes.staticRemotes) {
12
+ const outputPath = context.projectGraph.nodes[app].data.targets['build'].options.outputPath;
13
+ const directoryOfOutputPath = (0, path_1.dirname)(outputPath);
14
+ if (!commonOutputDirectory) {
15
+ commonOutputDirectory = directoryOfOutputPath;
16
+ }
17
+ else if (commonOutputDirectory !== directoryOfOutputPath ||
18
+ !outputPath.endsWith(app)) {
19
+ shouldMoveToCommonLocation = true;
20
+ }
21
+ }
22
+ if (shouldMoveToCommonLocation) {
23
+ commonOutputDirectory = (0, path_1.join)(devkit_1.workspaceRoot, 'tmp/static-remotes');
24
+ for (const app of remotes.staticRemotes) {
25
+ const outputPath = context.projectGraph.nodes[app].data.targets['build'].options
26
+ .outputPath;
27
+ (0, fs_1.cpSync)(outputPath, (0, path_1.join)(commonOutputDirectory, app), {
28
+ force: true,
29
+ recursive: true,
30
+ });
31
+ }
32
+ }
33
+ const staticRemotesIter = (0, file_server_impl_1.default)({
34
+ cors: true,
35
+ watch: false,
36
+ staticFilePath: commonOutputDirectory,
37
+ parallel: false,
38
+ spa: false,
39
+ withDeps: false,
40
+ host: options.host,
41
+ port: options.staticRemotesPort,
42
+ ssl: options.ssl,
43
+ sslCert: options.sslCert,
44
+ sslKey: options.sslKey,
45
+ }, context);
46
+ return staticRemotesIter;
47
+ }
48
+ exports.startStaticRemotesFileServer = startStaticRemotesFileServer;
@@ -0,0 +1,3 @@
1
+ import { type ExecutorContext } from '@nx/devkit';
2
+ import { type Schema } from './schema';
3
+ export default function moduleFederationDevServerExecutor(schema: Schema, context: ExecutorContext): AsyncGenerator<any, any, undefined>;
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const devkit_1 = require("@nx/devkit");
4
+ const lib_1 = require("./lib");
5
+ const rxjs_for_await_1 = require("@nx/devkit/src/utils/rxjs-for-await");
6
+ const async_iterable_1 = require("@nx/devkit/src/utils/async-iterable");
7
+ const module_federation_1 = require("@nx/webpack/src/utils/module-federation");
8
+ const wait_for_port_open_1 = require("@nx/web/src/utils/wait-for-port-open");
9
+ const file_server_impl_1 = require("@nx/web/src/executors/file-server/file-server.impl");
10
+ const ngcli_adapter_1 = require("nx/src/adapter/ngcli-adapter");
11
+ const dev_server_impl_1 = require("../../builders/dev-server/dev-server.impl");
12
+ const module_federation_2 = require("../../builders/utilities/module-federation");
13
+ const path_1 = require("path");
14
+ const fs_1 = require("fs");
15
+ async function* moduleFederationDevServerExecutor(schema, context) {
16
+ // Force Node to resolve to look for the nx binary that is inside node_modules
17
+ const nxBin = require.resolve('nx/bin/nx');
18
+ const options = (0, lib_1.normalizeOptions)(schema);
19
+ options.staticRemotesPort ??= options.port + 1;
20
+ const { projects: workspaceProjects } = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(context.projectGraph);
21
+ const project = workspaceProjects[context.projectName];
22
+ const currIter = options.static
23
+ ? (0, file_server_impl_1.default)({
24
+ port: options.port,
25
+ host: options.host,
26
+ ssl: options.ssl,
27
+ buildTarget: options.buildTarget,
28
+ parallel: false,
29
+ spa: false,
30
+ withDeps: false,
31
+ cors: true,
32
+ }, context)
33
+ : (0, rxjs_for_await_1.eachValueFrom)((0, dev_server_impl_1.executeDevServerBuilder)(options, await (0, ngcli_adapter_1.createBuilderContext)({
34
+ builderName: '@nx/angular:webpack-browser',
35
+ description: 'Build a browser application',
36
+ optionSchema: await Promise.resolve().then(() => require('../../builders/webpack-browser/schema.json')),
37
+ }, context)));
38
+ if (options.isInitialHost === false) {
39
+ return yield* currIter;
40
+ }
41
+ let pathToManifestFile = (0, path_1.join)(context.root, project.sourceRoot, 'assets/module-federation.manifest.json');
42
+ if (options.pathToManifestFile) {
43
+ const userPathToManifestFile = (0, path_1.join)(context.root, options.pathToManifestFile);
44
+ if (!(0, fs_1.existsSync)(userPathToManifestFile)) {
45
+ throw new Error(`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`);
46
+ }
47
+ else if ((0, path_1.extname)(options.pathToManifestFile) !== '.json') {
48
+ throw new Error(`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`);
49
+ }
50
+ pathToManifestFile = userPathToManifestFile;
51
+ }
52
+ (0, module_federation_2.validateDevRemotes)(options, workspaceProjects);
53
+ const moduleFederationConfig = (0, module_federation_1.getModuleFederationConfig)(project.targets.build.options.tsConfig, context.root, project.root, 'angular');
54
+ const remotes = (0, module_federation_1.getRemotes)(options.devRemotes, options.skipRemotes, moduleFederationConfig, {
55
+ projectName: project.name,
56
+ projectGraph: context.projectGraph,
57
+ root: context.root,
58
+ }, pathToManifestFile);
59
+ if (remotes.devRemotes.length > 0 && !schema.staticRemotesPort) {
60
+ options.staticRemotesPort = options.devRemotes.reduce((portToUse, r) => {
61
+ const remotePort = context.projectGraph.nodes[r].data.targets['serve'].options.port;
62
+ if (remotePort >= portToUse) {
63
+ return remotePort + 1;
64
+ }
65
+ else {
66
+ return portToUse;
67
+ }
68
+ }, options.staticRemotesPort);
69
+ }
70
+ await (0, lib_1.buildStaticRemotes)(remotes, nxBin, context, options);
71
+ const devRemoteIters = await (0, lib_1.startDevRemotes)(remotes, workspaceProjects, options, context);
72
+ const staticRemotesIter = remotes.staticRemotes.length > 0
73
+ ? (0, lib_1.startStaticRemotesFileServer)(remotes, context, options)
74
+ : undefined;
75
+ const removeBaseUrlEmission = (iter) => (0, async_iterable_1.mapAsyncIterable)(iter, (v) => ({
76
+ ...v,
77
+ baseUrl: undefined,
78
+ }));
79
+ return yield* (0, async_iterable_1.combineAsyncIterables)(removeBaseUrlEmission(currIter), ...devRemoteIters.map(removeBaseUrlEmission), ...(staticRemotesIter ? [removeBaseUrlEmission(staticRemotesIter)] : []), (0, async_iterable_1.createAsyncIterable)(async ({ next, done }) => {
80
+ if (!options.isInitialHost) {
81
+ done();
82
+ return;
83
+ }
84
+ if (remotes.remotePorts.length === 0) {
85
+ devkit_1.logger.info(`NX All remotes started, server ready at http://localhost:${options.port}`);
86
+ next({ success: true, baseUrl: `http://localhost:${options.port}` });
87
+ done();
88
+ return;
89
+ }
90
+ try {
91
+ const portsToWaitFor = staticRemotesIter
92
+ ? [options.staticRemotesPort, ...remotes.remotePorts]
93
+ : [...remotes.remotePorts];
94
+ await Promise.all(portsToWaitFor.map((port) => (0, wait_for_port_open_1.waitForPortOpen)(port, {
95
+ retries: 480,
96
+ retryDelay: 2500,
97
+ host: 'localhost',
98
+ })));
99
+ devkit_1.logger.info(`NX All remotes started, server ready at http://localhost:${options.port}`);
100
+ next({ success: true, baseUrl: `http://localhost:${options.port}` });
101
+ }
102
+ catch {
103
+ throw new Error(`Timed out waiting for remote to start. Check above for any errors.`);
104
+ }
105
+ finally {
106
+ done();
107
+ }
108
+ }));
109
+ }
110
+ exports.default = moduleFederationDevServerExecutor;
@@ -1,8 +1,7 @@
1
1
  {
2
- "version": 2,
3
- "outputCapture": "direct-nodejs",
4
2
  "$schema": "http://json-schema.org/draft-07/schema",
5
3
  "title": "Schema for Module Federation Dev Server",
4
+ "outputCapture": "direct-nodejs",
6
5
  "description": "The module-federation-dev-server executor is reserved exclusively for use with host Module Federation applications. It allows the user to specify which remote applications should be served with the host.",
7
6
  "type": "object",
8
7
  "presets": [
@@ -149,6 +148,13 @@
149
148
  }
150
149
  },
151
150
  "additionalProperties": false,
152
- "anyOf": [{ "required": ["buildTarget"] }, { "required": ["browserTarget"] }],
151
+ "anyOf": [
152
+ {
153
+ "required": ["buildTarget"]
154
+ },
155
+ {
156
+ "required": ["browserTarget"]
157
+ }
158
+ ],
153
159
  "examplesFile": "../../../docs/module-federation-dev-server-examples.md"
154
160
  }
@@ -1,5 +0,0 @@
1
- import type { Schema } from './schema';
2
- import { executeDevServerBuilder } from '../dev-server/dev-server.impl';
3
- export declare function executeModuleFederationDevServerBuilder(schema: Schema, context: import('@angular-devkit/architect').BuilderContext): ReturnType<typeof executeDevServerBuilder | any>;
4
- declare const _default: any;
5
- export default _default;
@@ -1,232 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.executeModuleFederationDevServerBuilder = void 0;
4
- const devkit_1 = require("@nx/devkit");
5
- const ngcli_adapter_1 = require("nx/src/adapter/ngcli-adapter");
6
- const dev_server_impl_1 = require("../dev-server/dev-server.impl");
7
- const project_graph_1 = require("nx/src/project-graph/project-graph");
8
- const executor_utils_1 = require("nx/src/command-line/run/executor-utils");
9
- const module_federation_1 = require("../utilities/module-federation");
10
- const fs_1 = require("fs");
11
- const path_1 = require("path");
12
- const module_federation_2 = require("@nx/webpack/src/utils/module-federation");
13
- const child_process_1 = require("child_process");
14
- const rxjs_1 = require("rxjs");
15
- const fs_2 = require("fs");
16
- function buildStaticRemotes(remotes, nxBin, context, options) {
17
- if (!remotes.staticRemotes.length) {
18
- return Promise.resolve();
19
- }
20
- const mappedLocationOfRemotes = {};
21
- for (const app of remotes.staticRemotes) {
22
- mappedLocationOfRemotes[app] = `http${options.ssl ? 's' : ''}://${options.host}:${options.staticRemotesPort}/${app}`;
23
- }
24
- process.env.NX_MF_DEV_SERVER_STATIC_REMOTES = JSON.stringify(mappedLocationOfRemotes);
25
- const staticRemoteBuildPromise = new Promise((res) => {
26
- devkit_1.logger.info(`NX Building ${remotes.staticRemotes.length} static remotes...`);
27
- const staticProcess = (0, child_process_1.fork)(nxBin, [
28
- 'run-many',
29
- `--target=build`,
30
- `--projects=${remotes.staticRemotes.join(',')}`,
31
- ...(context.target.configuration
32
- ? [`--configuration=${context.target.configuration}`]
33
- : []),
34
- ...(options.parallel ? [`--parallel=${options.parallel}`] : []),
35
- ], {
36
- cwd: context.workspaceRoot,
37
- stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
38
- });
39
- staticProcess.stdout.on('data', (data) => {
40
- const ANSII_CODE_REGEX = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
41
- const stdoutString = data.toString().replace(ANSII_CODE_REGEX, '');
42
- if (stdoutString.includes('Successfully ran target build')) {
43
- staticProcess.stdout.removeAllListeners('data');
44
- devkit_1.logger.info(`NX Built ${remotes.staticRemotes.length} static remotes`);
45
- res();
46
- }
47
- });
48
- staticProcess.stderr.on('data', (data) => devkit_1.logger.info(data.toString()));
49
- staticProcess.on('exit', (code) => {
50
- if (code !== 0) {
51
- throw new Error(`Remotes failed to build. See above for errors.`);
52
- }
53
- });
54
- process.on('SIGTERM', () => staticProcess.kill('SIGTERM'));
55
- process.on('exit', () => staticProcess.kill('SIGTERM'));
56
- });
57
- return staticRemoteBuildPromise;
58
- }
59
- function startStaticRemotesFileServer(remotes, projectGraph, options, context) {
60
- let shouldMoveToCommonLocation = false;
61
- let commonOutputDirectory;
62
- for (const app of remotes.staticRemotes) {
63
- const outputPath = projectGraph.nodes[app].data.targets['build'].options.outputPath;
64
- const directoryOfOutputPath = (0, path_1.dirname)(outputPath);
65
- if (!commonOutputDirectory) {
66
- commonOutputDirectory = directoryOfOutputPath;
67
- }
68
- else if (commonOutputDirectory !== directoryOfOutputPath ||
69
- !outputPath.endsWith(app)) {
70
- shouldMoveToCommonLocation = true;
71
- }
72
- }
73
- if (shouldMoveToCommonLocation) {
74
- commonOutputDirectory = (0, path_1.join)(devkit_1.workspaceRoot, 'tmp/static-remotes');
75
- for (const app of remotes.staticRemotes) {
76
- const outputPath = projectGraph.nodes[app].data.targets['build'].options.outputPath;
77
- (0, fs_2.cpSync)(outputPath, (0, path_1.join)(commonOutputDirectory, app), {
78
- force: true,
79
- recursive: true,
80
- });
81
- }
82
- }
83
- const staticRemotesIter$ = (0, rxjs_1.from)(Promise.resolve().then(() => require('@nx/web/src/executors/file-server/file-server.impl'))).pipe((0, rxjs_1.switchMap)((fileServerExecutor) => fileServerExecutor.default({
84
- cors: true,
85
- watch: false,
86
- staticFilePath: commonOutputDirectory,
87
- parallel: false,
88
- spa: false,
89
- withDeps: false,
90
- host: options.host,
91
- port: options.staticRemotesPort,
92
- ssl: options.ssl,
93
- sslCert: options.sslCert,
94
- sslKey: options.sslKey,
95
- }, {
96
- projectGraph,
97
- root: context.workspaceRoot,
98
- target: projectGraph.nodes[context.target.project].data.targets[context.target.target],
99
- targetName: context.target.target,
100
- projectName: context.target.project,
101
- configurationName: context.target.configuration,
102
- cwd: context.currentDirectory,
103
- isVerbose: options.verbose,
104
- projectsConfigurations: (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph),
105
- nxJsonConfiguration: (0, devkit_1.readNxJson)(),
106
- })));
107
- return staticRemotesIter$;
108
- }
109
- function startDevRemotes(remotes, workspaceProjects, options, context) {
110
- const devRemotes$ = [];
111
- for (const app of remotes.devRemotes) {
112
- if (!workspaceProjects[app].targets?.['serve']) {
113
- throw new Error(`Could not find "serve" target in "${app}" project.`);
114
- }
115
- else if (!workspaceProjects[app].targets?.['serve'].executor) {
116
- throw new Error(`Could not find executor for "serve" target in "${app}" project.`);
117
- }
118
- const runOptions = {};
119
- const [collection, executor] = workspaceProjects[app].targets['serve'].executor.split(':');
120
- const isUsingModuleFederationDevServerExecutor = executor.includes('module-federation-dev-server');
121
- const { schema } = (0, executor_utils_1.getExecutorInformation)(collection, executor, devkit_1.workspaceRoot, workspaceProjects);
122
- if ((options.verbose && schema.additionalProperties) ||
123
- 'verbose' in schema.properties) {
124
- runOptions.verbose = options.verbose;
125
- }
126
- if (isUsingModuleFederationDevServerExecutor) {
127
- runOptions.isInitialHost = false;
128
- }
129
- const serve$ = (0, ngcli_adapter_1.scheduleTarget)(context.workspaceRoot, {
130
- project: app,
131
- target: 'serve',
132
- configuration: context.target.configuration,
133
- runOptions,
134
- projects: workspaceProjects,
135
- }, options.verbose).then((obs) => {
136
- obs.toPromise().catch((err) => {
137
- throw new Error(`Remote '${app}' failed to serve correctly due to the following: \r\n${err.toString()}`);
138
- });
139
- });
140
- devRemotes$.push(serve$);
141
- }
142
- return devRemotes$;
143
- }
144
- function executeModuleFederationDevServerBuilder(schema, context) {
145
- // Force Node to resolve to look for the nx binary that is inside node_modules
146
- const nxBin = require.resolve('nx/bin/nx');
147
- const options = normalizeOptions(schema);
148
- options.staticRemotesPort ??= options.port + 1;
149
- const projectGraph = (0, devkit_1.readCachedProjectGraph)();
150
- const { projects: workspaceProjects } = (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
151
- const project = workspaceProjects[context.target.project];
152
- const staticFileServer = (0, rxjs_1.from)(Promise.resolve().then(() => require('@nx/web/src/executors/file-server/file-server.impl'))).pipe((0, rxjs_1.switchMap)((fileServerExecutor) => fileServerExecutor.default({
153
- port: options.port,
154
- host: options.host,
155
- ssl: options.ssl,
156
- buildTarget: options.buildTarget,
157
- parallel: false,
158
- spa: false,
159
- withDeps: false,
160
- cors: true,
161
- }, {
162
- projectGraph,
163
- root: context.workspaceRoot,
164
- target: projectGraph.nodes[context.target.project].data.targets[context.target.target],
165
- targetName: context.target.target,
166
- projectName: context.target.project,
167
- configurationName: context.target.configuration,
168
- cwd: context.currentDirectory,
169
- isVerbose: options.verbose,
170
- projectsConfigurations: { projects: workspaceProjects, version: 2 },
171
- nxJsonConfiguration: (0, devkit_1.readNxJson)(),
172
- })));
173
- const webpackDevServer = (0, dev_server_impl_1.executeDevServerBuilder)(options, context);
174
- const currExecutor = options.static ? staticFileServer : webpackDevServer;
175
- if (options.isInitialHost === false) {
176
- return currExecutor;
177
- }
178
- let pathToManifestFile = (0, path_1.join)(context.workspaceRoot, project.sourceRoot, 'assets/module-federation.manifest.json');
179
- if (options.pathToManifestFile) {
180
- const userPathToManifestFile = (0, path_1.join)(context.workspaceRoot, options.pathToManifestFile);
181
- if (!(0, fs_1.existsSync)(userPathToManifestFile)) {
182
- throw new Error(`The provided Module Federation manifest file path does not exist. Please check the file exists at "${userPathToManifestFile}".`);
183
- }
184
- else if ((0, path_1.extname)(options.pathToManifestFile) !== '.json') {
185
- throw new Error(`The Module Federation manifest file must be a JSON. Please ensure the file at ${userPathToManifestFile} is a JSON.`);
186
- }
187
- pathToManifestFile = userPathToManifestFile;
188
- }
189
- (0, module_federation_1.validateDevRemotes)(options, workspaceProjects);
190
- const moduleFederationConfig = (0, module_federation_2.getModuleFederationConfig)(project.targets.build.options.tsConfig, context.workspaceRoot, project.root, 'angular');
191
- const remotes = (0, module_federation_2.getRemotes)(options.devRemotes, options.skipRemotes, moduleFederationConfig, {
192
- projectName: project.name,
193
- projectGraph,
194
- root: context.workspaceRoot,
195
- }, pathToManifestFile);
196
- if (remotes.devRemotes.length > 0 && !schema.staticRemotesPort) {
197
- options.staticRemotesPort = options.devRemotes.reduce((portToUse, r) => {
198
- const remotePort = projectGraph.nodes[r].data.targets['serve'].options.port;
199
- if (remotePort >= portToUse) {
200
- return remotePort + 1;
201
- }
202
- }, options.staticRemotesPort);
203
- }
204
- const staticRemoteBuildPromise = buildStaticRemotes(remotes, nxBin, context, options);
205
- return (0, rxjs_1.from)(staticRemoteBuildPromise).pipe((0, rxjs_1.concatMap)(() => {
206
- const staticRemotesIter$ = remotes.staticRemotes.length > 0
207
- ? startStaticRemotesFileServer(remotes, projectGraph, options, context)
208
- : (0, rxjs_1.from)(Promise.resolve());
209
- const devRemotes$ = startDevRemotes(remotes, workspaceProjects, options, context);
210
- return devRemotes$.length > 0
211
- ? (0, rxjs_1.combineLatest)([...devRemotes$, staticRemotesIter$]).pipe((0, rxjs_1.concatMap)(() => currExecutor))
212
- : (0, rxjs_1.from)(staticRemotesIter$).pipe((0, rxjs_1.concatMap)(() => currExecutor));
213
- }));
214
- }
215
- exports.executeModuleFederationDevServerBuilder = executeModuleFederationDevServerBuilder;
216
- exports.default = require('@angular-devkit/architect').createBuilder(executeModuleFederationDevServerBuilder);
217
- function normalizeOptions(schema) {
218
- let buildTarget = schema.buildTarget;
219
- if (schema.browserTarget) {
220
- buildTarget ??= schema.browserTarget;
221
- delete schema.browserTarget;
222
- }
223
- return {
224
- ...schema,
225
- buildTarget,
226
- host: schema.host ?? 'localhost',
227
- port: schema.port ?? 4200,
228
- liveReload: schema.liveReload ?? true,
229
- open: schema.open ?? false,
230
- ssl: schema.ssl ?? false,
231
- };
232
- }