@angular-devkit/build-angular 15.0.0-next.3 → 15.0.0-next.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.
@@ -32,6 +32,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
33
  exports.execute = void 0;
34
34
  const architect_1 = require("@angular-devkit/architect");
35
+ const core_1 = require("@angular-devkit/core");
36
+ const karma_1 = require("karma");
37
+ const module_1 = require("module");
35
38
  const path = __importStar(require("path"));
36
39
  const rxjs_1 = require("rxjs");
37
40
  const operators_1 = require("rxjs/operators");
@@ -81,9 +84,15 @@ function execute(options, context, transforms = {}) {
81
84
  }
82
85
  return (0, rxjs_1.from)(initialize(options, context, transforms.webpackConfiguration)).pipe((0, operators_1.switchMap)(async ([karma, webpackConfig]) => {
83
86
  var _a, _b, _c, _d, _e;
84
- const karmaOptions = {
85
- singleRun,
86
- };
87
+ // Determine project name from builder context target
88
+ const projectName = (_a = context.target) === null || _a === void 0 ? void 0 : _a.project;
89
+ if (!projectName) {
90
+ throw new Error(`The 'karma' builder requires a target to be specified.`);
91
+ }
92
+ const karmaOptions = options.karmaConfig
93
+ ? {}
94
+ : getBuiltInKarmaConfig(context.workspaceRoot, projectName);
95
+ karmaOptions.singleRun = singleRun;
87
96
  // Convert browsers from a string to an array
88
97
  if (options.browsers) {
89
98
  karmaOptions.browsers = options.browsers.split(',');
@@ -97,10 +106,6 @@ function execute(options, context, transforms = {}) {
97
106
  karmaOptions.reporters = reporters;
98
107
  }
99
108
  }
100
- const projectName = (_a = context.target) === null || _a === void 0 ? void 0 : _a.project;
101
- if (!projectName) {
102
- throw new Error('The builder requires a target.');
103
- }
104
109
  if (!options.main) {
105
110
  (_b = webpackConfig.entry) !== null && _b !== void 0 ? _b : (webpackConfig.entry = {});
106
111
  if (typeof webpackConfig.entry === 'object' && !Array.isArray(webpackConfig.entry)) {
@@ -125,8 +130,8 @@ function execute(options, context, transforms = {}) {
125
130
  webpackConfig,
126
131
  logger: context.logger,
127
132
  };
128
- const config = await karma.config.parseConfig(path.resolve(context.workspaceRoot, options.karmaConfig), transforms.karmaOptions ? transforms.karmaOptions(karmaOptions) : karmaOptions, { promiseConfig: true, throwErrors: true });
129
- return [karma, config];
133
+ const parsedKarmaConfig = await karma_1.config.parseConfig(options.karmaConfig && path.resolve(context.workspaceRoot, options.karmaConfig), transforms.karmaOptions ? transforms.karmaOptions(karmaOptions) : karmaOptions, { promiseConfig: true, throwErrors: true });
134
+ return [karma, parsedKarmaConfig];
130
135
  }), (0, operators_1.switchMap)(([karma, karmaConfig]) => new rxjs_1.Observable((subscriber) => {
131
136
  var _a, _b, _c;
132
137
  var _d, _e;
@@ -149,6 +154,42 @@ function execute(options, context, transforms = {}) {
149
154
  })), (0, operators_1.defaultIfEmpty)({ success: false }));
150
155
  }
151
156
  exports.execute = execute;
157
+ function getBuiltInKarmaConfig(workspaceRoot, projectName) {
158
+ let coverageFolderName = projectName.charAt(0) === '@' ? projectName.slice(1) : projectName;
159
+ if (/[A-Z]/.test(coverageFolderName)) {
160
+ coverageFolderName = core_1.strings.dasherize(coverageFolderName);
161
+ }
162
+ const workspaceRootRequire = (0, module_1.createRequire)(workspaceRoot + '/');
163
+ return {
164
+ basePath: '',
165
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
166
+ plugins: [
167
+ 'karma-jasmine',
168
+ 'karma-chrome-launcher',
169
+ 'karma-jasmine-html-reporter',
170
+ 'karma-coverage',
171
+ '@angular-devkit/build-angular/plugins/karma',
172
+ ].map((p) => workspaceRootRequire(p)),
173
+ client: {
174
+ clearContext: false, // leave Jasmine Spec Runner output visible in browser
175
+ },
176
+ jasmineHtmlReporter: {
177
+ suppressAll: true, // removes the duplicated traces
178
+ },
179
+ coverageReporter: {
180
+ dir: path.join(workspaceRoot, 'coverage', coverageFolderName),
181
+ subdir: '.',
182
+ reporters: [{ type: 'html' }, { type: 'text-summary' }],
183
+ },
184
+ reporters: ['progress', 'kjhtml'],
185
+ port: 9876,
186
+ colors: true,
187
+ logLevel: karma_1.constants.LOG_INFO,
188
+ autoWatch: true,
189
+ browsers: ['Chrome'],
190
+ restartOnFileChange: true,
191
+ };
192
+ }
152
193
  exports.default = (0, architect_1.createBuilder)(execute);
153
194
  function getBuiltInMainFile() {
154
195
  const content = Buffer.from(`
@@ -38,7 +38,7 @@ export interface Schema {
38
38
  /**
39
39
  * The name of the Karma configuration file.
40
40
  */
41
- karmaConfig: string;
41
+ karmaConfig?: string;
42
42
  /**
43
43
  * The name of the main entry-point file.
44
44
  */
@@ -255,7 +255,7 @@
255
255
  }
256
256
  },
257
257
  "additionalProperties": false,
258
- "required": ["tsConfig", "karmaConfig"],
258
+ "required": ["tsConfig"],
259
259
  "definitions": {
260
260
  "assetPattern": {
261
261
  "oneOf": [
@@ -115,7 +115,7 @@ async function inlineLocales(options) {
115
115
  ast = (0, core_1.parseSync)(options.code, {
116
116
  babelrc: false,
117
117
  configFile: false,
118
- sourceType: 'script',
118
+ sourceType: 'unambiguous',
119
119
  filename: options.filename,
120
120
  });
121
121
  }
@@ -6,5 +6,8 @@
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
8
  /// <reference types="node" />
9
+ import type { Config } from '@angular/service-worker/config';
9
10
  import { promises as fsPromises } from 'fs';
10
11
  export declare function augmentAppWithServiceWorker(appRoot: string, workspaceRoot: string, outputPath: string, baseHref: string, ngswConfigPath?: string, inputputFileSystem?: typeof fsPromises, outputFileSystem?: typeof fsPromises): Promise<void>;
12
+ export declare function augmentAppWithServiceWorkerEsbuild(workspaceRoot: string, configPath: string, outputPath: string, baseHref: string): Promise<void>;
13
+ export declare function augmentAppWithServiceWorkerCore(config: Config, outputPath: string, baseHref: string, inputputFileSystem?: typeof fsPromises, outputFileSystem?: typeof fsPromises): Promise<void>;
@@ -30,7 +30,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
30
30
  return result;
31
31
  };
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.augmentAppWithServiceWorker = void 0;
33
+ exports.augmentAppWithServiceWorkerCore = exports.augmentAppWithServiceWorkerEsbuild = exports.augmentAppWithServiceWorker = void 0;
34
34
  const crypto = __importStar(require("crypto"));
35
35
  const fs_1 = require("fs");
36
36
  const path = __importStar(require("path"));
@@ -100,6 +100,33 @@ async function augmentAppWithServiceWorker(appRoot, workspaceRoot, outputPath, b
100
100
  throw error;
101
101
  }
102
102
  }
103
+ return augmentAppWithServiceWorkerCore(config, outputPath, baseHref, inputputFileSystem, outputFileSystem);
104
+ }
105
+ exports.augmentAppWithServiceWorker = augmentAppWithServiceWorker;
106
+ // This is currently used by the esbuild-based builder
107
+ async function augmentAppWithServiceWorkerEsbuild(workspaceRoot, configPath, outputPath, baseHref) {
108
+ // Read the configuration file
109
+ let config;
110
+ try {
111
+ const configurationData = await fs_1.promises.readFile(configPath, 'utf-8');
112
+ config = JSON.parse(configurationData);
113
+ }
114
+ catch (error) {
115
+ (0, error_1.assertIsError)(error);
116
+ if (error.code === 'ENOENT') {
117
+ // TODO: Generate an error object that can be consumed by the esbuild-based builder
118
+ const message = `Service worker configuration file "${path.relative(workspaceRoot, configPath)}" could not be found.`;
119
+ throw new Error(message);
120
+ }
121
+ else {
122
+ throw error;
123
+ }
124
+ }
125
+ // TODO: Return the output files and any errors/warnings
126
+ return augmentAppWithServiceWorkerCore(config, outputPath, baseHref);
127
+ }
128
+ exports.augmentAppWithServiceWorkerEsbuild = augmentAppWithServiceWorkerEsbuild;
129
+ async function augmentAppWithServiceWorkerCore(config, outputPath, baseHref, inputputFileSystem = fs_1.promises, outputFileSystem = fs_1.promises) {
103
130
  // Load ESM `@angular/service-worker/config` using the TypeScript dynamic import workaround.
104
131
  // Once TypeScript provides support for keeping the dynamic import this workaround can be
105
132
  // changed to a direct dynamic import.
@@ -135,4 +162,4 @@ async function augmentAppWithServiceWorker(appRoot, workspaceRoot, outputPath, b
135
162
  }
136
163
  }
137
164
  }
138
- exports.augmentAppWithServiceWorker = augmentAppWithServiceWorker;
165
+ exports.augmentAppWithServiceWorkerCore = augmentAppWithServiceWorkerCore;
@@ -114,7 +114,7 @@ async function getCommonConfig(wco) {
114
114
  }
115
115
  // process global scripts
116
116
  // Add a new asset for each entry.
117
- for (const { bundleName, inject, paths } of (0, helpers_1.globalScriptsByBundleName)(root, buildOptions.scripts)) {
117
+ for (const { bundleName, inject, paths } of (0, helpers_1.globalScriptsByBundleName)(buildOptions.scripts)) {
118
118
  // Lazy scripts don't get a hash, otherwise they can't be loaded by name.
119
119
  const hash = inject ? hashFormat.script : '';
120
120
  extraPlugins.push(new plugins_1.ScriptsWebpackPlugin({
@@ -122,7 +122,7 @@ async function getCommonConfig(wco) {
122
122
  sourceMap: scriptsSourceMap,
123
123
  scripts: paths,
124
124
  filename: `${path.basename(bundleName)}${hash}.js`,
125
- basePath: projectRoot,
125
+ basePath: root,
126
126
  }));
127
127
  }
128
128
  // process asset entries
@@ -5,12 +5,6 @@
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 { Configuration } from 'webpack';
9
- import { StyleElement } from '../../builders/browser/schema';
8
+ import type { Configuration } from 'webpack';
10
9
  import { WebpackConfigOptions } from '../../utils/build-options';
11
- export declare function resolveGlobalStyles(styleEntrypoints: StyleElement[], root: string, preserveSymlinks: boolean, skipResolution?: boolean): {
12
- entryPoints: Record<string, string[]>;
13
- noInjectNames: string[];
14
- paths: string[];
15
- };
16
10
  export declare function getStylesConfig(wco: WebpackConfigOptions): Configuration;
@@ -33,54 +33,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
33
33
  return (mod && mod.__esModule) ? mod : { "default": mod };
34
34
  };
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.getStylesConfig = exports.resolveGlobalStyles = void 0;
36
+ exports.getStylesConfig = void 0;
37
37
  const fs = __importStar(require("fs"));
38
38
  const mini_css_extract_plugin_1 = __importDefault(require("mini-css-extract-plugin"));
39
39
  const path = __importStar(require("path"));
40
+ const url_1 = require("url");
40
41
  const sass_service_1 = require("../../sass/sass-service");
41
42
  const sass_service_legacy_1 = require("../../sass/sass-service-legacy");
42
43
  const environment_options_1 = require("../../utils/environment-options");
43
44
  const plugins_1 = require("../plugins");
44
45
  const css_optimizer_plugin_1 = require("../plugins/css-optimizer-plugin");
46
+ const styles_webpack_plugin_1 = require("../plugins/styles-webpack-plugin");
45
47
  const helpers_1 = require("../utils/helpers");
46
- function resolveGlobalStyles(styleEntrypoints, root, preserveSymlinks, skipResolution = false) {
47
- const entryPoints = {};
48
- const noInjectNames = [];
49
- const paths = [];
50
- if (styleEntrypoints.length === 0) {
51
- return { entryPoints, noInjectNames, paths };
52
- }
53
- for (const style of (0, helpers_1.normalizeExtraEntryPoints)(styleEntrypoints, 'styles')) {
54
- let stylesheetPath = style.input;
55
- if (!skipResolution) {
56
- stylesheetPath = path.resolve(root, stylesheetPath);
57
- if (!fs.existsSync(stylesheetPath)) {
58
- try {
59
- stylesheetPath = require.resolve(style.input, { paths: [root] });
60
- }
61
- catch { }
62
- }
63
- }
64
- if (!preserveSymlinks) {
65
- stylesheetPath = fs.realpathSync(stylesheetPath);
66
- }
67
- // Add style entry points.
68
- if (entryPoints[style.bundleName]) {
69
- entryPoints[style.bundleName].push(stylesheetPath);
70
- }
71
- else {
72
- entryPoints[style.bundleName] = [stylesheetPath];
73
- }
74
- // Add non injected styles to the list.
75
- if (!style.inject) {
76
- noInjectNames.push(style.bundleName);
77
- }
78
- // Add global css paths.
79
- paths.push(stylesheetPath);
80
- }
81
- return { entryPoints, noInjectNames, paths };
82
- }
83
- exports.resolveGlobalStyles = resolveGlobalStyles;
84
48
  // eslint-disable-next-line max-lines-per-function
85
49
  function getStylesConfig(wco) {
86
50
  var _a, _b, _c;
@@ -93,10 +57,17 @@ function getStylesConfig(wco) {
93
57
  // use includePaths from appConfig
94
58
  const includePaths = (_c = (_b = (_a = buildOptions.stylePreprocessorOptions) === null || _a === void 0 ? void 0 : _a.includePaths) === null || _b === void 0 ? void 0 : _b.map((p) => path.resolve(root, p))) !== null && _c !== void 0 ? _c : [];
95
59
  // Process global styles.
96
- const { entryPoints, noInjectNames, paths: globalStylePaths, } = resolveGlobalStyles(buildOptions.styles, root, !!buildOptions.preserveSymlinks);
97
- if (noInjectNames.length > 0) {
98
- // Add plugin to remove hashes from lazy styles.
99
- extraPlugins.push(new plugins_1.RemoveHashPlugin({ chunkNames: noInjectNames, hashFormat }));
60
+ if (buildOptions.styles.length > 0) {
61
+ const { entryPoints, noInjectNames } = (0, helpers_1.normalizeGlobalStyles)(buildOptions.styles);
62
+ extraPlugins.push(new styles_webpack_plugin_1.StylesWebpackPlugin({
63
+ root,
64
+ entryPoints,
65
+ preserveSymlinks: buildOptions.preserveSymlinks,
66
+ }));
67
+ if (noInjectNames.length > 0) {
68
+ // Add plugin to remove hashes from lazy styles.
69
+ extraPlugins.push(new plugins_1.RemoveHashPlugin({ chunkNames: noInjectNames, hashFormat }));
70
+ }
100
71
  }
101
72
  const sassImplementation = environment_options_1.useLegacySass
102
73
  ? new sass_service_legacy_1.SassLegacyWorkerImplementation()
@@ -238,7 +209,7 @@ function getStylesConfig(wco) {
238
209
  },
239
210
  {
240
211
  loader: require.resolve('sass-loader'),
241
- options: getSassLoaderOptions(root, projectRoot, sassImplementation, includePaths, false, !buildOptions.verbose),
212
+ options: getSassLoaderOptions(root, sassImplementation, includePaths, false, !buildOptions.verbose, !!buildOptions.preserveSymlinks),
242
213
  },
243
214
  ],
244
215
  },
@@ -253,7 +224,7 @@ function getStylesConfig(wco) {
253
224
  },
254
225
  {
255
226
  loader: require.resolve('sass-loader'),
256
- options: getSassLoaderOptions(root, projectRoot, sassImplementation, includePaths, true, !buildOptions.verbose),
227
+ options: getSassLoaderOptions(root, sassImplementation, includePaths, true, !buildOptions.verbose, !!buildOptions.preserveSymlinks),
257
228
  },
258
229
  ],
259
230
  },
@@ -275,7 +246,6 @@ function getStylesConfig(wco) {
275
246
  },
276
247
  ];
277
248
  return {
278
- entry: entryPoints,
279
249
  module: {
280
250
  rules: styleLanguages.map(({ extensions, use }) => ({
281
251
  test: new RegExp(`\\.(?:${extensions.join('|')})$`, 'i'),
@@ -286,8 +256,7 @@ function getStylesConfig(wco) {
286
256
  // Global styles are only defined global styles
287
257
  {
288
258
  use: globalStyleLoaders,
289
- include: globalStylePaths,
290
- resourceQuery: { not: [/\?ngResource/] },
259
+ resourceQuery: /\?ngGlobalStyle/,
291
260
  },
292
261
  // Component styles are all styles except defined global styles
293
262
  {
@@ -330,24 +299,18 @@ function getTailwindConfigPath({ projectRoot, root }) {
330
299
  }
331
300
  return undefined;
332
301
  }
333
- function getSassLoaderOptions(root, projectRoot, implementation, includePaths, indentedSyntax, verbose) {
302
+ function getSassLoaderOptions(root, implementation, includePaths, indentedSyntax, verbose, preserveSymlinks) {
334
303
  return implementation instanceof sass_service_1.SassWorkerImplementation
335
304
  ? {
336
305
  sourceMap: true,
337
306
  api: 'modern',
338
307
  implementation,
339
- // Webpack importer is only implemented in the legacy API.
308
+ // Webpack importer is only implemented in the legacy API and we have our own custom Webpack importer.
340
309
  // See: https://github.com/webpack-contrib/sass-loader/blob/997f3eb41d86dd00d5fa49c395a1aeb41573108c/src/utils.js#L642-L651
341
310
  webpackImporter: false,
342
- sassOptions: {
343
- loadPaths: [
344
- ...includePaths,
345
- // Needed to resolve node packages and retain the same behaviour of with the legacy API as sass-loader resolves
346
- // scss also from the cwd and project root.
347
- // See: https://github.com/webpack-contrib/sass-loader/blob/997f3eb41d86dd00d5fa49c395a1aeb41573108c/src/utils.js#L307
348
- projectRoot,
349
- path.join(root, 'node_modules'),
350
- ],
311
+ sassOptions: (loaderContext) => ({
312
+ importers: [getSassResolutionImporter(loaderContext, root, preserveSymlinks)],
313
+ loadPaths: includePaths,
351
314
  // Use expanded as otherwise sass will remove comments that are needed for autoprefixer
352
315
  // Ex: /* autoprefixer grid: autoplace */
353
316
  // See: https://github.com/webpack-contrib/sass-loader/blob/45ad0be17264ceada5f0b4fb87e9357abe85c4ff/src/getSassOptions.js#L68-L70
@@ -356,7 +319,7 @@ function getSassLoaderOptions(root, projectRoot, implementation, includePaths, i
356
319
  quietDeps: !verbose,
357
320
  verbose,
358
321
  syntax: indentedSyntax ? 'indented' : 'scss',
359
- },
322
+ }),
360
323
  }
361
324
  : {
362
325
  sourceMap: true,
@@ -385,3 +348,33 @@ function getSassLoaderOptions(root, projectRoot, implementation, includePaths, i
385
348
  },
386
349
  };
387
350
  }
351
+ function getSassResolutionImporter(loaderContext, root, preserveSymlinks) {
352
+ const commonResolverOptions = {
353
+ conditionNames: ['sass', 'style'],
354
+ mainFields: ['sass', 'style', 'main', '...'],
355
+ extensions: ['.scss', '.sass', '.css'],
356
+ restrictions: [/\.((sa|sc|c)ss)$/i],
357
+ preferRelative: true,
358
+ symlinks: !preserveSymlinks,
359
+ };
360
+ // Sass also supports import-only files. If you name a file <name>.import.scss, it will only be loaded for imports, not for @uses.
361
+ // See: https://sass-lang.com/documentation/at-rules/import#import-only-files
362
+ const resolveImport = loaderContext.getResolve({
363
+ ...commonResolverOptions,
364
+ dependencyType: 'sass-import',
365
+ mainFiles: ['_index.import', '_index', 'index.import', 'index', '...'],
366
+ });
367
+ const resolveModule = loaderContext.getResolve({
368
+ ...commonResolverOptions,
369
+ dependencyType: 'sass-module',
370
+ mainFiles: ['_index', 'index', '...'],
371
+ });
372
+ return {
373
+ findFileUrl: (url, { fromImport }) => {
374
+ const resolve = fromImport ? resolveImport : resolveModule;
375
+ return resolve(root, url)
376
+ .then((file) => (0, url_1.pathToFileURL)(file))
377
+ .catch(() => null);
378
+ },
379
+ };
380
+ }
@@ -34,6 +34,8 @@ exports.ScriptsWebpackPlugin = void 0;
34
34
  const loader_utils_1 = require("loader-utils");
35
35
  const path = __importStar(require("path"));
36
36
  const webpack_1 = require("webpack");
37
+ const error_1 = require("../../utils/error");
38
+ const webpack_diagnostics_1 = require("../../utils/webpack-diagnostics");
37
39
  const Entrypoint = require('webpack/lib/Entrypoint');
38
40
  /**
39
41
  * The name of the plugin provided to Webpack when tapping Webpack compiler hooks.
@@ -81,18 +83,35 @@ class ScriptsWebpackPlugin {
81
83
  chunk.addGroup(entrypoint);
82
84
  compilation.entrypoints.set(this.options.name, entrypoint);
83
85
  compilation.chunks.add(chunk);
84
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
85
86
  compilation.assets[filename] = source;
86
87
  compilation.hooks.chunkAsset.call(chunk, filename);
87
88
  }
88
89
  apply(compiler) {
89
- if (!this.options.scripts || this.options.scripts.length === 0) {
90
+ if (this.options.scripts.length === 0) {
90
91
  return;
91
92
  }
92
- const scripts = this.options.scripts
93
- .filter((script) => !!script)
94
- .map((script) => path.resolve(this.options.basePath || '', script));
93
+ const resolver = compiler.resolverFactory.get('normal', {
94
+ preferRelative: true,
95
+ useSyncFileSystemCalls: true,
96
+ fileSystem: compiler.inputFileSystem,
97
+ });
95
98
  compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
99
+ const scripts = [];
100
+ for (const script of this.options.scripts) {
101
+ try {
102
+ const resolvedPath = resolver.resolveSync({}, this.options.basePath, script);
103
+ if (resolvedPath) {
104
+ scripts.push(resolvedPath);
105
+ }
106
+ else {
107
+ (0, webpack_diagnostics_1.addError)(compilation, `Cannot resolve '${script}'.`);
108
+ }
109
+ }
110
+ catch (error) {
111
+ (0, error_1.assertIsError)(error);
112
+ (0, webpack_diagnostics_1.addError)(compilation, error.message);
113
+ }
114
+ }
96
115
  compilation.hooks.additionalAssets.tapPromise(PLUGIN_NAME, async () => {
97
116
  if (await this.shouldSkip(compilation, scripts)) {
98
117
  if (this._cachedOutput) {
@@ -0,0 +1,19 @@
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.io/license
7
+ */
8
+ import type { Compiler } from 'webpack';
9
+ export interface StylesWebpackPluginOptions {
10
+ preserveSymlinks?: boolean;
11
+ root: string;
12
+ entryPoints: Record<string, string[]>;
13
+ }
14
+ export declare class StylesWebpackPlugin {
15
+ private readonly options;
16
+ private compilation;
17
+ constructor(options: StylesWebpackPluginOptions);
18
+ apply(compiler: Compiler): void;
19
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.io/license
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.StylesWebpackPlugin = void 0;
14
+ const assert_1 = __importDefault(require("assert"));
15
+ const error_1 = require("../../utils/error");
16
+ const webpack_diagnostics_1 = require("../../utils/webpack-diagnostics");
17
+ /**
18
+ * The name of the plugin provided to Webpack when tapping Webpack compiler hooks.
19
+ */
20
+ const PLUGIN_NAME = 'styles-webpack-plugin';
21
+ class StylesWebpackPlugin {
22
+ constructor(options) {
23
+ this.options = options;
24
+ }
25
+ apply(compiler) {
26
+ const { entryPoints, preserveSymlinks, root } = this.options;
27
+ const webpackOptions = compiler.options;
28
+ const entry = typeof webpackOptions.entry === 'function' ? webpackOptions.entry() : webpackOptions.entry;
29
+ const resolver = compiler.resolverFactory.get('global-styles', {
30
+ conditionNames: ['sass', 'less', 'style'],
31
+ mainFields: ['sass', 'less', 'style', 'main', '...'],
32
+ extensions: ['.scss', '.sass', '.less', '.css'],
33
+ restrictions: [/\.((le|sa|sc|c)ss)$/i],
34
+ preferRelative: true,
35
+ useSyncFileSystemCalls: true,
36
+ symlinks: !preserveSymlinks,
37
+ fileSystem: compiler.inputFileSystem,
38
+ });
39
+ webpackOptions.entry = async () => {
40
+ var _a, _b;
41
+ var _c;
42
+ const entrypoints = await entry;
43
+ for (const [bundleName, paths] of Object.entries(entryPoints)) {
44
+ (_a = entrypoints[bundleName]) !== null && _a !== void 0 ? _a : (entrypoints[bundleName] = {});
45
+ const entryImport = ((_b = (_c = entrypoints[bundleName]).import) !== null && _b !== void 0 ? _b : (_c.import = []));
46
+ for (const path of paths) {
47
+ try {
48
+ const resolvedPath = resolver.resolveSync({}, root, path);
49
+ if (resolvedPath) {
50
+ entryImport.push(`${resolvedPath}?ngGlobalStyle`);
51
+ }
52
+ else {
53
+ (0, assert_1.default)(this.compilation, 'Compilation cannot be undefined.');
54
+ (0, webpack_diagnostics_1.addError)(this.compilation, `Cannot resolve '${path}'.`);
55
+ }
56
+ }
57
+ catch (error) {
58
+ (0, assert_1.default)(this.compilation, 'Compilation cannot be undefined.');
59
+ (0, error_1.assertIsError)(error);
60
+ (0, webpack_diagnostics_1.addError)(this.compilation, error.message);
61
+ }
62
+ }
63
+ }
64
+ return entrypoints;
65
+ };
66
+ compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
67
+ this.compilation = compilation;
68
+ });
69
+ }
70
+ }
71
+ exports.StylesWebpackPlugin = StylesWebpackPlugin;
@@ -21,8 +21,12 @@ export declare type NormalizedEntryPoint = Required<Exclude<ScriptElement | Styl
21
21
  export declare function normalizeExtraEntryPoints(extraEntryPoints: (ScriptElement | StyleElement)[], defaultBundleName: string): NormalizedEntryPoint[];
22
22
  export declare function assetNameTemplateFactory(hashFormat: HashFormat): (resourcePath: string) => string;
23
23
  export declare function getInstrumentationExcludedPaths(root: string, excludedPaths: string[]): Set<string>;
24
+ export declare function normalizeGlobalStyles(styleEntrypoints: StyleElement[]): {
25
+ entryPoints: Record<string, string[]>;
26
+ noInjectNames: string[];
27
+ };
24
28
  export declare function getCacheSettings(wco: WebpackConfigOptions, angularVersion: string): WebpackOptionsNormalized['cache'];
25
- export declare function globalScriptsByBundleName(root: string, scripts: ScriptElement[]): {
29
+ export declare function globalScriptsByBundleName(scripts: ScriptElement[]): {
26
30
  bundleName: string;
27
31
  inject: boolean;
28
32
  paths: string[];
@@ -33,9 +33,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
33
33
  return (mod && mod.__esModule) ? mod : { "default": mod };
34
34
  };
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.getStatsOptions = exports.assetPatterns = exports.globalScriptsByBundleName = exports.getCacheSettings = exports.getInstrumentationExcludedPaths = exports.assetNameTemplateFactory = exports.normalizeExtraEntryPoints = exports.getOutputHashFormat = void 0;
36
+ exports.getStatsOptions = exports.assetPatterns = exports.globalScriptsByBundleName = exports.getCacheSettings = exports.normalizeGlobalStyles = exports.getInstrumentationExcludedPaths = exports.assetNameTemplateFactory = exports.normalizeExtraEntryPoints = exports.getOutputHashFormat = void 0;
37
37
  const crypto_1 = require("crypto");
38
- const fs_1 = require("fs");
39
38
  const glob_1 = __importDefault(require("glob"));
40
39
  const path = __importStar(require("path"));
41
40
  const schema_1 = require("../../builders/browser/schema");
@@ -130,6 +129,26 @@ function getInstrumentationExcludedPaths(root, excludedPaths) {
130
129
  return excluded;
131
130
  }
132
131
  exports.getInstrumentationExcludedPaths = getInstrumentationExcludedPaths;
132
+ function normalizeGlobalStyles(styleEntrypoints) {
133
+ var _a;
134
+ var _b;
135
+ const entryPoints = {};
136
+ const noInjectNames = [];
137
+ if (styleEntrypoints.length === 0) {
138
+ return { entryPoints, noInjectNames };
139
+ }
140
+ for (const style of normalizeExtraEntryPoints(styleEntrypoints, 'styles')) {
141
+ // Add style entry points.
142
+ (_a = entryPoints[_b = style.bundleName]) !== null && _a !== void 0 ? _a : (entryPoints[_b] = []);
143
+ entryPoints[style.bundleName].push(style.input);
144
+ // Add non injected styles to the list.
145
+ if (!style.inject) {
146
+ noInjectNames.push(style.bundleName);
147
+ }
148
+ }
149
+ return { entryPoints, noInjectNames };
150
+ }
151
+ exports.normalizeGlobalStyles = normalizeGlobalStyles;
133
152
  function getCacheSettings(wco, angularVersion) {
134
153
  const { enabled, path: cacheDirectory } = wco.buildOptions.cache;
135
154
  if (enabled) {
@@ -164,31 +183,22 @@ function getCacheSettings(wco, angularVersion) {
164
183
  return false;
165
184
  }
166
185
  exports.getCacheSettings = getCacheSettings;
167
- function globalScriptsByBundleName(root, scripts) {
186
+ function globalScriptsByBundleName(scripts) {
168
187
  return normalizeExtraEntryPoints(scripts, 'scripts').reduce((prev, curr) => {
169
188
  const { bundleName, inject, input } = curr;
170
- let resolvedPath = path.resolve(root, input);
171
- if (!(0, fs_1.existsSync)(resolvedPath)) {
172
- try {
173
- resolvedPath = require.resolve(input, { paths: [root] });
174
- }
175
- catch {
176
- throw new Error(`Script file ${input} does not exist.`);
177
- }
178
- }
179
189
  const existingEntry = prev.find((el) => el.bundleName === bundleName);
180
190
  if (existingEntry) {
181
191
  if (existingEntry.inject && !inject) {
182
192
  // All entries have to be lazy for the bundle to be lazy.
183
193
  throw new Error(`The ${bundleName} bundle is mixing injected and non-injected scripts.`);
184
194
  }
185
- existingEntry.paths.push(resolvedPath);
195
+ existingEntry.paths.push(input);
186
196
  }
187
197
  else {
188
198
  prev.push({
189
199
  bundleName,
190
200
  inject,
191
- paths: [resolvedPath],
201
+ paths: [input],
192
202
  });
193
203
  }
194
204
  return prev;