@nx/angular-rspack 23.1.0 → 23.1.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.
Files changed (36) hide show
  1. package/dist/lib/config/config-utils/browser-config.d.ts +4 -1
  2. package/dist/lib/config/config-utils/browser-config.d.ts.map +1 -1
  3. package/dist/lib/config/config-utils/browser-config.js +5 -18
  4. package/dist/lib/config/config-utils/server-config.d.ts +4 -1
  5. package/dist/lib/config/config-utils/server-config.d.ts.map +1 -1
  6. package/dist/lib/config/config-utils/server-config.js +10 -18
  7. package/dist/lib/config/config-utils/swc-transpilation.d.ts +16 -0
  8. package/dist/lib/config/config-utils/swc-transpilation.d.ts.map +1 -0
  9. package/dist/lib/config/config-utils/swc-transpilation.js +50 -0
  10. package/dist/lib/config/create-config.d.ts.map +1 -1
  11. package/dist/lib/config/create-config.js +20 -2
  12. package/dist/lib/models/augmented-compilation.d.ts +6 -0
  13. package/dist/lib/models/augmented-compilation.d.ts.map +1 -1
  14. package/dist/lib/plugins/angular-rspack-plugin.d.ts +9 -0
  15. package/dist/lib/plugins/angular-rspack-plugin.d.ts.map +1 -1
  16. package/dist/lib/plugins/angular-rspack-plugin.js +245 -83
  17. package/dist/lib/plugins/extract-licenses-plugin.d.ts +78 -0
  18. package/dist/lib/plugins/extract-licenses-plugin.d.ts.map +1 -0
  19. package/dist/lib/plugins/extract-licenses-plugin.js +217 -0
  20. package/dist/lib/plugins/loaders/angular-partial-transform.loader.d.ts +2 -2
  21. package/dist/lib/plugins/loaders/angular-partial-transform.loader.d.ts.map +1 -1
  22. package/dist/lib/plugins/loaders/angular-partial-transform.loader.js +78 -16
  23. package/dist/lib/plugins/loaders/angular-transform.loader.d.ts.map +1 -1
  24. package/dist/lib/plugins/loaders/angular-transform.loader.js +49 -20
  25. package/dist/lib/plugins/loaders/inline-source-map.d.ts +34 -0
  26. package/dist/lib/plugins/loaders/inline-source-map.d.ts.map +1 -0
  27. package/dist/lib/plugins/loaders/inline-source-map.js +76 -0
  28. package/dist/lib/plugins/ng-rspack.d.ts +18 -0
  29. package/dist/lib/plugins/ng-rspack.d.ts.map +1 -1
  30. package/dist/lib/plugins/ng-rspack.js +43 -9
  31. package/dist/lib/plugins/prerender-plugin.d.ts.map +1 -1
  32. package/dist/lib/plugins/prerender-plugin.js +26 -3
  33. package/dist/lib/utils/postcss-cli-resources.d.ts.map +1 -1
  34. package/dist/lib/utils/postcss-cli-resources.js +8 -4
  35. package/package.json +5 -11
  36. package/LICENSE +0 -22
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- var _AngularRspackPlugin__options, _AngularRspackPlugin_i18n, _AngularRspackPlugin_sourceFileCache, _AngularRspackPlugin_javascriptTransformer, _AngularRspackPlugin_angularCompilation, _AngularRspackPlugin_collectedStylesheetAssets, _AngularRspackPlugin_initializationError, _AngularRspackPlugin_emitError;
2
+ var _AngularRspackPlugin_instances, _AngularRspackPlugin__options, _AngularRspackPlugin_i18n, _AngularRspackPlugin_sourceFileCache, _AngularRspackPlugin_javascriptTransformer, _AngularRspackPlugin_angularCompilation, _AngularRspackPlugin_collectedStylesheetAssets, _AngularRspackPlugin_stylesheetMetafileInputsBySource, _AngularRspackPlugin_stylesheetMetafileInputs, _AngularRspackPlugin_collectedStylesheetMetafileInputs, _AngularRspackPlugin_useTypeScriptTranspilation, _AngularRspackPlugin_resourceDependencies, _AngularRspackPlugin_javascriptTransformerCache, _AngularRspackPlugin_diagnosticsPromise, _AngularRspackPlugin_initializationError, _AngularRspackPlugin_emitError, _AngularRspackPlugin_setupWarnings, _AngularRspackPlugin_applyBuildResultReporting, _AngularRspackPlugin_applyJitResourceResolution, _AngularRspackPlugin_exposeLoaderState, _AngularRspackPlugin_diagnosticModes, _AngularRspackPlugin_mergeStylesheetMetafileInputs;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.AngularRspackPlugin = void 0;
5
5
  const tslib_1 = require("tslib");
