@angular-devkit/build-angular 18.2.0-next.0 → 18.2.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.
package/package.json CHANGED
@@ -1,27 +1,27 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "18.2.0-next.0",
3
+ "version": "18.2.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.1802.0-next.0",
11
- "@angular-devkit/build-webpack": "0.1802.0-next.0",
12
- "@angular-devkit/core": "18.2.0-next.0",
13
- "@angular/build": "18.2.0-next.0",
14
- "@babel/core": "7.24.7",
15
- "@babel/generator": "7.24.7",
10
+ "@angular-devkit/architect": "0.1802.0-next.2",
11
+ "@angular-devkit/build-webpack": "0.1802.0-next.2",
12
+ "@angular-devkit/core": "18.2.0-next.2",
13
+ "@angular/build": "18.2.0-next.2",
14
+ "@babel/core": "7.24.9",
15
+ "@babel/generator": "7.24.10",
16
16
  "@babel/helper-annotate-as-pure": "7.24.7",
17
17
  "@babel/helper-split-export-declaration": "7.24.7",
18
18
  "@babel/plugin-transform-async-generator-functions": "7.24.7",
19
19
  "@babel/plugin-transform-async-to-generator": "7.24.7",
20
20
  "@babel/plugin-transform-runtime": "7.24.7",
21
- "@babel/preset-env": "7.24.7",
22
- "@babel/runtime": "7.24.7",
21
+ "@babel/preset-env": "7.24.8",
22
+ "@babel/runtime": "7.24.8",
23
23
  "@discoveryjs/json-ext": "0.6.0",
24
- "@ngtools/webpack": "18.2.0-next.0",
24
+ "@ngtools/webpack": "18.2.0-next.2",
25
25
  "@vitejs/plugin-basic-ssl": "1.1.0",
26
26
  "ansi-colors": "4.1.3",
27
27
  "autoprefixer": "10.4.19",
@@ -53,18 +53,18 @@
53
53
  "postcss-loader": "8.1.1",
54
54
  "resolve-url-loader": "5.0.0",
55
55
  "rxjs": "7.8.1",
56
- "sass": "1.77.7",
57
- "sass-loader": "14.2.1",
58
- "semver": "7.6.2",
56
+ "sass": "1.77.8",
57
+ "sass-loader": "15.0.0",
58
+ "semver": "7.6.3",
59
59
  "source-map-loader": "5.0.0",
60
60
  "source-map-support": "0.5.21",
61
- "terser": "5.29.2",
61
+ "terser": "5.31.3",
62
62
  "tree-kill": "1.2.2",
63
63
  "tslib": "2.6.3",
64
- "vite": "5.3.3",
64
+ "vite": "5.3.4",
65
65
  "watchpack": "2.4.1",
66
- "webpack": "5.92.1",
67
- "webpack-dev-middleware": "7.2.1",
66
+ "webpack": "5.93.0",
67
+ "webpack-dev-middleware": "7.3.0",
68
68
  "webpack-dev-server": "5.0.4",
69
69
  "webpack-merge": "6.0.1",
70
70
  "webpack-subresource-integrity": "5.1.0"
@@ -129,7 +129,7 @@
129
129
  "devkit",
130
130
  "sdk"
131
131
  ],
