@angular-devkit/build-angular 18.0.0-next.0 → 18.0.0-next.2

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 (31) hide show
  1. package/package.json +14 -14
  2. package/src/builders/application/execute-post-bundle.js +1 -1
  3. package/src/builders/application/options.d.ts +3 -1
  4. package/src/builders/application/options.js +11 -8
  5. package/src/builders/application/schema.d.ts +1 -1
  6. package/src/builders/application/schema.json +2 -1
  7. package/src/builders/browser/schema.d.ts +1 -1
  8. package/src/builders/browser/schema.json +2 -1
  9. package/src/builders/browser-esbuild/schema.d.ts +1 -1
  10. package/src/builders/browser-esbuild/schema.json +2 -1
  11. package/src/builders/karma/schema.d.ts +1 -1
  12. package/src/builders/karma/schema.json +2 -1
  13. package/src/builders/server/schema.d.ts +1 -1
  14. package/src/builders/server/schema.json +2 -1
  15. package/src/builders/web-test-runner/schema.d.ts +1 -1
  16. package/src/builders/web-test-runner/schema.json +2 -1
  17. package/src/tools/babel/plugins/index.d.ts +11 -0
  18. package/src/tools/babel/plugins/index.js +21 -0
  19. package/src/tools/babel/presets/application.js +4 -3
  20. package/src/tools/esbuild/javascript-transformer-worker.js +82 -26
  21. package/src/tools/sass/rebasing-importer.js +16 -6
  22. package/src/tools/webpack/utils/helpers.js +1 -1
  23. package/src/utils/index-file/inline-fonts.d.ts +0 -2
  24. package/src/utils/index-file/inline-fonts.js +3 -5
  25. package/src/utils/normalize-asset-patterns.d.ts +3 -1
  26. package/src/utils/normalize-asset-patterns.js +6 -1
  27. package/src/utils/normalize-cache.js +5 -4
  28. package/src/utils/postcss-configuration.d.ts +7 -1
  29. package/src/utils/postcss-configuration.js +13 -4
  30. package/src/utils/service-worker.d.ts +1 -1
  31. package/src/utils/service-worker.js +4 -1
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "18.0.0-next.0",
3
+ "version": "18.0.0-next.2",
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.3.0",
10
- "@angular-devkit/architect": "0.1800.0-next.0",
11
- "@angular-devkit/build-webpack": "0.1800.0-next.0",
12
- "@angular-devkit/core": "18.0.0-next.0",
10
+ "@angular-devkit/architect": "0.1800.0-next.2",
11
+ "@angular-devkit/build-webpack": "0.1800.0-next.2",
12
+ "@angular-devkit/core": "18.0.0-next.2",
13
13
  "@babel/core": "7.24.3",
14
14
  "@babel/generator": "7.24.1",
15
15
  "@babel/helper-annotate-as-pure": "7.22.5",
@@ -20,10 +20,10 @@
20
20
  "@babel/preset-env": "7.24.3",
21
21
  "@babel/runtime": "7.24.1",
22
22
  "@discoveryjs/json-ext": "0.5.7",
23
- "@ngtools/webpack": "18.0.0-next.0",
23
+ "@ngtools/webpack": "18.0.0-next.2",
24
24
  "@vitejs/plugin-basic-ssl": "1.1.0",
25
25
  "ansi-colors": "4.1.3",
26
- "autoprefixer": "10.4.18",
26
+ "autoprefixer": "10.4.19",
27
27
  "babel-loader": "9.1.3",
28
28
  "babel-plugin-istanbul": "6.1.1",
29
29
  "browserslist": "^4.21.5",
@@ -34,7 +34,7 @@
34
34
  "fast-glob": "3.3.2",
35
35
  "https-proxy-agent": "7.0.4",
36
36
  "http-proxy-middleware": "2.0.6",
37
- "inquirer": "9.2.16",
37
+ "inquirer": "9.2.17",
38
38
  "jsonc-parser": "3.2.1",
39
39
  "karma-source-map-support": "1.4.0",
40
40
  "less": "4.2.0",
@@ -47,9 +47,9 @@
47
47
  "open": "8.4.2",
48
48
  "ora": "5.4.1",
49
49
  "parse5-html-rewriting-stream": "7.0.0",
50
- "picomatch": "4.0.1",
50
+ "picomatch": "4.0.2",
51
51
  "piscina": "4.4.0",
52
- "postcss": "8.4.37",
52
+ "postcss": "8.4.38",
53
53
  "postcss-loader": "8.1.1",
54
54
  "resolve-url-loader": "5.0.0",
55
55
  "rxjs": "7.8.1",