@@ -7,6 +7,7 @@ const private_1 = require("@angular/build/private");
7
7
  const angular_rspack_compiler_1 = require("@nx/angular-rspack-compiler");
8
8
  const devkit_1 = require("@nx/devkit");
9
9
  const core_1 = require("@rspack/core");
10
+ const node_module_1 = require("node:module");
10
11
  const node_path_1 = require("node:path");
11
12
  const models_1 = require("../models");
12
13
  const get_locale_base_href_1 = require("../utils/get-locale-base-href");
@@ -15,8 +16,37 @@ const misc_helpers_1 = require("../utils/misc-helpers");
15
16
  const stats_1 = require("../utils/stats");
16
17
  const get_stats_options_1 = require("../config/config-utils/get-stats-options");
17
18
  const PLUGIN_NAME = 'AngularRspackPlugin';
19
+ // A project-scoped directory under the Angular CLI cache directory, with an
20
+ // `angular-rspack` leaf so the state never collides with @angular/build's own
21
+ // cache for the same project.
22
+ function getPersistentCachePath(options) {
23
+ // Skip disk caching in CI, where fresh checkouts never reuse it, and in
24
+ // web containers, where it brings no benefit, costs browser memory, and
25
+ // the lmdb-backed transformer cache is unsupported.
26
+ const ci = process.env['CI'];
27
+ if (ci === '1' || ci?.toLowerCase() === 'true') {
28
+ return undefined;
29
+ }
30
+ if (process.versions.webcontainer) {
31
+ return undefined;
32
+ }
33
+ // In Nx workspaces the project name scopes the cache. Outside them (plain
34
+ // programmatic `createConfig` usage) there is no project graph to name the
35
+ // project, so scope by the project root instead of skipping the cache.
36
+ let projectScope = options.projectName;
37
+ if (!projectScope) {
38
+ const relativeRoot = (0, node_path_1.relative)(devkit_1.workspaceRoot, options.root);
39
+ projectScope =
40
+ relativeRoot && !relativeRoot.startsWith('..')
41
+ ? relativeRoot.replace(/[\\/]/g, '-')
42
+ : (0, node_path_1.basename)(options.root);
43
+ }
44
+ const { version } = (0, node_module_1.createRequire)(__filename)('@angular/build/package.json');
45
+ return (0, node_path_1.join)(devkit_1.workspaceRoot, '.angular', 'cache', version, projectScope, 'angular-rspack');
46
+ }
18
47
  class AngularRspackPlugin {
19
48
  constructor(options, i18nOptions) {
49
+ _AngularRspackPlugin_instances.add(this);
20
50
  _AngularRspackPlugin__options.set(this, void 0);
21
51
  _AngularRspackPlugin_i18n.set(this, void 0);
22
52
  _AngularRspackPlugin_sourceFileCache.set(this, void 0);
@@ -24,11 +54,25 @@ class AngularRspackPlugin {
24
54
  // This will be defined in the apply method correctly
25
55
  _AngularRspackPlugin_angularCompilation.set(this, void 0);
26
56
  _AngularRspackPlugin_collectedStylesheetAssets.set(this, []);
57
+ // Latest bundled inputs per stylesheet, persisted across rebuilds since
58
+ // only re-bundled stylesheets produce new results.
59
+ _AngularRspackPlugin_stylesheetMetafileInputsBySource.set(this, new Map());
60
+ _AngularRspackPlugin_stylesheetMetafileInputs.set(this, {});
61
+ _AngularRspackPlugin_collectedStylesheetMetafileInputs.set(this, []);
62
+ _AngularRspackPlugin_useTypeScriptTranspilation.set(this, true);
63
+ _AngularRspackPlugin_resourceDependencies.set(this, void 0);
64
+ _AngularRspackPlugin_javascriptTransformerCache.set(this, void 0);
65
+ _AngularRspackPlugin_diagnosticsPromise.set(this, void 0);
27
66
  _AngularRspackPlugin_initializationError.set(this, void 0);
28
67
  _AngularRspackPlugin_emitError.set(this, void 0);
68
+ _AngularRspackPlugin_setupWarnings.set(this, []);
29
69
  tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin__options, options, "f");
30
70
  tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_i18n, i18nOptions, "f");
31
- tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_sourceFileCache, new angular_rspack_compiler_1.SourceFileCache(), "f");
71
+ const persistentCachePath = getPersistentCachePath(options);
72
+ tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_sourceFileCache, new angular_rspack_compiler_1.SourceFileCache(persistentCachePath), "f");
73
+ if (persistentCachePath) {
74
+ tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_javascriptTransformerCache, (0, angular_rspack_compiler_1.createJavascriptTransformerCache)(persistentCachePath), "f");
75
+ }
32
76
  tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_javascriptTransformer, new angular_rspack_compiler_1.JavaScriptTransformer({
33
77
  /**
34
78
  * Matches https://github.com/angular/angular-cli/blob/33ed6e875e509ebbaa0cbdb57be9e932f9915dff/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts#L89
@@ -39,14 +83,14 @@ class AngularRspackPlugin {
39
83
  thirdPartySourcemaps: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").sourceMap.vendor,
40
84
  advancedOptimizations: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").advancedOptimizations,
41
85
  jit: !tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").aot,
42
- }, (0, angular_rspack_compiler_1.maxWorkers)()), "f");
86
+ }, (0, angular_rspack_compiler_1.maxWorkers)(), tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_javascriptTransformerCache, "f")?.cache), "f");
43
87
  }
44
88
  apply(compiler) {
45
89
  const root = tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").root;
46
90
  // Both of these are exclusive to each other - only one of them can be used at a time
47
91
  // But they will happen before the compiler is created - so we can use them to set up the parallel compilation once
48
92
  compiler.hooks.beforeRun.tapAsync(PLUGIN_NAME, async (compiler, callback) => {
49
- await this.setupCompilation(root, compiler.options.resolve.tsConfig);
93
+ await this.setupCompilation(root, compiler.options.resolve);
50
94
  compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, async (params, callback) => {
51
95
  await this.buildAndAnalyze();
52
96
  callback();
@@ -65,16 +109,31 @@ class AngularRspackPlugin {
65
109
  if (!watchRunInitialized) {
66
110
  watchRunInitialized = true;
67
111
  compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, async (params, callback) => {
68
- const watchingModifiedFiles = compiler.watching?.compiler
69
- ?.modifiedFiles
70
- ? new Set(compiler.watching.compiler.modifiedFiles)
71
- : new Set();
112
+ const watchingCompiler = compiler.watching?.compiler;
113
+ const watchingModifiedFiles = new Set(watchingCompiler?.modifiedFiles);
114
+ const removedFiles = new Set(watchingCompiler?.removedFiles);
115
+ // Removed files invalidate the compilation like modified ones.
116
+ const changedFiles = new Set([
117
+ ...watchingModifiedFiles,
118
+ ...removedFiles,
119
+ ]);
72
120
  if (tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_angularCompilation, "f")) {
73
- tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_sourceFileCache, "f").invalidate(watchingModifiedFiles);
121
+ // The worker-based compilation tracks modified files itself;
122
+ // the in-process one takes them from the host options.
123
+ await tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_angularCompilation, "f").update?.(changedFiles);
124
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_sourceFileCache, "f").invalidate(changedFiles);
125
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_sourceFileCache, "f").prune(removedFiles);
126
+ for (const file of changedFiles) {
127
+ // Inline styles are keyed `<file>?class=...`; drop those
128
+ // along with the file's own entry.
129
+ for (const key of tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_stylesheetMetafileInputsBySource, "f").keys()) {
130
+ if (key === file || key.startsWith(`${file}?`)) {
131
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_stylesheetMetafileInputsBySource, "f").delete(key);
132
+ }
133
+ }
134
+ }
74
135
  }
75
- await this.setupCompilation(root, compiler.options.resolve.tsConfig, watchingModifiedFiles.size > 0
76
- ? watchingModifiedFiles
77
- : undefined);
136
+ await this.setupCompilation(root, compiler.options.resolve, changedFiles.size > 0 ? changedFiles : undefined, true);
78
137
  await this.buildAndAnalyze();
79
138
  // Update shared state for compilation hook
80
139
  currentWatchingModifiedFiles = watchingModifiedFiles;
@@ -84,24 +143,22 @@ class AngularRspackPlugin {
84
143
  callback();
85
144
  });
86
145
  compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
87
- // Surface a failed Angular compilation as a build error (like
88
- // @angular/build) instead of an exception that stalls the hooks chain.
89
- // Watch builds recover on the next rebuild's re-init.
146
+ // Surface a failed Angular compilation as a build error instead of an
147
+ // exception that stalls the hooks chain. Watch builds recover on the
148
+ // next rebuild's re-init.
90
149
  const angularCompilationError = tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_initializationError, "f") ?? tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_emitError, "f");
91
150
  if (angularCompilationError) {
92
151
  (0, rspack_diagnostics_1.addError)(compilation, angularCompilationError);
93
152
  }
94
- // Handle errors thrown by loaders that prevent sealing (but ignore for watch mode)
95
- compilation.hooks.afterSeal.tapAsync(PLUGIN_NAME, (callback) => {
96
- if (!watchRunInitialized && compilation.errors.length > 0) {
97
- const stats = compilation.getStats();
98
- const compilationError = (0, stats_1.statsErrorsToString)(stats.toJson(), (0, get_stats_options_1.getStatsOptions)(tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").verbose));
99
- callback(new Error(compilationError));
100
- }
101
- else {
102
- callback();
103
- }
104
- });
153
+ // Setup warnings describe the one-time compilation setup; repeat them
154
+ // while initialization keeps failing so they also land with the first
155
+ // successful build, then keep rebuilds quiet.
156
+ for (const setupWarning of tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_setupWarnings, "f")) {
157
+ (0, rspack_diagnostics_1.addWarning)(compilation, setupWarning);
158
+ }
159
+ if (!tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_initializationError, "f")) {
160
+ tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_setupWarnings, [], "f");
161
+ }
105
162
  compilation.hooks.processAssets.tap({
106
163
  name: PLUGIN_NAME,
107
164
  stage: compiler.rspack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,
@@ -165,10 +222,11 @@ class AngularRspackPlugin {
165
222
  // there is no (or only stale) compilation state to diagnose and the
166
223
  // failure is already reported as a compilation error. After an emit
167
224
  // failure diagnostics still run since they usually carry the root
168
- // cause, matching @angular/build's application builder.
225
+ // cause.
169
226
  try {
170
- if (!tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").skipTypeChecking && !tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_initializationError, "f")) {
171
- const { errors, warnings } = await tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_angularCompilation, "f").diagnoseFiles(angular_rspack_compiler_1.DiagnosticModes.All);
227
+ if (!tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_initializationError, "f")) {
228
+ const { errors, warnings } = await (tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_diagnosticsPromise, "f") ??
229
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_angularCompilation, "f").diagnoseFiles(tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_instances, "m", _AngularRspackPlugin_diagnosticModes).call(this)));
172
230
  for (const error of errors ?? []) {
173
231
  compilation.errors.push({
174
232
  name: PLUGIN_NAME,
@@ -192,12 +250,6 @@ class AngularRspackPlugin {
192
250
  // and hang the build. Surface it as a build error instead.
193
251
  (0, rspack_diagnostics_1.addError)(compilation, `Angular diagnostics failed.\n${formatError(error)}`);
194
252
  }
195
- try {
196
- await tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_javascriptTransformer, "f").close();
197
- }
198
- catch {
199
- // Best-effort cleanup that must never hang the build.
200
- }
201
253
  callback();
202
254
  });
203
255
  // Store compilation reference for budget checking in done hook
@@ -246,25 +298,7 @@ class AngularRspackPlugin {
246
298
  }
247
299
  }
248
300
  });
249
- compiler.hooks.afterDone.tap(PLUGIN_NAME, (stats) => {
250
- // Despite the typings, stats is undefined when the run fails before
251
- // producing stats (e.g. the afterSeal hook above fails the seal for a
252
- // build with errors). Rspack reports that failure itself.
253
- if (!stats) {
254
- return;
255
- }
256
- // Get stats options - merge defaults with user's config if provided
257
- const configStats = compiler.options.stats;
258
- const defaultStatsOptions = (0, get_stats_options_1.getStatsOptions)(tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").verbose);
259
- const statsOptions = typeof configStats === 'object' && configStats !== null
260
- ? { ...defaultStatsOptions, ...configStats }
261
- : defaultStatsOptions;
262
- (0, stats_1.rspackStatsLogger)(stats, statsOptions);
263
- // Don't forcibly exit the process with errors when in watch mode
264
- if (!watchRunInitialized && stats.hasErrors()) {
265
- process.exit(1);
266
- }
267
- });
301
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_instances, "m", _AngularRspackPlugin_applyBuildResultReporting).call(this, compiler, () => watchRunInitialized);
268
302
  // Dispose the shared component stylesheet bundler after a one-shot build so
269
303
  // its esbuild service (a child process and sockets, with @angular/build >=
270
304
  // 21.2.14) is released and `rspack build` can exit. Safe per-compiler: an
@@ -284,36 +318,33 @@ class AngularRspackPlugin {
284
318
  }
285
319
  callback();
286
320
  });
287
- // Failed builds skip the done hook (afterSeal fails the seal), so release
288
- // the esbuild service and worker pool here too. Runs on close for both
289
- // one-shot and watch; both teardowns are idempotent.
321
+ // Failed builds skip the done hook, so release the esbuild service here
322
+ // too; disposing the bundler again after a one-shot build is a no-op.
323
+ // The transformer closes only on shutdown: a per-build close would tear
324
+ // down its worker pool on every watch rebuild.
290
325
  compiler.hooks.shutdown.tapAsync(`${PLUGIN_NAME}_cleanup`, async (callback) => {
291
- try {
292
- await tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_javascriptTransformer, "f").close();
293
- await (0, angular_rspack_compiler_1.disposeComponentStylesheetBundler)();
294
- }
295
- catch {
296
- // Best-effort cleanup that must never fail the compiler teardown.
297
- }
298
- callback();
299
- });
300
- compiler.hooks.normalModuleFactory.tap(PLUGIN_NAME, (normalModuleFactory) => {
301
- normalModuleFactory.hooks.beforeResolve.tap(PLUGIN_NAME, (data) => {
302
- if (data.request.startsWith('angular:jit:')) {
303
- const path = data.request.split(';')[1];
304
- data.request = `${(0, node_path_1.normalize)((0, node_path_1.resolve)((0, node_path_1.dirname)(data.contextInfo.issuer), path))}?raw`;
326
+ // Isolated per close so a failing one cannot skip the rest and leak
327
+ // their resources (an unterminated compilation worker keeps the
328
+ // process alive). Kept sequential: the transformer writes results
329
+ // through the cache store, so its worker pool closes first.
330
+ const closeSafely = async (close) => {
331
+ try {
332
+ await close();
305
333
  }
306
- });
307
- });
308
- compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
309
- compilation[models_1.NG_RSPACK_SYMBOL_NAME] = () => ({
310
- javascriptTransformer: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_javascriptTransformer, "f"),
311
- typescriptFileCache: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_sourceFileCache, "f").typeScriptFileCache,
312
- angularCompilationFailed: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_initializationError, "f") !== undefined ||
313
- tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_emitError, "f") !== undefined,
314
- i18n: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_i18n, "f"),
315
- });
334
+ catch {
335
+ // Best-effort cleanup that must never fail the compiler teardown.
336
+ }
337
+ };
338
+ await closeSafely(() => tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_javascriptTransformer, "f").close());
339
+ await closeSafely(() => tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_javascriptTransformerCache, "f")?.close());
340
+ // Terminates the worker of a worker-based compilation, which would
341
+ // otherwise keep the process alive.
342
+ await closeSafely(() => tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_angularCompilation, "f")?.close?.());
343
+ await closeSafely(() => (0, angular_rspack_compiler_1.disposeComponentStylesheetBundler)());
344
+ callback();
316
345
  });
346
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_instances, "m", _AngularRspackPlugin_applyJitResourceResolution).call(this, compiler);
347
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_instances, "m", _AngularRspackPlugin_exposeLoaderState).call(this, compiler);
317
348
  if (tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").serviceWorker) {
318
349
  compiler.hooks.done.tapAsync(PLUGIN_NAME, async (compilation, callback) => {
319
350
  let providedLocales = tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").localize;
@@ -337,14 +368,50 @@ class AngularRspackPlugin {
337
368
  });
338
369
  }
339
370
  }
340
- async setupCompilation(root, tsConfig, modifiedFiles) {
371
+ /**
372
+ * Wires a compiler to consume this plugin instance's compilation state
373
+ * without running an Angular compilation of its own. The server compiler
374
+ * of an SSR build runs after the browser compiler
375
+ * (`dependencies: ['browser']`), whose program already includes the server
376
+ * entry points, so its loaders read the emitted files straight from this
377
+ * instance's caches.
378
+ */
379
+ applyToDependentCompiler(compiler) {
380
+ let watchRunInitialized = false;
381
+ let currentWatchingModifiedFiles = new Set();
382
+ // Keeps modified files watched across rebuilds (same invariant as the
383
+ // matching tap in apply()).
384
+ compiler.hooks.compilation.tap(PLUGIN_NAME + '_fileDeps', (compilation) => {
385
+ currentWatchingModifiedFiles.forEach((file) => {
386
+ compilation.fileDependencies.add(file);
387
+ });
388
+ });
389
+ compiler.hooks.watchRun.tap(PLUGIN_NAME, (watchRunCompiler) => {
390
+ watchRunInitialized = true;
391
+ currentWatchingModifiedFiles = new Set(watchRunCompiler.watching?.compiler?.modifiedFiles);
392
+ });
393
+ // Surface a failed Angular compilation on this compiler too; its loaders
394
+ // emit empty modules in that case.
395
+ compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
396
+ const angularCompilationError = tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_initializationError, "f") ?? tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_emitError, "f");
397
+ if (angularCompilationError) {
398
+ (0, rspack_diagnostics_1.addError)(compilation, angularCompilationError);
399
+ }
400
+ });
401
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_instances, "m", _AngularRspackPlugin_applyBuildResultReporting).call(this, compiler, () => watchRunInitialized);
402
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_instances, "m", _AngularRspackPlugin_applyJitResourceResolution).call(this, compiler);
403
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_instances, "m", _AngularRspackPlugin_exposeLoaderState).call(this, compiler);
404
+ }
405
+ async setupCompilation(root, resolve, modifiedFiles, watch = false) {
341
406
  tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_initializationError, undefined, "f");
