@angular-devkit/build-angular 15.0.0-rc.2 → 15.0.0-rc.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,37 +1,37 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "15.0.0-rc.2",
3
+ "version": "15.0.0-rc.4",
4
4
  "description": "Angular Webpack Build Facade",
5
5
  "main": "src/index.js",
6
6
  "typings": "src/index.d.ts",
7
7
  "builders": "builders.json",
8
8
  "dependencies": {
9
9
  "@ampproject/remapping": "2.2.0",
10
- "@angular-devkit/architect": "0.1500.0-rc.2",
11
- "@angular-devkit/build-webpack": "0.1500.0-rc.2",
12
- "@angular-devkit/core": "15.0.0-rc.2",
13
- "@babel/core": "7.19.6",
14
- "@babel/generator": "7.20.1",
10
+ "@angular-devkit/architect": "0.1500.0-rc.4",
11
+ "@angular-devkit/build-webpack": "0.1500.0-rc.4",
12
+ "@angular-devkit/core": "15.0.0-rc.4",
13
+ "@babel/core": "7.20.2",
14
+ "@babel/generator": "7.20.4",
15
15
  "@babel/helper-annotate-as-pure": "7.18.6",
16
16
  "@babel/plugin-proposal-async-generator-functions": "7.20.1",
17
17
  "@babel/plugin-transform-async-to-generator": "7.18.6",
18
18
  "@babel/plugin-transform-runtime": "7.19.6",
19
- "@babel/preset-env": "7.19.4",
19
+ "@babel/preset-env": "7.20.2",
20
20
  "@babel/runtime": "7.20.1",
21
21
  "@babel/template": "7.18.10",
22
22
  "@discoveryjs/json-ext": "0.5.7",
23
- "@ngtools/webpack": "15.0.0-rc.2",
23
+ "@ngtools/webpack": "15.0.0-rc.4",
24
24
  "ansi-colors": "4.1.3",
25
25
  "autoprefixer": "10.4.13",
26
- "babel-loader": "9.0.1",
26
+ "babel-loader": "9.1.0",
27
27
  "babel-plugin-istanbul": "6.1.1",
28
- "browserslist": "^4.9.1",
29
- "cacache": "17.0.1",
28
+ "browserslist": "4.21.4",
29
+ "cacache": "17.0.2",
30
30
  "chokidar": "3.5.3",
31
31
  "copy-webpack-plugin": "11.0.0",
32
32
  "critters": "0.0.16",
33
33
  "css-loader": "6.7.1",
34
- "esbuild-wasm": "0.15.12",
34
+ "esbuild-wasm": "0.15.13",
35
35
  "glob": "8.0.3",
36
36
  "https-proxy-agent": "5.0.1",
37
37
  "inquirer": "8.2.4",
@@ -40,20 +40,20 @@
40
40
  "less": "4.1.3",
41
41
  "less-loader": "11.1.0",
42
42
  "license-webpack-plugin": "4.0.2",
43
- "loader-utils": "3.2.0",
43
+ "loader-utils": "3.2.1",
44
+ "magic-string": "0.26.7",
44
45
  "mini-css-extract-plugin": "2.6.1",
45
- "minimatch": "5.1.0",
46
46
  "open": "8.4.0",
47
47
  "ora": "5.4.1",
48
48
  "parse5-html-rewriting-stream": "6.0.1",
49
49
  "piscina": "3.2.0",
50
- "postcss": "8.4.18",
50
+ "postcss": "8.4.19",
51
51
  "postcss-loader": "7.0.1",
52
52
  "regenerator-runtime": "0.13.10",
53
53
  "resolve-url-loader": "5.0.0",
54
54
  "rxjs": "6.6.7",
55
- "sass": "1.55.0",
56
- "sass-loader": "13.1.0",
55
+ "sass": "1.56.1",
56
+ "sass-loader": "13.2.0",
57
57
  "semver": "7.3.8",
58
58
  "source-map-loader": "4.0.1",
59
59
  "source-map-support": "0.5.21",
@@ -61,14 +61,14 @@
61
61
  "text-table": "0.2.0",
62
62
  "tree-kill": "1.2.2",
63
63
  "tslib": "2.4.1",
64
- "webpack": "5.74.0",
64
+ "webpack": "5.75.0",
65
65
  "webpack-dev-middleware": "5.3.3",
66
66
  "webpack-dev-server": "4.11.1",
67
67
  "webpack-merge": "5.8.0",
68
68
  "webpack-subresource-integrity": "5.1.0"
69
69
  },