132
- "packageManager": "yarn@4.3.0",
132
+ "packageManager": "yarn@4.3.1",
133
133
  "repository": {
134
134
  "type": "git",
135
135
  "url": "https://github.com/angular/angular-cli.git"
@@ -5,8 +5,8 @@
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.dev/license
7
7
  */
8
- import type { BuildOutputFile } from '@angular/build';
9
- import { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
8
+ import { Result } from '@angular/build/private';
9
+ import { BuilderContext } from '@angular-devkit/architect';
10
10
  import type { Plugin } from 'esbuild';
11
11
  import type { Schema as BrowserBuilderOptions } from './schema';
12
12
  /**
@@ -18,12 +18,9 @@ import type { Schema as BrowserBuilderOptions } from './schema';
18
18
  */
19
19
  export declare function buildEsbuildBrowser(userOptions: BrowserBuilderOptions, context: BuilderContext, infrastructureSettings?: {
20
20
  write?: boolean;
21
- }, plugins?: Plugin[]): AsyncIterable<BuilderOutput & {
22
- outputFiles?: BuildOutputFile[];
23
- assetFiles?: {
24
- source: string;
25
- destination: string;
26
- }[];
27
- }>;
21
+ }, plugins?: Plugin[]): AsyncIterable<Result>;
22
+ export declare function buildEsbuildBrowserArchitect(options: BrowserBuilderOptions, context: BuilderContext): AsyncGenerator<{
23
+ success: boolean;
24
+ }, void, unknown>;
28
25
  declare const _default: import("../../../../architect/src/internal").Builder<BrowserBuilderOptions & import("../../../../core/src").JsonObject>;
29
26
  export default _default;
@@ -11,6 +11,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.buildEsbuildBrowser = buildEsbuildBrowser;
14
+ exports.buildEsbuildBrowserArchitect = buildEsbuildBrowserArchitect;
14
15
  const private_1 = require("@angular/build/private");
15
16
  const architect_1 = require("@angular-devkit/architect");
16
17
  const promises_1 = __importDefault(require("node:fs/promises"));
