@angular-architects/native-federation-v4 21.1.7 → 21.1.9

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 (48) hide show
  1. package/collection.json +5 -0
  2. package/migration-collection.json +6 -0
  3. package/package.json +5 -5
  4. package/src/builders/build/builder.d.ts.map +1 -1
  5. package/src/builders/build/builder.js +45 -49
  6. package/src/builders/build/schema.d.ts +3 -5
  7. package/src/builders/build/schema.json +8 -29
  8. package/src/config/angular-skip-list.d.ts +3 -0
  9. package/src/config/angular-skip-list.d.ts.map +1 -0
  10. package/src/config/angular-skip-list.js +13 -0
  11. package/src/config/share-utils.d.ts +9 -0
  12. package/src/config/share-utils.d.ts.map +1 -0
  13. package/src/config/share-utils.js +32 -0
  14. package/src/config.d.ts +2 -2
  15. package/src/config.d.ts.map +1 -1
  16. package/src/config.js +2 -2
  17. package/src/schematics/init/files/federation.config.js__tmpl__ +19 -7
  18. package/src/schematics/init/schema.d.ts +0 -1
  19. package/src/schematics/init/schema.json +2 -6
  20. package/src/schematics/init/schematic.d.ts.map +1 -1
  21. package/src/schematics/init/schematic.js +50 -25
  22. package/src/schematics/update-v4/schema.d.ts +4 -0
  23. package/src/schematics/update-v4/schema.json +23 -0
  24. package/src/schematics/update-v4/schematic.d.ts +4 -0
  25. package/src/schematics/update-v4/schematic.d.ts.map +1 -0
  26. package/src/schematics/update-v4/schematic.js +225 -0
  27. package/src/utils/angular-bundler.d.ts +3 -8
  28. package/src/utils/angular-bundler.d.ts.map +1 -1
  29. package/src/utils/angular-bundler.js +10 -57
  30. package/src/utils/angular-esbuild-adapter.d.ts +5 -4
  31. package/src/utils/angular-esbuild-adapter.d.ts.map +1 -1
  32. package/src/utils/angular-esbuild-adapter.js +16 -19
  33. package/src/utils/angular-locales.d.ts.map +1 -1
  34. package/src/utils/create-federation-tsconfig.d.ts +6 -0
  35. package/src/utils/create-federation-tsconfig.d.ts.map +1 -0
  36. package/src/utils/create-federation-tsconfig.js +49 -0
  37. package/src/utils/get-fallback-platform.d.ts +3 -0
  38. package/src/utils/get-fallback-platform.d.ts.map +1 -0
  39. package/src/utils/get-fallback-platform.js +13 -0
  40. package/src/utils/node-modules-bundler.d.ts +3 -8
  41. package/src/utils/node-modules-bundler.d.ts.map +1 -1
  42. package/src/utils/node-modules-bundler.js +4 -8
  43. package/src/utils/normalize-context-options.d.ts +23 -0
  44. package/src/utils/normalize-context-options.d.ts.map +1 -0
  45. package/src/utils/normalize-context-options.js +18 -0
  46. package/src/utils/shared-mappings-plugin.d.ts +2 -2
  47. package/src/utils/shared-mappings-plugin.d.ts.map +1 -1
  48. package/src/utils/shared-mappings-plugin.js +4 -4
@@ -4,7 +4,7 @@ import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
4
4
  import { patchAngularBuildPackageJson, privateEntrySrc } from '../../utils/patch-angular-build.js';
5
5
  import { addPackageJsonDependency, getPackageJsonDependency, NodeDependencyType, } from '@schematics/angular/utility/dependencies';
6
6
  import * as path from 'path';