342
407
  tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_emitError, undefined, "f");
408
+ const tsConfig = resolve.tsConfig;
343
409
  const tsconfigPath = tsConfig
344
410
  ? typeof tsConfig === 'string'
345
411
  ? tsConfig
346
412
  : tsConfig.configFile
347
413
  : tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").tsConfig;
414
+ const isInitialSetup = tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_angularCompilation, "f") === undefined;
348
415
  try {
349
416
  const result = await (0, angular_rspack_compiler_1.setupCompilationWithAngularCompilation)({
350
417
  source: {
@@ -360,15 +427,31 @@ class AngularRspackPlugin {
360
427
  hasServer: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").hasServer,
361
428
  includePaths: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").stylePreprocessorOptions?.includePaths,
362
429
  sass: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").stylePreprocessorOptions?.sass,
430
+ watch,
431
+ sourceMap: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").sourceMap.scripts,
432
+ preserveSymlinks: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").preserveSymlinks,
433
+ // '...' splices rspack's default conditions back in; the rest are
434
+ // the bundler's custom conditions the program must match.
435
+ customConditions: resolve.conditionNames?.filter((c) => c !== '...'),
363
436
  }, tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_sourceFileCache, "f"), tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_angularCompilation, "f"), modifiedFiles);
364
437
  tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_angularCompilation, result.angularCompilation, "f");