@@ -35,19 +36,30 @@ async function* buildEsbuildBrowser(userOptions, context, infrastructureSettings
35
36
  for await (const result of (0, private_1.buildApplicationInternal)(normalizedOptions, context, {
36
37
  write: false,
37
38
  }, plugins && { codePlugins: plugins })) {
38
- if (infrastructureSettings?.write !== false && result.outputFiles) {
39
- // Write output files
40
- await writeResultFiles(result.outputFiles, result.assetFiles, fullOutputPath);
39
+ // Write the file directly from this builder to maintain webpack output compatibility
40
+ // and not output browser files into '/browser'.
41
+ if (infrastructureSettings?.write !== false &&
42
+ (result.kind === private_1.ResultKind.Full || result.kind === private_1.ResultKind.Incremental)) {
43
+ const directoryExists = new Set();
44
+ // Writes the output file to disk and ensures the containing directories are present
45
+ await (0, private_1.emitFilesToDisk)(Object.entries(result.files), async ([filePath, file]) => {
46
+ // Ensure output subdirectories exist
47
+ const basePath = node_path_1.default.dirname(filePath);
48
+ if (basePath && !directoryExists.has(basePath)) {
49
+ await promises_1.default.mkdir(node_path_1.default.join(fullOutputPath, basePath), { recursive: true });
50
+ directoryExists.add(basePath);
51
+ }
52
+ if (file.origin === 'memory') {
53
+ // Write file contents
54
+ await promises_1.default.writeFile(node_path_1.default.join(fullOutputPath, filePath), file.contents);
55
+ }
56
+ else {
57
+ // Copy file contents
58
+ await promises_1.default.copyFile(file.inputPath, node_path_1.default.join(fullOutputPath, filePath), promises_1.default.constants.COPYFILE_FICLONE);
59
+ }
60
+ });
41
61
  }
42
- // The builder system (architect) currently attempts to treat all results as JSON and
43
- // attempts to validate the object with a JSON schema validator. This can lead to slow
44
- // build completion (even after the actual build is fully complete) or crashes if the
45
- // size and/or quantity of output files is large. Architect only requires a `success`
46
- // property so that is all that will be passed here if the infrastructure settings have
47
- // not been explicitly set to avoid writes. Writing is only disabled when used directly
48
- // by the dev server which bypasses the architect behavior.
49
- const builderResult = infrastructureSettings?.write === false ? result : { success: result.success };
50
- yield builderResult;
62
+ yield result;
51
63
  }
52
64
  }
53
65
  function normalizeOptions(options) {
@@ -63,32 +75,9 @@ function normalizeOptions(options) {
63
75
  ...otherOptions,
64
76
  };
65
77
  }
66
- // We write the file directly from this builder to maintain webpack output compatibility
67
- // and not output browser files into '/browser'.
68
- async function writeResultFiles(outputFiles, assetFiles, outputPath) {
69
- const directoryExists = new Set();
70
- const ensureDirectoryExists = async (basePath) => {
71
- if (basePath && !directoryExists.has(basePath)) {
72
- await promises_1.default.mkdir(node_path_1.default.join(outputPath, basePath), { recursive: true });
73
- directoryExists.add(basePath);
74
- }
75
- };
76
- // Writes the output file to disk and ensures the containing directories are present
77
- await (0, private_1.emitFilesToDisk)(outputFiles, async (file) => {
78
- // Ensure output subdirectories exist
79
- const basePath = node_path_1.default.dirname(file.path);
80
- await ensureDirectoryExists(basePath);
81
- // Write file contents
82
- await promises_1.default.writeFile(node_path_1.default.join(outputPath, file.path), file.contents);
83
- });
84
- if (assetFiles?.length) {
85
- await (0, private_1.emitFilesToDisk)(assetFiles, async ({ source, destination }) => {
86
- const basePath = node_path_1.default.dirname(destination);
87
- // Ensure output subdirectories exist
88
- await ensureDirectoryExists(basePath);
89
- // Copy file contents
90
- await promises_1.default.copyFile(source, node_path_1.default.join(outputPath, destination), promises_1.default.constants.COPYFILE_FICLONE);
91
- });
78
+ async function* buildEsbuildBrowserArchitect(options, context) {
79
+ for await (const result of buildEsbuildBrowser(options, context)) {
80
+ yield { success: result.kind !== private_1.ResultKind.Failure };
92
81
  }
93
82
  }
94
- exports.default = (0, architect_1.createBuilder)(buildEsbuildBrowser);
83
+ exports.default = (0, architect_1.createBuilder)(buildEsbuildBrowserArchitect);
@@ -7,10 +7,10 @@
7
7
  */
8
8
  import type { ɵParsedMessage as LocalizeMessage } from '@angular/localize';
9
9
  import type { MessageExtractor } from '@angular/localize/tools';
10
- import type { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
10
+ import type { BuilderContext } from '@angular-devkit/architect';
11
11
  import type { NormalizedExtractI18nOptions } from './options';
12
12
  export declare function extractMessages(options: NormalizedExtractI18nOptions, builderName: string, context: BuilderContext, extractorConstructor: typeof MessageExtractor): Promise<{
13
- builderResult: BuilderOutput;
13
+ success: boolean;
14
14
  basePath: string;
15
15
  messages: LocalizeMessage[];
16
16
  useLegacyIds: boolean;
@@ -12,7 +12,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.extractMessages = extractMessages;
14
14
  const private_1 = require("@angular/build/private");
15
- const node_assert_1 = __importDefault(require("node:assert"));
16
15
  const node_path_1 = __importDefault(require("node:path"));
17
16
  const browser_esbuild_1 = require("../browser-esbuild");
18
17
  async function extractMessages(options, builderName, context, extractorConstructor) {
@@ -35,48 +34,31 @@ async function extractMessages(options, builderName, context, extractorConstruct
35
34
  else {
36
35
  build = browser_esbuild_1.buildEsbuildBrowser;
37
36
  }
38
- // Build the application with the build options
39
- let builderResult;
40
- try {
41
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
- for await (const result of build(buildOptions, context, { write: false })) {
43
- builderResult = result;
44
- break;
45
- }
46
- (0, node_assert_1.default)(builderResult !== undefined, 'Application builder did not provide a result.');
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ const builderResult = await first(build(buildOptions, context, { write: false }));
39
+ let success = false;
40
+ if (!builderResult || builderResult.kind === private_1.ResultKind.Failure) {
41
+ context.logger.error('Application build failed.');
47
42
  }
48
- catch (err) {
49
- builderResult = {
50
- success: false,
51
- error: err.message,
52
- };
43
+ else if (builderResult.kind !== private_1.ResultKind.Full) {
44
+ context.logger.error('Application build did not provide a full output.');
53
45
  }
54
- // Extract messages from each output JavaScript file.
55
- // Output files are only present on a successful build.
56
- if (builderResult.outputFiles) {
57
- // Store the JS and JS map files for lookup during extraction
58
- const files = new Map();
59
- for (const outputFile of builderResult.outputFiles) {
60
- if (outputFile.path.endsWith('.js')) {
61
- files.set(outputFile.path, outputFile.text);
62
- }
63
- else if (outputFile.path.endsWith('.js.map')) {
64
- files.set(outputFile.path, outputFile.text);
65
- }
66
- }
46
+ else {
67
47
  // Setup the localize message extractor based on the in-memory files
68
- const extractor = setupLocalizeExtractor(extractorConstructor, files, context);
69
- // Attempt extraction of all output JS files
70
- for (const filePath of files.keys()) {
48
+ const extractor = setupLocalizeExtractor(extractorConstructor, builderResult.files, context);
49
+ // Extract messages from each output JavaScript file.
50
+ // Output files are only present on a successful build.
51
+ for (const filePath of Object.keys(builderResult.files)) {
71
52
  if (!filePath.endsWith('.js')) {
72
53
  continue;
73
54
  }
74
55
  const fileMessages = extractor.extractMessages(filePath);
75
56
  messages.push(...fileMessages);
76
57
  }
58
+ success = true;
77
59
  }
78
60
  return {
79
- builderResult,
61
+ success,
80
62
  basePath: context.workspaceRoot,
81
63
  messages,
82
64
  // Legacy i18n identifiers are not supported with the new application builder
@@ -84,6 +66,7 @@ async function extractMessages(options, builderName, context, extractorConstruct
84
66
  };
85
67
  }
86
68
  function setupLocalizeExtractor(extractorConstructor, files, context) {
69
+ const textDecoder = new TextDecoder();
87
70
  // Setup a virtual file system instance for the extractor
88
71
  // * MessageExtractor itself uses readFile, relative and resolve
89
72
  // * Internal SourceFileLoader (sourcemap support) uses dirname, exists, readFile, and resolve
@@ -91,7 +74,11 @@ function setupLocalizeExtractor(extractorConstructor, files, context) {
91
74
  readFile(path) {
92
75
  // Output files are stored as relative to the workspace root
93
76
  const requestedPath = node_path_1.default.relative(context.workspaceRoot, path);
94
- const content = files.get(requestedPath);
77
+ const file = files[requestedPath];
78
+ let content;
79
+ if (file?.origin === 'memory') {
80
+ content = textDecoder.decode(file.contents);
81
+ }
95
82
  if (content === undefined) {
96
83
  throw new Error('Unknown file requested: ' + requestedPath);
97
84
  }
@@ -106,7 +93,7 @@ function setupLocalizeExtractor(extractorConstructor, files, context) {
106
93
  exists(path) {
107
94
  // Output files are stored as relative to the workspace root
108
95
  const requestedPath = node_path_1.default.relative(context.workspaceRoot, path);
109
- return files.has(requestedPath);
96
+ return files[requestedPath] !== undefined;
110
97
  },
111
98
  dirname(path) {
112
99
  return node_path_1.default.dirname(path);
@@ -137,3 +124,8 @@ function setupLocalizeExtractor(extractorConstructor, files, context) {
137
124
  });
138
125
  return extractor;
139
126
  }
127
+ async function first(iterable) {
128
+ for await (const value of iterable) {
129
+ return value;
130
+ }
131
+ }
@@ -75,6 +75,9 @@ async function execute(options, context, transforms) {
75
75
  builderName === '@angular-devkit/build-angular:browser-esbuild') {
76
76
  const { extractMessages } = await Promise.resolve().then(() => __importStar(require('./application-extraction')));
77
77
  extractionResult = await extractMessages(normalizedOptions, builderName, context, localizeToolsModule.MessageExtractor);
78
+ if (!extractionResult.success) {
79
+ return { success: false };
80
+ }
78
81
  }
79
82
  else {
80
83
  // Purge old build disk cache.
@@ -82,10 +85,10 @@ async function execute(options, context, transforms) {
82
85
  await (0, private_1.purgeStaleBuildCache)(context);
83
86
  const { extractMessages } = await Promise.resolve().then(() => __importStar(require('./webpack-extraction')));
84
87
  extractionResult = await extractMessages(normalizedOptions, builderName, context, transforms);
85
- }
86
- // Return the builder result if it failed
87
- if (!extractionResult.builderResult.success) {
88
- return extractionResult.builderResult;
88
+ // Return the builder result if it failed
89
+ if (!extractionResult.builderResult.success) {
90
+ return extractionResult.builderResult;
91
+ }
89
92
  }
90
93
  // Perform duplicate message checks
91
94
  const { checkDuplicateMessages } = localizeToolsModule;
@@ -139,12 +142,13 @@ async function createSerializer(localizeToolsModule, format, sourceLocale, baseP
139
142
  case schema_1.Format.LegacyMigrate:
140
143
  return new LegacyMessageIdMigrationSerializer(diagnostics);
141
144
  case schema_1.Format.Arb:
142
- const fileSystem = {
145
+ return new ArbTranslationSerializer(sourceLocale,
146
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
147
+ basePath, {
143
148
  relative(from, to) {
144
149
  return node_path_1.default.relative(from, to);
145
150
  },
146
- };
147
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
148
- return new ArbTranslationSerializer(sourceLocale, basePath, fileSystem);
151
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
152
+ });
149
153
  }
150
154
  }
@@ -37,8 +37,8 @@ async function normalizeOptions(context, projectName, options) {
37
37
  // Normalize xliff format extensions
38
38
  let format = options.format;
39
39
  switch (format) {
40
- case undefined:
41
40
  // Default format is xliff1
41
+ case undefined:
42
42
  case schema_1.Format.Xlf:
43
43
  case schema_1.Format.Xlif:
44
44
  case schema_1.Format.Xliff:
@@ -47,8 +47,8 @@ exports.default = (0, architect_1.createBuilder)(async (schema, ctx) => {
47
47
  ]);
48
48
  // Build the tests and abort on any build failure.
49
49
  const buildOutput = await buildTests(testFiles, testDir, options, ctx);
50
- if (!buildOutput.success) {
51
- return buildOutput;
50
+ if (buildOutput.kind === private_1.ResultKind.Failure) {
51
+ return { success: false };
52
52
  }
53
53
  // Run the built tests.
54
54
  return await runTests(wtr, `${testDir}/browser`, options);
@@ -153,8 +153,7 @@ exports.default = (0, babel_loader_1.custom)(() => {
153
153
  case 'error':
154
154
  this.emitError(message);
155
155
  break;
156
- case 'info':
157
- // Webpack does not currently have an informational diagnostic
156
+ case 'info': // Webpack does not currently have an informational diagnostic
158
157
  case 'warning':
159
158
  this.emitWarning(message);
160
159
  break;
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.normalizeCacheOptions = normalizeCacheOptions;
11
11
  const node_path_1 = require("node:path");
12
12
  /** Version placeholder is replaced during the build process with actual package version */
13
- const VERSION = '18.2.0-next.0';
13
+ const VERSION = '18.2.0-next.2';
14
14
  function hasCacheMetadata(value) {
15
15
  return (!!value &&
16
16
  typeof value === 'object' &&