7
- const SSR_VERSION = '^3.3.4';
7
+ const SSR_VERSION = '4.0.0-RC9';
8
8
  export function updatePackageJson(tree) {
9
9
  const packageJson = tree.readJson('package.json') ?? {};
10
10
  const scriptCall = 'node node_modules/@angular-architects/native-federation/src/patch-angular-build.js';
@@ -45,19 +45,7 @@ export default function config(options) {
45
45
  : noop;
46
46
  const ssr = isSsrProject(normalized);
47
47
  const server = ssr ? getSsrFilePath(normalized) : '';
48
- if (ssr) {
49
- console.log('SSR detected ...');
50
- console.log('Activating CORS ...');
51
- addPackageJsonDependency(tree, {
52
- name: 'cors',
53
- type: NodeDependencyType.Default,
54
- version: '^2.8.5',
55
- overwrite: false,
56
- });
57
- }
58
48
  updateWorkspaceConfig(tree, normalized, workspace, workspaceFileName, ssr);
59
- // updatePackageJson(tree);
60
- // patchAngularBuild(tree);
61
49
  addPackageJsonDependency(tree, {
62
50
  name: '@angular/animations',
63
51
  type: NodeDependencyType.Default,
@@ -77,12 +65,28 @@ export default function config(options) {
77
65
  overwrite: false,
78
66
  });
79
67
  addPackageJsonDependency(tree, {
80
- name: '@softarc/native-federation-node',
68
+ name: '@softarc/native-federation-orchestrator',
81
69
  type: NodeDependencyType.Default,
82
- version: SSR_VERSION,
83
- overwrite: true,
70
+ version: '4.0.0-RC4',
71
+ overwrite: false,
84
72
  });
85
73
  context.addTask(new NodePackageInstallTask());
74
+ if (ssr) {
75
+ console.log('SSR detected ...');
76
+ console.log('Activating CORS ...');
77
+ addPackageJsonDependency(tree, {
78
+ name: 'cors',
79
+ type: NodeDependencyType.Default,
80
+ version: '^2.8.5',
81
+ overwrite: false,
82
+ });
83
+ addPackageJsonDependency(tree, {
84
+ name: '@softarc/native-federation-node',
85
+ type: NodeDependencyType.Default,
86
+ version: SSR_VERSION,
87
+ overwrite: true,
88
+ });
89
+ }
86
90
  return chain([
87
91
  generateRule,
88
92
  makeMainAsync(main, options, remoteMap, manifestRelPath),
@@ -113,7 +117,8 @@ export function patchAngularBuild(tree) {
113
117
  }
114
118
  }
115
119
  function updateWorkspaceConfig(tree, options, workspace, workspaceFileName, ssr) {
116
- const { projectConfig, projectName, port } = options;
120
+ const { projectConfig, projectName, port, main, projectSourceRoot } = options;
121
+ const entryPoints = main ? [main] : [path.join(projectSourceRoot, 'main.ts')];
117
122
  if (!projectConfig?.architect?.build || !projectConfig?.architect?.serve) {
118
123
  throw new Error(`The project doesn't have a build or serve target in angular.json!`);
119
124
  }
@@ -134,7 +139,11 @@ function updateWorkspaceConfig(tree, options, workspace, workspaceFileName, ssr)
134
139
  projectConfig.architect.esbuild = originalBuild;
135
140
  projectConfig.architect.build = {
136
141
  builder: '@angular-architects/native-federation:build',
137
- options: {},
142
+ options: {
143
+ projectName,
144
+ cacheExternalArtifacts: true,
145
+ entryPoints,
146
+ },
138
147
  configurations: {
139
148
  production: {
140
149
  target: `${projectName}:esbuild:production`,
@@ -168,11 +177,14 @@ function updateWorkspaceConfig(tree, options, workspace, workspaceFileName, ssr)
168
177
  projectConfig.architect.serve = {
169
178
  builder: '@angular-architects/native-federation:build',
170
179
  options: {
180
+ projectName,
171
181
  target: `${projectName}:serve-original:development`,
172
182
  rebuildDelay: 500,
183
+ cacheExternalArtifacts: true,
173
184
  dev: true,
174
- cacheExternalArtifacts: false,
185
+ devServer: true,
175
186
  port: 0,
187
+ entryPoints,
176
188
  },
177
189
  };
178
190
  const serveSsr = projectConfig.architect['serve-ssr'];
@@ -292,11 +304,24 @@ function makeMainAsync(main, options, remoteMap, manifestRelPath) {
292
304
  const mainContent = tree.read(main);
293
305
  if (mainContent)
294
306
  tree.create(bootstrapName, mainContent);
307
+ const orchestratorImports = `import { initFederation } from '@softarc/native-federation-orchestrator';
308
+ import {
309
+ useShimImportMap,
310
+ consoleLogger,
311
+ globalThisStorageEntry,
312
+ } from '@softarc/native-federation-orchestrator/options';`;
313
+ const orchestratorOptions = `{
314
+ ...useShimImportMap({ shimMode: true }),
315
+ logger: consoleLogger,
316
+ storage: globalThisStorageEntry,
317
+ hostRemoteEntry: './remoteEntry.json',
318
+ logLevel: 'debug',
319
+ }`;
295
320
  let newMainContent = '';
296
321
  if (options.type === 'dynamic-host') {
297
- newMainContent = `import { initFederation } from '@angular-architects/native-federation';
322
+ newMainContent = `${orchestratorImports}
298
323
 
299
- initFederation('${manifestRelPath}')
324
+ initFederation('${manifestRelPath}', ${orchestratorOptions})
300
325
  .catch(err => console.error(err))
301
326
  .then(_ => import('./bootstrap'))
302
327
  .catch(err => console.error(err));
@@ -304,18 +329,18 @@ initFederation('${manifestRelPath}')
304
329
  }
305
330
  else if (options.type === 'host') {
306
331
  const manifest = JSON.stringify(remoteMap, null, 2).replace(/"/g, "'");
307
- newMainContent = `import { initFederation } from '@angular-architects/native-federation';
332
+ newMainContent = `${orchestratorImports}
308
333
 
309
- initFederation(${manifest})
334
+ initFederation(${manifest}, ${orchestratorOptions})
310
335
  .catch(err => console.error(err))
311
336
  .then(_ => import('./bootstrap'))
312
337
  .catch(err => console.error(err));
313
338
  `;
314
339
  }
315
340
  else {
316
- newMainContent = `import { initFederation } from '@angular-architects/native-federation';
341
+ newMainContent = `${orchestratorImports}
317
342
 
318
- initFederation()
343
+ initFederation({ '${options.project}': './remoteEntry.json' }, ${orchestratorOptions})
319
344
  .catch(err => console.error(err))
320
345
  .then(_ => import('./bootstrap'))
321
346
  .catch(err => console.error(err));
@@ -0,0 +1,4 @@
1
+ export interface UpdateV4Schema {
2
+ project: string;
3
+ orchestrator: boolean;
4
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "http://json-schema.org/schema",
3
+ "$id": "update-v4",
4
+ "title": "",
5
+ "type": "object",
6
+ "properties": {
7
+ "project": {
8
+ "type": "string",
9
+ "description": "The project to migrate to v4",
10
+ "$default": {
11
+ "$source": "argv",
12
+ "index": 0
13
+ },
14
+ "x-prompt": "Project name (press enter for default project)"
15
+ },
16
+ "orchestrator": {
17
+ "type": "boolean",
18
+ "description": "Switch main.ts to use @softarc/native-federation-orchestrator instead of the legacy runtime",
19
+ "default": false,
20
+ "x-prompt": "Would you like to use the new orchestrator runtime? (recommended)"
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,4 @@
1
+ import type { Rule } from '@angular-devkit/schematics';
2
+ import type { UpdateV4Schema } from './schema.js';
3
+ export default function updateV4(options: UpdateV4Schema): Rule;
4
+ //# sourceMappingURL=schematic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schematic.d.ts","sourceRoot":"","sources":["../../../../src/schematics/update-v4/schematic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAQ,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAelD,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAgB9D"}
@@ -0,0 +1,225 @@
1
+ import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
2
+ import { getWorkspaceFileName } from '../init/schematic.js';
3
+ import * as path from 'path';
4
+ const V3_PACKAGE = '@angular-architects/native-federation';
5
+ const V4_PACKAGE = '@angular-architects/native-federation-v4';
6
+ const V3_BUILDER = `${V3_PACKAGE}:build`;
7
+ const V4_BUILDER = `${V4_PACKAGE}:build`;
8
+ const V3_RUNTIME_IMPORT = `@angular-architects/native-federation`;
9
+ const V4_RUNTIME_IMPORT = `@softarc/native-federation-runtime`;
10
+ const ORCHESTRATOR_PACKAGE = `@softarc/native-federation-orchestrator`;
11
+ export default function updateV4(options) {
12
+ return async function (tree, context) {
13
+ const workspaceFileName = getWorkspaceFileName(tree);
14
+ const workspace = JSON.parse(tree.read(workspaceFileName)?.toString('utf8') ?? '{}');
15
+ enableEsmInPackageJson(tree);
16
+ updateBuilderReferences(tree, workspace, workspaceFileName);
17
+ migrateFederationConfigs(tree, workspace, options);
18
+ migrateMainTs(tree, workspace, options);
19
+ if (options.orchestrator) {
20
+ installOrchestratorPackage(tree);
21
+ migrateMainTsToOrchestrator(tree, workspace, options);
22
+ context.addTask(new NodePackageInstallTask());
23
+ }
24
+ };
25
+ }
26
+ /**
27
+ * Step 1: Add "type": "module" to the root package.json
28
+ */
29
+ function enableEsmInPackageJson(tree) {
30
+ const packageJson = JSON.parse(tree.read('package.json')?.toString('utf8') ?? '{}');
31
+ if (packageJson.type === 'module') {
32
+ return;
33
+ }
34
+ packageJson.type = 'module';
35
+ tree.overwrite('package.json', JSON.stringify(packageJson, null, 2));
36
+ console.log('Updated package.json: added "type": "module"');
37
+ }
38
+ /**
39
+ * Step 2: Update all builder references in angular.json / workspace.json
40
+ * from @angular-architects/native-federation:build to @angular-architects/native-federation-v4:build
41
+ */
42
+ function updateBuilderReferences(tree, workspace, workspaceFileName) {
43
+ let modified = false;
44
+ for (const projectName of Object.keys(workspace.projects ?? {})) {
45
+ const project = workspace.projects[projectName];
46
+ const architect = project?.architect ?? {};
47
+ const sourceRoot = (project?.sourceRoot ?? '').replace(/\\/g, '/');
48
+ for (const targetName of Object.keys(architect)) {
49
+ const target = architect[targetName];
50
+ if (target?.builder === V3_BUILDER) {
51
+ target.builder = V4_BUILDER;
52
+ modified = true;
53
+ console.log(`Updated builder for "${projectName}:${targetName}" to ${V4_BUILDER}`);
54
+ }
55
+ // Add entryPoints and projectName to NF builder targets if not already set
56
+ if ((target?.builder === V3_BUILDER || target?.builder === V4_BUILDER) &&
57
+ !target?.options?.entryPoints) {
58
+ target.options ??= {};
59
+ target.options.entryPoints = [path.join(sourceRoot, 'main.ts')];
60
+ if (!target.options.projectName) {
61
+ target.options.projectName = projectName;
62
+ }
63
+ modified = true;
64
+ }
65
+ }
66
+ }
67
+ if (modified) {
68
+ tree.overwrite(workspaceFileName, JSON.stringify(workspace, null, '\t'));
69
+ }
70
+ }
71
+ /**
72
+ * Step 3: Migrate federation.config.js files from CJS to ESM
73
+ * - require() → import
74
+ * - module.exports = → export default
75
+ * - Update package references from v3 to v4
76
+ */
77
+ function migrateFederationConfigs(tree, workspace, options) {
78
+ const projects = resolveProjects(workspace, options);
79
+ for (const { projectRoot } of projects) {
80
+ const configPath = path.join(projectRoot, 'federation.config.js');
81
+ if (!tree.exists(configPath)) {
82
+ continue;
83
+ }
84
+ let content = tree.readText(configPath);
85
+ const originalContent = content;
86
+ // Convert CJS require to ESM import
87
+ // Matches: const { foo, bar } = require('...');
88
+ const requireRegex = /const\s+(\{[^}]+\})\s*=\s*require\(\s*['"]([^'"]+)['"]\s*\)\s*;?/g;
89
+ const imports = [];
90
+ content = content.replace(requireRegex, (_match, bindings, modulePath) => {
91
+ const updatedPath = modulePath.replace(V3_PACKAGE, V4_PACKAGE);
92
+ imports.push(`import ${bindings} from '${updatedPath}';`);
93
+ return ''; // Remove the require line; import will be prepended
94
+ });
95
+ // Prepend collected imports at the top (after removing old requires)
96
+ if (imports.length > 0) {
97
+ content = imports.join('\n') + '\n' + content.trimStart();
98
+ }
99
+ // Convert module.exports = to export default
100
+ content = content.replace(/module\.exports\s*=\s*/, 'export default ');
101
+ // Also update any remaining inline @angular-architects/native-federation references
102
+ // (e.g. in comments or other import paths) to the v4 package
103
+ content = content.replace(new RegExp(escapeRegExp(V3_PACKAGE + '/config'), 'g'), V4_PACKAGE + '/config');
104
+ content = content.replace(new RegExp(escapeRegExp(V3_PACKAGE) + '(?!/)', 'g'), V4_PACKAGE);
105
+ if (content !== originalContent) {
106
+ tree.overwrite(configPath, content);
107
+ console.log(`Migrated ${configPath} to ESM`);
108
+ }
109
+ }
110
+ }
111
+ /**
112
+ * Step 4: Update main.ts imports from @angular-architects/native-federation
113
+ * to @softarc/native-federation-runtime
114
+ */
115
+ function migrateMainTs(tree, workspace, options) {
116
+ const projects = resolveProjects(workspace, options);
117
+ for (const { projectConfig } of projects) {
118
+ const main = projectConfig?.architect?.build?.options?.browser ??
119
+ projectConfig?.architect?.build?.options?.main ??
120
+ projectConfig?.architect?.esbuild?.options?.browser ??
121
+ projectConfig?.architect?.esbuild?.options?.main;
122
+ if (!main || !tree.exists(main)) {
123
+ continue;
124
+ }
125
+ let content = tree.readText(main);
126
+ const originalContent = content;
127
+ // Update initFederation import
128
+ content = content.replace(new RegExp(escapeRegExp(V3_RUNTIME_IMPORT), 'g'), V4_RUNTIME_IMPORT);
129
+ if (content !== originalContent) {
130
+ tree.overwrite(main, content);
131
+ console.log(`Updated initFederation import in ${main}`);
132
+ }
133
+ }
134
+ }
135
+ /**
136
+ * Optional Step 5: Add @softarc/native-federation-orchestrator to package.json dependencies
137
+ */
138
+ function installOrchestratorPackage(tree) {
139
+ const packageJson = JSON.parse(tree.read('package.json')?.toString('utf8') ?? '{}');
140
+ if (!packageJson.dependencies) {
141
+ packageJson.dependencies = {};
142
+ }
143
+ if (!packageJson.dependencies[ORCHESTRATOR_PACKAGE]) {
144
+ packageJson.dependencies[ORCHESTRATOR_PACKAGE] = '^4.0.0-RC4';
145
+ tree.overwrite('package.json', JSON.stringify(packageJson, null, 2));
146
+ console.log(`Added ${ORCHESTRATOR_PACKAGE} to dependencies`);
147
+ }
148
+ }
149
+ /**
150
+ * Optional Step 6: Surgically update main.ts to use the orchestrator.
151
+ *
152
+ * - Replaces the initFederation import source with @softarc/native-federation-orchestrator
153
+ * - Adds the orchestrator /options import
154
+ * - Rewrites the initFederation() call:
155
+ * - If it had a first argument, keeps it and appends the orchestrator options as second arg
156
+ * - If it had no arguments, uses {} as first arg and the orchestrator options as second arg
157
+ */
158
+ function migrateMainTsToOrchestrator(tree, workspace, options) {
159
+ const projects = resolveProjects(workspace, options);
160
+ const orchestratorOptions = `{
161
+ ...useShimImportMap({ shimMode: true }),
162
+ logger: consoleLogger,
163
+ storage: globalThisStorageEntry,
164
+ hostRemoteEntry: './remoteEntry.json',
165
+ logLevel: 'debug',
166
+ }`;
167
+ const optionsImport = `import {
168
+ useShimImportMap,
169
+ consoleLogger,
170
+ globalThisStorageEntry,
171
+ } from '${ORCHESTRATOR_PACKAGE}/options';`;
172
+ for (const { projectConfig } of projects) {
173
+ const main = projectConfig?.architect?.build?.options?.browser ??
174
+ projectConfig?.architect?.build?.options?.main ??
175
+ projectConfig?.architect?.esbuild?.options?.browser ??
176
+ projectConfig?.architect?.esbuild?.options?.main;
177
+ if (!main || !tree.exists(main)) {
178
+ continue;
179
+ }
180
+ let content = tree.readText(main);
181
+ // 1. Replace the import source to the orchestrator package
182
+ content = content.replace(new RegExp(`from\\s+['"](?:${escapeRegExp(V4_RUNTIME_IMPORT)}|${escapeRegExp(V3_RUNTIME_IMPORT)})['"]`, 'g'), `from '${ORCHESTRATOR_PACKAGE}'`);
183
+ // 2. Add the /options import after the orchestrator import line
184
+ if (!content.includes(`${ORCHESTRATOR_PACKAGE}/options`)) {
185
+ content = content.replace(new RegExp(`(import\\s+\\{[^}]*\\}\\s+from\\s+['"]${escapeRegExp(ORCHESTRATOR_PACKAGE)}['"];?)`), `$1\n${optionsImport}`);
186
+ }
187
+ // 3. Rewrite initFederation(...) call — extract existing first arg if present
188
+ const initMatch = content.match(/initFederation\s*\(([^)]*)\)/s);
189
+ if (initMatch) {
190
+ const existingArgs = initMatch[1].trim();
191
+ const firstArg = existingArgs.length > 0 ? existingArgs : '{}';
192
+ content = content.replace(initMatch[0], `initFederation(${firstArg}, ${orchestratorOptions})`);
193
+ }
194
+ tree.overwrite(main, content);
195
+ console.log(`Switched ${main} to use the orchestrator`);
196
+ }
197
+ }
198
+ function resolveProjects(workspace, options) {
199
+ const projects = [];
200
+ if (options.project) {
201
+ const projectConfig = workspace.projects?.[options.project];
202
+ if (projectConfig) {
203
+ projects.push({
204
+ projectName: options.project,
205
+ projectRoot: projectConfig.root?.replace(/\\/g, '/') ?? '',
206
+ projectConfig,
207
+ });
208
+ }
209
+ }
210
+ else {
211
+ // Migrate all projects
212
+ for (const projectName of Object.keys(workspace.projects ?? {})) {
213
+ const projectConfig = workspace.projects[projectName];
214
+ projects.push({
215
+ projectName,
216
+ projectRoot: projectConfig.root?.replace(/\\/g, '/') ?? '',
217
+ projectConfig,
218
+ });
219
+ }
220
+ }
221
+ return projects;
222
+ }
223
+ function escapeRegExp(str) {
224
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
225
+ }
@@ -1,12 +1,7 @@
1
1
  import * as esbuild from 'esbuild';
2
- import { type SourceFileCache } from '@angular/build/private';
3
- import type { BuilderContext } from '@angular-devkit/architect';
4
- import type { ApplicationBuilderOptions } from '@angular/build';
5
- import type { EntryPoint, FederationCache } from '@softarc/native-federation';
6
- import type { MappedPath } from '@softarc/native-federation/internal';
7
- export interface AngularBundleResult {
2
+ import type { NormalizedContextOptions } from './normalize-context-options.js';
3
+ export declare function createAngularEsbuildContext(options: NormalizedContextOptions): Promise<{
8
4
  ctx: esbuild.BuildContext;
9
5
  pluginDisposed: Promise<void>;
10
- }
11
- export declare function createAngularEsbuildContext(builderOptions: ApplicationBuilderOptions, context: BuilderContext, entryPoints: EntryPoint[], external: string[], outdir: string, tsConfigPath: string, mappedPaths: MappedPath[], cache: FederationCache<SourceFileCache>, dev?: boolean, hash?: boolean, chunks?: boolean, platform?: 'browser' | 'node', optimizedMappings?: boolean): Promise<AngularBundleResult>;
6
+ }>;
12
7
  //# sourceMappingURL=angular-bundler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"angular-bundler.d.ts","sourceRoot":"","sources":["../../../src/utils/angular-bundler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAOnC,OAAO,EAML,KAAK,eAAe,EAGrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAOhE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAKtE,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC;IAC1B,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,wBAAsB,2BAA2B,CAC/C,cAAc,EAAE,yBAAyB,EACzC,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,UAAU,EAAE,EACzB,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,UAAU,EAAE,EACzB,KAAK,EAAE,eAAe,CAAC,eAAe,CAAC,EACvC,GAAG,CAAC,EAAE,OAAO,EACb,IAAI,GAAE,OAAe,EACrB,MAAM,CAAC,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,SAAS,GAAG,MAAM,EAC7B,iBAAiB,CAAC,EAAE,OAAO,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAkI9B"}
1
+ {"version":3,"file":"angular-bundler.d.ts","sourceRoot":"","sources":["../../../src/utils/angular-bundler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAoBnC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAG/E,wBAAsB,2BAA2B,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC;IAC5F,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC;IAC1B,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B,CAAC,CAkJD"}
@@ -1,14 +1,16 @@
1
1
  import * as esbuild from 'esbuild';
2
2
  import * as path from 'path';
3
- import * as fs from 'fs';
4
3
  import { createRequire } from 'node:module';
5
- import { isDeepStrictEqual } from 'node:util';
6
- import JSON5 from 'json5';
7
4
  import { transformSupportedBrowsersToTargets, getSupportedBrowsers, generateSearchDirectories, findTailwindConfiguration, loadPostcssConfiguration, } from '@angular/build/private';
8
5
  import { normalizeOptimization, normalizeSourceMaps, } from '@angular-devkit/build-angular/src/utils/index.js';
9
- import { createSharedMappingsPlugin } from './shared-mappings-plugin.js';
10
6
  import { createAwaitableCompilerPlugin } from './create-awaitable-compiler-plugin.js';
11
- export async function createAngularEsbuildContext(builderOptions, context, entryPoints, external, outdir, tsConfigPath, mappedPaths, cache, dev, hash = false, chunks, platform, optimizedMappings) {
7
+ import { createFederationTsConfig } from './create-federation-tsconfig.js';
8
+ export async function createAngularEsbuildContext(options) {
9
+ const { builderOptions, context, entryPoints, external, outdir, cache, dev, hash, chunks, platform, optimizedMappings, } = options;
10
+ let tsConfigPath = options.tsConfigPath;
11
+ if (!tsConfigPath) {
12
+ throw new Error('tsConfigPath is required for Angular/esbuild context creation');
13
+ }
12
14
  const workspaceRoot = context.workspaceRoot;
13
15
  const projectMetadata = await context.getProjectMetadata(context.target.project);
14
16
  const projectRoot = path.join(workspaceRoot, projectMetadata['root'] ?? '');
@@ -32,7 +34,7 @@ export async function createAngularEsbuildContext(builderOptions, context, entry
32
34
  fileReplacements[path.join(workspaceRoot, replacement.replace)] = path.join(workspaceRoot, replacement.with);
33
35
  }
34
36
  }
35
- tsConfigPath = createTsConfigForFederation(workspaceRoot, tsConfigPath, entryPoints, optimizedMappings);
37
+ tsConfigPath = createFederationTsConfig(workspaceRoot, tsConfigPath, entryPoints, optimizedMappings);
36
38
  const pluginOptions = {
37
39
  sourcemap: !!sourcemapOptions.scripts && (sourcemapOptions.hidden ? 'external' : true),
38
40
  thirdPartySourcemaps: sourcemapOptions.vendor,
@@ -95,13 +97,9 @@ export async function createAngularEsbuildContext(builderOptions, context, entry
95
97
  format: 'esm',
96
98
  target: target,
97
99
  logLimit: 0,
98
- plugins: [
99
- compilerPlugin,
100
- ...(mappedPaths && mappedPaths.length > 0 ? [createSharedMappingsPlugin(mappedPaths)] : []),
101
- commonjsPlugin(),
102
- ],
100
+ plugins: [compilerPlugin, commonjsPlugin()],
103
101
  define: {
104
- ...(!dev ? { ngDevMode: 'false' } : {}),
102
+ ngDevMode: dev ? 'true' : 'false',
105
103
  ngJitMode: 'false',
106
104
  },
107
105
  ...(builderOptions.loader ? { loader: builderOptions.loader } : {}),
@@ -120,48 +118,3 @@ async function getTailwindConfig(searchDirectories) {
120
118
  package: createRequire(tailwindConfigurationPath).resolve('tailwindcss'),
121
119
  };
122
120
  }
123
- /**
124
- * Creates a tsconfig.federation.json that includes the federation entry points.
125
- */
126
- function createTsConfigForFederation(workspaceRoot, tsConfigPath, entryPoints, optimizedMappings) {
127
- const fullTsConfigPath = path.join(workspaceRoot, tsConfigPath);
128
- const tsconfigDir = path.dirname(fullTsConfigPath);
129
- const tsconfigAsString = fs.readFileSync(fullTsConfigPath, 'utf-8');
130
- const tsconfig = JSON5.parse(tsconfigAsString);
131
- tsconfig.files = entryPoints
132
- .filter(ep => ep.fileName.startsWith('.'))
133
- .map(ep => path.relative(tsconfigDir, ep.fileName).replace(/\\\\/g, '/'));
134
- if (optimizedMappings) {
135
- const filtered = entryPoints
136
- .filter(ep => !ep.fileName.startsWith('.'))
137
- .map(ep => path.relative(tsconfigDir, ep.fileName).replace(/\\\\/g, '/'));
138
- if (!tsconfig.include) {
139
- tsconfig.include = [];
140
- }
141
- for (const ep of filtered) {
142
- if (!tsconfig.include.includes(ep)) {
143
- tsconfig.include.push(ep);
144
- }
145
- }
146
- }
147
- const content = JSON5.stringify(tsconfig, null, 2);
148
- const tsconfigFedPath = path.join(tsconfigDir, 'tsconfig.federation.json');
149
- if (!doesFileExistAndJsonEqual(tsconfigFedPath, content)) {
150
- fs.writeFileSync(tsconfigFedPath, JSON.stringify(tsconfig, null, 2));
151
- }
152
- return tsconfigFedPath;
153
- }
154
- function doesFileExistAndJsonEqual(filePath, content) {
155
- if (!fs.existsSync(filePath)) {
156
- return false;
157
- }
158
- try {
159
- const currentContent = fs.readFileSync(filePath, 'utf-8');
160
- const currentJson = JSON5.parse(currentContent);
161
- const newJson = JSON5.parse(content);
162
- return isDeepStrictEqual(currentJson, newJson);
163
- }
164
- catch {
165
- return false;
166
- }
167
- }
@@ -1,10 +1,11 @@
1
- import { type NFBuildAdapter } from '@softarc/native-federation';
1
+ import { type NFBuildAdapter, type NFBuildAdapterContext, type FederationCache } from '@softarc/native-federation';
2
2
  import * as esbuild from 'esbuild';
3
+ import type { SourceFileCache } from '@angular/build/private';
3
4
  import type { BuilderContext } from '@angular-devkit/architect';
4
5
  import type { ApplicationBuilderOptions } from '@angular/build';
5
- export interface EsbuildContextResult {
6
- ctx: esbuild.BuildContext;
6
+ export interface EsbuildContextResult extends NFBuildAdapterContext<esbuild.BuildContext> {
7
7
  pluginDisposed: Promise<void>;
8
+ cache: FederationCache<SourceFileCache>;
8
9
  }
9
- export declare function createAngularBuildAdapter(builderOptions: ApplicationBuilderOptions, context: BuilderContext): NFBuildAdapter;
10
+ export declare function createAngularBuildAdapter(ngBuilderOptions: ApplicationBuilderOptions, context: BuilderContext): NFBuildAdapter;
10
11
  //# sourceMappingURL=angular-esbuild-adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"angular-esbuild-adapter.d.ts","sourceRoot":"","sources":["../../../src/utils/angular-esbuild-adapter.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,cAAc,EAKpB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAKhE,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC;IAC1B,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AA+FD,wBAAgB,yBAAyB,CACvC,cAAc,EAAE,yBAAyB,EACzC,OAAO,EAAE,cAAc,GACtB,cAAc,CAqHhB"}
1
+ {"version":3,"file":"angular-esbuild-adapter.d.ts","sourceRoot":"","sources":["../../../src/utils/angular-esbuild-adapter.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,cAAc,EAGnB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACrB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAKhE,MAAM,WAAW,oBAAqB,SAAQ,qBAAqB,CAAC,OAAO,CAAC,YAAY,CAAC;IACvF,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,KAAK,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;CACzC;AAsCD,wBAAgB,yBAAyB,CACvC,gBAAgB,EAAE,yBAAyB,EAC3C,OAAO,EAAE,cAAc,GACtB,cAAc,CA8FhB"}
@@ -4,12 +4,7 @@ import { AbortedError } from '@softarc/native-federation/internal';
4
4
  import * as esbuild from 'esbuild';
5
5
  import { createAngularEsbuildContext } from './angular-bundler.js';
6
6
  import { createNodeModulesEsbuildContext } from './node-modules-bundler.js';
7
- async function createEsbuildContext(builderOptions, context, entryPoints, external, outdir, tsConfigPath, mappedPaths, cache, dev, isNodeModules, hash = false, chunks, platform, optimizedMappings) {
8
- if (isNodeModules) {
9
- return createNodeModulesEsbuildContext(builderOptions, context, entryPoints, external, outdir, mappedPaths, cache, dev, hash, chunks, platform);
10
- }
11
- return createAngularEsbuildContext(builderOptions, context, entryPoints, external, outdir, tsConfigPath, mappedPaths, cache, dev, hash, chunks, platform, optimizedMappings);
12
- }
7
+ import { normalizeContextOptions } from './normalize-context-options.js';
13
8
  function writeResult(result, outdir) {
14
9
  const writtenFiles = [];
15
10
  for (const outFile of result.outputFiles ?? []) {
@@ -42,7 +37,7 @@ function setNgServerMode() {
42
37
  console.error('Error patching file ', fileToPatch, '\nIs it write-protected?');
43
38
  }
44
39
  }
45
- export function createAngularBuildAdapter(builderOptions, context) {
40
+ export function createAngularBuildAdapter(ngBuilderOptions, context) {
46
41
  const bundleContextCache = new Map();
47
42
  const dispose = async (name) => {
48
43
  if (name) {
@@ -65,21 +60,23 @@ export function createAngularBuildAdapter(builderOptions, context) {
65
60
  await Promise.all(disposals);
66
61
  await esbuild.stop();
67
62
  };
68
- const setup = async (options) => {
69
- const { entryPoints, tsConfigPath, external, outdir, mappedPaths, bundleName, isNodeModules, dev, chunks, hash, platform, optimizedMappings, cache, } = options;
63
+ const setup = async (name, adapterOptions) => {
70
64
  setNgServerMode();
71
- if (bundleContextCache.has(bundleName)) {
65
+ if (bundleContextCache.has(name)) {
72
66
  return;
73
67
  }
74
- const { ctx, pluginDisposed } = await createEsbuildContext(builderOptions, context, entryPoints, external, outdir, tsConfigPath, mappedPaths, cache, dev, isNodeModules, hash, chunks, platform, optimizedMappings);
75
- bundleContextCache.set(bundleName, {
68
+ const normalizedOptions = normalizeContextOptions(ngBuilderOptions, context, adapterOptions);
69
+ const { ctx, pluginDisposed } = normalizedOptions.isMappingOrExposed
70
+ ? await createAngularEsbuildContext(normalizedOptions)
71
+ : await createNodeModulesEsbuildContext(normalizedOptions);
72
+ bundleContextCache.set(name, {
76
73
  ctx,
77
74
  pluginDisposed,
78
- outdir,
79
- cache,
80
- isNodeModules,
81
- dev: !!dev,
82
- name: bundleName,
75
+ outdir: normalizedOptions.outdir,
76
+ cache: normalizedOptions.cache,
77
+ isMappingOrExposed: normalizedOptions.isMappingOrExposed,
78
+ dev: normalizedOptions.dev,
79
+ name,
83
80
  });
84
81
  };
85
82
  const build = async (name, opts = {}) => {
@@ -91,8 +88,8 @@ export function createAngularBuildAdapter(builderOptions, context) {
91
88
  throw new AbortedError('[build] Aborted before rebuild');
92
89
  }
93
90
  try {
94
- if (opts.files) {
95
- bundleContext.cache.bundlerCache.invalidate(new Set(opts.files));
91
+ if (opts.modifiedFiles) {
92
+ bundleContext.cache.bundlerCache.invalidate(new Set(opts.modifiedFiles));
96
93
  }
97
94
  const result = await bundleContext.ctx.rebuild();
98
95
  const writtenFiles = writeResult(result, bundleContext.outdir);
@@ -1 +1 @@
1
- {"version":3,"file":"angular-locales.d.ts","sourceRoot":"","sources":["../../../src/utils/angular-locales.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAE/E,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,cAAc,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,qEAuBzD"}
1
+ {"version":3,"file":"angular-locales.d.ts","sourceRoot":"","sources":["../../../src/utils/angular-locales.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAE/E,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,cAAc,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,qEA0BzD"}
@@ -0,0 +1,6 @@
1
+ import type { EntryPoint } from '@softarc/native-federation';
2
+ /**
3
+ * Creates a tsconfig.federation.json that includes the federation entry points.
4
+ */
5
+ export declare function createFederationTsConfig(workspaceRoot: string, tsConfigPath: string, entryPoints: EntryPoint[], optimizedMappings?: boolean): string;
6
+ //# sourceMappingURL=create-federation-tsconfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-federation-tsconfig.d.ts","sourceRoot":"","sources":["../../../src/utils/create-federation-tsconfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAM7D;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,UAAU,EAAE,EACzB,iBAAiB,CAAC,EAAE,OAAO,GAC1B,MAAM,CAoCR"}