@angular-devkit/build-angular 17.1.2 → 17.2.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/package.json +31 -32
  2. package/src/builders/application/build-action.js +0 -4
  3. package/src/builders/application/execute-build.js +8 -15
  4. package/src/builders/application/index.js +19 -3
  5. package/src/builders/application/options.d.ts +3 -0
  6. package/src/builders/application/options.js +12 -1
  7. package/src/builders/application/setup-bundling.js +2 -2
  8. package/src/builders/dev-server/options.js +3 -2
  9. package/src/builders/dev-server/schema.json +1 -1
  10. package/src/builders/extract-i18n/options.js +3 -2
  11. package/src/builders/extract-i18n/schema.json +1 -1
  12. package/src/builders/jest/index.js +44 -5
  13. package/src/builders/jest/jest.config.mjs +11 -0
  14. package/src/tools/babel/plugins/elide-angular-metadata.d.ts +1 -1
  15. package/src/tools/babel/plugins/elide-angular-metadata.js +38 -30
  16. package/src/tools/babel/plugins/pure-toplevel-functions.d.ts +1 -1
  17. package/src/tools/babel/plugins/pure-toplevel-functions.js +3 -4
  18. package/src/tools/esbuild/angular/compilation/angular-compilation.d.ts +9 -2
  19. package/src/tools/esbuild/angular/compilation/angular-compilation.js +11 -3
  20. package/src/tools/esbuild/angular/compilation/aot-compilation.d.ts +2 -2
  21. package/src/tools/esbuild/angular/compilation/aot-compilation.js +19 -8
  22. package/src/tools/esbuild/angular/compilation/index.d.ts +1 -1
  23. package/src/tools/esbuild/angular/compilation/index.js +2 -1
  24. package/src/tools/esbuild/angular/compilation/jit-compilation.d.ts +2 -2
  25. package/src/tools/esbuild/angular/compilation/jit-compilation.js +12 -6
  26. package/src/tools/esbuild/angular/compilation/parallel-compilation.d.ts +2 -2
  27. package/src/tools/esbuild/angular/compilation/parallel-compilation.js +2 -2
  28. package/src/tools/esbuild/angular/compilation/parallel-worker.d.ts +2 -1
  29. package/src/tools/esbuild/angular/compilation/parallel-worker.js +2 -2
  30. package/src/tools/esbuild/angular/compiler-plugin.js +7 -7
  31. package/src/tools/esbuild/application-code-bundle.js +2 -2
  32. package/src/tools/esbuild/budget-stats.js +5 -0
  33. package/src/tools/esbuild/bundler-context.js +6 -0
  34. package/src/tools/esbuild/bundler-execution-result.d.ts +2 -0
  35. package/src/tools/esbuild/bundler-execution-result.js +6 -0
  36. package/src/tools/esbuild/compiler-plugin-options.js +2 -1
  37. package/src/tools/esbuild/global-scripts.js +3 -4
  38. package/src/tools/esbuild/global-styles.js +2 -1
  39. package/src/tools/esbuild/stylesheets/bundle-options.d.ts +2 -0
  40. package/src/tools/esbuild/stylesheets/bundle-options.js +1 -0
  41. package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.d.ts +7 -0
  42. package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.js +24 -8
  43. package/src/tools/esbuild/utils.d.ts +5 -8
  44. package/src/tools/esbuild/utils.js +64 -31
  45. package/src/tools/vite/angular-memory-plugin.js +6 -5
  46. package/src/tools/webpack/utils/stats.d.ts +1 -0
  47. package/src/tools/webpack/utils/stats.js +98 -47
  48. package/src/utils/environment-options.d.ts +2 -0
  49. package/src/utils/environment-options.js +5 -1
  50. package/src/utils/postcss-configuration.d.ts +11 -0
  51. package/src/utils/postcss-configuration.js +77 -0
