@angular-devkit/build-angular 19.0.0-next.8 → 19.0.0-next.9
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/LICENSE +5 -5
- package/package.json +10 -10
- package/src/builders/karma/application_builder.js +97 -45
- package/src/utils/normalize-cache.js +1 -1
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
The MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2010-2024 Google LLC. https://angular.dev/license
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
9
9
|
copies of the Software, and to permit persons to whom the Software is
|
|
10
10
|
furnished to do so, subject to the following conditions:
|
|
11
11
|
|
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
|
13
|
-
copies or substantial portions of the Software.
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
14
|
|
|
15
15
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
16
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
17
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
-
SOFTWARE.
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-devkit/build-angular",
|
|
3
|
-
"version": "19.0.0-next.
|
|
3
|
+
"version": "19.0.0-next.9",
|
|
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.1900.0-next.
|
|
11
|
-
"@angular-devkit/build-webpack": "0.1900.0-next.
|
|
12
|
-
"@angular-devkit/core": "19.0.0-next.
|
|
13
|
-
"@angular/build": "19.0.0-next.
|
|
10
|
+
"@angular-devkit/architect": "0.1900.0-next.9",
|
|
11
|
+
"@angular-devkit/build-webpack": "0.1900.0-next.9",
|
|
12
|
+
"@angular-devkit/core": "19.0.0-next.9",
|
|
13
|
+
"@angular/build": "19.0.0-next.9",
|
|
14
14
|
"@babel/core": "7.25.2",
|
|
15
15
|
"@babel/generator": "7.25.6",
|
|
16
16
|
"@babel/helper-annotate-as-pure": "7.24.7",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@babel/preset-env": "7.25.4",
|
|
22
22
|
"@babel/runtime": "7.25.6",
|
|
23
23
|
"@discoveryjs/json-ext": "0.6.1",
|
|
24
|
-
"@ngtools/webpack": "19.0.0-next.
|
|
24
|
+
"@ngtools/webpack": "19.0.0-next.9",
|
|
25
25
|
"@vitejs/plugin-basic-ssl": "1.1.0",
|
|
26
26
|
"ansi-colors": "4.1.3",
|
|
27
27
|
"autoprefixer": "10.4.20",
|
|
@@ -53,17 +53,17 @@
|
|
|
53
53
|
"postcss-loader": "8.1.1",
|
|
54
54
|
"resolve-url-loader": "5.0.0",
|
|
55
55
|
"rxjs": "7.8.1",
|
|
56
|
-
"sass": "1.79.
|
|
56
|
+
"sass": "1.79.4",
|
|
57
57
|
"sass-loader": "16.0.2",
|
|
58
58
|
"semver": "7.6.3",
|
|
59
59
|
"source-map-loader": "5.0.0",
|
|
60
60
|
"source-map-support": "0.5.21",
|
|
61
|
-
"terser": "5.
|
|
61
|
+
"terser": "5.34.1",
|
|
62
62
|
"tree-kill": "1.2.2",
|
|
63
63
|
"tslib": "2.7.0",
|
|
64
64
|
"vite": "5.4.8",
|
|
65
65
|
"watchpack": "2.4.2",
|
|
66
|
-
"webpack": "5.
|
|
66
|
+
"webpack": "5.95.0",
|
|
67
67
|
"webpack-dev-middleware": "7.4.2",
|
|
68
68
|
"webpack-dev-server": "5.1.0",
|
|
69
69
|
"webpack-merge": "6.0.1",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"@angular/localize": "^19.0.0-next.0",
|
|
78
78
|
"@angular/platform-server": "^19.0.0-next.0",
|
|
79
79
|
"@angular/service-worker": "^19.0.0-next.0",
|
|
80
|
-
"@angular/ssr": "^19.0.0-next.
|
|
80
|
+
"@angular/ssr": "^19.0.0-next.9",
|
|
81
81
|
"@web/test-runner": "^0.19.0",
|
|
82
82
|
"browser-sync": "^3.0.2",
|
|
83
83
|
"jest": "^29.5.0",
|
|
@@ -29,16 +29,19 @@ 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.execute = execute;
|
|
34
37
|
exports.writeTestFiles = writeTestFiles;
|
|
35
38
|
const build_1 = require("@angular/build");
|
|
36
39
|
const private_1 = require("@angular/build/private");
|
|
37
40
|
const crypto_1 = require("crypto");
|
|
41
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
38
42
|
const fs = __importStar(require("fs/promises"));
|
|
39
43
|
const path = __importStar(require("path"));
|
|
40
44
|
const rxjs_1 = require("rxjs");
|
|
41
|
-
const read_tsconfig_1 = require("../../utils/read-tsconfig");
|
|
42
45
|
const schema_1 = require("../browser-esbuild/schema");
|
|
43
46
|
const find_tests_1 = require("./find-tests");
|
|
44
47
|
class ApplicationBuildError extends Error {
|
|
@@ -47,8 +50,56 @@ class ApplicationBuildError extends Error {
|
|
|
47
50
|
this.name = 'ApplicationBuildError';
|
|
48
51
|
}
|
|
49
52
|
}
|
|
53
|
+
function injectKarmaReporter(context, buildOptions, karmaConfig, subscriber) {
|
|
54
|
+
const reporterName = 'angular-progress-notifier';
|
|
55
|
+
class ProgressNotifierReporter {
|
|
56
|
+
emitter;
|
|
57
|
+
static $inject = ['emitter'];
|
|
58
|
+
constructor(emitter) {
|
|
59
|
+
this.emitter = emitter;
|
|
60
|
+
this.startWatchingBuild();
|
|
61
|
+
}
|
|
62
|
+
startWatchingBuild() {
|
|
63
|
+
void (async () => {
|
|
64
|
+
for await (const buildOutput of (0, private_1.buildApplicationInternal)({
|
|
65
|
+
...buildOptions,
|
|
66
|
+
watch: true,
|
|
67
|
+
}, context)) {
|
|
68
|
+
if (buildOutput.kind === private_1.ResultKind.Failure) {
|
|
69
|
+
subscriber.next({ success: false, message: 'Build failed' });
|
|
70
|
+
}
|
|
71
|
+
else if (buildOutput.kind === private_1.ResultKind.Incremental ||
|
|
72
|
+
buildOutput.kind === private_1.ResultKind.Full) {
|
|
73
|
+
await writeTestFiles(buildOutput.files, buildOptions.outputPath);
|
|
74
|
+
this.emitter.refreshFiles();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
})();
|
|
78
|
+
}
|
|
79
|
+
onRunComplete = function (_browsers, results) {
|
|
80
|
+
if (results.exitCode === 0) {
|
|
81
|
+
subscriber.next({ success: true });
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
subscriber.next({ success: false });
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
karmaConfig.reporters ??= [];
|
|
89
|
+
karmaConfig.reporters.push(reporterName);
|
|
90
|
+
karmaConfig.plugins ??= [];
|
|
91
|
+
karmaConfig.plugins.push({
|
|
92
|
+
[`reporter:${reporterName}`]: [
|
|
93
|
+
'factory',
|
|
94
|
+
Object.assign((...args) => new ProgressNotifierReporter(...args), ProgressNotifierReporter),
|
|
95
|
+
],
|
|
96
|
+
});
|
|
97
|
+
}
|
|
50
98
|
function execute(options, context, karmaOptions, transforms = {}) {
|
|
51
|
-
return (0, rxjs_1.from)(initializeApplication(options, context, karmaOptions, transforms)).pipe((0, rxjs_1.switchMap)(([karma, karmaConfig]) => new rxjs_1.Observable((subscriber) => {
|
|
99
|
+
return (0, rxjs_1.from)(initializeApplication(options, context, karmaOptions, transforms)).pipe((0, rxjs_1.switchMap)(([karma, karmaConfig, buildOptions]) => new rxjs_1.Observable((subscriber) => {
|
|
100
|
+
if (options.watch) {
|
|
101
|
+
injectKarmaReporter(context, buildOptions, karmaConfig, subscriber);
|
|
102
|
+
}
|
|
52
103
|
// Complete the observable once the Karma server returns.
|
|
53
104
|
const karmaServer = new karma.Server(karmaConfig, (exitCode) => {
|
|
54
105
|
subscriber.next({ success: exitCode === 0 });
|
|
@@ -76,41 +127,36 @@ async function getProjectSourceRoot(context) {
|
|
|
76
127
|
const sourceRoot = (projectMetadata.sourceRoot ?? projectMetadata.root ?? '');
|
|
77
128
|
return path.join(context.workspaceRoot, sourceRoot);
|
|
78
129
|
}
|
|
79
|
-
|
|
80
|
-
|
|
130
|
+
function normalizePolyfills(polyfills) {
|
|
131
|
+
if (typeof polyfills === 'string') {
|
|
132
|
+
return [polyfills];
|
|
133
|
+
}
|
|
134
|
+
return polyfills ?? [];
|
|
135
|
+
}
|
|
136
|
+
async function collectEntrypoints(options, context, projectSourceRoot) {
|
|
81
137
|
// Glob for files to test.
|
|
82
138
|
const testFiles = await (0, find_tests_1.findTests)(options.include ?? [], options.exclude ?? [], context.workspaceRoot, projectSourceRoot);
|
|
83
139
|
const entryPoints = new Set([
|
|
84
140
|
...testFiles,
|
|
85
141
|
'@angular-devkit/build-angular/src/builders/karma/init_test_bed.js',
|
|
86
142
|
]);
|
|
87
|
-
|
|
88
|
-
const [polyfills, hasZoneTesting] = extractZoneTesting(options.polyfills);
|
|
89
|
-
if (hasZoneTesting) {
|
|
90
|
-
entryPoints.add('zone.js/testing');
|
|
91
|
-
}
|
|
92
|
-
const tsConfigPath = path.resolve(context.workspaceRoot, options.tsConfig);
|
|
93
|
-
const tsConfig = await (0, read_tsconfig_1.readTsconfig)(tsConfigPath);
|
|
94
|
-
const localizePackageInitEntryPoint = '@angular/localize/init';
|
|
95
|
-
const hasLocalizeType = tsConfig.options.types?.some((t) => t === '@angular/localize' || t === localizePackageInitEntryPoint);
|
|
96
|
-
if (hasLocalizeType) {
|
|
97
|
-
polyfills.push(localizePackageInitEntryPoint);
|
|
98
|
-
}
|
|
99
|
-
return [entryPoints, polyfills];
|
|
143
|
+
return entryPoints;
|
|
100
144
|
}
|
|
101
145
|
async function initializeApplication(options, context, karmaOptions, transforms = {}) {
|
|
102
146
|
if (transforms.webpackConfiguration) {
|
|
103
147
|
context.logger.warn(`This build is using the application builder but transforms.webpackConfiguration was provided. The transform will be ignored.`);
|
|
104
148
|
}
|
|
105
|
-
const
|
|
106
|
-
const
|
|
149
|
+
const outputPath = path.join(context.workspaceRoot, 'dist/test-out', (0, crypto_1.randomUUID)());
|
|
150
|
+
const projectSourceRoot = await getProjectSourceRoot(context);
|
|
151
|
+
const [karma, entryPoints] = await Promise.all([
|
|
107
152
|
Promise.resolve().then(() => __importStar(require('karma'))),
|
|
108
|
-
collectEntrypoints(options, context),
|
|
109
|
-
fs.rm(
|
|
153
|
+
collectEntrypoints(options, context, projectSourceRoot),
|
|
154
|
+
fs.rm(outputPath, { recursive: true, force: true }),
|
|
110
155
|
]);
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
156
|
+
const instrumentForCoverage = options.codeCoverage
|
|
157
|
+
? createInstrumentationFilter(projectSourceRoot, getInstrumentationExcludedPaths(context.workspaceRoot, options.codeCoverageExclude ?? []))
|
|
158
|
+
: undefined;
|
|
159
|
+
const buildOptions = {
|
|
114
160
|
entryPoints,
|
|
115
161
|
tsConfig: options.tsConfig,
|
|
116
162
|
outputPath,
|
|
@@ -123,10 +169,13 @@ async function initializeApplication(options, context, karmaOptions, transforms
|
|
|
123
169
|
styles: true,
|
|
124
170
|
vendor: true,
|
|
125
171
|
},
|
|
172
|
+
instrumentForCoverage,
|
|
126
173
|
styles: options.styles,
|
|
127
|
-
polyfills,
|
|
174
|
+
polyfills: normalizePolyfills(options.polyfills),
|
|
128
175
|
webWorkerTsConfig: options.webWorkerTsConfig,
|
|
129
|
-
}
|
|
176
|
+
};
|
|
177
|
+
// Build tests with `application` builder, using test files as entry points.
|
|
178
|
+
const buildOutput = await first((0, private_1.buildApplicationInternal)(buildOptions, context));
|
|
130
179
|
if (buildOutput.kind === private_1.ResultKind.Failure) {
|
|
131
180
|
throw new ApplicationBuildError('Build failed');
|
|
132
181
|
}
|
|
@@ -134,22 +183,19 @@ async function initializeApplication(options, context, karmaOptions, transforms
|
|
|
134
183
|
throw new ApplicationBuildError('A full build result is required from the application builder.');
|
|
135
184
|
}
|
|
136
185
|
// Write test files
|
|
137
|
-
await writeTestFiles(buildOutput.files,
|
|
186
|
+
await writeTestFiles(buildOutput.files, buildOptions.outputPath);
|
|
138
187
|
karmaOptions.files ??= [];
|
|
139
188
|
karmaOptions.files.push(
|
|
140
189
|
// Serve polyfills first.
|
|
141
|
-
{ pattern: `${
|
|
190
|
+
{ pattern: `${outputPath}/polyfills.js`, type: 'module' },
|
|
142
191
|
// Allow loading of chunk-* files but don't include them all on load.
|
|
143
|
-
{ pattern: `${
|
|
144
|
-
|
|
145
|
-
{ pattern: `${testDir}/worker-*.js`, type: 'module', included: false },
|
|
146
|
-
// `zone.js/testing`, served but not included on page load.
|
|
147
|
-
{ pattern: `${testDir}/testing.js`, type: 'module', included: false },
|
|
192
|
+
{ pattern: `${outputPath}/{chunk,worker}-*.js`, type: 'module', included: false });
|
|
193
|
+
karmaOptions.files.push(
|
|
148
194
|
// Serve remaining JS on page load, these are the test entrypoints.
|
|
149
|
-
{ pattern: `${
|
|
195
|
+
{ pattern: `${outputPath}/*.js`, type: 'module' });
|
|
150
196
|
if (options.styles?.length) {
|
|
151
197
|
// Serve CSS outputs on page load, these are the global styles.
|
|
152
|
-
karmaOptions.files.push({ pattern: `${
|
|
198
|
+
karmaOptions.files.push({ pattern: `${outputPath}/*.css`, type: 'css' });
|
|
153
199
|
}
|
|
154
200
|
const parsedKarmaConfig = await karma.config.parseConfig(options.karmaConfig && path.resolve(context.workspaceRoot, options.karmaConfig), transforms.karmaOptions ? transforms.karmaOptions(karmaOptions) : karmaOptions, { promiseConfig: true, throwErrors: true });
|
|
155
201
|
// Remove the webpack plugin/framework:
|
|
@@ -173,7 +219,7 @@ async function initializeApplication(options, context, karmaOptions, transforms
|
|
|
173
219
|
!parsedKarmaConfig.reporters?.some((r) => r === 'coverage' || r === 'coverage-istanbul')) {
|
|
174
220
|
parsedKarmaConfig.reporters = (parsedKarmaConfig.reporters ?? []).concat(['coverage']);
|
|
175
221
|
}
|
|
176
|
-
return [karma, parsedKarmaConfig];
|
|
222
|
+
return [karma, parsedKarmaConfig, buildOptions];
|
|
177
223
|
}
|
|
178
224
|
async function writeTestFiles(files, testDir) {
|
|
179
225
|
const directoryExists = new Set();
|
|
@@ -199,15 +245,6 @@ async function writeTestFiles(files, testDir) {
|
|
|
199
245
|
}
|
|
200
246
|
});
|
|
201
247
|
}
|
|
202
|
-
function extractZoneTesting(polyfills) {
|
|
203
|
-
if (typeof polyfills === 'string') {
|
|
204
|
-
polyfills = [polyfills];
|
|
205
|
-
}
|
|
206
|
-
polyfills ??= [];
|
|
207
|
-
const polyfillsWithoutZoneTesting = polyfills.filter((polyfill) => polyfill !== 'zone.js/testing');
|
|
208
|
-
const hasZoneTesting = polyfills.length !== polyfillsWithoutZoneTesting.length;
|
|
209
|
-
return [polyfillsWithoutZoneTesting, hasZoneTesting];
|
|
210
|
-
}
|
|
211
248
|
/** Returns the first item yielded by the given generator and cancels the execution. */
|
|
212
249
|
async function first(generator) {
|
|
213
250
|
for await (const value of generator) {
|
|
@@ -215,3 +252,18 @@ async function first(generator) {
|
|
|
215
252
|
}
|
|
216
253
|
throw new Error('Expected generator to emit at least once.');
|
|
217
254
|
}
|
|
255
|
+
function createInstrumentationFilter(includedBasePath, excludedPaths) {
|
|
256
|
+
return (request) => {
|
|
257
|
+
return (!excludedPaths.has(request) &&
|
|
258
|
+
!/\.(e2e|spec)\.tsx?$|[\\/]node_modules[\\/]/.test(request) &&
|
|
259
|
+
request.startsWith(includedBasePath));
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function getInstrumentationExcludedPaths(root, excludedPaths) {
|
|
263
|
+
const excluded = new Set();
|
|
264
|
+
for (const excludeGlob of excludedPaths) {
|
|
265
|
+
const excludePath = excludeGlob[0] === '/' ? excludeGlob.slice(1) : excludeGlob;
|
|
266
|
+
fast_glob_1.default.sync(excludePath, { cwd: root }).forEach((p) => excluded.add(path.join(root, p)));
|
|
267
|
+
}
|
|
268
|
+
return excluded;
|
|
269
|
+
}
|
|
@@ -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 = '19.0.0-next.
|
|
13
|
+
const VERSION = '19.0.0-next.9';
|
|
14
14
|
function hasCacheMetadata(value) {
|
|
15
15
|
return (!!value &&
|
|
16
16
|
typeof value === 'object' &&
|