70
70
  "optionalDependencies": {
71
- "esbuild": "0.15.12"
71
+ "esbuild": "0.15.13"
72
72
  },
73
73
  "peerDependencies": {
74
74
  "@angular/compiler-cli": "^15.0.0-next",
@@ -331,47 +331,41 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
331
331
  return result;
332
332
  });
333
333
  build.onLoad({ filter: compilerOptions.allowJs ? /\.[cm]?[jt]sx?$/ : /\.[cm]?tsx?$/ }, (args) => (0, profiling_1.profileAsync)('NG_EMIT_TS*', async () => {
334
- var _a, _b, _c, _d, _e;
334
+ var _a, _b, _c, _d, _e, _f;
335
335
  assert.ok(fileEmitter, 'Invalid plugin execution order');
336
+ const request = (_b = (_a = pluginOptions.fileReplacements) === null || _a === void 0 ? void 0 : _a[args.path]) !== null && _b !== void 0 ? _b : args.path;
336
337
  // The filename is currently used as a cache key. Since the cache is memory only,
337
338
  // the options cannot change and do not need to be represented in the key. If the
338
339
  // cache is later stored to disk, then the options that affect transform output
339
340
  // would need to be added to the key as well as a check for any change of content.
340
- let contents = (_a = pluginOptions.sourceFileCache) === null || _a === void 0 ? void 0 : _a.typeScriptFileCache.get((0, node_url_1.pathToFileURL)(args.path).href);
341
+ let contents = (_c = pluginOptions.sourceFileCache) === null || _c === void 0 ? void 0 : _c.typeScriptFileCache.get((0, node_url_1.pathToFileURL)(request).href);
341
342
  if (contents === undefined) {
342
- const typescriptResult = await fileEmitter((_c = (_b = pluginOptions.fileReplacements) === null || _b === void 0 ? void 0 : _b[args.path]) !== null && _c !== void 0 ? _c : args.path);
343
+ const typescriptResult = await fileEmitter(request);
343
344
  if (!typescriptResult) {
344
345
  // No TS result indicates the file is not part of the TypeScript program.
345
346
  // If allowJs is enabled and the file is JS then defer to the next load hook.
346
- if (compilerOptions.allowJs && /\.[cm]?js$/.test(args.path)) {
347
+ if (compilerOptions.allowJs && /\.[cm]?js$/.test(request)) {
347
348
  return undefined;
348
349
  }
349
350
  // Otherwise return an error
350
351
  return {
351
352
  errors: [
352
- {
353
- text: `File '${args.path}' is missing from the TypeScript compilation.`,
354
- notes: [
355
- {
356
- text: `Ensure the file is part of the TypeScript program via the 'files' or 'include' property.`,
357
- },
358
- ],
359
- },
353
+ createMissingFileError(request, args.path, (_d = build.initialOptions.absWorkingDir) !== null && _d !== void 0 ? _d : ''),
360
354
  ],
361
355
  };
362
356
  }
363
- const data = (_d = typescriptResult.content) !== null && _d !== void 0 ? _d : '';
357
+ const data = (_e = typescriptResult.content) !== null && _e !== void 0 ? _e : '';
364
358
  // The pre-transformed data is used as a cache key. Since the cache is memory only,
365
359
  // the options cannot change and do not need to be represented in the key. If the
366
360
  // cache is later stored to disk, then the options that affect transform output
367
361
  // would need to be added to the key as well.
368
362
  contents = babelDataCache.get(data);
369
363
  if (contents === undefined) {
370
- const transformedData = await transformWithBabel(args.path, data, pluginOptions);
364
+ const transformedData = await transformWithBabel(request, data, pluginOptions);
371
365
  contents = Buffer.from(transformedData, 'utf-8');
372
366
  babelDataCache.set(data, contents);
373
367
  }
374
- (_e = pluginOptions.sourceFileCache) === null || _e === void 0 ? void 0 : _e.typeScriptFileCache.set((0, node_url_1.pathToFileURL)(args.path).href, contents);
368
+ (_f = pluginOptions.sourceFileCache) === null || _f === void 0 ? void 0 : _f.typeScriptFileCache.set((0, node_url_1.pathToFileURL)(request).href, contents);
375
369
  }
376
370
  return {
377
371
  contents,
@@ -504,3 +498,19 @@ function findAffectedFiles(builder, { ignoreForDiagnostics, ignoreForEmit, incre
504
498
  }
505
499
  return affectedFiles;
506
500
  }
501
+ function createMissingFileError(request, original, root) {
502
+ const error = {
503
+ text: `File '${path.relative(root, request)}' is missing from the TypeScript compilation.`,
504
+ notes: [
505
+ {
506
+ text: `Ensure the file is part of the TypeScript program via the 'files' or 'include' property.`,
507
+ },
508
+ ],
509
+ };
510
+ if (request !== original) {
511
+ error.notes.push({
512
+ text: `File is requested from a file replacement of '${path.relative(root, original)}'.`,
513
+ });
514
+ }
515
+ return error;
516
+ }
@@ -33,6 +33,14 @@ function createCssResourcePlugin() {
33
33
  if (args.kind !== 'url-token' || ((_a = args.pluginData) === null || _a === void 0 ? void 0 : _a[CSS_RESOURCE_RESOLUTION])) {
34
34
  return null;
35
35
  }
36
+ // If root-relative, absolute or protocol relative url, mark as external to leave the
37
+ // path/URL in place.
38
+ if (/^((?:\w+:)?\/\/|data:|chrome:|#|\/)/.test(args.path)) {
39
+ return {
40
+ path: args.path,
41
+ external: true,
42
+ };
43
+ }
36
44
  const { importer, kind, resolveDir, namespace, pluginData = {} } = args;
37
45
  pluginData[CSS_RESOURCE_RESOLUTION] = true;
38
46
  const result = await build.resolve(args.path, {
@@ -7,6 +7,7 @@
7
7
  */
8
8
  import { BuilderContext } from '@angular-devkit/architect';
9
9
  import { BuildFailure, BuildInvalidate, BuildOptions, BuildResult, Message, OutputFile } from 'esbuild';
10
+ import { FileInfo } from '../../utils/index-file/augment-index-html';
10
11
  /**
11
12
  * Determines if an unknown value is an esbuild BuildFailure error object thrown by esbuild.
12
13
  * @param value A potential esbuild BuildFailure error object.
@@ -24,8 +25,9 @@ export declare function isEsBuildFailure(value: unknown): value is BuildFailure;
24
25
  * @returns If output files are generated, the full esbuild BuildResult; if not, the
25
26
  * warnings and errors for the attempted build.
26
27
  */
27
- export declare function bundle(optionsOrInvalidate: BuildOptions | BuildInvalidate): Promise<(BuildResult & {
28
+ export declare function bundle(workspaceRoot: string, optionsOrInvalidate: BuildOptions | BuildInvalidate): Promise<(BuildResult & {
28
29
  outputFiles: OutputFile[];
30
+ initialFiles: FileInfo[];
29
31
  }) | (BuildFailure & {
30
32
  outputFiles?: never;
31
33
  })>;
@@ -9,6 +9,7 @@
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.logMessages = exports.bundle = exports.isEsBuildFailure = void 0;
11
11
  const esbuild_1 = require("esbuild");
12
+ const node_path_1 = require("node:path");
12
13
  /**
13
14
  * Determines if an unknown value is an esbuild BuildFailure error object thrown by esbuild.
14
15
  * @param value A potential esbuild BuildFailure error object.
@@ -29,14 +30,17 @@ exports.isEsBuildFailure = isEsBuildFailure;
29
30
  * @returns If output files are generated, the full esbuild BuildResult; if not, the
30
31
  * warnings and errors for the attempted build.
31
32
  */
32
- async function bundle(optionsOrInvalidate) {
33
+ async function bundle(workspaceRoot, optionsOrInvalidate) {
34
+ var _a, _b;
35
+ let result;
33
36
  try {
34
37
  if (typeof optionsOrInvalidate === 'function') {
35
- return (await optionsOrInvalidate());
38
+ result = (await optionsOrInvalidate());
36
39
  }
37
40
  else {
38
- return await (0, esbuild_1.build)({
41
+ result = await (0, esbuild_1.build)({
39
42
  ...optionsOrInvalidate,
43
+ metafile: true,
40
44
  write: false,
41
45
  });
42
46
  }
@@ -50,6 +54,23 @@ async function bundle(optionsOrInvalidate) {
50
54
  throw failure;
51
55
  }
52
56
  }
57
+ const initialFiles = [];
58
+ for (const outputFile of result.outputFiles) {
59
+ // Entries in the metafile are relative to the `absWorkingDir` option which is set to the workspaceRoot
60
+ const relativeFilePath = (0, node_path_1.relative)(workspaceRoot, outputFile.path);
61
+ const entryPoint = (_b = (_a = result.metafile) === null || _a === void 0 ? void 0 : _a.outputs[relativeFilePath]) === null || _b === void 0 ? void 0 : _b.entryPoint;
62
+ outputFile.path = relativeFilePath;
63
+ if (entryPoint) {
64
+ // An entryPoint value indicates an initial file
65
+ initialFiles.push({
66
+ file: outputFile.path,
67
+ // The first part of the filename is the name of file (e.g., "polyfills" for "polyfills.7S5G3MDY.js")
68
+ name: (0, node_path_1.basename)(outputFile.path).split('.')[0],
69
+ extension: (0, node_path_1.extname)(outputFile.path),
70
+ });
71
+ }
72
+ }
73
+ return { ...result, initialFiles };
53
74
  }
54
75
  exports.bundle = bundle;
55
76
  async function logMessages(context, { errors, warnings }) {
@@ -29,12 +29,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
29
29
  __setModuleDefault(result, mod);
30
30
  return result;
31
31
  };
32
+ var __importDefault = (this && this.__importDefault) || function (mod) {
33
+ return (mod && mod.__esModule) ? mod : { "default": mod };
34
+ };
32
35
  Object.defineProperty(exports, "__esModule", { value: true });
33
36
  exports.buildEsbuildBrowser = void 0;
34
37
  const architect_1 = require("@angular-devkit/architect");
35
- const assert = __importStar(require("assert"));
36
- const fs = __importStar(require("fs/promises"));
37
- const path = __importStar(require("path"));
38
+ const node_assert_1 = __importDefault(require("node:assert"));
39
+ const fs = __importStar(require("node:fs/promises"));
40
+ const path = __importStar(require("node:path"));
38
41
  const utils_1 = require("../../utils");
39
42
  const copy_assets_1 = require("../../utils/copy-assets");
40
43
  const error_1 = require("../../utils/error");
@@ -53,9 +56,10 @@ const watcher_1 = require("./watcher");
53
56
  * Represents the result of a single builder execute call.
54
57
  */
55
58
  class ExecutionResult {
56
- constructor(success, codeRebuild, codeBundleCache) {
59
+ constructor(success, codeRebuild, globalStylesRebuild, codeBundleCache) {
57
60
  this.success = success;
58
61
  this.codeRebuild = codeRebuild;
62
+ this.globalStylesRebuild = globalStylesRebuild;
59
63
  this.codeBundleCache = codeBundleCache;
60
64
  }
61
65
  get output() {
@@ -68,6 +72,7 @@ class ExecutionResult {
68
72
  (_a = this.codeBundleCache) === null || _a === void 0 ? void 0 : _a.invalidate([...fileChanges.modified, ...fileChanges.removed]);
69
73
  return {
70
74
  codeRebuild: this.codeRebuild,
75
+ globalStylesRebuild: this.globalStylesRebuild,
71
76
  codeBundleCache: this.codeBundleCache,
72
77
  fileChanges,
73
78
  };
@@ -87,9 +92,9 @@ async function execute(options, context, rebuildState) {
87
92
  : undefined;
88
93
  const [codeResults, styleResults] = await Promise.all([
89
94
  // Execute esbuild to bundle the application code
90
- (0, esbuild_1.bundle)((_b = rebuildState === null || rebuildState === void 0 ? void 0 : rebuildState.codeRebuild) !== null && _b !== void 0 ? _b : createCodeBundleOptions(options, target, codeBundleCache)),
95
+ (0, esbuild_1.bundle)(workspaceRoot, (_b = rebuildState === null || rebuildState === void 0 ? void 0 : rebuildState.codeRebuild) !== null && _b !== void 0 ? _b : createCodeBundleOptions(options, target, codeBundleCache)),
91
96
  // Execute esbuild to bundle the global stylesheets
92
- bundleGlobalStylesheets(options, target),
97
+ (0, esbuild_1.bundle)(workspaceRoot, (_c = rebuildState === null || rebuildState === void 0 ? void 0 : rebuildState.globalStylesRebuild) !== null && _c !== void 0 ? _c : createGlobalStylesBundleOptions(options, target)),
93
98
  ]);
94
99
  // Log all warnings and errors generated during bundling
95
100
  await (0, esbuild_1.logMessages)(context, {
@@ -98,34 +103,17 @@ async function execute(options, context, rebuildState) {
98
103
  });
99
104
  // Return if the bundling failed to generate output files or there are errors
100
105
  if (!codeResults.outputFiles || codeResults.errors.length) {
101
- return new ExecutionResult(false, rebuildState === null || rebuildState === void 0 ? void 0 : rebuildState.codeRebuild, codeBundleCache);
102
- }
103
- // Structure the code bundling output files
104
- const initialFiles = [];
105
- const outputFiles = [];
106
- for (const outputFile of codeResults.outputFiles) {
107
- // Entries in the metafile are relative to the `absWorkingDir` option which is set to the workspaceRoot
108
- const relativeFilePath = path.relative(workspaceRoot, outputFile.path);
109
- const entryPoint = (_d = (_c = codeResults.metafile) === null || _c === void 0 ? void 0 : _c.outputs[relativeFilePath]) === null || _d === void 0 ? void 0 : _d.entryPoint;
110
- outputFile.path = relativeFilePath;
111
- if (entryPoint) {
112
- // An entryPoint value indicates an initial file
113
- initialFiles.push({
114
- file: outputFile.path,
115
- // The first part of the filename is the name of file (e.g., "polyfills" for "polyfills.7S5G3MDY.js")
116
- name: path.basename(outputFile.path).split('.')[0],
117
- extension: path.extname(outputFile.path),
118
- });
119
- }
120
- outputFiles.push(outputFile);
106
+ return new ExecutionResult(false, rebuildState === null || rebuildState === void 0 ? void 0 : rebuildState.codeRebuild, (_d = (styleResults.outputFiles && styleResults.rebuild)) !== null && _d !== void 0 ? _d : rebuildState === null || rebuildState === void 0 ? void 0 : rebuildState.globalStylesRebuild, codeBundleCache);
121
107
  }
122
- // Add global stylesheets output files
123
- outputFiles.push(...styleResults.outputFiles);
124
- initialFiles.push(...styleResults.initialFiles);
125
108
  // Return if the global stylesheet bundling has errors
126
- if (styleResults.errors.length) {
127
- return new ExecutionResult(false, codeResults.rebuild, codeBundleCache);
109
+ if (!styleResults.outputFiles || styleResults.errors.length) {
110
+ return new ExecutionResult(false, codeResults.rebuild, rebuildState === null || rebuildState === void 0 ? void 0 : rebuildState.globalStylesRebuild, codeBundleCache);
128
111
  }
112
+ // Filter global stylesheet initial files
113
+ styleResults.initialFiles = styleResults.initialFiles.filter(({ name }) => { var _a; return (_a = options.globalStyles.find((style) => style.name === name)) === null || _a === void 0 ? void 0 : _a.initial; });
114
+ // Combine the bundling output files
115
+ const initialFiles = [...codeResults.initialFiles, ...styleResults.initialFiles];
116
+ const outputFiles = [...codeResults.outputFiles, ...styleResults.outputFiles];
129
117
  // Generate index HTML file
130
118
  if (indexHtmlOptions) {
131
119
  // Create an index HTML generator that reads from the in-memory output files
@@ -175,12 +163,12 @@ async function execute(options, context, rebuildState) {
175
163
  }
176
164
  catch (error) {
177
165
  context.logger.error(error instanceof Error ? error.message : `${error}`);
178
- return new ExecutionResult(false, codeResults.rebuild, codeBundleCache);
166
+ return new ExecutionResult(false, codeResults.rebuild, styleResults.rebuild, codeBundleCache);
179
167
  }
180
168
  }
181
169
  const buildTime = Number(process.hrtime.bigint() - startTime) / 10 ** 9;
182
170
  context.logger.info(`Complete. [${buildTime.toFixed(3)} seconds]`);
183
- return new ExecutionResult(true, codeResults.rebuild, codeBundleCache);
171
+ return new ExecutionResult(true, codeResults.rebuild, styleResults.rebuild, codeBundleCache);
184
172
  }
185
173
  function createOutputFileFromText(path, text) {
186
174
  return {
@@ -219,7 +207,6 @@ function createCodeBundleOptions(options, target, sourceFileCache) {
219
207
  conditions: ['es2020', 'es2015', 'module'],
220
208
  resolveExtensions: ['.ts', '.tsx', '.mjs', '.js'],
221
209
  logLevel: options.verbose ? 'debug' : 'silent',
222
- metafile: true,
223
210
  minify: optimizationOptions.scripts,
224
211
  pure: ['forwardRef'],
225
212
  outdir: workspaceRoot,
@@ -262,53 +249,49 @@ function createCodeBundleOptions(options, target, sourceFileCache) {
262
249
  },
263
250
  };
264
251
  }
265
- async function bundleGlobalStylesheets(options, target) {
266
- const { workspaceRoot, optimizationOptions, sourcemapOptions, outputNames, globalStyles, preserveSymlinks, externalDependencies, stylePreprocessorOptions, } = options;
267
- const outputFiles = [];
268
- const initialFiles = [];
269
- const errors = [];
270
- const warnings = [];
271
- for (const { name, files, initial } of globalStyles) {
272
- const virtualEntryData = files
273
- .map((file) => `@import '${file.replace(/\\/g, '/')}';`)
274
- .join('\n');
275
- const sheetResult = await (0, stylesheets_1.bundleStylesheetText)(virtualEntryData, { virtualName: `angular:style/global;${name}`, resolvePath: workspaceRoot }, {
276
- workspaceRoot,
277
- optimization: !!optimizationOptions.styles.minify,
278
- sourcemap: !!sourcemapOptions.styles && (sourcemapOptions.hidden ? 'external' : true),
279
- outputNames: initial ? outputNames : { media: outputNames.media },
280
- includePaths: stylePreprocessorOptions === null || stylePreprocessorOptions === void 0 ? void 0 : stylePreprocessorOptions.includePaths,
281
- preserveSymlinks,
282
- externalDependencies,
283
- target,
284
- });
285
- errors.push(...sheetResult.errors);
286
- warnings.push(...sheetResult.warnings);
287
- if (!sheetResult.path) {
288
- // Failed to process the stylesheet
289
- assert.ok(sheetResult.errors.length, `Global stylesheet processing for '${name}' failed with no errors.`);
290
- continue;
291
- }
292
- // The virtual stylesheets will be named `stdin` by esbuild. This must be replaced
293
- // with the actual name of the global style and the leading directory separator must
294
- // also be removed to make the path relative.
295
- const sheetPath = sheetResult.path.replace('stdin', name);
296
- let sheetContents = sheetResult.contents;
297
- if (sheetResult.map) {
298
- outputFiles.push(createOutputFileFromText(sheetPath + '.map', sheetResult.map));
299
- sheetContents = sheetContents.replace('sourceMappingURL=stdin.css.map', `sourceMappingURL=${name}.css.map`);
300
- }
301
- outputFiles.push(createOutputFileFromText(sheetPath, sheetContents));
302
- if (initial) {
303
- initialFiles.push({
304
- file: sheetPath,
305
- name,
306
- extension: '.css',
307
- });
308
- }
309
- outputFiles.push(...sheetResult.resourceFiles);
252
+ function createGlobalStylesBundleOptions(options, target) {
253
+ const { workspaceRoot, optimizationOptions, sourcemapOptions, outputNames, globalStyles, preserveSymlinks, externalDependencies, stylePreprocessorOptions, watch, } = options;
254
+ const buildOptions = (0, stylesheets_1.createStylesheetBundleOptions)({
255
+ workspaceRoot,
256
+ optimization: !!optimizationOptions.styles.minify,
257
+ sourcemap: !!sourcemapOptions.styles,
258
+ preserveSymlinks,
259
+ target,
260
+ externalDependencies,
261
+ outputNames,
262
+ includePaths: stylePreprocessorOptions === null || stylePreprocessorOptions === void 0 ? void 0 : stylePreprocessorOptions.includePaths,
263
+ });
264
+ buildOptions.incremental = watch;
265
+ const namespace = 'angular:styles/global';
266
+ buildOptions.entryPoints = {};
267
+ for (const { name } of globalStyles) {
268
+ buildOptions.entryPoints[name] = `${namespace};${name}`;
310
269
  }
311
- return { outputFiles, initialFiles, errors, warnings };
270
+ buildOptions.plugins.unshift({
271
+ name: 'angular-global-styles',
272
+ setup(build) {
273
+ build.onResolve({ filter: /^angular:styles\/global;/ }, (args) => {
274
+ if (args.kind !== 'entry-point') {
275
+ return null;
276
+ }
277
+ return {
278
+ path: args.path.split(';', 2)[1],
279
+ namespace,
280
+ };
281
+ });
282
+ build.onLoad({ filter: /./, namespace }, (args) => {
283
+ var _a;
284
+ const files = (_a = globalStyles.find(({ name }) => name === args.path)) === null || _a === void 0 ? void 0 : _a.files;
285
+ (0, node_assert_1.default)(files, `global style name should always be found [${args.path}]`);
286
+ return {
287
+ contents: files.map((file) => `@import '${file.replace(/\\/g, '/')}';`).join('\n'),
288
+ loader: 'css',
289
+ resolveDir: workspaceRoot,
290
+ };
291
+ });
292
+ },
293
+ });
294
+ return buildOptions;
312
295
  }
313
296
  /**
314
297
  * Main execution function for the esbuild-based application builder.
@@ -18,6 +18,7 @@ function isSassException(error) {
18
18
  }
19
19
  function shutdownSassWorkerPool() {
20
20
  sassWorkerPool === null || sassWorkerPool === void 0 ? void 0 : sassWorkerPool.close();
21
+ sassWorkerPool = undefined;
21
22
  }
22
23
  exports.shutdownSassWorkerPool = shutdownSassWorkerPool;
23
24
  function createSassPlugin(options) {
@@ -26,7 +27,7 @@ function createSassPlugin(options) {
26
27
  setup(build) {
27
28
  build.onLoad({ filter: /\.s[ac]ss$/ }, async (args) => {
28
29
  // Lazily load Sass when a Sass file is found
29
- sassWorkerPool !== null && sassWorkerPool !== void 0 ? sassWorkerPool : (sassWorkerPool = new sass_service_1.SassWorkerImplementation());
30
+ sassWorkerPool !== null && sassWorkerPool !== void 0 ? sassWorkerPool : (sassWorkerPool = new sass_service_1.SassWorkerImplementation(true));
30
31
  const warnings = [];
31
32
  try {
32
33
  const data = await (0, promises_1.readFile)(args.path, 'utf-8');
@@ -37,6 +38,48 @@ function createSassPlugin(options) {
37
38
  sourceMap: options.sourcemap,
38
39
  sourceMapIncludeSources: options.sourcemap,
39
40
  quietDeps: true,
41
+ importers: [
42
+ {
43
+ findFileUrl: async (url, { previousResolvedModules }) => {
44
+ let result = await build.resolve(url, {
45
+ kind: 'import-rule',
46
+ // This should ideally be the directory of the importer file from Sass
47
+ // but that is not currently available from the Sass importer API.
48
+ resolveDir: build.initialOptions.absWorkingDir,
49
+ });
50
+ // Workaround to support Yarn PnP without access to the importer file from Sass
51
+ if (!result.path && (previousResolvedModules === null || previousResolvedModules === void 0 ? void 0 : previousResolvedModules.size)) {
52
+ for (const previous of previousResolvedModules) {
53
+ result = await build.resolve(url, {
54
+ kind: 'import-rule',
55
+ resolveDir: previous,
56
+ });
57
+ }
58
+ }
59
+ // Check for package deep imports
60
+ if (!result.path) {
61
+ const parts = url.split('/');
62
+ const hasScope = parts.length > 2 && parts[0].startsWith('@');
63
+ if (hasScope || parts.length > 1) {
64
+ const [nameOrScope, nameOrFirstPath, ...pathPart] = parts;
65
+ const packageName = hasScope
66
+ ? `${nameOrScope}/${nameOrFirstPath}`
67
+ : nameOrScope;
68
+ const packageResult = await build.resolve(packageName + '/package.json', {
69
+ kind: 'import-rule',
70
+ // This should ideally be the directory of the importer file from Sass
71
+ // but that is not currently available from the Sass importer API.
72
+ resolveDir: build.initialOptions.absWorkingDir,
73
+ });
74
+ if (packageResult.path) {
75
+ return (0, node_url_1.pathToFileURL)((0, node_path_1.join)((0, node_path_1.dirname)(packageResult.path), !hasScope ? nameOrFirstPath : '', ...pathPart));
76
+ }
77
+ }
78
+ }
79
+ return result.path ? (0, node_url_1.pathToFileURL)(result.path) : null;
80
+ },
81
+ },
82
+ ],
40
83
  logger: {
41
84
  warn: (text, { deprecation, span }) => {
42
85
  warnings.push({
@@ -5,7 +5,7 @@
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
- import type { OutputFile } from 'esbuild';
8
+ import type { BuildOptions, OutputFile } from 'esbuild';
9
9
  export interface BundleStylesheetOptions {
10
10
  workspaceRoot: string;
11
11
  optimization: boolean;
@@ -19,6 +19,9 @@ export interface BundleStylesheetOptions {
19
19
  externalDependencies?: string[];
20
20
  target: string[];
21
21
  }
22
+ export declare function createStylesheetBundleOptions(options: BundleStylesheetOptions): BuildOptions & {
23
+ plugins: NonNullable<BuildOptions['plugins']>;
24
+ };
22
25
  /**
23
26
  * Bundle a stylesheet that exists as a file on the filesystem.
24
27
  *
@@ -30,23 +30,18 @@ var __importStar = (this && this.__importStar) || function (mod) {
30
30
  return result;
31
31
  };
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.bundleStylesheetText = exports.bundleStylesheetFile = void 0;
33
+ exports.bundleStylesheetText = exports.bundleStylesheetFile = exports.createStylesheetBundleOptions = void 0;
34
34
  const path = __importStar(require("path"));
35
35
  const css_resource_plugin_1 = require("./css-resource-plugin");
36
36
  const esbuild_1 = require("./esbuild");
37
37
  const sass_plugin_1 = require("./sass-plugin");
38
- async function bundleStylesheet(entry, options) {
39
- var _a, _b, _c;
40
- const loadPaths = (_a = options.includePaths) !== null && _a !== void 0 ? _a : [];
41
- // Needed to resolve node packages.
42
- loadPaths.push(path.join(options.workspaceRoot, 'node_modules'));
43
- // Execute esbuild
44
- const result = await (0, esbuild_1.bundle)({
45
- ...entry,
38
+ function createStylesheetBundleOptions(options) {
39
+ var _a, _b;
40
+ return {
46
41
  absWorkingDir: options.workspaceRoot,
47
42
  bundle: true,
48
- entryNames: (_b = options.outputNames) === null || _b === void 0 ? void 0 : _b.bundles,
49
- assetNames: (_c = options.outputNames) === null || _c === void 0 ? void 0 : _c.media,
43
+ entryNames: (_a = options.outputNames) === null || _a === void 0 ? void 0 : _a.bundles,
44
+ assetNames: (_b = options.outputNames) === null || _b === void 0 ? void 0 : _b.media,
50
45
  logLevel: 'silent',
51
46
  minify: options.optimization,
52
47
  sourcemap: options.sourcemap,
@@ -59,9 +54,17 @@ async function bundleStylesheet(entry, options) {
59
54
  conditions: ['style', 'sass'],
60
55
  mainFields: ['style', 'sass'],
61
56
  plugins: [
62
- (0, sass_plugin_1.createSassPlugin)({ sourcemap: !!options.sourcemap, loadPaths }),
57
+ (0, sass_plugin_1.createSassPlugin)({ sourcemap: !!options.sourcemap, loadPaths: options.includePaths }),
63
58
  (0, css_resource_plugin_1.createCssResourcePlugin)(),
64
59
  ],
60
+ };
61
+ }
62
+ exports.createStylesheetBundleOptions = createStylesheetBundleOptions;
63
+ async function bundleStylesheet(entry, options) {
64
+ // Execute esbuild
65
+ const result = await (0, esbuild_1.bundle)(options.workspaceRoot, {
66
+ ...createStylesheetBundleOptions(options),
67
+ ...entry,
65
68
  });
66
69
  // Extract the result of the bundling from the output files
67
70
  let contents = '';
@@ -70,7 +73,6 @@ async function bundleStylesheet(entry, options) {
70
73
  const resourceFiles = [];
71
74
  if (result.outputFiles) {
72
75
  for (const outputFile of result.outputFiles) {
73
- outputFile.path = path.relative(options.workspaceRoot, outputFile.path);
74
76
  const filename = path.basename(outputFile.path);
75
77
  if (filename.endsWith('.css')) {
76
78
  outputPath = outputFile.path;