@@ -10,23 +10,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
10
10
  return (mod && mod.__esModule) ? mod : { "default": mod };
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.getSupportedNodeTargets = exports.transformSupportedBrowsersToTargets = exports.convertOutputFile = exports.createOutputFileFromData = exports.createOutputFileFromText = exports.emitFilesToDisk = exports.writeResultFiles = exports.getFeatureSupport = exports.logMessages = exports.withNoProgress = exports.withSpinner = exports.calculateEstimatedTransferSizes = exports.logBuildStats = void 0;
13
+ exports.logMessages = exports.getSupportedNodeTargets = exports.transformSupportedBrowsersToTargets = exports.convertOutputFile = exports.createOutputFileFromData = exports.createOutputFileFromText = exports.emitFilesToDisk = exports.writeResultFiles = exports.getFeatureSupport = exports.withNoProgress = exports.withSpinner = exports.calculateEstimatedTransferSizes = exports.logBuildStats = void 0;
14
14
  const esbuild_1 = require("esbuild");
15
15
  const node_crypto_1 = require("node:crypto");
16
16
  const node_fs_1 = require("node:fs");
17
17
  const promises_1 = __importDefault(require("node:fs/promises"));
18
- const node_path_1 = __importDefault(require("node:path"));
18
+ const node_path_1 = require("node:path");
19
+ const node_url_1 = require("node:url");
19
20
  const node_zlib_1 = require("node:zlib");
20
21
  const semver_1 = require("semver");
21
22
  const spinner_1 = require("../../utils/spinner");
22
23
  const stats_1 = require("../webpack/utils/stats");
23
24
  const bundler_context_1 = require("./bundler-context");