@@ -58,14 +58,14 @@
58
58
  "semver": "7.6.0",
59
59
  "source-map-loader": "5.0.0",
60
60
  "source-map-support": "0.5.21",
61
- "terser": "5.29.2",
61
+ "terser": "5.30.2",
62
62
  "tree-kill": "1.2.2",
63
63
  "tslib": "2.6.2",
64
- "undici": "6.9.0",
65
- "vite": "5.2.2",
64
+ "undici": "6.11.1",
65
+ "vite": "5.2.7",
66
66
  "watchpack": "2.4.1",
67
67
  "webpack": "5.91.0",
68
- "webpack-dev-middleware": "7.1.1",
68
+ "webpack-dev-middleware": "7.2.1",
69
69
  "webpack-dev-server": "5.0.4",
70
70
  "webpack-merge": "5.10.0",
71
71
  "webpack-subresource-integrity": "5.1.0"
@@ -86,7 +86,7 @@
86
86
  "ng-packagr": "^18.0.0-next.0",
87
87
  "protractor": "^7.0.0",
88
88
  "tailwindcss": "^2.0.0 || ^3.0.0",
89
- "typescript": ">=5.2 <5.5"
89
+ "typescript": ">=5.4 <5.5"
90
90
  },
91
91
  "peerDependenciesMeta": {
92
92
  "@angular/localize": {
@@ -75,7 +75,7 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
75
75
  // If localization is enabled, service worker is handled in the inlining process.
76
76
  if (serviceWorker) {
77
77
  try {
78
- const serviceWorkerResult = await (0, service_worker_1.augmentAppWithServiceWorkerEsbuild)(workspaceRoot, serviceWorker, options.baseHref || '/',
78
+ const serviceWorkerResult = await (0, service_worker_1.augmentAppWithServiceWorkerEsbuild)(workspaceRoot, serviceWorker, options.baseHref || '/', options.indexHtmlOptions?.output,
79
79
  // Ensure additional files recently added are used
80
80
  [...outputFiles, ...additionalOutputFiles], assetFiles);
81
81
  additionalOutputFiles.push((0, utils_1.createOutputFileFromText)('ngsw.json', serviceWorkerResult.manifest, bundler_context_1.BuildOutputFileType.Browser));
@@ -99,7 +99,9 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
99
99
  sourcemapOptions: import("../..").SourceMapObject;
100
100
  tsconfig: string;
101
101
  projectRoot: string;
102
- assets: import("../..").AssetPatternObject[] | undefined;
102
+ assets: (import("../..").AssetPatternObject & {
103
+ output: string;
104
+ })[] | undefined;
103
105
  outputNames: {
104
106
  bundles: string;
105
107
  media: string;
@@ -21,7 +21,6 @@ const environment_options_1 = require("../../utils/environment-options");
21
21
  const i18n_options_1 = require("../../utils/i18n-options");
22
22
  const normalize_cache_1 = require("../../utils/normalize-cache");
23
23
  const postcss_configuration_1 = require("../../utils/postcss-configuration");
24
- const tailwind_1 = require("../../utils/tailwind");
25
24
  const schema_1 = require("./schema");
26
25
  /**
27
26
  * Normalize the user provided options by creating full paths for all path based options
@@ -108,11 +107,13 @@ async function normalizeOptions(context, projectName, options, extensions) {
108
107
  loaderExtensions[extension] = value;
109
108
  }
110
109
  }
111
- const postcssConfiguration = await (0, postcss_configuration_1.loadPostcssConfiguration)(workspaceRoot, projectRoot);
110
+ // A configuration file can exist in the project or workspace root
111
+ const searchDirectories = await (0, postcss_configuration_1.generateSearchDirectories)([projectRoot, workspaceRoot]);
112
+ const postcssConfiguration = await (0, postcss_configuration_1.loadPostcssConfiguration)(searchDirectories);
112
113
  // Skip tailwind configuration if postcss is customized
113
114
  const tailwindConfiguration = postcssConfiguration
114
115
  ? undefined
115
- : await getTailwindConfig(workspaceRoot, projectRoot, context);
116
+ : await getTailwindConfig(searchDirectories, workspaceRoot, context);
116
117
  const globalStyles = normalizeGlobalEntries(options.styles, 'styles');
117
118
  const globalScripts = normalizeGlobalEntries(options.scripts, 'scripts');
118
119
  let indexHtmlOptions;
@@ -211,7 +212,9 @@ async function normalizeOptions(context, projectName, options, extensions) {
211
212
  fileReplacements,
212
213
  globalStyles,
213
214
  globalScripts,
214
- serviceWorker: typeof serviceWorker === 'string' ? node_path_1.default.join(workspaceRoot, serviceWorker) : undefined,
215
+ serviceWorker: serviceWorker
216
+ ? node_path_1.default.join(workspaceRoot, typeof serviceWorker === 'string' ? serviceWorker : 'src/ngsw-config.json')
217
+ : undefined,
215
218
  indexHtmlOptions,
216
219
  tailwindConfiguration,
217
220
  postcssConfiguration,
@@ -228,13 +231,13 @@ async function normalizeOptions(context, projectName, options, extensions) {
228
231
  };
229
232
  }
230
233
  exports.normalizeOptions = normalizeOptions;
231
- async function getTailwindConfig(workspaceRoot, projectRoot, context) {
232
- const tailwindConfigurationPath = await (0, tailwind_1.findTailwindConfigurationFile)(workspaceRoot, projectRoot);
234
+ async function getTailwindConfig(searchDirectories, workspaceRoot, context) {
235
+ const tailwindConfigurationPath = (0, postcss_configuration_1.findTailwindConfiguration)(searchDirectories);
233
236
  if (!tailwindConfigurationPath) {
234
237
  return undefined;
235
238
  }
236
- // Create a node resolver at the project root as a directory
237
- const resolver = (0, node_module_1.createRequire)(projectRoot + '/');
239
+ // Create a node resolver from the configuration file
240
+ const resolver = (0, node_module_1.createRequire)(tailwindConfigurationPath);
238
241
  try {
239
242
  return {
240
243
  file: tailwindConfigurationPath,
@@ -221,7 +221,7 @@ export interface AssetPatternClass {
221
221
  /**
222
222
  * Absolute path within the output.
223
223
  */
224
- output: string;
224
+ output?: string;
225
225
  }
226
226
  export interface Budget {
227
227
  /**
@@ -560,11 +560,12 @@
560
560
  },
561
561
  "output": {
562
562
  "type": "string",
563
+ "default": "",
563
564
  "description": "Absolute path within the output."
564
565
  }
565
566
  },
566
567
  "additionalProperties": false,
567
- "required": ["glob", "input", "output"]
568
+ "required": ["glob", "input"]
568
569
  },
569
570
  {
570
571
  "type": "string"
@@ -196,7 +196,7 @@ export interface AssetPatternClass {
196
196
  /**
197
197
  * Absolute path within the output.
198
198
  */
199
- output: string;
199
+ output?: string;
200
200
  }
201
201
  export interface Budget {
202
202
  /**
@@ -454,11 +454,12 @@
454
454
  },
455
455
  "output": {
456
456
  "type": "string",
457
+ "default": "",
457
458
  "description": "Absolute path within the output."
458
459
  }
459
460
  },
460
461
  "additionalProperties": false,
461
- "required": ["glob", "input", "output"]
462
+ "required": ["glob", "input"]
462
463
  },
463
464
  {
464
465
  "type": "string"
@@ -201,7 +201,7 @@ export interface AssetPatternClass {
201
201
  /**
202
202
  * Absolute path within the output.
203
203
  */
204
- output: string;
204
+ output?: string;
205
205
  }
206
206
  export interface Budget {
207
207
  /**
@@ -466,11 +466,12 @@
466
466
  },
467
467
  "output": {
468
468
  "type": "string",
469
+ "default": "",
469
470
  "description": "Absolute path within the output."
470
471
  }
471
472
  },
472
473
  "additionalProperties": false,
473
- "required": ["glob", "input", "output"]
474
+ "required": ["glob", "input"]
474
475
  },
475
476
  {
476
477
  "type": "string"
@@ -115,7 +115,7 @@ export interface AssetPatternClass {
115
115
  /**
116
116
  * Absolute path within the output.
117
117
  */
118
- output: string;
118
+ output?: string;
119
119
  }
120
120
  /**
121
121
  * Override which browsers tests are run against. Set to `false` to not use any browser.
@@ -290,6 +290,7 @@
290
290
  },
291
291
  "output": {
292
292
  "type": "string",
293
+ "default": "",
293
294
  "description": "Absolute path within the output."
294
295
  },
295
296
  "ignore": {
@@ -301,7 +302,7 @@
301
302
  }
302
303
  },
303
304
  "additionalProperties": false,
304
- "required": ["glob", "input", "output"]
305
+ "required": ["glob", "input"]
305
306
  },
306
307
  {
307
308
  "type": "string"
@@ -139,7 +139,7 @@ export interface AssetPatternClass {
139
139
  /**
140
140
  * Absolute path within the output.
141
141
  */
142
- output: string;
142
+ output?: string;
143
143
  }
144
144
  export interface FileReplacement {
145
145
  replace?: string;
@@ -251,11 +251,12 @@
251
251
  },
252
252
  "output": {
253
253
  "type": "string",
254
+ "default": "",
254
255
  "description": "Absolute path within the output."
255
256
  }
256
257
  },
257
258
  "additionalProperties": false,
258
- "required": ["glob", "input", "output"]
259
+ "required": ["glob", "input"]
259
260
  },
260
261
  {
261
262
  "type": "string"
@@ -107,7 +107,7 @@ export interface AssetPatternClass {
107
107
  /**
108
108
  * Absolute path within the output.
109
109
  */
110
- output: string;
110
+ output?: string;
111
111
  }
112
112
  export interface FileReplacement {
113
113
  replace?: string;
@@ -269,6 +269,7 @@
269
269
  },
270
270
  "output": {
271
271
  "type": "string",
272
+ "default": "",
272
273
  "description": "Absolute path within the output."
273
274
  },
274
275
  "ignore": {
@@ -280,7 +281,7 @@
280
281
  }
281
282
  },
282
283
  "additionalProperties": false,
283
- "required": ["glob", "input", "output"]
284
+ "required": ["glob", "input"]
284
285
  },
285
286
  {
286
287
  "type": "string"
@@ -0,0 +1,11 @@
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
+ export { default as adjustStaticMembers } from './adjust-static-class-members';
9
+ export { default as adjustTypeScriptEnums } from './adjust-typescript-enums';
10
+ export { default as elideAngularMetadata } from './elide-angular-metadata';
11
+ export { default as markTopLevelPure } from './pure-toplevel-functions';
@@ -0,0 +1,21 @@
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.markTopLevelPure = exports.elideAngularMetadata = exports.adjustTypeScriptEnums = exports.adjustStaticMembers = void 0;
14
+ var adjust_static_class_members_1 = require("./adjust-static-class-members");
15
+ Object.defineProperty(exports, "adjustStaticMembers", { enumerable: true, get: function () { return __importDefault(adjust_static_class_members_1).default; } });
16
+ var adjust_typescript_enums_1 = require("./adjust-typescript-enums");
17
+ Object.defineProperty(exports, "adjustTypeScriptEnums", { enumerable: true, get: function () { return __importDefault(adjust_typescript_enums_1).default; } });
18
+ var elide_angular_metadata_1 = require("./elide-angular-metadata");
19
+ Object.defineProperty(exports, "elideAngularMetadata", { enumerable: true, get: function () { return __importDefault(elide_angular_metadata_1).default; } });
20
+ var pure_toplevel_functions_1 = require("./pure-toplevel-functions");
21
+ Object.defineProperty(exports, "markTopLevelPure", { enumerable: true, get: function () { return __importDefault(pure_toplevel_functions_1).default; } });
@@ -147,11 +147,12 @@ function default_1(api, options) {
147
147
  needRuntimeTransform = true;
148
148
  }
149
149
  if (options.optimize) {
150
+ const { adjustStaticMembers, adjustTypeScriptEnums, elideAngularMetadata, markTopLevelPure, } = require('../plugins');
150
151
  if (options.optimize.pureTopLevel) {
151
- plugins.push(require('../plugins/pure-toplevel-functions').default);
152
+ plugins.push(markTopLevelPure);
152
153
  }
153
- plugins.push(require('../plugins/elide-angular-metadata').default, [require('../plugins/adjust-typescript-enums').default, { loose: true }], [
154
- require('../plugins/adjust-static-class-members').default,
154
+ plugins.push(elideAngularMetadata, adjustTypeScriptEnums, [
155
+ adjustStaticMembers,
155
156
  { wrapDecorators: options.optimize.wrapDecorators },
156
157
  ]);
157
158
  }
@@ -34,8 +34,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
34
34
  };
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const core_1 = require("@babel/core");
37
+ const node_fs_1 = __importDefault(require("node:fs"));
38
+ const node_path_1 = __importDefault(require("node:path"));
37
39
  const piscina_1 = __importDefault(require("piscina"));
38
- const application_1 = __importStar(require("../../tools/babel/presets/application"));
39
40
  const load_esm_1 = require("../../utils/load-esm");
40
41
  const textDecoder = new TextDecoder();
41
42
  const textEncoder = new TextEncoder();
@@ -47,22 +48,41 @@ async function transformJavaScript(request) {
47
48
  return piscina_1.default.move(textEncoder.encode(transformedData));
48
49
  }
49
50
  exports.default = transformJavaScript;
51
+ /**
52
+ * Cached instance of the compiler-cli linker's createEs2015LinkerPlugin function.
53
+ */
50
54
  let linkerPluginCreator;
55
+ /**
56
+ * Cached instance of the compiler-cli linker's needsLinking function.
57
+ */
58
+ let needsLinking;
51
59
  async function transformWithBabel(filename, data, options) {
52
- const shouldLink = !options.skipLinker && (await (0, application_1.requiresLinking)(filename, data));
60
+ const shouldLink = !options.skipLinker && (await requiresLinking(filename, data));
53
61
  const useInputSourcemap = options.sourcemap &&
54
62
  (!!options.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(filename));
63
+ const plugins = [];
64
+ // Lazy load the linker plugin only when linking is required
65
+ if (shouldLink) {
66
+ const linkerPlugin = await createLinkerPlugin(options);
67
+ plugins.push(linkerPlugin);
68
+ }
69
+ if (options.advancedOptimizations) {
70
+ const sideEffectFree = options.sideEffects === false;
71
+ const safeAngularPackage = sideEffectFree && /[\\/]node_modules[\\/]@angular[\\/]/.test(filename);
72
+ const { adjustStaticMembers, adjustTypeScriptEnums, elideAngularMetadata, markTopLevelPure } = await Promise.resolve().then(() => __importStar(require('../babel/plugins')));
73
+ if (safeAngularPackage) {
74
+ plugins.push(markTopLevelPure);
75
+ }
76
+ plugins.push(elideAngularMetadata, adjustTypeScriptEnums, [
77
+ adjustStaticMembers,
78
+ { wrapDecorators: sideEffectFree },
79
+ ]);
80
+ }
55
81
  // If no additional transformations are needed, return the data directly
56
- if (!options.advancedOptimizations && !shouldLink) {
82
+ if (plugins.length === 0) {
57
83
  // Strip sourcemaps if they should not be used
58
84
  return useInputSourcemap ? data : data.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, '');
59
85
  }
60
- const sideEffectFree = options.sideEffects === false;
61
- const safeAngularPackage = sideEffectFree && /[\\/]node_modules[\\/]@angular[\\/]/.test(filename);
62
- // Lazy load the linker plugin only when linking is required
63
- if (shouldLink) {
64
- linkerPluginCreator ??= (await (0, load_esm_1.loadEsmModule)('@angular/compiler-cli/linker/babel')).createEs2015LinkerPlugin;
65
- }
66
86
  const result = await (0, core_1.transformAsync)(data, {
67
87
  filename,
68
88
  inputSourceMap: (useInputSourcemap ? undefined : false),
@@ -71,23 +91,7 @@ async function transformWithBabel(filename, data, options) {
71
91
  configFile: false,
72
92
  babelrc: false,
73
93
  browserslistConfigFile: false,
74
- plugins: [],
75
- presets: [
76
- [
77
- application_1.default,
78
- {
79
- angularLinker: linkerPluginCreator && {
80
- shouldLink,
81
- jitMode: options.jit,
82
- linkerPluginCreator,
83
- },
84
- optimize: options.advancedOptimizations && {
85
- pureTopLevel: safeAngularPackage,
86
- wrapDecorators: sideEffectFree,
87
- },
88
- },
89
- ],
90
- ],
94
+ plugins,
91
95
  });
92
96
  const outputCode = result?.code ?? data;
93
97
  // Strip sourcemaps if they should not be used.
@@ -96,3 +100,55 @@ async function transformWithBabel(filename, data, options) {
96
100
  ? outputCode
97
101
  : outputCode.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, '');
98
102
  }
103
+ async function requiresLinking(path, source) {
104
+ // @angular/core and @angular/compiler will cause false positives
105
+ // Also, TypeScript files do not require linking
106
+ if (/[\\/]@angular[\\/](?:compiler|core)|\.tsx?$/.test(path)) {
107
+ return false;
108
+ }
109
+ if (!needsLinking) {
110
+ // Load ESM `@angular/compiler-cli/linker` using the TypeScript dynamic import workaround.
111
+ // Once TypeScript provides support for keeping the dynamic import this workaround can be
112
+ // changed to a direct dynamic import.
113
+ const linkerModule = await (0, load_esm_1.loadEsmModule)('@angular/compiler-cli/linker');
114
+ needsLinking = linkerModule.needsLinking;
115
+ }
116
+ return needsLinking(path, source);
117
+ }
118
+ async function createLinkerPlugin(options) {
119
+ linkerPluginCreator ??= (await (0, load_esm_1.loadEsmModule)('@angular/compiler-cli/linker/babel')).createEs2015LinkerPlugin;
120
+ const linkerPlugin = linkerPluginCreator({
121
+ linkerJitMode: options.jit,
122
+ // This is a workaround until https://github.com/angular/angular/issues/42769 is fixed.
123
+ sourceMapping: false,
124
+ logger: {
125
+ level: 1, // Info level
126
+ debug(...args) {
127
+ // eslint-disable-next-line no-console
128
+ console.debug(args);
129
+ },
130
+ info(...args) {
131
+ // eslint-disable-next-line no-console
132
+ console.info(args);
133
+ },
134
+ warn(...args) {
135
+ // eslint-disable-next-line no-console
136
+ console.warn(args);
137
+ },
138
+ error(...args) {
139
+ // eslint-disable-next-line no-console
140
+ console.error(args);
141
+ },
142
+ },
143
+ fileSystem: {
144
+ resolve: node_path_1.default.resolve,
145
+ exists: node_fs_1.default.existsSync,
146
+ dirname: node_path_1.default.dirname,
147
+ relative: node_path_1.default.relative,
148
+ readFile: node_fs_1.default.readFileSync,
149
+ // Node.JS types don't overlap the Compiler types.
150
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
151
+ },
152
+ });
153
+ return linkerPlugin;
154
+ }
@@ -205,15 +205,25 @@ class RelativeUrlRebasingImporter extends UrlRebasingImporter {
205
205
  foundImports = [];
206
206
  cachedEntries = { files: new Set(), directories: new Set() };
207
207
  for (const entry of entries) {
208
- const isDirectory = entry.isDirectory();
208
+ let isDirectory;
209
+ let isFile;
210
+ if (entry.isSymbolicLink()) {
211
+ const stats = (0, node_fs_1.statSync)((0, node_path_1.join)(entry.path, entry.name));
212
+ isDirectory = stats.isDirectory();
213
+ isFile = stats.isFile();
214
+ }
215
+ else {
216
+ isDirectory = entry.isDirectory();
217
+ isFile = entry.isFile();
218
+ }
209
219
  if (isDirectory) {
210
220
  cachedEntries.directories.add(entry.name);
221
+ // Record if the name should be checked as a directory with an index file
222
+ if (checkDirectory && !hasStyleExtension && entry.name === filename) {
223
+ hasPotentialIndex = true;
224
+ }
211
225
  }
212
- // Record if the name should be checked as a directory with an index file
213
- if (checkDirectory && !hasStyleExtension && entry.name === filename && isDirectory) {
214
- hasPotentialIndex = true;
215
- }
216
- if (!entry.isFile()) {
226
+ if (!isFile) {
217
227
  continue;
218
228
  }
219
229
  cachedEntries.files.add(entry.name);
@@ -206,7 +206,7 @@ function assetPatterns(root, assets) {
206
206
  return assets.map((asset, index) => {
207
207
  // Resolve input paths relative to workspace root and add slash at the end.
208
208
  // eslint-disable-next-line prefer-const
209
- let { input, output, ignore = [], glob } = asset;
209
+ let { input, output = '', ignore = [], glob } = asset;
210
210
  input = path.resolve(root, input).replace(/\\/g, '/');
211
211
  input = input.endsWith('/') ? input : input + '/';
212
212
  output = output.endsWith('/') ? output : output + '/';
@@ -5,8 +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
- /// <reference types="node" />
9
- import { URL } from 'node:url';
10
8
  import { NormalizedCachedOptions } from '../normalize-cache';
11
9
  export interface InlineFontsOptions {
12
10
  minify?: boolean;
@@ -36,8 +36,6 @@ const node_crypto_1 = require("node:crypto");
36
36
  const promises_1 = require("node:fs/promises");
37
37
  const https = __importStar(require("node:https"));
38
38
  const node_path_1 = require("node:path");
39
- const node_url_1 = require("node:url");
40
- const package_version_1 = require("../package-version");
41
39
  const html_rewriting_stream_1 = require("./html-rewriting-stream");
42
40
  const SUPPORTED_PROVIDERS = {
43
41
  'fonts.googleapis.com': {
@@ -161,7 +159,7 @@ class InlineFontsProcessor {
161
159
  async getResponse(url) {
162
160
  let cacheFile;
163
161
  if (this.cachePath) {
164
- const key = (0, node_crypto_1.createHash)(CONTENT_HASH_ALGORITHM).update(`${package_version_1.VERSION}|${url}`).digest('hex');
162
+ const key = (0, node_crypto_1.createHash)(CONTENT_HASH_ALGORITHM).update(`${url}`).digest('hex');
165
163
  cacheFile = (0, node_path_1.join)(this.cachePath, key);
166
164
  }
167
165
  if (cacheFile) {
@@ -226,7 +224,7 @@ class InlineFontsProcessor {
226
224
  return data;
227
225
  }
228
226
  async processURL(url) {
229
- const normalizedURL = url instanceof node_url_1.URL ? url : this.createNormalizedUrl(url);
227
+ const normalizedURL = url instanceof URL ? url : this.createNormalizedUrl(url);
230
228
  if (!normalizedURL) {
231
229
  return;
232
230
  }
@@ -255,7 +253,7 @@ class InlineFontsProcessor {
255
253
  }
256
254
  createNormalizedUrl(value) {
257
255
  // Need to convert '//' to 'https://' because the URL parser will fail with '//'.
258
- const url = new node_url_1.URL(value.startsWith('//') ? `https:${value}` : value, 'resolve://');
256
+ const url = new URL(value.startsWith('//') ? `https:${value}` : value, 'resolve://');
259
257
  switch (url.protocol) {
260
258
  case 'http:':
261
259
  case 'https:':
@@ -9,4 +9,6 @@ import { AssetPattern, AssetPatternClass } from '../builders/browser/schema';
9
9
  export declare class MissingAssetSourceRootException extends Error {
10
10
  constructor(path: string);
11
11
  }
12
- export declare function normalizeAssetPatterns(assetPatterns: AssetPattern[], workspaceRoot: string, projectRoot: string, projectSourceRoot: string | undefined): AssetPatternClass[];
12
+ export declare function normalizeAssetPatterns(assetPatterns: AssetPattern[], workspaceRoot: string, projectRoot: string, projectSourceRoot: string | undefined): (AssetPatternClass & {
13
+ output: string;
14
+ })[];
@@ -29,9 +29,13 @@ 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.normalizeAssetPatterns = exports.MissingAssetSourceRootException = void 0;
34
37
  const fs_1 = require("fs");
38
+ const node_assert_1 = __importDefault(require("node:assert"));
35
39
  const path = __importStar(require("path"));
36
40
  class MissingAssetSourceRootException extends Error {
37
41
  constructor(path) {
@@ -80,8 +84,9 @@ function normalizeAssetPatterns(assetPatterns, workspaceRoot, projectRoot, proje
80
84
  assetPattern = { glob, input, output };
81
85
  }
82
86
  else {
83
- assetPattern.output = path.join('.', assetPattern.output);
87
+ assetPattern.output = path.join('.', assetPattern.output ?? '');
84
88
  }
89
+ (0, node_assert_1.default)(assetPattern.output !== undefined);
85
90
  if (assetPattern.output.startsWith('..')) {
86
91
  throw new Error('An asset cannot be written to a location outside of the output path.');
87
92
  }
@@ -8,8 +8,9 @@
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.normalizeCacheOptions = void 0;
11
- const path_1 = require("path");
12
- const package_version_1 = require("./package-version");
11
+ const node_path_1 = require("node:path");
12
+ /** Version placeholder is replaced during the build process with actual package version */
13
+ const VERSION = '18.0.0-next.2';
13
14
  function hasCacheMetadata(value) {
14
15
  return (!!value &&
15
16
  typeof value === 'object' &&
@@ -33,11 +34,11 @@ function normalizeCacheOptions(projectMetadata, worspaceRoot) {
33
34
  break;
34
35
  }
35
36
  }
36
- const cacheBasePath = (0, path_1.resolve)(worspaceRoot, path);
37
+ const cacheBasePath = (0, node_path_1.resolve)(worspaceRoot, path);
37
38
  return {
38
39
  enabled: cacheEnabled,
39
40
  basePath: cacheBasePath,
40
- path: (0, path_1.join)(cacheBasePath, package_version_1.VERSION),
41
+ path: (0, node_path_1.join)(cacheBasePath, VERSION),
41
42
  };
42
43
  }
43
44
  exports.normalizeCacheOptions = normalizeCacheOptions;
@@ -8,4 +8,10 @@
8
8
  export interface PostcssConfiguration {
9
9
  plugins: [name: string, options?: object | string][];
10
10
  }
11
- export declare function loadPostcssConfiguration(workspaceRoot: string, projectRoot: string): Promise<PostcssConfiguration | undefined>;
11
+ export interface SearchDirectory {
12
+ root: string;
13
+ files: Set<string>;
14
+ }
15
+ export declare function generateSearchDirectories(roots: string[]): Promise<SearchDirectory[]>;
16
+ export declare function findTailwindConfiguration(searchDirectories: SearchDirectory[]): string | undefined;
17
+ export declare function loadPostcssConfiguration(searchDirectories: SearchDirectory[]): Promise<PostcssConfiguration | undefined>;
@@ -7,16 +7,23 @@
7
7
  * found in the LICENSE file at https://angular.io/license
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.loadPostcssConfiguration = void 0;
10
+ exports.loadPostcssConfiguration = exports.findTailwindConfiguration = exports.generateSearchDirectories = void 0;
11
11
  const promises_1 = require("node:fs/promises");
12
12
  const node_path_1 = require("node:path");
13
13
  const postcssConfigurationFiles = ['postcss.config.json', '.postcssrc.json'];
14
+ const tailwindConfigFiles = [
15
+ 'tailwind.config.js',
16
+ 'tailwind.config.cjs',
17
+ 'tailwind.config.mjs',
18
+ 'tailwind.config.ts',
19
+ ];
14
20
  async function generateSearchDirectories(roots) {
15
21
  return await Promise.all(roots.map((root) => (0, promises_1.readdir)(root, { withFileTypes: true }).then((entries) => ({
16
22
  root,
17
23
  files: new Set(entries.filter((entry) => entry.isFile()).map((entry) => entry.name)),
18
24
  }))));
19
25
  }
26
+ exports.generateSearchDirectories = generateSearchDirectories;
20
27
  function findFile(searchDirectories, potentialFiles) {
21
28
  for (const { root, files } of searchDirectories) {
22
29
  for (const potential of potentialFiles) {
@@ -27,14 +34,16 @@ function findFile(searchDirectories, potentialFiles) {
27
34
  }
28
35
  return undefined;
29
36
  }
37
+ function findTailwindConfiguration(searchDirectories) {
38
+ return findFile(searchDirectories, tailwindConfigFiles);
39
+ }
40
+ exports.findTailwindConfiguration = findTailwindConfiguration;
30
41
  async function readPostcssConfiguration(configurationFile) {
31
42
  const data = await (0, promises_1.readFile)(configurationFile, 'utf-8');
32
43
  const config = JSON.parse(data);
33
44
  return config;
34
45
  }
35
- async function loadPostcssConfiguration(workspaceRoot, projectRoot) {
36
- // A configuration file can exist in the project or workspace root
37
- const searchDirectories = await generateSearchDirectories([projectRoot, workspaceRoot]);
46
+ async function loadPostcssConfiguration(searchDirectories) {
38
47
  const configPath = findFile(searchDirectories, postcssConfigurationFiles);
39
48
  if (!configPath) {
40
49
  return undefined;
@@ -12,7 +12,7 @@ import { promises as fsPromises } from 'node:fs';
12
12
  import { BuildOutputFile } from '../tools/esbuild/bundler-context';
13
13
  import { BuildOutputAsset } from '../tools/esbuild/bundler-execution-result';
14
14
  export declare function augmentAppWithServiceWorker(appRoot: string, workspaceRoot: string, outputPath: string, baseHref: string, ngswConfigPath?: string, inputputFileSystem?: typeof fsPromises, outputFileSystem?: typeof fsPromises): Promise<void>;
15
- export declare function augmentAppWithServiceWorkerEsbuild(workspaceRoot: string, configPath: string, baseHref: string, outputFiles: BuildOutputFile[], assetFiles: BuildOutputAsset[]): Promise<{
15
+ export declare function augmentAppWithServiceWorkerEsbuild(workspaceRoot: string, configPath: string, baseHref: string, indexHtml: string | undefined, outputFiles: BuildOutputFile[], assetFiles: BuildOutputAsset[]): Promise<{
16
16
  manifest: string;
17
17
  assetFiles: BuildOutputAsset[];
18
18
  }>;
@@ -159,12 +159,15 @@ async function augmentAppWithServiceWorker(appRoot, workspaceRoot, outputPath, b
159
159
  }
160
160
  exports.augmentAppWithServiceWorker = augmentAppWithServiceWorker;
161
161
  // This is currently used by the esbuild-based builder
162
- async function augmentAppWithServiceWorkerEsbuild(workspaceRoot, configPath, baseHref, outputFiles, assetFiles) {
162
+ async function augmentAppWithServiceWorkerEsbuild(workspaceRoot, configPath, baseHref, indexHtml, outputFiles, assetFiles) {
163
163
  // Read the configuration file
164
164
  let config;
165
165
  try {
166
166
  const configurationData = await node_fs_1.promises.readFile(configPath, 'utf-8');
167
167
  config = JSON.parse(configurationData);
168
+ if (indexHtml) {
169
+ config.index = indexHtml;
170
+ }
168
171
  }
169
172
  catch (error) {
170
173
  (0, error_1.assertIsError)(error);