@angular-architects/native-federation-v4 21.1.6 → 21.1.8

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 (55) hide show
  1. package/collection.json +5 -0
  2. package/migration-collection.json +6 -0
  3. package/package.json +11 -3
  4. package/src/builders/build/builder.d.ts.map +1 -1
  5. package/src/builders/build/builder.js +112 -95
  6. package/src/builders/build/schema.d.ts +3 -4
  7. package/src/builders/build/schema.json +8 -26
  8. package/src/builders/build/setup-builder-env-variables.js +3 -1
  9. package/src/config/angular-skip-list.d.ts +3 -0
  10. package/src/config/angular-skip-list.d.ts.map +1 -0
  11. package/src/config/angular-skip-list.js +13 -0
  12. package/src/config/share-utils.d.ts +9 -0
  13. package/src/config/share-utils.d.ts.map +1 -0
  14. package/src/config/share-utils.js +32 -0
  15. package/src/config.d.ts +2 -2
  16. package/src/config.d.ts.map +1 -1
  17. package/src/config.js +2 -2
  18. package/src/schematics/init/files/federation.config.js__tmpl__ +19 -7
  19. package/src/schematics/init/schema.d.ts +0 -1
  20. package/src/schematics/init/schema.json +2 -6
  21. package/src/schematics/init/schematic.d.ts.map +1 -1
  22. package/src/schematics/init/schematic.js +50 -25
  23. package/src/schematics/update-v4/schema.d.ts +4 -0
  24. package/src/schematics/update-v4/schema.json +23 -0
  25. package/src/schematics/update-v4/schematic.d.ts +4 -0
  26. package/src/schematics/update-v4/schematic.d.ts.map +1 -0
  27. package/src/schematics/update-v4/schematic.js +225 -0
  28. package/src/utils/angular-bundler.d.ts +7 -0
  29. package/src/utils/angular-bundler.d.ts.map +1 -0
  30. package/src/utils/angular-bundler.js +120 -0
  31. package/src/utils/angular-esbuild-adapter.d.ts +8 -3
  32. package/src/utils/angular-esbuild-adapter.d.ts.map +1 -1
  33. package/src/utils/angular-esbuild-adapter.js +63 -245
  34. package/src/utils/angular-locales.d.ts.map +1 -1
  35. package/src/utils/create-federation-tsconfig.d.ts +6 -0
  36. package/src/utils/create-federation-tsconfig.d.ts.map +1 -0
  37. package/src/utils/create-federation-tsconfig.js +49 -0
  38. package/src/utils/get-fallback-platform.d.ts +3 -0
  39. package/src/utils/get-fallback-platform.d.ts.map +1 -0
  40. package/src/utils/get-fallback-platform.js +13 -0
  41. package/src/utils/node-modules-bundler.d.ts +7 -0
  42. package/src/utils/node-modules-bundler.d.ts.map +1 -0
  43. package/src/utils/node-modules-bundler.js +109 -0
  44. package/src/utils/normalize-context-options.d.ts +23 -0
  45. package/src/utils/normalize-context-options.d.ts.map +1 -0
  46. package/src/utils/normalize-context-options.js +18 -0
  47. package/src/utils/shared-mappings-plugin.d.ts +2 -2
  48. package/src/utils/shared-mappings-plugin.d.ts.map +1 -1
  49. package/src/utils/shared-mappings-plugin.js +4 -4
  50. package/src/utils/create-compiler-options.d.ts +0 -6
  51. package/src/utils/create-compiler-options.d.ts.map +0 -1
  52. package/src/utils/create-compiler-options.js +0 -41
  53. package/src/utils/mem-resuts.d.ts +0 -29
  54. package/src/utils/mem-resuts.d.ts.map +0 -1
  55. package/src/utils/mem-resuts.js +0 -50
@@ -1,74 +1,98 @@
1
- import { logger, AbortedError } from '@softarc/native-federation/internal';
2
- import * as esbuild from 'esbuild';
3
- import { transformSupportedBrowsersToTargets, getSupportedBrowsers, generateSearchDirectories, findTailwindConfiguration, loadPostcssConfiguration, } from '@angular/build/private';
4
- import { createCompilerPluginOptions } from './create-compiler-options.js';
5
- import { normalizeOptimization, normalizeSourceMaps, } from '@angular-devkit/build-angular/src/utils/index.js';
6
- import { createRequire } from 'node:module';
7
1
  import * as fs from 'fs';
