module-federation-angular-adapter 0.2200.0 → 0.2200.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "module-federation-angular-adapter",
3
- "version": "0.2200.0",
3
+ "version": "0.2200.1",
4
4
  "generators": "./collection.json",
5
5
  "builders": "./builders.json",
6
6
  "schematics": "./collection.json",
@@ -1 +1 @@
1
- {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../../src/builders/build/builder.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAiB1C,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,aAAa,EAGnB,MAAM,2BAA2B,CAAC;AAsBnC,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAwEtE,wBAAuB,UAAU,CAC/B,gBAAgB,EAAE,eAAe,GAAG,iBAAiB,EACrD,OAAO,EAAE,cAAc,GACtB,aAAa,CAAC,aAAa,CAAC,CAke9B;wBAkE2C,GAAG;AAA/C,wBAAgD"}
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../../src/builders/build/builder.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAiB1C,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,aAAa,EAGnB,MAAM,2BAA2B,CAAC;AAoBnC,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA0EtE,wBAAuB,UAAU,CAC/B,gBAAgB,EAAE,eAAe,GAAG,iBAAiB,EACrD,OAAO,EAAE,cAAc,GACtB,aAAa,CAAC,aAAa,CAAC,CAqe9B;wBAkE2C,GAAG;AAA/C,wBAAgD"}
@@ -5,11 +5,13 @@ import * as path from "path";
5
5
  import { buildApplication, } from "@angular/build";
6
6
  import { buildApplicationInternal, normalizeDevServerOptions, serveWithVite, SourceFileCache, } from "@angular/build/private";
7
7
  import { createBuilder, targetFromTargetString, } from "@angular-devkit/architect";
8
- import { createFederationCache, getExternals, normalizeFederationOptions, } from "@softarc/native-federation";
8
+ import { createFederationCache, } from "@softarc/native-federation";
9
9
  import { AbortedError, createNfWatcher, getDefaultCachePath, logger, RebuildQueue, setLogLevel, syncNfFileWatcher, } from "@softarc/native-federation/internal";
10
10
  import { checkForInvalidImports } from "./../../utils/check-for-invalid-imports.js";
11
11
  import { federationBuildNotifier } from "./federation-build-notifier.js";
12
12
  import { createMfFederationBuilder, } from "../../tools/mf/build-for-federation.js";
13
+ import { loadFederationConfig } from "../../tools/mf/load-federation-config.js";
14
+ import { getHostExternals } from "./get-externals.js";
13
15
  import { getI18nConfig, translateFederationArtifacts } from "./i18n.js";
14
16
  import { updateScriptTags } from "./update-index-html.js";
15
17
  const originalWrite = process.stderr.write.bind(process.stderr);
@@ -126,30 +128,26 @@ export async function* runBuilder(nfBuilderOptions, context) {
126
128
  const devServerOutputPath = !differentDevServerOutputPath
127
129
  ? browserOutputPath
128
130
  : path.join(outputOptions.base, outputOptions.browser, localeFilter[0]);
129
- const entryPoints = nfBuilderOptions.entryPoints && nfBuilderOptions.entryPoints.length > 0
130
- ? nfBuilderOptions.entryPoints
131
- : [path.join(path.dirname(federationTsConfig), "src/main.ts")];
132
131
  const cachePath = getDefaultCachePath(context.workspaceRoot);
133
- const normalized = await normalizeFederationOptions({
134
- projectName: nfBuilderOptions.projectName,
135
- workspaceRoot: context.workspaceRoot,
132
+ const federationCache = createFederationCache(cachePath, new SourceFileCache(cachePath));
133
+ const config = await loadFederationConfig(context.workspaceRoot, inferConfigPath(federationTsConfig, context.workspaceRoot, nfBuilderOptions.federationConfigPath));
134
+ // `config.name` is the share scope / manifest id prefix (`<name>:@angular/core`);
135
+ // fall back to the project name so it's never empty.
136
+ if (!config.name) {
137
+ config.name = context.target.project;
138
+ }
139
+ checkForInvalidImports(Object.keys(config.shared ?? {}), "externals");
140
+ const fedOptions = {
136
141
  outputPath: browserOutputPath,
137
- federationConfig: inferConfigPath(federationTsConfig, context.workspaceRoot, nfBuilderOptions.federationConfigPath),
138
142
  tsConfig: federationTsConfig,
139
- verbose: ngBuilderOptions.verbose,
140
- watch: ngBuilderOptions.watch,
141
143
  dev: !!nfBuilderOptions.dev,
142
- entryPoints,
143
- buildNotifications: nfBuilderOptions.buildNotifications,
144
- cacheExternalArtifacts: nfBuilderOptions.cacheExternalArtifacts !== false,
145
- }, createFederationCache(cachePath, new SourceFileCache(cachePath)));
146
- checkForInvalidImports(Object.values(normalized.config.sharedMappings), "shared mappings");
147
- checkForInvalidImports(Object.keys(normalized.config.shared), "externals");
144
+ watch,
145
+ federationCache,
146
+ };
148
147
  const start = process.hrtime();
149
148
  logger.measure(start, "To load the federation config.");
150
- const externals = getExternals(normalized.config);
151
- // MF side builder (M2.1) replaces NF's adapter + buildForFederation/rebuildForFederation.
152
- const mfBuilder = await createMfFederationBuilder(normalized.config, normalized.options, externals, {
149
+ const externals = getHostExternals(config.shared);
150
+ const mfBuilder = await createMfFederationBuilder(config, fedOptions, externals, {
153
151
  builderOptions: {
154
152
  ...ngBuilderOptions,
155
153
  plugins: nfBuilderOptions.plugins,
@@ -185,7 +183,7 @@ export async function* runBuilder(nfBuilderOptions, context) {
185
183
  (req, res, next) => {
186
184
  const rawUrl = removeBaseHref(req, ngBuilderOptions.baseHref);
187
185
  const url = new URL(rawUrl || "/", "http://localhost").pathname;
188
- const fileName = path.join(normalized.options.workspaceRoot, devServerOutputPath, url);
186
+ const fileName = path.join(context.workspaceRoot, devServerOutputPath, url);
189
187
  const exists = fs.existsSync(fileName);
190
188
  if (url !== "/" && url !== "" && exists) {
191
189
  const lookup = mrmime.lookup;
@@ -214,11 +212,11 @@ export async function* runBuilder(nfBuilderOptions, context) {
214
212
  if (nfWatcher) {
215
213
  nfWatcher.addPaths(path.dirname(path.resolve(context.workspaceRoot, federationTsConfig)));
216
214
  }
217
- if (fs.existsSync(normalized.options.outputPath)) {
218
- fs.rmSync(normalized.options.outputPath, { recursive: true });
215
+ if (fs.existsSync(browserOutputPath)) {
216
+ fs.rmSync(browserOutputPath, { recursive: true });
219
217
  }
220
- if (!fs.existsSync(normalized.options.outputPath)) {
221
- fs.mkdirSync(normalized.options.outputPath, { recursive: true });
218
+ if (!fs.existsSync(browserOutputPath)) {
219
+ fs.mkdirSync(browserOutputPath, { recursive: true });
222
220
  }
223
221
  let federationResult;
224
222
  try {
@@ -234,7 +232,7 @@ export async function* runBuilder(nfBuilderOptions, context) {
234
232
  await mfBuilder.dispose().catch(() => undefined);
235
233
  }
236
234
  if (nfWatcher) {
237
- syncNfFileWatcher(nfWatcher, normalized.options.federationCache.bundlerCache);
235
+ syncNfFileWatcher(nfWatcher, federationCache.bundlerCache);
238
236
  }
239
237
  const hasLocales = i18n?.locales && Object.keys(i18n.locales).length > 0;
240
238
  if (hasLocales && localeFilter) {
@@ -305,7 +303,7 @@ export async function* runBuilder(nfBuilderOptions, context) {
305
303
  nfWatcher.clear();
306
304
  federationResult = await mfBuilder.rebuild(changedFiles);
307
305
  if (nfWatcher) {
308
- syncNfFileWatcher(nfWatcher, normalized.options.federationCache.bundlerCache);
306
+ syncNfFileWatcher(nfWatcher, federationCache.bundlerCache);
309
307
  }
310
308
  if (signal?.aborted) {
311
309
  throw new AbortedError("[builder] After federation build.");
@@ -364,6 +362,12 @@ export async function* runBuilder(nfBuilderOptions, context) {
364
362
  if (isLocalDevelopment) {
365
363
  federationBuildNotifier.stopEventServer();
366
364
  }
365
+ // Angular's CLI leaves the esbuild service child alive after a non-watch
366
+ // build, so the process never exits. Unref'd: rides the leaked child to
367
+ // fire, then force-exits. ref: https://github.com/angular/angular-cli/issues/33201
368
+ if (!watch) {
369
+ setTimeout(() => process.exit(ngBuildStatus.success ? 0 : 1), 100).unref();
370
+ }
367
371
  }
368
372
  yield ngBuildStatus;
369
373
  }
@@ -1,18 +1,7 @@
1
- import { type SharedConfig } from '../../index.js';
2
1
  /**
3
- * MF equivalent of NF's `getExternals` (host path, M1.5): the packages the
4
- * Angular app build must mark `external` so they resolve from the shared scope
5
- * (es-module-shims import map, finding #6) instead of being bundled. For a pure
6
- * host this is exactly the shared singleton set.
7
- *
8
- * Mirrors NF's trivial `[...Object.keys(shared), ...sharedMappings, ...externals]`,
9
- * MF-shaped: the keys of the MF `shared` map (+ any extra explicit externals).
10
- *
11
- * ⚠️ The builder call-site swap (replacing `getExternals(normalized.config)` at
12
- * `builder.ts:297`) is performed in **M2.1**, not here: that line and
13
- * `buildForFederation` (`builder.ts:425`) consume the *same* `normalized.config`,
14
- * so the externals source and the side-build's `shared` must switch to MF
15
- * together — otherwise the host externalizes deps nothing provides.
2
+ * Packages the Angular app build must mark `external` so they resolve from the
3
+ * shared scope instead of being bundled the keys of the MF `shared` map plus
4
+ * any extra explicit externals. Replaces NF's `getExternals`.
16
5
  */
17
- export declare function getHostExternals(shared?: SharedConfig, extraExternals?: string[]): string[];
6
+ export declare function getHostExternals(shared?: Record<string, unknown>, extraExternals?: string[]): string[];
18
7
  //# sourceMappingURL=get-externals.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-externals.d.ts","sourceRoot":"","sources":["../../../../src/builders/build/get-externals.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE3E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,GAAE,YAAqC,EAC7C,cAAc,GAAE,MAAM,EAAO,GAC5B,MAAM,EAAE,CAEV"}
1
+ {"version":3,"file":"get-externals.d.ts","sourceRoot":"","sources":["../../../../src/builders/build/get-externals.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAA0B,EACxD,cAAc,GAAE,MAAM,EAAO,GAC5B,MAAM,EAAE,CAEV"}
@@ -1,18 +1,8 @@
1
1
  import { DEFAULT_ANGULAR_SHARED } from '../../index.js';
2
2
  /**
3
- * MF equivalent of NF's `getExternals` (host path, M1.5): the packages the
4
- * Angular app build must mark `external` so they resolve from the shared scope
5
- * (es-module-shims import map, finding #6) instead of being bundled. For a pure
6
- * host this is exactly the shared singleton set.
7
- *
8
- * Mirrors NF's trivial `[...Object.keys(shared), ...sharedMappings, ...externals]`,
9
- * MF-shaped: the keys of the MF `shared` map (+ any extra explicit externals).
10
- *
11
- * ⚠️ The builder call-site swap (replacing `getExternals(normalized.config)` at
12
- * `builder.ts:297`) is performed in **M2.1**, not here: that line and
13
- * `buildForFederation` (`builder.ts:425`) consume the *same* `normalized.config`,
14
- * so the externals source and the side-build's `shared` must switch to MF
15
- * together — otherwise the host externalizes deps nothing provides.
3
+ * Packages the Angular app build must mark `external` so they resolve from the
4
+ * shared scope instead of being bundled the keys of the MF `shared` map plus
5
+ * any extra explicit externals. Replaces NF's `getExternals`.
16
6
  */
17
7
  export function getHostExternals(shared = DEFAULT_ANGULAR_SHARED, extraExternals = []) {
18
8
  return [...new Set([...Object.keys(shared), ...extraExternals])];
@@ -1 +1 @@
1
- {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../../src/builders/remote/builder.ts"],"names":[],"mappings":"AAAA,OAAO,yCAAyC,CAAC;AAOjD,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAiB,MAAM,2BAA2B,CAAC;AAmBnG,OAAO,KAAK,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAWlF;;;;;GAKG;AAEH,wBAAuB,gBAAgB,CACrC,gBAAgB,EAAE,qBAAqB,GAAG,uBAAuB,EACjE,OAAO,EAAE,cAAc,GACtB,aAAa,CAAC,aAAa,CAAC,CAmL9B;wBAGiD,GAAG;AAArD,wBAAsD"}
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../../src/builders/remote/builder.ts"],"names":[],"mappings":"AAAA,OAAO,yCAAyC,CAAC;AAOjD,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAiB,MAAM,2BAA2B,CAAC;AAiBnG,OAAO,KAAK,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAWlF;;;;;GAKG;AAEH,wBAAuB,gBAAgB,CACrC,gBAAgB,EAAE,qBAAqB,GAAG,uBAAuB,EACjE,OAAO,EAAE,cAAc,GACtB,aAAa,CAAC,aAAa,CAAC,CAmL9B;wBAGiD,GAAG;AAArD,wBAAsD"}
@@ -3,9 +3,11 @@ import * as path from 'path';
3
3
  import { existsSync, mkdirSync, rmSync } from 'fs';
4
4
  import { SourceFileCache } from '@angular/build/private';
5
5
  import { createBuilder } from '@angular-devkit/architect';
6
- import { getExternals, normalizeFederationOptions, createFederationCache, } from '@softarc/native-federation';
6
+ import { createFederationCache } from '@softarc/native-federation';
7
7
  import { logger, setLogLevel, RebuildQueue, AbortedError, getDefaultCachePath, syncNfFileWatcher, } from '@softarc/native-federation/internal';
8
8
  import { createMfFederationBuilder } from '../../tools/mf/build-for-federation.js';
9
+ import { loadFederationConfig } from '../../tools/mf/load-federation-config.js';
10
+ import { getHostExternals } from '../build/get-externals.js';
9
11
  import { checkForInvalidImports } from '../../utils/check-for-invalid-imports.js';
10
12
  import { resolveNgBuilderOptions } from './resolve-ng-options.js';
11
13
  import { inferFederationConfigPath } from './infer-config-path.js';
@@ -24,33 +26,28 @@ export async function* runRemoteBuilder(nfBuilderOptions, context) {
24
26
  const absoluteBrowserOutput = path.resolve(context.workspaceRoot, browserOutputPath);
25
27
  const { ngBuilderOptions, projectRoot, projectSourceRoot } = await resolveNgBuilderOptions(nfBuilderOptions, context);
26
28
  setLogLevel(nfBuilderOptions.verbose ? 'verbose' : 'info');
27
- // Unlike the regular build builder, remote never bundles a main.ts / polyfills.
28
- // Entry points come from the schema override or, when omitted, from the
29
- // `exposes` map in federation.config.{mjs,js} (resolved by normalizeFederationOptions).
30
- const entryPoints = nfBuilderOptions.entryPoints?.length
31
- ? nfBuilderOptions.entryPoints
32
- : undefined;
33
29
  const cachePath = getDefaultCachePath(context.workspaceRoot);
34
- const normalized = await normalizeFederationOptions({
35
- projectName: nfBuilderOptions.projectName,
36
- workspaceRoot: context.workspaceRoot,
30
+ const federationCache = createFederationCache(cachePath, new SourceFileCache(cachePath));
31
+ const config = await loadFederationConfig(context.workspaceRoot, inferFederationConfigPath(federationTsConfig, context.workspaceRoot));
32
+ // Share scope / manifest id prefix; fall back to the project name so it's never empty.
33
+ if (!config.name) {
34
+ config.name = context.target.project;
35
+ }
36
+ checkForInvalidImports(Object.keys(config.shared ?? {}), 'externals');
37
+ const fedOptions = {
37
38
  outputPath: browserOutputPath,
38
- federationConfig: inferFederationConfigPath(federationTsConfig, context.workspaceRoot),
39
39
  tsConfig: federationTsConfig,
40
- verbose: nfBuilderOptions.verbose,
41
- watch: nfBuilderOptions.watch,
42
40
  dev: !!nfBuilderOptions.dev,
43
- entryPoints,
44
- cacheExternalArtifacts: nfBuilderOptions.cacheExternalArtifacts !== false,
45
- }, createFederationCache(cachePath, new SourceFileCache(cachePath)));
46
- checkForInvalidImports(Object.values(normalized.config.sharedMappings), 'shared mappings');
47
- checkForInvalidImports(Object.keys(normalized.config.shared), 'externals');
41
+ watch: nfBuilderOptions.watch,
42
+ federationCache,
43
+ };
48
44
  const start = process.hrtime();
49
45
  logger.measure(start, 'To load the federation config.');
50
- const externals = getExternals(normalized.config);
51
- // MF side builder (M2.1) replaces NF's adapter + buildForFederation/rebuildForFederation.
52
- // Holds one esbuild context (Angular compiler + moduleFederationPlugin) for build + rebuilds.
53
- const mfBuilder = await createMfFederationBuilder(normalized.config, normalized.options, externals, { builderOptions: ngBuilderOptions, context });
46
+ const externals = getHostExternals(config.shared);
47
+ const mfBuilder = await createMfFederationBuilder(config, fedOptions, externals, {
48
+ builderOptions: ngBuilderOptions,
49
+ context,
50
+ });
54
51
  const assetEntries = normalizeRemoteAssetEntries(nfBuilderOptions.assets, context.workspaceRoot, projectRoot, projectSourceRoot);
55
52
  const changeWatcher = nfBuilderOptions.watch
56
53
  ? createDebouncedChangeWatcher(nfBuilderOptions.rebuildDelay)
@@ -61,10 +58,10 @@ export async function* runRemoteBuilder(nfBuilderOptions, context) {
61
58
  changeWatcher.watcher.addPaths(assetDir);
62
59
  }
63
60
  }
64
- if (existsSync(normalized.options.outputPath)) {
65
- rmSync(normalized.options.outputPath, { recursive: true });
61
+ if (existsSync(browserOutputPath)) {
62
+ rmSync(browserOutputPath, { recursive: true });
66
63
  }
67
- mkdirSync(normalized.options.outputPath, { recursive: true });
64
+ mkdirSync(browserOutputPath, { recursive: true });
68
65
  try {
69
66
  await mfBuilder.build();
70
67
  }
@@ -74,7 +71,7 @@ export async function* runRemoteBuilder(nfBuilderOptions, context) {
74
71
  }
75
72
  await copyAllAssets(assetEntries, absoluteBrowserOutput, context.workspaceRoot);
76
73
  if (changeWatcher) {
77
- syncNfFileWatcher(changeWatcher.watcher, normalized.options.federationCache.bundlerCache);
74
+ syncNfFileWatcher(changeWatcher.watcher, federationCache.bundlerCache);
78
75
  }
79
76
  const rebuildQueue = new RebuildQueue();
80
77
  try {
@@ -114,7 +111,7 @@ export async function* runRemoteBuilder(nfBuilderOptions, context) {
114
111
  // remain in pendingPaths and will drive the next iteration.
115
112
  for (const p of changedFiles)
116
113
  changeWatcher.pendingPaths.delete(p);
117
- syncNfFileWatcher(changeWatcher.watcher, normalized.options.federationCache.bundlerCache);
114
+ syncNfFileWatcher(changeWatcher.watcher, federationCache.bundlerCache);
118
115
  if (signal?.aborted) {
119
116
  throw new AbortedError('[remote-builder] After federation build.');
120
117
  }
@@ -147,6 +144,11 @@ export async function* runRemoteBuilder(nfBuilderOptions, context) {
147
144
  rebuildQueue.dispose();
148
145
  await mfBuilder.dispose();
149
146
  await changeWatcher?.watcher.close();
147
+ // Force-exit the leaked esbuild service on a non-watch build (see build
148
+ // builder). ref: https://github.com/angular/angular-cli/issues/33201
149
+ if (!nfBuilderOptions.watch) {
150
+ setTimeout(() => process.exit(0), 100).unref();
151
+ }
150
152
  }
151
153
  }
152
154
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1 +1 @@
1
- {"version":3,"file":"make-main-async.d.ts","sourceRoot":"","sources":["../../../../../src/schematics/init/steps/make-main-async.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAsBtD,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,EAC1B,SAAS,EAAE,OAAO,EAClB,eAAe,EAAE,MAAM,GACtB,IAAI,CA0BN"}
1
+ {"version":3,"file":"make-main-async.d.ts","sourceRoot":"","sources":["../../../../../src/schematics/init/steps/make-main-async.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAsBtD,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,EAC1B,SAAS,EAAE,OAAO,EAClB,eAAe,EAAE,MAAM,GACtB,IAAI,CAyBN"}
@@ -26,10 +26,9 @@ export function makeMainAsync(main, options, remoteMap, manifestRelPath) {
26
26
  const federationArg = getFederationArg(options, remoteMap, manifestRelPath);
27
27
  tree.overwrite(main, `${FEDERATION_IMPORT}
28
28
 
29
- initFederation(${federationArg})
30
- .catch(err => console.error(err))
31
- .then(_ => import('./bootstrap'))
32
- .catch(err => console.error(err));
29
+ initFederation(${federationArg});
30
+
31
+ import('./bootstrap').catch(err => console.error(err));
33
32
  `);
34
33
  };
35
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"angular-bundler.d.ts","sourceRoot":"","sources":["../../../../src/tools/esbuild/angular-bundler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAiBnC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AAGzF,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,wBAAwB,EAOjC,KAAK,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/D,OAAO,CAAC;IACT,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC;IAC1B,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B,CAAC,CAsJD"}
1
+ {"version":3,"file":"angular-bundler.d.ts","sourceRoot":"","sources":["../../../../src/tools/esbuild/angular-bundler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAiBnC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AAGzF,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,wBAAwB,EAOjC,KAAK,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/D,OAAO,CAAC;IACT,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC;IAC1B,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B,CAAC,CAyJD"}
@@ -103,8 +103,11 @@ extra = {}) {
103
103
  sourcemap: sourcemapOptions.scripts,
104
104
  minify: !dev,
105
105
  supported: {
106
- 'async-await': false,
106
+ // Never set `'async-await': false`: the MF v2 container and
107
+ // `virtual-share-module:*` wrappers emit top-level await, which esbuild
108
+ // cannot downlevel when async/await is marked unsupported.
107
109
  'object-rest-spread': false,
110
+ 'top-level-await': true,
108
111
  },
109
112
  splitting: chunks,
110
113
  platform: platform ?? 'browser',
@@ -5,24 +5,15 @@ import type { FederationCache } from '@softarc/native-federation';
5
5
  import type { FederationSharedInput } from './to-plugin-config.js';
6
6
  import type { NfInternalOptions } from '../../builders/build/schema.js';
7
7
  /**
8
- * Minimal normalized-config shape this driver reads. NF's
9
- * `NormalizedFederationConfig` satisfies it structurally (transitional — Phase 3
10
- * replaces the config loader with `withModuleFederation`).
8
+ * The MF config shape emitted by `withModuleFederation`; `exposes` values are
9
+ * source-path strings. `NormalizedModuleFederationConfig` satisfies it structurally.
11
10
  */
12
11
  export interface NormalizedConfig {
13
12
  name: string;
14
13
  filename?: string;
15
- exposes?: Record<string, {
16
- file: string;
17
- }>;
14
+ exposes?: Record<string, string>;
18
15
  shared?: Record<string, FederationSharedInput>;
19
- sharedMappings?: Record<string, string>;
20
16
  remotes?: Record<string, string>;
21
- chunks?: boolean;
22
- /** NF puts `features` on the config; `optimizedMappings` reads `ignoreUnusedDeps`. */
23
- features?: {
24
- ignoreUnusedDeps?: boolean;
25
- };
26
17
  }
27
18
  /** Federation options the builder already computed (subset NF's `fedOptions` provides). */
28
19
  export interface FederationOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"build-for-federation.d.ts","sourceRoot":"","sources":["../../../../src/tools/mf/build-for-federation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAQlE,OAAO,KAAK,EAEV,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAExE;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sFAAsF;IACtF,QAAQ,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3C;AAED,2FAA2F;AAC3F,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,+GAA+G;IAC/G,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,eAAe,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;CACnD;AAED,wFAAwF;AACxF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AA4BD,2CAA2C;AAC3C,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,yBAAyB,GAAG,iBAAiB,CAAC;IAC9D,OAAO,EAAE,cAAc,CAAC;CACzB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnC,gFAAgF;IAChF,OAAO,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC7D,2EAA2E;IAC3E,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,gBAAgB,EACxB,UAAU,EAAE,iBAAiB,EAC7B,SAAS,EAAE,MAAM,EAAE,EACnB,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,mBAAmB,CAAC,CAuD9B"}
1
+ {"version":3,"file":"build-for-federation.d.ts","sourceRoot":"","sources":["../../../../src/tools/mf/build-for-federation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAKlE,OAAO,KAAK,EAEV,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAExE;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,2FAA2F;AAC3F,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,+GAA+G;IAC/G,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,eAAe,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;CACnD;AAED,wFAAwF;AACxF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAaD,2CAA2C;AAC3C,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,yBAAyB,GAAG,iBAAiB,CAAC;IAC9D,OAAO,EAAE,cAAc,CAAC;CACzB;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnC,gFAAgF;IAChF,OAAO,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC7D,2EAA2E;IAC3E,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,gBAAgB,EACxB,UAAU,EAAE,iBAAiB,EAC7B,SAAS,EAAE,MAAM,EAAE,EACnB,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,mBAAmB,CAAC,CAmD9B"}
@@ -1,33 +1,18 @@
1
1
  import { normalizeContextOptions } from '../../utils/normalize-context-options.js';
2
2
  import { createFederationEsbuildContext } from './federation-side-build.js';
3
- import { toExposedEntryPoints, } from './federation-entry-points.js';
4
- /** Shared-mappingsentry points (mirrors NF's `bundleExposedAndMappings`). */
5
- function toMappingEntryPoints(sharedMappings = {}) {
6
- return Object.entries(sharedMappings).map(([entryPoint, mappedImport]) => ({
7
- fileName: entryPoint,
8
- outName: mappedImport.replace(/[^A-Za-z0-9]/g, '_') + '.js',
9
- key: mappedImport,
10
- }));
11
- }
12
- /** NF normalized config → the MF plugin's `FederationConfigInput` (exposes value → file path). */
3
+ import { toExposedEntryPoints } from './federation-entry-points.js';
4
+ /** MF config the MF plugin's `FederationConfigInput` (exposes values are already source paths). */
13
5
  function toFederationConfigInput(config) {
14
- const exposes = {};
15
- for (const [key, expose] of Object.entries(config.exposes ?? {})) {
16
- exposes[key] = expose.file;
17
- }
18
6
  return {
19
7
  name: config.name,
20
8
  filename: config.filename,
21
- exposes,
9
+ exposes: config.exposes,
22
10
  shared: config.shared,
23
11
  remotes: config.remotes,
24
12
  };
25
13
  }
26
14
  export async function createMfFederationBuilder(config, fedOptions, externals, ctx) {
27
- const entryPoints = [
28
- ...toMappingEntryPoints(config.sharedMappings),
29
- ...toExposedEntryPoints(config.exposes),
30
- ];
15
+ const entryPoints = toExposedEntryPoints(config.exposes);
31
16
  const options = normalizeContextOptions(ctx.builderOptions, ctx.context, {
32
17
  entryPoints,
33
18
  outdir: fedOptions.outputPath,
@@ -35,10 +20,9 @@ export async function createMfFederationBuilder(config, fedOptions, externals, c
35
20
  external: externals,
36
21
  dev: !!fedOptions.dev,
37
22
  watch: fedOptions.watch,
38
- mappedPaths: config.sharedMappings ?? {},
39
- chunks: config.chunks,
23
+ mappedPaths: {},
40
24
  hash: !fedOptions.dev,
41
- optimizedMappings: !!config.features?.ignoreUnusedDeps,
25
+ optimizedMappings: false,
42
26
  isMappingOrExposed: true,
43
27
  cache: fedOptions.federationCache,
44
28
  });
@@ -9,15 +9,9 @@ export interface FederationEntryPoint {
9
9
  outName: string;
10
10
  key?: string;
11
11
  }
12
- /** A config `exposes` entry — only the source `file` is needed to build it. */
13
- export interface ExposeInput {
14
- file: string;
15
- }
16
12
  /**
17
- * Derive the side-build entry points from a federation config's `exposes`
18
- * (M2.1). Mirrors NF's `bundleExposedAndMappings`:
19
- * `{ fileName: expose.file, outName: key + '.js', key }`. Shared-mappings
20
- * entries (if still used) are concatenated by the caller.
13
+ * Derive the side-build entry points from a federation config's `exposes`, whose
14
+ * values are source-path strings: `{ fileName: sourcePath, outName: key + '.js', key }`.
21
15
  */
22
- export declare function toExposedEntryPoints(exposes?: Record<string, ExposeInput>): FederationEntryPoint[];
16
+ export declare function toExposedEntryPoints(exposes?: Record<string, string>): FederationEntryPoint[];
23
17
  //# sourceMappingURL=federation-entry-points.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"federation-entry-points.d.ts","sourceRoot":"","sources":["../../../../src/tools/mf/federation-entry-points.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAM,GACxC,oBAAoB,EAAE,CAMxB"}
1
+ {"version":3,"file":"federation-entry-points.d.ts","sourceRoot":"","sources":["../../../../src/tools/mf/federation-entry-points.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACnC,oBAAoB,EAAE,CAMxB"}
@@ -1,12 +1,10 @@
1
1
  /**
2
- * Derive the side-build entry points from a federation config's `exposes`
3
- * (M2.1). Mirrors NF's `bundleExposedAndMappings`:
4
- * `{ fileName: expose.file, outName: key + '.js', key }`. Shared-mappings
5
- * entries (if still used) are concatenated by the caller.
2
+ * Derive the side-build entry points from a federation config's `exposes`, whose
3
+ * values are source-path strings: `{ fileName: sourcePath, outName: key + '.js', key }`.
6
4
  */
7
5
  export function toExposedEntryPoints(exposes = {}) {
8
- return Object.entries(exposes).map(([key, expose]) => ({
9
- fileName: expose.file,
6
+ return Object.entries(exposes).map(([key, sourcePath]) => ({
7
+ fileName: sourcePath,
10
8
  outName: key + '.js',
11
9
  key,
12
10
  }));
@@ -0,0 +1,9 @@
1
+ import type { NormalizedModuleFederationConfig } from '../../config/with-module-federation.js';
2
+ /**
3
+ * Load the MF-shaped federation config (the default export of
4
+ * `federation.config.{mjs,js}`). Replaces NF's `normalizeFederationOptions`,
5
+ * which assumed the NF shape (`features`, `sharedMappings`, object `exposes`)
6
+ * and crashed on the MF config.
7
+ */
8
+ export declare function loadFederationConfig(workspaceRoot: string, federationConfig: string): Promise<NormalizedModuleFederationConfig>;
9
+ //# sourceMappingURL=load-federation-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-federation-config.d.ts","sourceRoot":"","sources":["../../../../src/tools/mf/load-federation-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,wCAAwC,CAAC;AAE/F;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,gCAAgC,CAAC,CAkB3C"}
@@ -0,0 +1,20 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { pathToFileURL } from 'url';
4
+ /**
5
+ * Load the MF-shaped federation config (the default export of
6
+ * `federation.config.{mjs,js}`). Replaces NF's `normalizeFederationOptions`,
7
+ * which assumed the NF shape (`features`, `sharedMappings`, object `exposes`)
8
+ * and crashed on the MF config.
9
+ */
10
+ export async function loadFederationConfig(workspaceRoot, federationConfig) {
11
+ const fullConfigPath = path.join(workspaceRoot, federationConfig);
12
+ if (!fs.existsSync(fullConfigPath)) {
13
+ throw new Error('Expected ' + fullConfigPath);
14
+ }
15
+ const loaded = (await import(pathToFileURL(fullConfigPath).href));
16
+ if (!loaded?.default) {
17
+ throw new Error(`Federation config at ${fullConfigPath} must have a default export (the result of withModuleFederation).`);
18
+ }
19
+ return loaded.default;
20
+ }
@@ -25,7 +25,9 @@ export interface FederationSharedInput {
25
25
  requiredVersion?: string;
26
26
  version?: string;
27
27
  eager?: boolean;
28
- includeSecondaries?: boolean;
28
+ includeSecondaries?: boolean | {
29
+ skip?: string | string[];
30
+ };
29
31
  }
30
32
  /**
31
33
  * Map a normalized federation config → `moduleFederationPlugin` options (the
@@ -1 +1 @@
1
- {"version":3,"file":"to-plugin-config.d.ts","sourceRoot":"","sources":["../../../../src/tools/mf/to-plugin-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAEhF;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;AAG1E;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,8EAA8E;IAC9E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAqBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,qBAAqB,EAC1B,QAAQ,SAAmB,GAC1B,cAAc,CAQhB"}
1
+ {"version":3,"file":"to-plugin-config.d.ts","sourceRoot":"","sources":["../../../../src/tools/mf/to-plugin-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAEhF;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;AAG1E;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,8EAA8E;IAC9E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB,CAAC,EAAE,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAC;CAC7D;AAqBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,qBAAqB,EAC1B,QAAQ,SAAmB,GAC1B,cAAc,CAQhB"}
@@ -9,8 +9,8 @@ function mapShared(shared) {
9
9
  requiredVersion: cfg.requiredVersion ?? '*',
10
10
  version: cfg.version,
11
11
  eager: cfg.eager,
12
- // Spike-confirmed (finding #4): the esbuild plugin DOES support
13
- // `includeSecondaries` so it maps 1:1, contra M3.1's table.
12
+ // Plugin types narrow to `boolean`, but `getSecondaries` accepts the
13
+ // `{ skip }` object form too pass through as-is.
14
14
  includeSecondaries: cfg.includeSecondaries,
15
15
  };
16
16
  }