365
438
  tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_collectedStylesheetAssets, result.collectedStylesheetAssets, "f");
439
+ tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_collectedStylesheetMetafileInputs, result.collectedStylesheetMetafileInputs ?? [], "f");
440
+ tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_useTypeScriptTranspilation, result.useTypeScriptTranspilation ?? true, "f");
441
+ tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_resourceDependencies, result.resourceDependencies, "f");
442
+ if (isInitialSetup) {
443
+ tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_setupWarnings, result.setupWarnings ?? [], "f");
444
+ }
366
445
  }
367
446
  catch (error) {
447
+ if (isInitialSetup) {
448
+ tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_setupWarnings, error?.setupWarnings ?? [], "f");
449
+ }
368
450
  tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_initializationError, `Angular compilation initialization failed.\n${formatError(error)}`, "f");
369
451
  }
370
452
  }
371
453
  async buildAndAnalyze() {
454
+ tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_diagnosticsPromise, undefined, "f");
372
455
  if (tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_initializationError, "f")) {
373
456
  return;
374
457
  }
@@ -378,10 +461,89 @@ class AngularRspackPlugin {
378
461
  catch (error) {
379
462
  tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_emitError, `Angular compilation emit failed.\n${formatError(error)}`, "f");
380
463
  }
464
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_instances, "m", _AngularRspackPlugin_mergeStylesheetMetafileInputs).call(this);
465
+ // Start diagnostics now so they overlap with bundling; with the
466
+ // worker-based compilation it runs off the main thread and the emit hook
467
+ // only waits for what is left. Diagnostics still run after an emit
468
+ // failure since they usually carry the root cause.
469
+ const diagnosticsPromise = tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_angularCompilation, "f").diagnoseFiles(tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_instances, "m", _AngularRspackPlugin_diagnosticModes).call(this));
470
+ // Failed builds skip the emit hook that reports the result; don't
471
+ // leave the rejection unhandled.
472
+ diagnosticsPromise.catch(() => { });
473
+ tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_diagnosticsPromise, diagnosticsPromise, "f");
381
474
  }