24
- function logBuildStats(logger, metafile, initial, budgetFailures, changedFiles, estimatedTransferSizes) {
25
- const stats = [];
25
+ function logBuildStats(metafile, initial, budgetFailures, colors, changedFiles, estimatedTransferSizes, ssrOutputEnabled, verbose) {
26
+ const browserStats = [];
27
+ const serverStats = [];
26
28
  let unchangedCount = 0;
27
29
  for (const [file, output] of Object.entries(metafile.outputs)) {
28
30
  // Only display JavaScript and CSS files
29
- if (!file.endsWith('.js') && !file.endsWith('.css')) {
31
+ if (!/\.(?:css|m?js)$/.test(file)) {
30
32
  continue;
31
33
  }
32
34
  // Skip internal component resources
@@ -39,28 +41,40 @@ function logBuildStats(logger, metafile, initial, budgetFailures, changedFiles,
39
41
  ++unchangedCount;
40
42
  continue;
41
43
  }
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ const isPlatformServer = output['ng-platform-server'];
46
+ if (isPlatformServer && !ssrOutputEnabled) {
47
+ // Only log server build stats when SSR is enabled.
48
+ continue;
49
+ }
42
50
  let name = initial.get(file)?.name;
43
51
  if (name === undefined && output.entryPoint) {
44
- name = node_path_1.default
45
- .basename(output.entryPoint)
52
+ name = (0, node_path_1.basename)(output.entryPoint)
46
53
  .replace(/\.[cm]?[jt]s$/, '')
47
54
  .replace(/[\\/.]/g, '-');
48
55
  }
49
- stats.push({
56
+ const stat = {
50
57
  initial: initial.has(file),
51
58
  stats: [file, name ?? '-', output.bytes, estimatedTransferSizes?.get(file) ?? '-'],
52
- });
59
+ };
60
+ if (isPlatformServer) {
61
+ serverStats.push(stat);
62
+ }
63
+ else {
64
+ browserStats.push(stat);
65
+ }
53
66
  }
54
- if (stats.length > 0) {
55
- const tableText = (0, stats_1.generateBuildStatsTable)(stats, true, unchangedCount === 0, !!estimatedTransferSizes, budgetFailures);
56
- logger.info('\n' + tableText + '\n');
67
+ if (browserStats.length > 0 || serverStats.length > 0) {
68
+ const tableText = (0, stats_1.generateEsbuildBuildStatsTable)([browserStats, serverStats], colors, unchangedCount === 0, !!estimatedTransferSizes, budgetFailures, verbose);
69
+ return tableText + '\n';
57
70
  }
58
71
  else if (changedFiles !== undefined) {
59
- logger.info('\nNo output file changes.\n');
72
+ return '\nNo output file changes.\n';
60
73
  }
61
74
  if (unchangedCount > 0) {
62
- logger.info(`Unchanged output files: ${unchangedCount}`);
75
+ return `Unchanged output files: ${unchangedCount}`;
63
76
  }
77
+ return '';
64
78
  }
65
79
  exports.logBuildStats = logBuildStats;
66
80
  async function calculateEstimatedTransferSizes(outputFiles) {
@@ -117,17 +131,6 @@ async function withNoProgress(text, action) {
117
131
  return action();
118
132
  }
119
133
  exports.withNoProgress = withNoProgress;
120
- async function logMessages(logger, { errors, warnings }) {
121
- if (warnings?.length) {
122
- const warningMessages = await (0, esbuild_1.formatMessages)(warnings, { kind: 'warning', color: true });
123
- logger.warn(warningMessages.join('\n'));
124
- }
125
- if (errors?.length) {
126
- const errorMessages = await (0, esbuild_1.formatMessages)(errors, { kind: 'error', color: true });
127
- logger.error(errorMessages.join('\n'));
128
- }
129
- }
130
- exports.logMessages = logMessages;
131
134
  /**
132
135
  * Generates a syntax feature object map for Angular applications based on a list of targets.
133
136
  * A full set of feature names can be found here: https://esbuild.github.io/api/#supported
@@ -179,9 +182,9 @@ exports.getFeatureSupport = getFeatureSupport;
179
182
  async function writeResultFiles(outputFiles, assetFiles, { base, browser, media, server }) {
180
183
  const directoryExists = new Set();
181
184
  const ensureDirectoryExists = async (destPath) => {
182
- const basePath = node_path_1.default.dirname(destPath);
185
+ const basePath = (0, node_path_1.dirname)(destPath);
183
186
  if (!directoryExists.has(basePath)) {
184
- await promises_1.default.mkdir(node_path_1.default.join(base, basePath), { recursive: true });
187
+ await promises_1.default.mkdir((0, node_path_1.join)(base, basePath), { recursive: true });
185
188
  directoryExists.add(basePath);
186
189
  }
187
190
  };
@@ -202,19 +205,19 @@ async function writeResultFiles(outputFiles, assetFiles, { base, browser, media,
202
205
  default:
203
206
  throw new Error(`Unhandled write for file "${file.path}" with type "${bundler_context_1.BuildOutputFileType[file.type]}".`);
204
207
  }
205
- const destPath = node_path_1.default.join(outputDir, file.path);
208
+ const destPath = (0, node_path_1.join)(outputDir, file.path);
206
209
  // Ensure output subdirectories exist
207
210
  await ensureDirectoryExists(destPath);
208
211
  // Write file contents
209
- await promises_1.default.writeFile(node_path_1.default.join(base, destPath), file.contents);
212
+ await promises_1.default.writeFile((0, node_path_1.join)(base, destPath), file.contents);
210
213
  });
211
214
  if (assetFiles?.length) {
212
215
  await emitFilesToDisk(assetFiles, async ({ source, destination }) => {
213
- const destPath = node_path_1.default.join(browser, destination);
216
+ const destPath = (0, node_path_1.join)(browser, destination);
214
217
  // Ensure output subdirectories exist
215
218
  await ensureDirectoryExists(destPath);
216
219
  // Copy file contents
217
- await promises_1.default.copyFile(source, node_path_1.default.join(base, destPath), node_fs_1.constants.COPYFILE_FICLONE);
220
+ await promises_1.default.copyFile(source, (0, node_path_1.join)(base, destPath), node_fs_1.constants.COPYFILE_FICLONE);
218
221
  });
219
222
  }
220
223
  }
@@ -341,3 +344,33 @@ function getSupportedNodeTargets() {
341
344
  return SUPPORTED_NODE_VERSIONS.split('||').map((v) => 'node' + (0, semver_1.coerce)(v)?.version);
342
345
  }
343
346
  exports.getSupportedNodeTargets = getSupportedNodeTargets;
347
+ async function logMessages(logger, executionResult, options) {
348
+ const { outputOptions: { base, server, browser }, ssrOptions, jsonLogs, colors: color, } = options;
349
+ const { warnings, errors, prerenderedRoutes } = executionResult;
350
+ const warningMessages = warnings.length
351
+ ? await (0, esbuild_1.formatMessages)(warnings, { kind: 'warning', color })
352
+ : [];
353
+ const errorMessages = errors.length ? await (0, esbuild_1.formatMessages)(errors, { kind: 'error', color }) : [];
354
+ if (jsonLogs) {
355
+ // JSON format output
356
+ const manifest = {
357
+ errors: errorMessages,
358
+ warnings: warningMessages,
359
+ outputPaths: {
360
+ root: (0, node_url_1.pathToFileURL)(base),
361
+ browser: (0, node_url_1.pathToFileURL)((0, node_path_1.join)(base, browser)),
362
+ server: ssrOptions ? (0, node_url_1.pathToFileURL)((0, node_path_1.join)(base, server)) : undefined,
363
+ },
364
+ prerenderedRoutes,
365
+ };
366
+ logger.info(JSON.stringify(manifest, undefined, 2));
367
+ return;
368
+ }
369
+ if (warningMessages.length) {
370
+ logger.warn(warningMessages.join('\n'));
371
+ }
372
+ if (errorMessages.length) {
373
+ logger.error(errorMessages.join('\n'));
374
+ }
375
+ }
376
+ exports.logMessages = logMessages;
@@ -214,12 +214,13 @@ exports.createAngularMemoryPlugin = createAngularMemoryPlugin;
214
214
  */
215
215
  async function loadViteClientCode(file) {
216
216
  const originalContents = await (0, promises_1.readFile)(file, 'utf-8');
217
- let contents = originalContents.replace('You can also disable this overlay by setting', '');
218
- contents = contents.replace(
217
+ const firstUpdate = originalContents.replace('You can also disable this overlay by setting', '');
218
+ (0, node_assert_1.default)(originalContents !== firstUpdate, 'Failed to update Vite client error overlay text. (1)');
219
+ const secondUpdate = firstUpdate.replace(
219
220
  // eslint-disable-next-line max-len
220
- '<code part="config-option-name">server.hmr.overlay</code> to <code part="config-option-value">false</code> in <code part="config-file-name">vite.config.js.</code>', '');
221
- (0, node_assert_1.default)(originalContents !== contents, 'Failed to update Vite client error overlay text.');
222
- return contents;
221
+ '<code part="config-option-name">server.hmr.overlay</code> to <code part="config-option-value">false</code> in <code part="config-file-name">${hmrConfigName}.</code>', '');
222
+ (0, node_assert_1.default)(firstUpdate !== secondUpdate, 'Failed to update Vite client error overlay text. (2)');
223
+ return secondUpdate;
223
224
  }
224
225
  function pathnameWithoutBasePath(url, basePath) {
225
226
  const parsedUrl = new URL(url, 'http://localhost');
@@ -22,6 +22,7 @@ export interface BundleStats {
22
22
  initial: boolean;
23
23
  stats: BundleStatsData;
24
24
  }
25
+ export declare function generateEsbuildBuildStatsTable([browserStats, serverStats]: [browserStats: BundleStats[], serverStats: BundleStats[]], colors: boolean, showTotalSize: boolean, showEstimatedTransferSize: boolean, budgetFailures?: BudgetCalculatorResult[], verbose?: boolean): string;
25
26
  export declare function generateBuildStatsTable(data: BundleStats[], colors: boolean, showTotalSize: boolean, showEstimatedTransferSize: boolean, budgetFailures?: BudgetCalculatorResult[]): string;
26
27
  export declare function statsWarningsToString(json: StatsCompilation, statsConfig: WebpackStatsOptions): string;
27
28
  export declare function statsErrorsToString(json: StatsCompilation, statsConfig: WebpackStatsOptions): string;
@@ -33,11 +33,9 @@ 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.webpackStatsLogger = exports.generateBuildEventStats = exports.createWebpackLoggingCallback = exports.statsHasWarnings = exports.statsHasErrors = exports.statsErrorsToString = exports.statsWarningsToString = exports.generateBuildStatsTable = exports.formatSize = void 0;
37
- const core_1 = require("@angular-devkit/core");
38
- const assert_1 = __importDefault(require("assert"));
39
- const path = __importStar(require("path"));
40
- const text_table_1 = __importDefault(require("text-table"));
36
+ exports.webpackStatsLogger = exports.generateBuildEventStats = exports.createWebpackLoggingCallback = exports.statsHasWarnings = exports.statsHasErrors = exports.statsErrorsToString = exports.statsWarningsToString = exports.generateBuildStatsTable = exports.generateEsbuildBuildStatsTable = exports.formatSize = void 0;
37
+ const node_assert_1 = __importDefault(require("node:assert"));
38
+ const path = __importStar(require("node:path"));
41
39
  const utils_1 = require("../../../utils");
42
40
  const color_1 = require("../../../utils/color");
43
41
  const async_chunks_1 = require("./async-chunks");
@@ -55,8 +53,8 @@ function formatSize(size) {
55
53
  }
56
54
  exports.formatSize = formatSize;
57
55
  function getBuildDuration(webpackStats) {
58
- (0, assert_1.default)(webpackStats.builtAt, 'buildAt cannot be undefined');
59
- (0, assert_1.default)(webpackStats.time, 'time cannot be undefined');
56
+ (0, node_assert_1.default)(webpackStats.builtAt, 'buildAt cannot be undefined');
57
+ (0, node_assert_1.default)(webpackStats.time, 'time cannot be undefined');
60
58
  return Date.now() - webpackStats.builtAt + webpackStats.time;
61
59
  }
62
60
  function generateBundleStats(info) {
@@ -73,9 +71,31 @@ function generateBundleStats(info) {
73
71
  stats: [files, names, rawSize, estimatedTransferSize],
74
72
  };
75
73
  }
74
+ function generateEsbuildBuildStatsTable([browserStats, serverStats], colors, showTotalSize, showEstimatedTransferSize, budgetFailures, verbose) {
75
+ const bundleInfo = generateBuildStatsData(browserStats, colors, showTotalSize, showEstimatedTransferSize, budgetFailures, verbose);
76
+ if (serverStats.length) {
77
+ const m = (x) => (colors ? color_1.colors.magenta(x) : x);
78
+ if (browserStats.length) {
79
+ bundleInfo.unshift([m('Browser bundles')]);
80
+ // Add seperators between browser and server logs
81
+ bundleInfo.push([], []);
82
+ }
83
+ bundleInfo.push([m('Server bundles')], ...generateBuildStatsData(serverStats, colors, false, false, undefined, verbose));
84
+ }
85
+ return generateTableText(bundleInfo, colors);
86
+ }
87
+ exports.generateEsbuildBuildStatsTable = generateEsbuildBuildStatsTable;
76
88
  function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTransferSize, budgetFailures) {
77
- const g = (x) => (colors ? color_1.colors.greenBright(x) : x);
78
- const c = (x) => (colors ? color_1.colors.cyanBright(x) : x);
89
+ const bundleInfo = generateBuildStatsData(data, colors, showTotalSize, showEstimatedTransferSize, budgetFailures, true);
90
+ return generateTableText(bundleInfo, colors);
91
+ }
92
+ exports.generateBuildStatsTable = generateBuildStatsTable;
93
+ function generateBuildStatsData(data, colors, showTotalSize, showEstimatedTransferSize, budgetFailures, verbose) {
94
+ if (data.length === 0) {
95
+ return [];
96
+ }
97
+ const g = (x) => (colors ? color_1.colors.green(x) : x);
98
+ const c = (x) => (colors ? color_1.colors.cyan(x) : x);
79
99
  const r = (x) => (colors ? color_1.colors.redBright(x) : x);
80
100
  const y = (x) => (colors ? color_1.colors.yellowBright(x) : x);
81
101
  const bold = (x) => (colors ? color_1.colors.bold(x) : x);
@@ -94,7 +114,9 @@ function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTrans
94
114
  const changedEntryChunksStats = [];
95
115
  const changedLazyChunksStats = [];
96
116
  let initialTotalRawSize = 0;
117
+ let changedLazyChunksCount = 0;
97
118
  let initialTotalEstimatedTransferSize;
119
+ const maxLazyChunksWithoutBudgetFailures = 15;
98
120
  const budgets = new Map();
99
121
  if (budgetFailures) {
100
122
  for (const { label, severity } of budgetFailures) {
@@ -117,12 +139,21 @@ function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTrans
117
139
  });
118
140
  for (const { initial, stats } of data) {
119
141
  const [files, names, rawSize, estimatedTransferSize] = stats;
142
+ if (!initial &&
143
+ !verbose &&
144
+ changedLazyChunksStats.length >= maxLazyChunksWithoutBudgetFailures &&
145
+ !budgets.has(names) &&
146
+ !budgets.has(files)) {
147
+ // Limit the number of lazy chunks displayed in the stats table when there is no budget failure and not in verbose mode.
148
+ changedLazyChunksCount++;
149
+ continue;
150
+ }
120
151
  const getRawSizeColor = getSizeColor(names, files);
121
152
  let data;
122
153
  if (showEstimatedTransferSize) {
123
154
  data = [
124
155
  g(files),
125
- names,
156
+ dim(names),
126
157
  getRawSizeColor(typeof rawSize === 'number' ? formatSize(rawSize) : rawSize),
127
158
  c(typeof estimatedTransferSize === 'number'
128
159
  ? formatSize(estimatedTransferSize)
@@ -132,7 +163,7 @@ function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTrans
132
163
  else {
133
164
  data = [
134
165
  g(files),
135
- names,
166
+ dim(names),
136
167
  getRawSizeColor(typeof rawSize === 'number' ? formatSize(rawSize) : rawSize),
137
168
  '',
138
169
  ];
@@ -151,24 +182,22 @@ function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTrans
151
182
  }
152
183
  else {
153
184
  changedLazyChunksStats.push(data);
185
+ changedLazyChunksCount++;
154
186
  }
155
187
  }
156
188
  const bundleInfo = [];
157
- const baseTitles = ['Names', 'Raw Size'];
158
- const tableAlign = ['l', 'l', 'r'];
189
+ const baseTitles = ['Names', 'Raw size'];
159
190
  if (showEstimatedTransferSize) {
160
- baseTitles.push('Estimated Transfer Size');
161
- tableAlign.push('r');
191
+ baseTitles.push('Estimated transfer size');
162
192
  }
163
193
  // Entry chunks
164
194
  if (changedEntryChunksStats.length) {
165
- bundleInfo.push(['Initial Chunk Files', ...baseTitles].map(bold), ...changedEntryChunksStats);
195
+ bundleInfo.push(['Initial chunk files', ...baseTitles].map(bold), ...changedEntryChunksStats);
166
196
  if (showTotalSize) {
167
- bundleInfo.push([]);
168
197
  const initialSizeTotalColor = getSizeColor('bundle initial', undefined, (x) => x);
169
198
  const totalSizeElements = [
170
199
  ' ',
171
- 'Initial Total',
200
+ 'Initial total',
172
201
  initialSizeTotalColor(formatSize(initialTotalRawSize)),
173
202
  ];
174
203
  if (showEstimatedTransferSize) {
@@ -176,7 +205,7 @@ function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTrans
176
205
  ? formatSize(initialTotalEstimatedTransferSize)
177
206
  : '-');
178
207
  }
179
- bundleInfo.push(totalSizeElements.map(bold));
208
+ bundleInfo.push([], totalSizeElements.map(bold));
180
209
  }
181
210
  }
182
211
  // Seperator
@@ -185,18 +214,54 @@ function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTrans
185
214
  }
186
215
  // Lazy chunks
187
216
  if (changedLazyChunksStats.length) {
188
- bundleInfo.push(['Lazy Chunk Files', ...baseTitles].map(bold), ...changedLazyChunksStats);
217
+ bundleInfo.push(['Lazy chunk files', ...baseTitles].map(bold), ...changedLazyChunksStats);
218
+ if (changedLazyChunksCount > changedLazyChunksStats.length) {
219
+ bundleInfo.push([
220
+ dim(`...and ${changedLazyChunksCount - changedLazyChunksStats.length} more lazy chunks files. ` +
221
+ 'Use "--verbose" to show all the files.'),
222
+ ]);
223
+ }
189
224
  }
190
- return (0, text_table_1.default)(bundleInfo, {
191
- hsep: dim(' | '),
192
- stringLength: (s) => (0, color_1.removeColor)(s).length,
193
- align: tableAlign,
194
- });
225
+ return bundleInfo;
195
226
  }
196
- exports.generateBuildStatsTable = generateBuildStatsTable;
197
- function generateBuildStats(hash, time, colors) {
198
- const w = (x) => (colors ? color_1.colors.bold.white(x) : x);
199
- return `Build at: ${w(new Date().toISOString())} - Hash: ${w(hash)} - Time: ${w('' + time)}ms`;
227
+ function generateTableText(bundleInfo, colors) {
228
+ const skipText = (value) => value.includes('...and ');
229
+ const longest = [];
230
+ for (const item of bundleInfo) {
231
+ for (let i = 0; i < item.length; i++) {
232
+ if (item[i] === undefined) {
233
+ continue;
234
+ }
235
+ const currentItem = item[i].toString();
236
+ if (skipText(currentItem)) {
237
+ continue;
238
+ }
239
+ const currentLongest = (longest[i] ??= 0);
240
+ const currentItemLength = (0, color_1.removeColor)(currentItem).length;
241
+ if (currentLongest < currentItemLength) {
242
+ longest[i] = currentItemLength;
243
+ }
244
+ }
245
+ }
246
+ const seperator = colors ? color_1.colors.dim(' | ') : ' | ';
247
+ const outputTable = [];
248
+ for (const item of bundleInfo) {
249
+ for (let i = 0; i < longest.length; i++) {
250
+ if (item[i] === undefined) {
251
+ continue;
252
+ }
253
+ const currentItem = item[i].toString();
254
+ if (skipText(currentItem)) {
255
+ continue;
256
+ }
257
+ const currentItemLength = (0, color_1.removeColor)(currentItem).length;
258
+ const stringPad = ' '.repeat(longest[i] - currentItemLength);
259
+ // Values in columns at index 2 and 3 (Raw and Estimated sizes) are always right aligned.
260
+ item[i] = i >= 2 ? stringPad + currentItem : currentItem + stringPad;
261
+ }
262
+ outputTable.push(item.join(seperator));
263
+ }
264
+ return outputTable.join('\n');
200
265
  }
201
266
  // We use this cache because we can have multiple builders running in the same process,
202
267
  // where each builder has different output path.
@@ -210,6 +275,7 @@ statsConfig, budgetFailures) {
210
275
  }
211
276
  const colors = statsConfig.colors;
212
277
  const rs = (x) => (colors ? color_1.colors.reset(x) : x);
278
+ const w = (x) => (colors ? color_1.colors.bold.white(x) : x);
213
279
  const changedChunksStats = [];
214
280
  let unchangedChunkNumber = 0;
215
281
  let hasEstimatedTransferSizes = false;
@@ -247,24 +313,9 @@ statsConfig, budgetFailures) {
247
313
  // Such us index generation, service worker augmentation etc...
248
314
  // This will correct the time and include these.
249
315
  const time = getBuildDuration(json);
250
- if (unchangedChunkNumber > 0) {
251
- return ('\n' +
252
- rs(core_1.tags.stripIndents `
253
- ${statsTable}
254
-
255
- ${unchangedChunkNumber} unchanged chunks
256
-
257
- ${generateBuildStats(json.hash || '', time, colors)}
258
- `));
259
- }
260
- else {
261
- return ('\n' +
262
- rs(core_1.tags.stripIndents `
263
- ${statsTable}
264
-
265
- ${generateBuildStats(json.hash || '', time, colors)}
266
- `));
267
- }
316
+ return rs(`\n${statsTable}\n\n` +
317
+ (unchangedChunkNumber > 0 ? `${unchangedChunkNumber} unchanged chunks\n\n` : '') +
318
+ `Build at: ${w(new Date().toISOString())} - Hash: ${w(json.hash || '')} - Time: ${w('' + time)}ms`);
268
319
  }
269
320
  function statsWarningsToString(json, statsConfig) {
270
321
  const colors = statsConfig.colors;
@@ -13,3 +13,5 @@ export declare const useParallelTs: boolean;
13
13
  export declare const useLegacySass: boolean;
14
14
  export declare const debugPerformance: boolean;
15
15
  export declare const shouldWatchRoot: boolean;
16
+ export declare const useTypeChecking: boolean;
17
+ export declare const useJSONBuildLogs: boolean;
@@ -7,7 +7,7 @@
7
7
  * found in the LICENSE file at https://angular.io/license
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.shouldWatchRoot = exports.debugPerformance = exports.useLegacySass = exports.useParallelTs = exports.maxWorkers = exports.allowMinify = exports.shouldBeautify = exports.allowMangle = void 0;
10
+ exports.useJSONBuildLogs = exports.useTypeChecking = exports.shouldWatchRoot = exports.debugPerformance = exports.useLegacySass = exports.useParallelTs = exports.maxWorkers = exports.allowMinify = exports.shouldBeautify = exports.allowMangle = void 0;
11
11
  const color_1 = require("./color");
12
12
  function isDisabled(variable) {
13
13
  return variable === '0' || variable.toLowerCase() === 'false';
@@ -83,3 +83,7 @@ const debugPerfVariable = process.env['NG_BUILD_DEBUG_PERF'];
83
83
  exports.debugPerformance = isPresent(debugPerfVariable) && isEnabled(debugPerfVariable);
84
84
  const watchRootVariable = process.env['NG_BUILD_WATCH_ROOT'];
85
85
  exports.shouldWatchRoot = isPresent(watchRootVariable) && isEnabled(watchRootVariable);
86
+ const typeCheckingVariable = process.env['NG_BUILD_TYPE_CHECK'];
87
+ exports.useTypeChecking = !isPresent(typeCheckingVariable) || !isDisabled(typeCheckingVariable);
88
+ const buildLogsJsonVariable = process.env['NG_BUILD_LOGS_JSON'];
89
+ exports.useJSONBuildLogs = isPresent(buildLogsJsonVariable) && isEnabled(buildLogsJsonVariable);
@@ -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 interface PostcssConfiguration {
9
+ plugins: [name: string, options?: object][];
10
+ }
11
+ export declare function loadPostcssConfiguration(workspaceRoot: string, projectRoot: string): Promise<PostcssConfiguration | undefined>;
@@ -0,0 +1,77 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.loadPostcssConfiguration = void 0;
11
+ const promises_1 = require("node:fs/promises");
12
+ const node_path_1 = require("node:path");
13
+ const postcssConfigurationFiles = ['postcss.config.json', '.postcssrc.json'];
14
+ async function generateSearchDirectories(roots) {
15
+ return await Promise.all(roots.map((root) => (0, promises_1.readdir)(root, { withFileTypes: true }).then((entries) => ({
16
+ root,
17
+ files: new Set(entries.filter((entry) => entry.isFile()).map((entry) => entry.name)),
18
+ }))));
19
+ }
20
+ function findFile(searchDirectories, potentialFiles) {
21
+ for (const { root, files } of searchDirectories) {
22
+ for (const potential of potentialFiles) {
23
+ if (files.has(potential)) {
24
+ return (0, node_path_1.join)(root, potential);
25
+ }
26
+ }
27
+ }
28
+ return undefined;
29
+ }
30
+ async function readPostcssConfiguration(configurationFile) {
31
+ const data = await (0, promises_1.readFile)(configurationFile, 'utf-8');
32
+ const config = JSON.parse(data);
33
+ return config;
34
+ }
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]);
38
+ const configPath = findFile(searchDirectories, postcssConfigurationFiles);
39
+ if (!configPath) {
40
+ return undefined;
41
+ }
42
+ const raw = await readPostcssConfiguration(configPath);
43
+ // If no plugins are defined, consider it equivalent to no configuration
44
+ if (!raw.plugins || typeof raw.plugins !== 'object') {
45
+ return undefined;
46
+ }
47
+ // Normalize plugin array form
48
+ if (Array.isArray(raw.plugins)) {
49
+ if (raw.plugins.length < 1) {
50
+ return undefined;
51
+ }
52
+ const config = { plugins: [] };
53
+ for (const element of raw.plugins) {
54
+ if (typeof element === 'string') {
55
+ config.plugins.push([element]);
56
+ }
57
+ else {
58
+ config.plugins.push(element);
59
+ }
60
+ }
61
+ return config;
62
+ }
63
+ // Normalize plugin object map form
64
+ const entries = Object.entries(raw.plugins);
65
+ if (entries.length < 1) {
66
+ return undefined;
67
+ }
68
+ const config = { plugins: [] };
69
+ for (const [name, options] of entries) {
70
+ if (!options || typeof options !== 'object') {
71
+ continue;
72
+ }
73
+ config.plugins.push([name, options]);
74
+ }
75
+ return config;
76
+ }
77
+ exports.loadPostcssConfiguration = loadPostcssConfiguration;