8
2
  import * as path from 'path';
9
- import { createSharedMappingsPlugin } from './shared-mappings-plugin.js';
10
- import { transformAsync } from '@babel/core';
11
- import JSON5 from 'json5';
12
- import { isDeepStrictEqual } from 'node:util';
13
- import { createAwaitableCompilerPlugin } from './create-awaitable-compiler-plugin.js';
14
- export function createAngularBuildAdapter(builderOptions, context) {
15
- const contextCache = new Map();
3
+ import { AbortedError } from '@softarc/native-federation/internal';
4
+ import * as esbuild from 'esbuild';
5
+ import { createAngularEsbuildContext } from './angular-bundler.js';
6
+ import { createNodeModulesEsbuildContext } from './node-modules-bundler.js';
7
+ import { normalizeContextOptions } from './normalize-context-options.js';
8
+ function writeResult(result, outdir) {
9
+ const writtenFiles = [];
10
+ for (const outFile of result.outputFiles ?? []) {
11
+ const fileName = path.basename(outFile.path);
12
+ const filePath = path.join(outdir, fileName);
13
+ fs.writeFileSync(filePath, outFile.text);
14
+ writtenFiles.push(filePath);
15
+ }
16
+ return writtenFiles;
17
+ }
18
+ /**
19
+ * Patches @angular/core to infer ngServerMode at runtime.
20
+ * Usually, ngServerMode is set during bundling. However, we need to infer this
21
+ * value at runtime as we are using the same shared bundle for @angular/core
22
+ * on the server and in the browser.
23
+ */
24
+ function setNgServerMode() {
25
+ const fileToPatch = 'node_modules/@angular/core/fesm2022/core.mjs';
26
+ const lineToAdd = `if (typeof globalThis.ngServerMode ==='undefined') globalThis.ngServerMode = (typeof window === 'undefined') ? true : false;`;
27
+ try {
28
+ if (fs.existsSync(fileToPatch)) {
29
+ let content = fs.readFileSync(fileToPatch, 'utf-8');
30
+ if (!content.includes(lineToAdd)) {
31
+ content = lineToAdd + '\n' + content;
32
+ fs.writeFileSync(fileToPatch, content);
33
+ }
34
+ }
35
+ }
36
+ catch {
37
+ console.error('Error patching file ', fileToPatch, '\nIs it write-protected?');
38
+ }
39
+ }
40
+ export function createAngularBuildAdapter(ngBuilderOptions, context) {
41
+ const bundleContextCache = new Map();
16
42
  const dispose = async (name) => {
17
43
  if (name) {
18
- if (!contextCache.has(name))
44
+ if (!bundleContextCache.has(name))
19
45
  throw new Error(`Could not dispose of non-existing build '${name}'`);
20
- const entry = contextCache.get(name);
46
+ const entry = bundleContextCache.get(name);
21
47
  await entry.ctx.dispose();
22
48
  await entry.pluginDisposed;
23
- contextCache.delete(name);
49
+ bundleContextCache.delete(name);
24
50
  return;
25
51
  }
26
- // Dispose all if no specific build provided
27
52
  const disposals = [];
28
- for (const [, entry] of contextCache) {
53
+ for (const [, entry] of bundleContextCache) {
29
54
  disposals.push((async () => {
30
55
  await entry.ctx.dispose();
31
56
  await entry.pluginDisposed;
32
57
  })());
33
58
  }
34
- contextCache.clear();
59
+ bundleContextCache.clear();
35
60
  await Promise.all(disposals);
61
+ await esbuild.stop();
36
62
  };
37
- const setup = async (options) => {
38
- const { entryPoints, tsConfigPath, external, outdir, mappedPaths, bundleName, isNodeModules, dev, chunks, hash, platform, optimizedMappings, cache, } = options;
63
+ const setup = async (name, adapterOptions) => {
39
64
  setNgServerMode();
40
- if (contextCache.has(bundleName)) {
65
+ if (bundleContextCache.has(name)) {
41
66
  return;
42
67
  }
43
- const { ctx, pluginDisposed } = await createEsbuildContext(builderOptions, context, entryPoints, external, outdir, tsConfigPath, mappedPaths, cache.bundlerCache, dev, isNodeModules, hash, chunks, platform, optimizedMappings);
44
- contextCache.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, {
45
73
  ctx,
46
74
  pluginDisposed,
47
- outdir,
48
- isNodeModules,
49
- dev: !!dev,
50
- name: bundleName,
51
- entryPoints,
52
- workspaceRoot: context.workspaceRoot,
75
+ outdir: normalizedOptions.outdir,
76
+ cache: normalizedOptions.cache,
77
+ isMappingOrExposed: normalizedOptions.isMappingOrExposed,
78
+ dev: normalizedOptions.dev,
79
+ name,
53
80
  });
54
81
  };
55
82
  const build = async (name, opts = {}) => {
56
- const cached = contextCache.get(name);
57
- if (!cached) {
83
+ const bundleContext = bundleContextCache.get(name);
84
+ if (!bundleContext) {
58
85
  throw new Error(`No context found for build "${name}". Call setup() first.`);
59
86
  }
60
87
  if (opts?.signal?.aborted) {
61
88
  throw new AbortedError('[build] Aborted before rebuild');
62
89
  }
63
90
  try {
64
- const result = await cached.ctx.rebuild();
65
- const writtenFiles = writeResult(result, cached.outdir);
66
- if (cached.isNodeModules) {
67
- const scriptFiles = writtenFiles.filter(f => f.endsWith('.js') || f.endsWith('.mjs'));
68
- for (const file of scriptFiles) {
69
- await link(file, cached.dev);
70
- }
91
+ if (opts.files) {
92
+ bundleContext.cache.bundlerCache.invalidate(new Set(opts.files));
71
93
  }
94
+ const result = await bundleContext.ctx.rebuild();
95
+ const writtenFiles = writeResult(result, bundleContext.outdir);
72
96
  return writtenFiles.map(fileName => ({ fileName }));
73
97
  }
74
98
  catch (error) {
@@ -80,209 +104,3 @@ export function createAngularBuildAdapter(builderOptions, context) {
80
104
  };
81
105
  return { setup, build, dispose };
82
106
  }
83
- async function link(outfile, dev) {
84
- const code = fs.readFileSync(outfile, 'utf-8');
85
- try {
86
- const linkerEsm = await loadEsmModule('@angular/compiler-cli/linker/babel');
87
- const linker = linkerEsm.default;
88
- const result = await transformAsync(code, {
89
- filename: outfile,
90
- compact: !dev,
91
- configFile: false,
92
- babelrc: false,
93
- minified: !dev,
94
- browserslistConfigFile: false,
95
- plugins: [linker],
96
- });
97
- if (!result)
98
- logger.warn(`File ${outfile} could not be linked.`);
99
- if (!result?.code) {
100
- logger.warn(`File ${outfile} seems to be empty.`);
101
- return;
102
- }
103
- fs.writeFileSync(outfile, result.code, 'utf-8');
104
- }
105
- catch (e) {
106
- logger.error('error linking');
107
- if (fs.existsSync(`${outfile}.error`)) {
108
- fs.unlinkSync(`${outfile}.error`);
109
- }
110
- fs.renameSync(outfile, `${outfile}.error`);
111
- throw e;
112
- }
113
- }
114
- async function createEsbuildContext(builderOptions, context, entryPoints, external, outdir, tsConfigPath, mappedPaths, sourceFileCache, dev, isNodeModules, hash = false, chunks, platform, optimizedMappings) {
115
- const workspaceRoot = context.workspaceRoot;
116
- const projectMetadata = await context.getProjectMetadata(context.target.project);
117
- const projectRoot = path.join(workspaceRoot, projectMetadata['root'] ?? '');
118
- const browsers = getSupportedBrowsers(projectRoot, context.logger);
119
- const target = transformSupportedBrowsersToTargets(browsers);
120
- const optimizationOptions = normalizeOptimization(builderOptions.optimization);
121
- const sourcemapOptions = normalizeSourceMaps(builderOptions.sourceMap);
122
- const searchDirectories = await generateSearchDirectories([projectRoot, workspaceRoot]);
123
- const postcssConfiguration = await loadPostcssConfiguration(searchDirectories);
124
- const tailwindConfiguration = postcssConfiguration
125
- ? undefined
126
- : await getTailwindConfig(searchDirectories);
127
- const outputNames = {
128
- bundles: '[name]',
129
- media: 'media/[name]',
130
- };
131
- let fileReplacements;
132
- if (builderOptions.fileReplacements) {
133
- for (const replacement of builderOptions.fileReplacements) {
134
- fileReplacements ??= {};
135
- fileReplacements[path.join(workspaceRoot, replacement.replace)] = path.join(workspaceRoot, replacement.with);
136
- }
137
- }
138
- if (!optimizedMappings) {
139
- tsConfigPath = createTsConfigForFederation(workspaceRoot, tsConfigPath, entryPoints);
140
- }
141
- const pluginOptions = createCompilerPluginOptions({
142
- workspaceRoot,
143
- optimizationOptions,
144
- sourcemapOptions,
145
- tsconfig: tsConfigPath,
146
- outputNames,
147
- fileReplacements,
148
- externalDependencies: external,
149
- preserveSymlinks: builderOptions.preserveSymlinks,
150
- stylePreprocessorOptions: builderOptions.stylePreprocessorOptions,
151
- advancedOptimizations: !dev,
152
- inlineStyleLanguage: builderOptions.inlineStyleLanguage,
153
- jit: false,
154
- tailwindConfiguration,
155
- postcssConfiguration,
156
- incremental: !isNodeModules,
157
- }, target, sourceFileCache);
158
- const commonjsPluginModule = await import('@chialab/esbuild-plugin-commonjs');
159
- const commonjsPlugin = commonjsPluginModule.default;
160
- pluginOptions.styleOptions.externalDependencies = [];
161
- const [compilerPlugin, pluginDisposed] = createAwaitableCompilerPlugin(pluginOptions.pluginOptions, pluginOptions.styleOptions);
162
- const config = {
163
- entryPoints: entryPoints.map(ep => ({
164
- in: ep.fileName,
165
- out: path.parse(ep.outName).name,
166
- })),
167
- outdir,
168
- entryNames: hash ? '[name]-[hash]' : '[name]',
169
- write: false,
170
- external,
171
- logLevel: 'warning',
172
- bundle: true,
173
- sourcemap: sourcemapOptions.scripts,
174
- minify: !dev,
175
- supported: {
176
- 'async-await': false,
177
- 'object-rest-spread': false,
178
- },
179
- splitting: chunks,
180
- platform: platform ?? 'browser',
181
- format: 'esm',
182
- target: target,
183
- logLimit: isNodeModules ? 1 : 0,
184
- plugins: [
185
- compilerPlugin,
186
- ...(mappedPaths && mappedPaths.length > 0 ? [createSharedMappingsPlugin(mappedPaths)] : []),
187
- commonjsPlugin(),
188
- ],
189
- define: {
190
- ...(!dev ? { ngDevMode: 'false' } : {}),
191
- ngJitMode: 'false',
192
- },
193
- ...(builderOptions.loader ? { loader: builderOptions.loader } : {}),
194
- resolveExtensions: ['.ts', '.tsx', '.mjs', '.js', '.cjs'],
195
- };
196
- const ctx = await esbuild.context(config);
197
- return { ctx, pluginDisposed };
198
- }
199
- async function getTailwindConfig(searchDirectories) {
200
- const tailwindConfigurationPath = findTailwindConfiguration(searchDirectories);
201
- if (!tailwindConfigurationPath) {
202
- return undefined;
203
- }
204
- return {
205
- file: tailwindConfigurationPath,
206
- package: createRequire(tailwindConfigurationPath).resolve('tailwindcss'),
207
- };
208
- }
209
- function createTsConfigForFederation(workspaceRoot, tsConfigPath, entryPoints) {
210
- const fullTsConfigPath = path.join(workspaceRoot, tsConfigPath);
211
- const tsconfigDir = path.dirname(fullTsConfigPath);
212
- const filtered = entryPoints
213
- .filter(ep => !ep.fileName.includes('/node_modules/') && !ep.fileName.startsWith('.'))
214
- .map(ep => path.relative(tsconfigDir, ep.fileName).replace(/\\\\/g, '/'));
215
- const tsconfigAsString = fs.readFileSync(fullTsConfigPath, 'utf-8');
216
- const tsconfig = JSON5.parse(tsconfigAsString);
217
- if (!tsconfig.include) {
218
- tsconfig.include = [];
219
- }
220
- for (const ep of filtered) {
221
- if (!tsconfig.include.includes(ep)) {
222
- tsconfig.include.push(ep);
223
- }
224
- }
225
- const content = JSON5.stringify(tsconfig, null, 2);
226
- const tsconfigFedPath = path.join(tsconfigDir, 'tsconfig.federation.json');
227
- if (!doesFileExistAndJsonEqual(tsconfigFedPath, content)) {
228
- fs.writeFileSync(tsconfigFedPath, JSON.stringify(tsconfig, null, 2));
229
- }
230
- tsConfigPath = tsconfigFedPath;
231
- return tsConfigPath;
232
- }
233
- /**
234
- * Checks if a file exists and if its content is equal to the provided content.
235
- * If the file does not exist, it returns false.
236
- * If the file or its content is invalid JSON, it returns false.
237
- * @param {string} path - The path to the file
238
- * @param {string} content - The content to compare with
239
- * @returns {boolean} - Returns true if the file exists and its content is equal to the provided content
240
- */
241
- function doesFileExistAndJsonEqual(path, content) {
242
- if (!fs.existsSync(path)) {
243
- return false;
244
- }
245
- try {
246
- const currentContent = fs.readFileSync(path, 'utf-8');
247
- const currentJson = JSON5.parse(currentContent);
248
- const newJson = JSON5.parse(content);
249
- return isDeepStrictEqual(currentJson, newJson);
250
- }
251
- catch {
252
- return false;
253
- }
254
- }
255
- function writeResult(result, outdir) {
256
- const writtenFiles = [];
257
- for (const outFile of result.outputFiles ?? []) {
258
- const fileName = path.basename(outFile.path);
259
- const filePath = path.join(outdir, fileName);
260
- fs.writeFileSync(filePath, outFile.text);
261
- writtenFiles.push(filePath);
262
- }
263
- return writtenFiles;
264
- }
265
- export function loadEsmModule(modulePath) {
266
- return new Function('modulePath', `return import(modulePath);`)(modulePath);
267
- }
268
- //
269
- // Usually, ngServerMode is set during bundling. However, we need to infer this
270
- // value at runtime as we are using the same shared bundle for @angular/core
271
- // on the server and in the browser.
272
- //
273
- function setNgServerMode() {
274
- const fileToPatch = 'node_modules/@angular/core/fesm2022/core.mjs';
275
- const lineToAdd = `if (typeof globalThis.ngServerMode ==='undefined') globalThis.ngServerMode = (typeof window === 'undefined') ? true : false;`;
276
- try {
277
- if (fs.existsSync(fileToPatch)) {
278
- let content = fs.readFileSync(fileToPatch, 'utf-8');
279
- if (!content.includes(lineToAdd)) {
280
- content = lineToAdd + '\n' + content;
281
- fs.writeFileSync(fileToPatch, content);
282
- }
283
- }
284
- }
285
- catch {
286
- console.error('Error patching file ', fileToPatch, '\nIs it write-protected?');
287
- }
288
- }
@@ -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"}
@@ -0,0 +1,49 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import JSON5 from 'json5';
4
+ import { isDeepStrictEqual } from 'util';
5
+ /**
6
+ * Creates a tsconfig.federation.json that includes the federation entry points.
7
+ */
8
+ export function createFederationTsConfig(workspaceRoot, tsConfigPath, entryPoints, optimizedMappings) {
9
+ const fullTsConfigPath = path.join(workspaceRoot, tsConfigPath);
10
+ const tsconfigDir = path.dirname(fullTsConfigPath);
11
+ const tsconfigAsString = fs.readFileSync(fullTsConfigPath, 'utf-8');
12
+ const tsconfig = JSON5.parse(tsconfigAsString);
13
+ tsconfig.files = entryPoints
14
+ .filter(ep => ep.fileName.startsWith('.'))
15
+ .map(ep => path.relative(tsconfigDir, ep.fileName).replace(/\\\\/g, '/'));
16
+ if (optimizedMappings) {
17
+ const filtered = entryPoints
18
+ .filter(ep => !ep.fileName.startsWith('.'))
19
+ .map(ep => path.relative(tsconfigDir, ep.fileName).replace(/\\\\/g, '/'));
20
+ if (!tsconfig.include) {
21
+ tsconfig.include = [];
22
+ }
23
+ for (const ep of filtered) {
24
+ if (!tsconfig.include.includes(ep)) {
25
+ tsconfig.include.push(ep);
26
+ }
27
+ }
28
+ }
29
+ const content = JSON5.stringify(tsconfig, null, 2);
30
+ const tsconfigFedPath = path.join(tsconfigDir, 'tsconfig.federation.json');
31
+ if (!doesFileExistAndJsonEqual(tsconfigFedPath, content)) {
32
+ fs.writeFileSync(tsconfigFedPath, JSON.stringify(tsconfig, null, 2));
33
+ }
34
+ return tsconfigFedPath;
35
+ }
36
+ function doesFileExistAndJsonEqual(filePath, content) {
37
+ if (!fs.existsSync(filePath)) {
38
+ return false;
39
+ }
40
+ try {
41
+ const currentContent = fs.readFileSync(filePath, 'utf-8');
42
+ const currentJson = JSON5.parse(currentContent);
43
+ const newJson = JSON5.parse(content);
44
+ return isDeepStrictEqual(currentJson, newJson);
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ }
@@ -0,0 +1,3 @@
1
+ export declare const DEFAULT_SERVER_DEPS_LIST: string[];
2
+ export declare function getDefaultPlatform(cur: string): 'browser' | 'node';
3
+ //# sourceMappingURL=get-fallback-platform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-fallback-platform.d.ts","sourceRoot":"","sources":["../../../src/utils/get-fallback-platform.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,EAAE,MAAM,EAI5C,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAMlE"}
@@ -0,0 +1,13 @@
1
+ export const DEFAULT_SERVER_DEPS_LIST = [
2
+ '@angular/platform-server',
3
+ '@angular/platform-server/init',
4
+ '@angular/ssr',
5
+ ];
6
+ export function getDefaultPlatform(cur) {
7
+ if (DEFAULT_SERVER_DEPS_LIST.find(e => cur.startsWith(e))) {
8
+ return 'node';
9
+ }
10
+ else {
11
+ return 'browser';
12
+ }
13
+ }
@@ -0,0 +1,7 @@
1
+ import * as esbuild from 'esbuild';
2
+ import type { NormalizedContextOptions } from './normalize-context-options.js';
3
+ export declare function createNodeModulesEsbuildContext(options: NormalizedContextOptions): Promise<{
4
+ ctx: esbuild.BuildContext;
5
+ pluginDisposed: Promise<void>;
6
+ }>;
7
+ //# sourceMappingURL=node-modules-bundler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-modules-bundler.d.ts","sourceRoot":"","sources":["../../../src/utils/node-modules-bundler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAanC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAiE/E,wBAAsB,+BAA+B,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC;IAChG,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC;IAC1B,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B,CAAC,CAqFD"}
@@ -0,0 +1,109 @@
1
+ import * as esbuild from 'esbuild';
2
+ import * as path from 'path';
3
+ import * as fs from 'fs';
4
+ import { transformSupportedBrowsersToTargets, getSupportedBrowsers, JavaScriptTransformer, Cache, } from '@angular/build/private';
5
+ import { normalizeSourceMaps } from '@angular-devkit/build-angular/src/utils/index.js';
6
+ const LINKER_DECLARATION_PREFIX = 'ɵɵngDeclare';
7
+ /**
8
+ * Excludes @angular/core and @angular/compiler which define the declarations
9
+ * and would cause false positives.
10
+ */
11
+ function requiresLinking(filePath, source) {
12
+ if (/[\\/]@angular[\\/](?:compiler|core)[\\/]/.test(filePath)) {
13
+ return false;
14
+ }
15
+ return source.includes(LINKER_DECLARATION_PREFIX);
16
+ }
17
+ /**
18
+ * Creates an esbuild plugin that applies the Angular linker to partially compiled
19
+ * Angular libraries like a design system.
20
+ *
21
+ * Uses Angular's JavaScriptTransformer which handles linking internally.
22
+ */
23
+ function createAngularLinkerPlugin(jsTransformer, advancedOptimizations) {
24
+ return {
25
+ name: 'angular-linker',
26
+ setup(build) {
27
+ build.onLoad({ filter: /\.m?js$/ }, async (args) => {
28
+ const contents = await fs.promises.readFile(args.path, 'utf-8');
29
+ const needsLinking = requiresLinking(args.path, contents);
30
+ if (!needsLinking && !advancedOptimizations) {
31
+ return null;
32
+ }
33
+ const result = await jsTransformer.transformData(args.path, contents, !needsLinking, undefined);
34
+ return {
35
+ contents: Buffer.from(result).toString('utf-8'),
36
+ loader: 'js',
37
+ };
38
+ });
39
+ },
40
+ };
41
+ }
42
+ const jsTransformerCacheStores = new Map();
43
+ function getOrCreateJsTransformerCacheStore(cachePath) {
44
+ let store = jsTransformerCacheStores.get(cachePath);
45
+ if (!store) {
46
+ store = new Map();
47
+ jsTransformerCacheStores.set(cachePath, store);
48
+ }
49
+ return store;
50
+ }
51
+ export async function createNodeModulesEsbuildContext(options) {
52
+ const { builderOptions, context, entryPoints, external, outdir, cache, dev, hash, chunks, platform, } = options;
53
+ const workspaceRoot = context.workspaceRoot;
54
+ const projectMetadata = await context.getProjectMetadata(context.target.project);
55
+ const projectRoot = path.join(workspaceRoot, projectMetadata['root'] ?? '');
56
+ const browsers = getSupportedBrowsers(projectRoot, context.logger);
57
+ const target = transformSupportedBrowsersToTargets(browsers);
58
+ const sourcemapOptions = normalizeSourceMaps(builderOptions.sourceMap);
59
+ const commonjsPluginModule = await import('@chialab/esbuild-plugin-commonjs');
60
+ const commonjsPlugin = commonjsPluginModule.default;
61
+ // Create JavaScriptTransformer for handling Angular partial compilation linking
62
+ const advancedOptimizations = !dev;
63
+ const jsTransformerCacheStore = getOrCreateJsTransformerCacheStore(cache.cachePath);
64
+ const jsTransformerCache = new Cache(jsTransformerCacheStore, 'jstransformer');
65
+ const jsTransformer = new JavaScriptTransformer({
66
+ sourcemap: !!sourcemapOptions.scripts,
67
+ thirdPartySourcemaps: false,
68
+ advancedOptimizations,
69
+ jit: false,
70
+ }, 1, // maxThreads - keep low for node_modules bundling
71
+ jsTransformerCache);
72
+ const config = {
73
+ entryPoints: entryPoints.map(ep => ({
74
+ in: ep.fileName,
75
+ out: path.parse(ep.outName).name,
76
+ })),
77
+ outdir,
78
+ entryNames: hash ? '[name]-[hash]' : '[name]',
79
+ write: false,
80
+ external,
81
+ logLevel: 'warning',
82
+ bundle: true,
83
+ sourcemap: sourcemapOptions.scripts,
84
+ minify: !dev,
85
+ supported: {
86
+ 'async-await': false,
87
+ 'object-rest-spread': false,
88
+ },
89
+ splitting: chunks,
90
+ platform: platform ?? 'browser',
91
+ format: 'esm',
92
+ target: target,
93
+ logLimit: 1,
94
+ plugins: [createAngularLinkerPlugin(jsTransformer, advancedOptimizations), commonjsPlugin()],
95
+ define: {
96
+ ngDevMode: dev ? 'true' : 'false',
97
+ ngJitMode: 'false',
98
+ },
99
+ ...(builderOptions.loader ? { loader: builderOptions.loader } : {}),
100
+ resolveExtensions: ['.mjs', '.js', '.cjs'],
101
+ };
102
+ const ctx = await esbuild.context(config);
103
+ const originalDispose = ctx.dispose.bind(ctx);
104
+ ctx.dispose = async () => {
105
+ await originalDispose();
106
+ await jsTransformer.close();
107
+ };
108
+ return { ctx, pluginDisposed: Promise.resolve() };
109
+ }
@@ -0,0 +1,23 @@
1
+ import type { ApplicationBuilderOptions } from '@angular/build';
2
+ import type { BuilderContext } from '@angular-devkit/architect';
3
+ import type { SourceFileCache } from '@angular/build/private';
4
+ import type { FederationCache, EntryPoint, NFBuildAdapterOptions } from '@softarc/native-federation';
5
+ import type { PathToImport } from '@softarc/native-federation/internal';
6
+ export interface NormalizedContextOptions {
7
+ builderOptions: ApplicationBuilderOptions;
8
+ context: BuilderContext;
9
+ entryPoints: EntryPoint[];
10
+ external: string[];
11
+ outdir: string;
12
+ tsConfigPath?: string;
13
+ mappedPaths: PathToImport;
14
+ cache: FederationCache<SourceFileCache>;
15
+ dev: boolean;
16
+ isMappingOrExposed: boolean;
17
+ hash: boolean;
18
+ chunks?: boolean;
19
+ platform?: 'browser' | 'node';
20
+ optimizedMappings: boolean;
21
+ }
22
+ export declare function normalizeContextOptions(builderOptions: ApplicationBuilderOptions, context: BuilderContext, adapterOptions: NFBuildAdapterOptions<SourceFileCache>): NormalizedContextOptions;
23
+ //# sourceMappingURL=normalize-context-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-context-options.d.ts","sourceRoot":"","sources":["../../../src/utils/normalize-context-options.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,EACV,eAAe,EACf,UAAU,EACV,qBAAqB,EACtB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAExE,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,yBAAyB,CAAC;IAC1C,OAAO,EAAE,cAAc,CAAC;IACxB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,YAAY,CAAC;IAC1B,KAAK,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;IACxC,GAAG,EAAE,OAAO,CAAC;IACb,kBAAkB,EAAE,OAAO,CAAC;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC9B,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,yBAAyB,EACzC,OAAO,EAAE,cAAc,EACvB,cAAc,EAAE,qBAAqB,CAAC,eAAe,CAAC,GACrD,wBAAwB,CAiB1B"}
@@ -0,0 +1,18 @@
1
+ export function normalizeContextOptions(builderOptions, context, adapterOptions) {
2
+ return {
3
+ builderOptions,
4
+ context,
5
+ entryPoints: adapterOptions.entryPoints,
6
+ external: adapterOptions.external,
7
+ outdir: adapterOptions.outdir,
8
+ tsConfigPath: adapterOptions.tsConfigPath,
9
+ mappedPaths: adapterOptions.mappedPaths,
10
+ cache: adapterOptions.cache,
11
+ dev: !!adapterOptions.dev,
12
+ isMappingOrExposed: !!adapterOptions.isMappingOrExposed,
13
+ hash: !!adapterOptions.hash,
14
+ chunks: adapterOptions.chunks,
15
+ platform: adapterOptions.platform,
16
+ optimizedMappings: !!adapterOptions.optimizedMappings,
17
+ };
18
+ }
@@ -1,4 +1,4 @@
1
1
  import type { Plugin } from 'esbuild';
2
- import type { MappedPath } from '@softarc/native-federation/internal';
3
- export declare function createSharedMappingsPlugin(mappedPaths: MappedPath[]): Plugin;
2
+ import type { PathToImport } from '@softarc/native-federation/internal';
3
+ export declare function createSharedMappingsPlugin(mappedPaths: PathToImport): Plugin;
4
4
  //# sourceMappingURL=shared-mappings-plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared-mappings-plugin.d.ts","sourceRoot":"","sources":["../../../src/utils/shared-mappings-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,SAAS,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAEtE,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM,CA8B5E"}
1
+ {"version":3,"file":"shared-mappings-plugin.d.ts","sourceRoot":"","sources":["../../../src/utils/shared-mappings-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,SAAS,CAAC;AAEnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAExE,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,YAAY,GAAG,MAAM,CA8B5E"}
@@ -4,20 +4,20 @@ export function createSharedMappingsPlugin(mappedPaths) {
4
4
  name: 'custom',
5
5
  setup(build) {
6
6
  build.onResolve({ filter: /^[.]/ }, async (args) => {
7
- let mappedPath = null;
7
+ let mappedPath = undefined;
8
8
  let isSelf = false;
9
9
  if (args.kind === 'import-statement') {
10
10
  const importPath = path.join(args.resolveDir, args.path);
11
11
  if (mappedPaths) {
12
- mappedPath = mappedPaths.find(p => importPath.startsWith(path.dirname(p.path))) ?? null;
12
+ mappedPath = Object.keys(mappedPaths).find(p => importPath.startsWith(path.dirname(p)));
13
13
  }
14
14
  }
15
15
  if (mappedPath) {
16
- isSelf = args.importer.startsWith(path.dirname(mappedPath.path));
16
+ isSelf = args.importer.startsWith(path.dirname(mappedPath));
17
17
  }
18
18
  if (mappedPath && !isSelf) {
19
19
  return {
20
- path: mappedPath.key,
20
+ path: mappedPaths[mappedPath],
21
21
  external: true,
22
22
  };
23
23
  }
@@ -1,6 +0,0 @@
1
- import { type SourceFileCache } from '@angular/build/private';
2
- export declare function createCompilerPluginOptions(options: any, target: string[], sourceFileCache?: SourceFileCache): {
3
- pluginOptions: any[0];
4
- styleOptions: any[1];
5
- };
6
- //# sourceMappingURL=create-compiler-options.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-compiler-options.d.ts","sourceRoot":"","sources":["../../../src/utils/create-compiler-options.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE,MAAM,EAAE,EAChB,eAAe,CAAC,EAAE,eAAe,GAChC;IACD,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACtB,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;CACtB,CAwDA"}