382
475
  }
383
476
  exports.AngularRspackPlugin = AngularRspackPlugin;
384
- _AngularRspackPlugin__options = new WeakMap(), _AngularRspackPlugin_i18n = new WeakMap(), _AngularRspackPlugin_sourceFileCache = new WeakMap(), _AngularRspackPlugin_javascriptTransformer = new WeakMap(), _AngularRspackPlugin_angularCompilation = new WeakMap(), _AngularRspackPlugin_collectedStylesheetAssets = new WeakMap(), _AngularRspackPlugin_initializationError = new WeakMap(), _AngularRspackPlugin_emitError = new WeakMap();
477
+ _AngularRspackPlugin__options = new WeakMap(), _AngularRspackPlugin_i18n = new WeakMap(), _AngularRspackPlugin_sourceFileCache = new WeakMap(), _AngularRspackPlugin_javascriptTransformer = new WeakMap(), _AngularRspackPlugin_angularCompilation = new WeakMap(), _AngularRspackPlugin_collectedStylesheetAssets = new WeakMap(), _AngularRspackPlugin_stylesheetMetafileInputsBySource = new WeakMap(), _AngularRspackPlugin_stylesheetMetafileInputs = new WeakMap(), _AngularRspackPlugin_collectedStylesheetMetafileInputs = new WeakMap(), _AngularRspackPlugin_useTypeScriptTranspilation = new WeakMap(), _AngularRspackPlugin_resourceDependencies = new WeakMap(), _AngularRspackPlugin_javascriptTransformerCache = new WeakMap(), _AngularRspackPlugin_diagnosticsPromise = new WeakMap(), _AngularRspackPlugin_initializationError = new WeakMap(), _AngularRspackPlugin_emitError = new WeakMap(), _AngularRspackPlugin_setupWarnings = new WeakMap(), _AngularRspackPlugin_instances = new WeakSet(), _AngularRspackPlugin_applyBuildResultReporting = function _AngularRspackPlugin_applyBuildResultReporting(compiler, isWatchRun) {
478
+ compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
479
+ // Handle errors thrown by loaders that prevent sealing (but ignore for watch mode)
480
+ compilation.hooks.afterSeal.tapAsync(PLUGIN_NAME, (callback) => {
481
+ if (!isWatchRun() && compilation.errors.length > 0) {
482
+ const stats = compilation.getStats();
483
+ const compilationError = (0, stats_1.statsErrorsToString)(stats.toJson(), (0, get_stats_options_1.getStatsOptions)(tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").verbose));
484
+ callback(new Error(compilationError));
485
+ }
486
+ else {
487
+ callback();
488
+ }
489
+ });
490
+ });
491
+ compiler.hooks.afterDone.tap(PLUGIN_NAME, (stats) => {
492
+ // Despite the typings, stats is undefined when the run fails before
493
+ // producing stats (e.g. the afterSeal hook above fails the seal for a
494
+ // build with errors). Rspack reports that failure itself.
495
+ if (!stats) {
496
+ return;
497
+ }
498
+ // Get stats options - merge defaults with user's config if provided
499
+ const configStats = compiler.options.stats;
500
+ const defaultStatsOptions = (0, get_stats_options_1.getStatsOptions)(tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").verbose);
501
+ const statsOptions = typeof configStats === 'object' && configStats !== null
502
+ ? { ...defaultStatsOptions, ...configStats }
503
+ : defaultStatsOptions;
504
+ (0, stats_1.rspackStatsLogger)(stats, statsOptions);
505
+ // Don't forcibly exit the process with errors when in watch mode
506
+ if (!isWatchRun() && stats.hasErrors()) {
507
+ process.exit(1);
508
+ }
509
+ });
510
+ }, _AngularRspackPlugin_applyJitResourceResolution = function _AngularRspackPlugin_applyJitResourceResolution(compiler) {
511
+ compiler.hooks.normalModuleFactory.tap(PLUGIN_NAME, (normalModuleFactory) => {
512
+ normalModuleFactory.hooks.beforeResolve.tap(PLUGIN_NAME, (data) => {
513
+ if (data.request.startsWith('angular:jit:')) {
514
+ const path = data.request.split(';')[1];
515
+ data.request = `${(0, node_path_1.normalize)((0, node_path_1.resolve)((0, node_path_1.dirname)(data.contextInfo.issuer), path))}?raw`;
516
+ }
517
+ });
518
+ });
519
+ }, _AngularRspackPlugin_exposeLoaderState = function _AngularRspackPlugin_exposeLoaderState(compiler) {
520
+ compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
521
+ compilation[models_1.NG_RSPACK_SYMBOL_NAME] = () => ({
522
+ javascriptTransformer: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_javascriptTransformer, "f"),
523
+ typescriptFileCache: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_sourceFileCache, "f").typeScriptFileCache,
524
+ babelFileCache: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_sourceFileCache, "f").babelFileCache,
525
+ useTypeScriptTranspilation: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_useTypeScriptTranspilation, "f"),
526
+ angularCompilationFailed: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_initializationError, "f") !== undefined ||
527
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_emitError, "f") !== undefined,
528
+ stylesheetMetafileInputs: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_stylesheetMetafileInputs, "f"),
529
+ resourceDependencies: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_resourceDependencies, "f"),
530
+ i18n: tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_i18n, "f"),
531
+ });
532
+ });
533
+ }, _AngularRspackPlugin_diagnosticModes = function _AngularRspackPlugin_diagnosticModes() {
534
+ return tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin__options, "f").skipTypeChecking
535
+ ? (angular_rspack_compiler_1.DiagnosticModes.All & ~angular_rspack_compiler_1.DiagnosticModes.Semantic)
536
+ : angular_rspack_compiler_1.DiagnosticModes.All;
537
+ }, _AngularRspackPlugin_mergeStylesheetMetafileInputs = function _AngularRspackPlugin_mergeStylesheetMetafileInputs() {
538
+ for (const { source, inputs } of tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_collectedStylesheetMetafileInputs, "f")) {
539
+ tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_stylesheetMetafileInputsBySource, "f").set(source, inputs);
540
+ }
541
+ const flattened = {};
542
+ for (const inputs of tslib_1.__classPrivateFieldGet(this, _AngularRspackPlugin_stylesheetMetafileInputsBySource, "f").values()) {
543
+ Object.assign(flattened, inputs);
544
+ }
545
+ tslib_1.__classPrivateFieldSet(this, _AngularRspackPlugin_stylesheetMetafileInputs, flattened, "f");
546
+ };
385
547
  function formatError(error) {
386
548
  return error instanceof Error
387
549
  ? (error.stack ?? error.message)
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ import type { Compiler, RspackPluginInstance } from '@rspack/core';
9
+ /**
10
+ * The subset of the esbuild `Metafile` structure consumed by `extractLicenses`.
11
+ * Built here from the rspack chunk graph instead of an esbuild bundling step.
12
+ */
13
+ interface LicenseMetafile {
14
+ outputs: Record<string | number, {
15
+ inputs: Record<string, {
16
+ bytesInOutput: number;
17
+ }>;
18
+ }>;
19
+ }
20
+ /**
21
+ * Extracts license information for each node module package included in the output
22
+ * files of the built code. This includes JavaScript and CSS output files. The esbuild
23
+ * metafile generated during the bundling steps is used as the source of information
24
+ * regarding what input files where included and where they are located. A path segment
25
+ * of `node_modules` is used to indicate that a file belongs to a package and its license
26
+ * should be include in the output licenses file.
27
+ *
28
+ * The package name and license field are extracted from the `package.json` file for the
29
+ * package. If a license file (e.g., `LICENSE`) is present in the root of the package, it
30
+ * will also be included in the output licenses file.
31
+ *
32
+ * Vendored from `@angular/build` (`src/tools/esbuild/license-extractor.ts`, identical
33
+ * across the supported Angular majors) since it is not exposed in the package's public
34
+ * or private API. Only the esbuild `Metafile` type import is replaced with the local
35
+ * `LicenseMetafile` interface.
36
+ *
37
+ * @param metafile An esbuild metafile object.
38
+ * @param rootDirectory The root directory of the workspace.
39
+ * @returns A string containing the content of the output licenses file.
40
+ */
41
+ export declare function extractLicenses(metafile: LicenseMetafile, rootDirectory: string): Promise<string>;
42
+ /**
43
+ * License extraction inputs collected so far, keyed by the plugin instance
44
+ * (one per compiler) that produced them. Sharing one map across the browser
45
+ * and server compilers makes each emit the union of both, since they write
46
+ * the licenses file to the same output location.
47
+ */
48
+ export type SharedLicenseInputs = Map<object, Record<string, {
49
+ bytesInOutput: number;
50
+ }>>;
51
+ export interface ExtractLicensesPluginOptions {
52
+ /**
53
+ * Asset name for the licenses file, relative to the compilation output path.
54
+ */
55
+ outputFilename: string;
56
+ /**
57
+ * The root directory of the workspace.
58
+ */
59
+ rootDirectory: string;
60
+ /**
61
+ * Inputs shared with the other compilers of the build, when it has several.
62
+ */
63
+ sharedInputs?: SharedLicenseInputs;
64
+ }
65
+ /**
66
+ * Emits a licenses file for the node module packages included in the output,
67
+ * mirroring the `@angular/build` application builder's `extractLicenses`
68
+ * behavior and output. Feeds the chunk graph's module paths to the vendored
69
+ * extractor in place of an esbuild metafile.
70
+ */
71
+ export declare class ExtractLicensesPlugin implements RspackPluginInstance {
72
+ private options;
73
+ private readonly sharedInputs;
74
+ constructor(options: ExtractLicensesPluginOptions);
75
+ apply(compiler: Compiler): void;
76
+ }
77
+ export {};
78
+ //# sourceMappingURL=extract-licenses-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-licenses-plugin.d.ts","sourceRoot":"","sources":["../../../src/lib/plugins/extract-licenses-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAU,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAK3E;;;GAGG;AACH,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CACb,MAAM,GAAG,MAAM,EACf;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,aAAa,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CACtD,CAAC;CACH;AAoCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,eAAe,EACzB,aAAa,EAAE,MAAM,mBA4HtB;AAID;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,GAAG,CACnC,MAAM,EACN,MAAM,CAAC,MAAM,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,CAC1C,CAAC;AAEF,MAAM,WAAW,4BAA4B;IAC3C;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAED;;;;;GAKG;AACH,qBAAa,qBAAsB,YAAW,oBAAoB;IAGpD,OAAO,CAAC,OAAO;IAF3B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IAEnD,YAAoB,OAAO,EAAE,4BAA4B,EAExD;IAED,KAAK,CAAC,QAAQ,EAAE,QAAQ,QAoDvB;CACF"}