@angular/build 20.1.0-rc.0 → 20.1.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.
- package/package.json +11 -11
- package/src/builders/application/build-action.js +2 -1
- package/src/builders/dev-server/vite-server.js +8 -0
- package/src/builders/karma/application_builder.d.ts +2 -4
- package/src/builders/karma/application_builder.js +91 -29
- package/src/builders/karma/find-tests.js +4 -4
- package/src/builders/karma/index.d.ts +4 -7
- package/src/builders/karma/index.js +2 -88
- package/src/builders/karma/options.d.ts +42 -0
- package/src/builders/karma/options.js +43 -0
- package/src/builders/karma/schema.d.ts +1 -1
- package/src/builders/karma/schema.json +2 -1
- package/src/builders/unit-test/builder.d.ts +3 -3
- package/src/builders/unit-test/builder.js +14 -8
- package/src/builders/unit-test/index.d.ts +3 -3
- package/src/builders/unit-test/karma-bridge.d.ts +2 -2
- package/src/builders/unit-test/karma-bridge.js +3 -0
- package/src/builders/unit-test/options.d.ts +4 -3
- package/src/builders/unit-test/options.js +3 -0
- package/src/builders/unit-test/schema.d.ts +8 -1
- package/src/builders/unit-test/schema.json +16 -2
- package/src/index.d.ts +2 -0
- package/src/index.js +5 -1
- package/src/private.d.ts +9 -1
- package/src/private.js +2 -3
- package/src/tools/angular/compilation/factory.d.ts +1 -1
- package/src/tools/angular/compilation/factory.js +2 -2
- package/src/tools/esbuild/angular/diagnostics.js +5 -2
- package/src/tools/esbuild/application-code-bundle.js +3 -7
- package/src/tools/esbuild/global-styles.js +2 -1
- package/src/tools/sass/rebasing-importer.js +2 -1
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/path.d.ts +29 -0
- package/src/utils/path.js +37 -0
- package/src/utils/server-rendering/prerender.js +2 -1
- package/src/utils/service-worker.js +4 -3
- package/src/utils/version.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular/build",
|
|
3
|
-
"version": "20.1.
|
|
3
|
+
"version": "20.1.1",
|
|
4
4
|
"description": "Official build system for Angular",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Angular CLI",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"builders": "builders.json",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@ampproject/remapping": "2.3.0",
|
|
26
|
-
"@angular-devkit/architect": "0.2001.
|
|
26
|
+
"@angular-devkit/architect": "0.2001.1",
|
|
27
27
|
"@babel/core": "7.27.7",
|
|
28
28
|
"@babel/helper-annotate-as-pure": "7.27.3",
|
|
29
29
|
"@babel/helper-split-export-declaration": "7.24.7",
|
|
@@ -53,17 +53,17 @@
|
|
|
53
53
|
"lmdb": "3.4.1"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@angular/core": "^20.0.0
|
|
57
|
-
"@angular/compiler": "^20.0.0
|
|
58
|
-
"@angular/compiler-cli": "^20.0.0
|
|
59
|
-
"@angular/localize": "^20.0.0
|
|
60
|
-
"@angular/platform-browser": "^20.0.0
|
|
61
|
-
"@angular/platform-server": "^20.0.0
|
|
62
|
-
"@angular/service-worker": "^20.0.0
|
|
63
|
-
"@angular/ssr": "^20.1.
|
|
56
|
+
"@angular/core": "^20.0.0",
|
|
57
|
+
"@angular/compiler": "^20.0.0",
|
|
58
|
+
"@angular/compiler-cli": "^20.0.0",
|
|
59
|
+
"@angular/localize": "^20.0.0",
|
|
60
|
+
"@angular/platform-browser": "^20.0.0",
|
|
61
|
+
"@angular/platform-server": "^20.0.0",
|
|
62
|
+
"@angular/service-worker": "^20.0.0",
|
|
63
|
+
"@angular/ssr": "^20.1.1",
|
|
64
64
|
"karma": "^6.4.0",
|
|
65
65
|
"less": "^4.2.0",
|
|
66
|
-
"ng-packagr": "^20.0.0
|
|
66
|
+
"ng-packagr": "^20.0.0",
|
|
67
67
|
"postcss": "^8.4.0",
|
|
68
68
|
"tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0",
|
|
69
69
|
"tslib": "^2.3.0",
|
|
@@ -50,6 +50,7 @@ const bundler_context_1 = require("../../tools/esbuild/bundler-context");
|
|
|
50
50
|
const sass_language_1 = require("../../tools/esbuild/stylesheets/sass-language");
|
|
51
51
|
const utils_1 = require("../../tools/esbuild/utils");
|
|
52
52
|
const environment_options_1 = require("../../utils/environment-options");
|
|
53
|
+
const path_1 = require("../../utils/path");
|
|
53
54
|
const results_1 = require("./results");
|
|
54
55
|
// Watch workspace for package manager changes
|
|
55
56
|
const packageWatchFiles = [
|
|
@@ -91,7 +92,7 @@ async function* runEsBuildBuildAction(action, options) {
|
|
|
91
92
|
// Ignore the output and cache paths to avoid infinite rebuild cycles
|
|
92
93
|
outputOptions.base,
|
|
93
94
|
cacheOptions.basePath,
|
|
94
|
-
`${
|
|
95
|
+
`${(0, path_1.toPosixPath)(workspaceRoot)}/**/.*/**`,
|
|
95
96
|
];
|
|
96
97
|
// Setup a watcher
|
|
97
98
|
const { createWatcher } = await Promise.resolve().then(() => __importStar(require('../../tools/esbuild/watcher')));
|
|
@@ -55,6 +55,7 @@ const utils_2 = require("../../utils");
|
|
|
55
55
|
const environment_options_1 = require("../../utils/environment-options");
|
|
56
56
|
const load_esm_1 = require("../../utils/load-esm");
|
|
57
57
|
const results_1 = require("../application/results");
|
|
58
|
+
const schema_1 = require("../application/schema");
|
|
58
59
|
const internal_1 = require("./internal");
|
|
59
60
|
/**
|
|
60
61
|
* Build options that are also present on the dev server but are only passed
|
|
@@ -114,6 +115,13 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
114
115
|
// https://nodejs.org/api/process.html#processsetsourcemapsenabledval
|
|
115
116
|
process.setSourceMapsEnabled(true);
|
|
116
117
|
}
|
|
118
|
+
if (serverOptions.hmr &&
|
|
119
|
+
(browserOptions.outputHashing === schema_1.OutputHashing.All ||
|
|
120
|
+
browserOptions.outputHashing === schema_1.OutputHashing.Bundles)) {
|
|
121
|
+
serverOptions.hmr = false;
|
|
122
|
+
context.logger.warn(`Hot Module Replacement (HMR) is disabled because the 'outputHashing' option is set to '${browserOptions.outputHashing}'. ` +
|
|
123
|
+
'HMR is incompatible with this setting.');
|
|
124
|
+
}
|
|
117
125
|
const componentsHmrCanBeUsed = browserOptions.aot && serverOptions.liveReload && serverOptions.hmr;
|
|
118
126
|
// Enable to support link-based component style hot reloading (`NG_HMR_CSTYLES=1` can be used to enable)
|
|
119
127
|
browserOptions.externalRuntimeStyles = componentsHmrCanBeUsed && environment_options_1.useComponentStyleHmr;
|
|
@@ -6,10 +6,8 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import type { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
|
|
9
|
-
import type { ConfigOptions } from 'karma';
|
|
10
9
|
import { ResultFile } from '../application/results';
|
|
11
10
|
import { Schema as KarmaBuilderOptions } from './schema';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}): AsyncIterable<BuilderOutput>;
|
|
11
|
+
import type { KarmaBuilderTransformsOptions } from './index';
|
|
12
|
+
export declare function execute(options: KarmaBuilderOptions, context: BuilderContext, transforms?: KarmaBuilderTransformsOptions): AsyncIterable<BuilderOutput>;
|
|
15
13
|
export declare function writeTestFiles(files: Record<string, ResultFile>, testDir: string): Promise<void>;
|
|
@@ -39,13 +39,16 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
return result;
|
|
40
40
|
};
|
|
41
41
|
})();
|
|
42
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
43
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
44
|
+
};
|
|
42
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
46
|
exports.execute = execute;
|
|
44
47
|
exports.writeTestFiles = writeTestFiles;
|
|
45
48
|
const node_crypto_1 = require("node:crypto");
|
|
46
49
|
const fs = __importStar(require("node:fs/promises"));
|
|
47
50
|
const node_module_1 = require("node:module");
|
|
48
|
-
const
|
|
51
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
49
52
|
const tinyglobby_1 = require("tinyglobby");
|
|
50
53
|
const bundler_context_1 = require("../../tools/esbuild/bundler-context");
|
|
51
54
|
const utils_1 = require("../../tools/esbuild/utils");
|
|
@@ -55,6 +58,7 @@ const index_1 = require("../application/index");
|
|
|
55
58
|
const results_1 = require("../application/results");
|
|
56
59
|
const schema_1 = require("../application/schema");
|
|
57
60
|
const find_tests_1 = require("./find-tests");
|
|
61
|
+
const options_1 = require("./options");
|
|
58
62
|
const localResolve = (0, node_module_1.createRequire)(__filename).resolve;
|
|
59
63
|
const isWindows = process.platform === 'win32';
|
|
60
64
|
class ApplicationBuildError extends Error {
|
|
@@ -79,20 +83,23 @@ class AngularAssetsMiddleware {
|
|
|
79
83
|
// The latest build files will use the platform path separator.
|
|
80
84
|
let pathname = url.pathname.slice(1);
|
|
81
85
|
if (isWindows) {
|
|
82
|
-
pathname = pathname.replaceAll(
|
|
86
|
+
pathname = pathname.replaceAll(node_path_1.default.posix.sep, node_path_1.default.win32.sep);
|
|
83
87
|
}
|
|
84
88
|
const file = this.latestBuildFiles.files[pathname];
|
|
85
89
|
if (!file) {
|
|
86
90
|
next();
|
|
87
91
|
return;
|
|
88
92
|
}
|
|
93
|
+
// Implementation of serverFile can be found here:
|
|
94
|
+
// https://github.com/karma-runner/karma/blob/84f85e7016efc2266fa6b3465f494a3fa151c85c/lib/middleware/common.js#L10
|
|
89
95
|
switch (file.origin) {
|
|
90
96
|
case 'disk':
|
|
91
97
|
this.serveFile(file.inputPath, undefined, res, undefined, undefined, /* doNotCache */ true);
|
|
92
98
|
break;
|
|
93
99
|
case 'memory':
|
|
94
100
|
// Include pathname to help with Content-Type headers.
|
|
95
|
-
this.serveFile(`/unused/${url.pathname}`, undefined, res, undefined, file.contents,
|
|
101
|
+
this.serveFile(`/unused/${url.pathname}`, undefined, res, undefined, file.contents,
|
|
102
|
+
/* doNotCache */ false);
|
|
96
103
|
break;
|
|
97
104
|
}
|
|
98
105
|
}
|
|
@@ -228,13 +235,15 @@ function injectKarmaReporter(buildOptions, buildIterator, karmaConfig, controlle
|
|
|
228
235
|
],
|
|
229
236
|
});
|
|
230
237
|
}
|
|
231
|
-
function execute(options, context,
|
|
238
|
+
function execute(options, context, transforms) {
|
|
239
|
+
const normalizedOptions = (0, options_1.normalizeOptions)(context, options);
|
|
240
|
+
const karmaOptions = getBaseKarmaOptions(normalizedOptions, context);
|
|
232
241
|
let karmaServer;
|
|
233
242
|
return new ReadableStream({
|
|
234
243
|
async start(controller) {
|
|
235
244
|
let init;
|
|
236
245
|
try {
|
|
237
|
-
init = await initializeApplication(
|
|
246
|
+
init = await initializeApplication(normalizedOptions, context, karmaOptions, transforms);
|
|
238
247
|
}
|
|
239
248
|
catch (err) {
|
|
240
249
|
if (err instanceof ApplicationBuildError) {
|
|
@@ -272,13 +281,7 @@ async function getProjectSourceRoot(context) {
|
|
|
272
281
|
const { projectSourceRoot } = (0, project_metadata_1.getProjectRootPaths)(context.workspaceRoot, projectMetadata);
|
|
273
282
|
return projectSourceRoot;
|
|
274
283
|
}
|
|
275
|
-
function normalizePolyfills(polyfills) {
|
|
276
|
-
if (typeof polyfills === 'string') {
|
|
277
|
-
polyfills = [polyfills];
|
|
278
|
-
}
|
|
279
|
-
else if (!polyfills) {
|
|
280
|
-
polyfills = [];
|
|
281
|
-
}
|
|
284
|
+
function normalizePolyfills(polyfills = []) {
|
|
282
285
|
const jasmineGlobalEntryPoint = localResolve('./polyfills/jasmine_global.js');
|
|
283
286
|
const jasmineGlobalCleanupEntrypoint = localResolve('./polyfills/jasmine_global_cleanup.js');
|
|
284
287
|
const sourcemapEntrypoint = localResolve('./polyfills/init_sourcemaps.js');
|
|
@@ -293,12 +296,12 @@ function normalizePolyfills(polyfills) {
|
|
|
293
296
|
}
|
|
294
297
|
async function collectEntrypoints(options, context, projectSourceRoot) {
|
|
295
298
|
// Glob for files to test.
|
|
296
|
-
const testFiles = await (0, find_tests_1.findTests)(options.include
|
|
299
|
+
const testFiles = await (0, find_tests_1.findTests)(options.include, options.exclude, context.workspaceRoot, projectSourceRoot);
|
|
297
300
|
return (0, find_tests_1.getTestEntrypoints)(testFiles, { projectSourceRoot, workspaceRoot: context.workspaceRoot });
|
|
298
301
|
}
|
|
299
302
|
// eslint-disable-next-line max-lines-per-function
|
|
300
|
-
async function initializeApplication(options, context, karmaOptions, transforms
|
|
301
|
-
const outputPath =
|
|
303
|
+
async function initializeApplication(options, context, karmaOptions, transforms) {
|
|
304
|
+
const outputPath = node_path_1.default.join(context.workspaceRoot, 'dist/test-out', (0, node_crypto_1.randomUUID)());
|
|
302
305
|
const projectSourceRoot = await getProjectSourceRoot(context);
|
|
303
306
|
const [karma, entryPoints] = await Promise.all([
|
|
304
307
|
Promise.resolve().then(() => __importStar(require('karma'))),
|
|
@@ -329,19 +332,13 @@ async function initializeApplication(options, context, karmaOptions, transforms
|
|
|
329
332
|
index: false,
|
|
330
333
|
outputHashing: schema_1.OutputHashing.None,
|
|
331
334
|
optimization: false,
|
|
332
|
-
sourceMap: options.
|
|
333
|
-
? {
|
|
334
|
-
scripts: true,
|
|
335
|
-
styles: true,
|
|
336
|
-
vendor: true,
|
|
337
|
-
}
|
|
338
|
-
: options.sourceMap,
|
|
335
|
+
sourceMap: options.sourceMap,
|
|
339
336
|
instrumentForCoverage,
|
|
340
337
|
styles: options.styles,
|
|
341
338
|
scripts: options.scripts,
|
|
342
339
|
polyfills,
|
|
343
340
|
webWorkerTsConfig: options.webWorkerTsConfig,
|
|
344
|
-
watch: options.watch
|
|
341
|
+
watch: options.watch,
|
|
345
342
|
stylePreprocessorOptions: options.stylePreprocessorOptions,
|
|
346
343
|
inlineStyleLanguage: options.inlineStyleLanguage,
|
|
347
344
|
fileReplacements: options.fileReplacements,
|
|
@@ -410,6 +407,7 @@ async function initializeApplication(options, context, karmaOptions, transforms
|
|
|
410
407
|
scriptsFiles.push({
|
|
411
408
|
pattern: `${outputPath}/${outputName}`,
|
|
412
409
|
watched: false,
|
|
410
|
+
included: typeof scriptEntry === 'string' ? true : scriptEntry.inject !== false,
|
|
413
411
|
type: 'js',
|
|
414
412
|
});
|
|
415
413
|
}
|
|
@@ -436,7 +434,7 @@ async function initializeApplication(options, context, karmaOptions, transforms
|
|
|
436
434
|
// Serve CSS outputs on page load, these are the global styles.
|
|
437
435
|
karmaOptions.files.push({ pattern: `*.css`, type: 'css', watched: false });
|
|
438
436
|
}
|
|
439
|
-
const parsedKarmaConfig = await karma.config.parseConfig(options.karmaConfig
|
|
437
|
+
const parsedKarmaConfig = await karma.config.parseConfig(options.karmaConfig, transforms?.karmaOptions ? await transforms.karmaOptions(karmaOptions) : karmaOptions, { promiseConfig: true, throwErrors: true });
|
|
440
438
|
// Check for jsdom which does not support executing ESM scripts.
|
|
441
439
|
// If present, remove jsdom and issue a warning.
|
|
442
440
|
const updatedBrowsers = parsedKarmaConfig.browsers?.filter((browser) => browser !== 'jsdom');
|
|
@@ -480,8 +478,8 @@ async function initializeApplication(options, context, karmaOptions, transforms
|
|
|
480
478
|
junitReporterOptions.outputDir = context.workspaceRoot;
|
|
481
479
|
}
|
|
482
480
|
else if (typeof junitReporterOptions.outputDir === 'string' &&
|
|
483
|
-
!
|
|
484
|
-
junitReporterOptions.outputDir =
|
|
481
|
+
!node_path_1.default.isAbsolute(junitReporterOptions.outputDir)) {
|
|
482
|
+
junitReporterOptions.outputDir = node_path_1.default.join(context.workspaceRoot, junitReporterOptions.outputDir);
|
|
485
483
|
}
|
|
486
484
|
}
|
|
487
485
|
else {
|
|
@@ -511,9 +509,9 @@ async function writeTestFiles(files, testDir) {
|
|
|
511
509
|
if (file.type !== bundler_context_1.BuildOutputFileType.Browser && file.type !== bundler_context_1.BuildOutputFileType.Media) {
|
|
512
510
|
return;
|
|
513
511
|
}
|
|
514
|
-
const fullFilePath =
|
|
512
|
+
const fullFilePath = node_path_1.default.join(testDir, filePath);
|
|
515
513
|
// Ensure output subdirectories exist
|
|
516
|
-
const fileBasePath =
|
|
514
|
+
const fileBasePath = node_path_1.default.dirname(fullFilePath);
|
|
517
515
|
if (fileBasePath && !directoryExists.has(fileBasePath)) {
|
|
518
516
|
await fs.mkdir(fileBasePath, { recursive: true });
|
|
519
517
|
directoryExists.add(fileBasePath);
|
|
@@ -554,7 +552,71 @@ function getInstrumentationExcludedPaths(root, excludedPaths) {
|
|
|
554
552
|
const excluded = new Set();
|
|
555
553
|
for (const excludeGlob of excludedPaths) {
|
|
556
554
|
const excludePath = excludeGlob[0] === '/' ? excludeGlob.slice(1) : excludeGlob;
|
|
557
|
-
(0, tinyglobby_1.globSync)(excludePath, { cwd: root }).forEach((p) => excluded.add(
|
|
555
|
+
(0, tinyglobby_1.globSync)(excludePath, { cwd: root }).forEach((p) => excluded.add(node_path_1.default.join(root, p)));
|
|
558
556
|
}
|
|
559
557
|
return excluded;
|
|
560
558
|
}
|
|
559
|
+
function getBaseKarmaOptions(options, context) {
|
|
560
|
+
// Determine project name from builder context target
|
|
561
|
+
const projectName = context.target?.project;
|
|
562
|
+
if (!projectName) {
|
|
563
|
+
throw new Error(`The 'karma' builder requires a target to be specified.`);
|
|
564
|
+
}
|
|
565
|
+
const karmaOptions = options.karmaConfig
|
|
566
|
+
? {}
|
|
567
|
+
: getBuiltInKarmaConfig(context.workspaceRoot, projectName);
|
|
568
|
+
const singleRun = !options.watch;
|
|
569
|
+
karmaOptions.singleRun = singleRun;
|
|
570
|
+
// Workaround https://github.com/angular/angular-cli/issues/28271, by clearing context by default
|
|
571
|
+
// for single run executions. Not clearing context for multi-run (watched) builds allows the
|
|
572
|
+
// Jasmine Spec Runner to be visible in the browser after test execution.
|
|
573
|
+
karmaOptions.client ??= {};
|
|
574
|
+
karmaOptions.client.clearContext ??= singleRun;
|
|
575
|
+
// Convert browsers from a string to an array
|
|
576
|
+
if (options.browsers) {
|
|
577
|
+
karmaOptions.browsers = options.browsers;
|
|
578
|
+
}
|
|
579
|
+
if (options.reporters) {
|
|
580
|
+
karmaOptions.reporters = options.reporters;
|
|
581
|
+
}
|
|
582
|
+
return karmaOptions;
|
|
583
|
+
}
|
|
584
|
+
function getBuiltInKarmaConfig(workspaceRoot, projectName) {
|
|
585
|
+
let coverageFolderName = projectName.charAt(0) === '@' ? projectName.slice(1) : projectName;
|
|
586
|
+
coverageFolderName = coverageFolderName.toLowerCase();
|
|
587
|
+
const workspaceRootRequire = (0, node_module_1.createRequire)(workspaceRoot + '/');
|
|
588
|
+
// Any changes to the config here need to be synced to: packages/schematics/angular/config/files/karma.conf.js.template
|
|
589
|
+
return {
|
|
590
|
+
basePath: '',
|
|
591
|
+
frameworks: ['jasmine'],
|
|
592
|
+
plugins: [
|
|
593
|
+
'karma-jasmine',
|
|
594
|
+
'karma-chrome-launcher',
|
|
595
|
+
'karma-jasmine-html-reporter',
|
|
596
|
+
'karma-coverage',
|
|
597
|
+
].map((p) => workspaceRootRequire(p)),
|
|
598
|
+
jasmineHtmlReporter: {
|
|
599
|
+
suppressAll: true, // removes the duplicated traces
|
|
600
|
+
},
|
|
601
|
+
coverageReporter: {
|
|
602
|
+
dir: node_path_1.default.join(workspaceRoot, 'coverage', coverageFolderName),
|
|
603
|
+
subdir: '.',
|
|
604
|
+
reporters: [{ type: 'html' }, { type: 'text-summary' }],
|
|
605
|
+
},
|
|
606
|
+
reporters: ['progress', 'kjhtml'],
|
|
607
|
+
browsers: ['Chrome'],
|
|
608
|
+
customLaunchers: {
|
|
609
|
+
// Chrome configured to run in a bazel sandbox.
|
|
610
|
+
// Disable the use of the gpu and `/dev/shm` because it causes Chrome to
|
|
611
|
+
// crash on some environments.
|
|
612
|
+
// See:
|
|
613
|
+
// https://github.com/puppeteer/puppeteer/blob/v1.0.0/docs/troubleshooting.md#tips
|
|
614
|
+
// https://stackoverflow.com/questions/50642308/webdriverexception-unknown-error-devtoolsactiveport-file-doesnt-exist-while-t
|
|
615
|
+
ChromeHeadlessNoSandbox: {
|
|
616
|
+
base: 'ChromeHeadless',
|
|
617
|
+
flags: ['--no-sandbox', '--headless', '--disable-gpu', '--disable-dev-shm-usage'],
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
restartOnFileChange: true,
|
|
621
|
+
};
|
|
622
|
+
}
|
|
@@ -12,6 +12,7 @@ exports.getTestEntrypoints = getTestEntrypoints;
|
|
|
12
12
|
const node_fs_1 = require("node:fs");
|
|
13
13
|
const node_path_1 = require("node:path");
|
|
14
14
|
const tinyglobby_1 = require("tinyglobby");
|
|
15
|
+
const path_1 = require("../../utils/path");
|
|
15
16
|
/* Go through all patterns and find unique list of files */
|
|
16
17
|
async function findTests(include, exclude, workspaceRoot, projectSourceRoot) {
|
|
17
18
|
const matchingTestsPromises = include.map((pattern) => findMatchingTests(pattern, exclude, workspaceRoot, projectSourceRoot));
|
|
@@ -39,7 +40,6 @@ function getTestEntrypoints(testFiles, { projectSourceRoot, workspaceRoot }) {
|
|
|
39
40
|
return [uniqueName, testFile];
|
|
40
41
|
}));
|
|
41
42
|
}
|
|
42
|
-
const normalizePath = (path) => path.replace(/\\/g, '/');
|
|
43
43
|
const removeLeadingSlash = (pattern) => {
|
|
44
44
|
if (pattern.charAt(0) === '/') {
|
|
45
45
|
return pattern.substring(1);
|
|
@@ -62,9 +62,9 @@ function removeRoots(path, roots) {
|
|
|
62
62
|
}
|
|
63
63
|
async function findMatchingTests(pattern, ignore, workspaceRoot, projectSourceRoot) {
|
|
64
64
|
// normalize pattern, glob lib only accepts forward slashes
|
|
65
|
-
let normalizedPattern =
|
|
65
|
+
let normalizedPattern = (0, path_1.toPosixPath)(pattern);
|
|
66
66
|
normalizedPattern = removeLeadingSlash(normalizedPattern);
|
|
67
|
-
const relativeProjectRoot =
|
|
67
|
+
const relativeProjectRoot = (0, path_1.toPosixPath)((0, node_path_1.relative)(workspaceRoot, projectSourceRoot) + '/');
|
|
68
68
|
// remove relativeProjectRoot to support relative paths from root
|
|
69
69
|
// such paths are easy to get when running scripts via IDEs
|
|
70
70
|
normalizedPattern = removeRelativeRoot(normalizedPattern, relativeProjectRoot);
|
|
@@ -84,7 +84,7 @@ async function findMatchingTests(pattern, ignore, workspaceRoot, projectSourceRo
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
// normalize the patterns in the ignore list
|
|
87
|
-
const normalizedIgnorePatternList = ignore.map((pattern) => removeRelativeRoot(removeLeadingSlash(
|
|
87
|
+
const normalizedIgnorePatternList = ignore.map((pattern) => removeRelativeRoot(removeLeadingSlash((0, path_1.toPosixPath)(pattern)), relativeProjectRoot));
|
|
88
88
|
return (0, tinyglobby_1.glob)(normalizedPattern, {
|
|
89
89
|
cwd: projectSourceRoot,
|
|
90
90
|
absolute: true,
|
|
@@ -8,16 +8,13 @@
|
|
|
8
8
|
import { type Builder, type BuilderContext, type BuilderOutput } from '@angular-devkit/architect';
|
|
9
9
|
import type { ConfigOptions } from 'karma';
|
|
10
10
|
import type { Schema as KarmaBuilderOptions } from './schema';
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
};
|
|
11
|
+
export interface KarmaBuilderTransformsOptions {
|
|
12
|
+
karmaOptions?: (options: ConfigOptions) => ConfigOptions | Promise<ConfigOptions>;
|
|
13
|
+
}
|
|
15
14
|
/**
|
|
16
15
|
* @experimental Direct usage of this function is considered experimental.
|
|
17
16
|
*/
|
|
18
|
-
export declare function execute(options: KarmaBuilderOptions, context: BuilderContext, transforms?:
|
|
19
|
-
karmaOptions?: (options: KarmaConfigOptions) => KarmaConfigOptions;
|
|
20
|
-
}): AsyncIterable<BuilderOutput>;
|
|
17
|
+
export declare function execute(options: KarmaBuilderOptions, context: BuilderContext, transforms?: KarmaBuilderTransformsOptions): AsyncIterable<BuilderOutput>;
|
|
21
18
|
export type { KarmaBuilderOptions };
|
|
22
19
|
declare const builder: Builder<KarmaBuilderOptions>;
|
|
23
20
|
export default builder;
|
|
@@ -39,101 +39,15 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
return result;
|
|
40
40
|
};
|
|
41
41
|
})();
|
|
42
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
43
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
44
|
-
};
|
|
45
42
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
43
|
exports.execute = execute;
|
|
47
44
|
const architect_1 = require("@angular-devkit/architect");
|
|
48
|
-
const node_module_1 = require("node:module");
|
|
49
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
50
45
|
/**
|
|
51
46
|
* @experimental Direct usage of this function is considered experimental.
|
|
52
47
|
*/
|
|
53
|
-
async function* execute(options, context, transforms
|
|
48
|
+
async function* execute(options, context, transforms) {
|
|
54
49
|
const { execute } = await Promise.resolve().then(() => __importStar(require('./application_builder')));
|
|
55
|
-
|
|
56
|
-
yield* execute(options, context, karmaOptions, transforms);
|
|
57
|
-
}
|
|
58
|
-
function getBaseKarmaOptions(options, context) {
|
|
59
|
-
let singleRun;
|
|
60
|
-
if (options.watch !== undefined) {
|
|
61
|
-
singleRun = !options.watch;
|
|
62
|
-
}
|
|
63
|
-
// Determine project name from builder context target
|
|
64
|
-
const projectName = context.target?.project;
|
|
65
|
-
if (!projectName) {
|
|
66
|
-
throw new Error(`The 'karma' builder requires a target to be specified.`);
|
|
67
|
-
}
|
|
68
|
-
const karmaOptions = options.karmaConfig
|
|
69
|
-
? {}
|
|
70
|
-
: getBuiltInKarmaConfig(context.workspaceRoot, projectName);
|
|
71
|
-
karmaOptions.singleRun = singleRun;
|
|
72
|
-
// Workaround https://github.com/angular/angular-cli/issues/28271, by clearing context by default
|
|
73
|
-
// for single run executions. Not clearing context for multi-run (watched) builds allows the
|
|
74
|
-
// Jasmine Spec Runner to be visible in the browser after test execution.
|
|
75
|
-
karmaOptions.client ??= {};
|
|
76
|
-
karmaOptions.client.clearContext ??= singleRun ?? false; // `singleRun` defaults to `false` per Karma docs.
|
|
77
|
-
// Convert browsers from a string to an array
|
|
78
|
-
if (typeof options.browsers === 'string' && options.browsers) {
|
|
79
|
-
karmaOptions.browsers = options.browsers.split(',').map((browser) => browser.trim());
|
|
80
|
-
}
|
|
81
|
-
else if (options.browsers === false) {
|
|
82
|
-
karmaOptions.browsers = [];
|
|
83
|
-
}
|
|
84
|
-
if (options.reporters) {
|
|
85
|
-
// Split along commas to make it more natural, and remove empty strings.
|
|
86
|
-
const reporters = options.reporters
|
|
87
|
-
.reduce((acc, curr) => acc.concat(curr.split(',')), [])
|
|
88
|
-
.filter((x) => !!x);
|
|
89
|
-
if (reporters.length > 0) {
|
|
90
|
-
karmaOptions.reporters = reporters;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return karmaOptions;
|
|
94
|
-
}
|
|
95
|
-
function getBuiltInKarmaConfig(workspaceRoot, projectName) {
|
|
96
|
-
let coverageFolderName = projectName.charAt(0) === '@' ? projectName.slice(1) : projectName;
|
|
97
|
-
coverageFolderName = coverageFolderName.toLowerCase();
|
|
98
|
-
const workspaceRootRequire = (0, node_module_1.createRequire)(workspaceRoot + '/');
|
|
99
|
-
// Any changes to the config here need to be synced to: packages/schematics/angular/config/files/karma.conf.js.template
|
|
100
|
-
return {
|
|
101
|
-
basePath: '',
|
|
102
|
-
rootUrl: '/',
|
|
103
|
-
frameworks: ['jasmine'],
|
|
104
|
-
plugins: [
|
|
105
|
-
'karma-jasmine',
|
|
106
|
-
'karma-chrome-launcher',
|
|
107
|
-
'karma-jasmine-html-reporter',
|
|
108
|
-
'karma-coverage',
|
|
109
|
-
].map((p) => workspaceRootRequire(p)),
|
|
110
|
-
proxies: {
|
|
111
|
-
'/': '/base/',
|
|
112
|
-
},
|
|
113
|
-
jasmineHtmlReporter: {
|
|
114
|
-
suppressAll: true, // removes the duplicated traces
|
|
115
|
-
},
|
|
116
|
-
coverageReporter: {
|
|
117
|
-
dir: node_path_1.default.join(workspaceRoot, 'coverage', coverageFolderName),
|
|
118
|
-
subdir: '.',
|
|
119
|
-
reporters: [{ type: 'html' }, { type: 'text-summary' }],
|
|
120
|
-
},
|
|
121
|
-
reporters: ['progress', 'kjhtml'],
|
|
122
|
-
browsers: ['Chrome'],
|
|
123
|
-
customLaunchers: {
|
|
124
|
-
// Chrome configured to run in a bazel sandbox.
|
|
125
|
-
// Disable the use of the gpu and `/dev/shm` because it causes Chrome to
|
|
126
|
-
// crash on some environments.
|
|
127
|
-
// See:
|
|
128
|
-
// https://github.com/puppeteer/puppeteer/blob/v1.0.0/docs/troubleshooting.md#tips
|
|
129
|
-
// https://stackoverflow.com/questions/50642308/webdriverexception-unknown-error-devtoolsactiveport-file-doesnt-exist-while-t
|
|
130
|
-
ChromeHeadlessNoSandbox: {
|
|
131
|
-
base: 'ChromeHeadless',
|
|
132
|
-
flags: ['--no-sandbox', '--headless', '--disable-gpu', '--disable-dev-shm-usage'],
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
restartOnFileChange: true,
|
|
136
|
-
};
|
|
50
|
+
yield* execute(options, context, transforms);
|
|
137
51
|
}
|
|
138
52
|
const builder = (0, architect_1.createBuilder)(execute);
|
|
139
53
|
exports.default = builder;
|
|
@@ -0,0 +1,42 @@
|
|
|
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.dev/license
|
|
7
|
+
*/
|
|
8
|
+
import type { BuilderContext } from '@angular-devkit/architect';
|
|
9
|
+
import { Schema as KarmaBuilderOptions } from './schema';
|
|
10
|
+
export type NormalizedKarmaBuilderOptions = ReturnType<typeof normalizeOptions>;
|
|
11
|
+
export declare function normalizeOptions(context: BuilderContext, options: KarmaBuilderOptions): {
|
|
12
|
+
sourceMap: import("./schema").SourceMapUnion | undefined;
|
|
13
|
+
karmaConfig: string | undefined;
|
|
14
|
+
reporters: string[] | undefined;
|
|
15
|
+
browsers: string[] | undefined;
|
|
16
|
+
watch: boolean;
|
|
17
|
+
include: string[];
|
|
18
|
+
exclude: string[];
|
|
19
|
+
aot?: boolean;
|
|
20
|
+
assets?: import("./schema").AssetPattern[];
|
|
21
|
+
codeCoverage?: boolean;
|
|
22
|
+
codeCoverageExclude?: string[];
|
|
23
|
+
define?: {
|
|
24
|
+
[key: string]: string;
|
|
25
|
+
};
|
|
26
|
+
externalDependencies?: string[];
|
|
27
|
+
fileReplacements?: import("./schema").FileReplacement[];
|
|
28
|
+
inlineStyleLanguage?: import("./schema").InlineStyleLanguage;
|
|
29
|
+
loader?: {
|
|
30
|
+
[key: string]: any;
|
|
31
|
+
};
|
|
32
|
+
main?: string;
|
|
33
|
+
poll?: number;
|
|
34
|
+
polyfills?: string[];
|
|
35
|
+
preserveSymlinks?: boolean;
|
|
36
|
+
progress?: boolean;
|
|
37
|
+
scripts?: import("./schema").ScriptElement[];
|
|
38
|
+
stylePreprocessorOptions?: import("./schema").StylePreprocessorOptions;
|
|
39
|
+
styles?: import("./schema").StyleElement[];
|
|
40
|
+
tsConfig: string;
|
|
41
|
+
webWorkerTsConfig?: string;
|
|
42
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
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.dev/license
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.normalizeOptions = normalizeOptions;
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
function normalizeOptions(context, options) {
|
|
13
|
+
const { sourceMap, karmaConfig, browsers, watch = true, include = [], exclude = [], reporters = [], ...rest } = options;
|
|
14
|
+
let normalizedBrowsers;
|
|
15
|
+
if (typeof options.browsers === 'string' && options.browsers) {
|
|
16
|
+
normalizedBrowsers = options.browsers.split(',').map((browser) => browser.trim());
|
|
17
|
+
}
|
|
18
|
+
else if (options.browsers === false) {
|
|
19
|
+
normalizedBrowsers = [];
|
|
20
|
+
}
|
|
21
|
+
// Split along commas to make it more natural, and remove empty strings.
|
|
22
|
+
const normalizedReporters = reporters
|
|
23
|
+
.reduce((acc, curr) => acc.concat(curr.split(',')), [])
|
|
24
|
+
.filter((x) => !!x);
|
|
25
|
+
// Sourcemaps are always needed when code coverage is enabled.
|
|
26
|
+
const normalizedSourceMap = options.codeCoverage
|
|
27
|
+
? {
|
|
28
|
+
scripts: true,
|
|
29
|
+
styles: true,
|
|
30
|
+
vendor: true,
|
|
31
|
+
}
|
|
32
|
+
: sourceMap;
|
|
33
|
+
return {
|
|
34
|
+
...rest,
|
|
35
|
+
sourceMap: normalizedSourceMap,
|
|
36
|
+
karmaConfig: karmaConfig ? (0, node_path_1.resolve)(context.workspaceRoot, karmaConfig) : undefined,
|
|
37
|
+
reporters: normalizedReporters.length ? normalizedReporters : undefined,
|
|
38
|
+
browsers: normalizedBrowsers,
|
|
39
|
+
watch,
|
|
40
|
+
include,
|
|
41
|
+
exclude,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
|
|
9
9
|
import type { ApplicationBuilderExtensions } from '../application/options';
|
|
10
|
-
import type { Schema as
|
|
11
|
-
export type {
|
|
10
|
+
import type { Schema as UnitTestBuilderOptions } from './schema';
|
|
11
|
+
export type { UnitTestBuilderOptions };
|
|
12
12
|
/**
|
|
13
13
|
* @experimental Direct usage of this function is considered experimental.
|
|
14
14
|
*/
|
|
15
|
-
export declare function execute(options:
|
|
15
|
+
export declare function execute(options: UnitTestBuilderOptions, context: BuilderContext, extensions?: ApplicationBuilderExtensions): AsyncIterable<BuilderOutput>;
|
|
@@ -18,6 +18,7 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
18
18
|
const virtual_module_plugin_1 = require("../../tools/esbuild/virtual-module-plugin");
|
|
19
19
|
const error_1 = require("../../utils/error");
|
|
20
20
|
const load_esm_1 = require("../../utils/load-esm");
|
|
21
|
+
const path_1 = require("../../utils/path");
|
|
21
22
|
const application_1 = require("../application");
|
|
22
23
|
const results_1 = require("../application/results");
|
|
23
24
|
const schema_1 = require("../application/schema");
|
|
@@ -73,7 +74,7 @@ async function* execute(options, context, extensions = {}) {
|
|
|
73
74
|
// Setup test file build options based on application build target options
|
|
74
75
|
const buildTargetOptions = (await context.validateOptions(await context.getTargetOptions(normalizedOptions.buildTarget), await context.getBuilderNameForTarget(normalizedOptions.buildTarget)));
|
|
75
76
|
buildTargetOptions.polyfills = (0, options_1.injectTestingPolyfills)(buildTargetOptions.polyfills);
|
|
76
|
-
const outputPath = node_path_1.default.join(context.workspaceRoot, generateOutputPath());
|
|
77
|
+
const outputPath = (0, path_1.toPosixPath)(node_path_1.default.join(context.workspaceRoot, generateOutputPath()));
|
|
77
78
|
const buildOptions = {
|
|
78
79
|
...buildTargetOptions,
|
|
79
80
|
watch: normalizedOptions.watch,
|
|
@@ -94,7 +95,11 @@ async function* execute(options, context, extensions = {}) {
|
|
|
94
95
|
optimization: false,
|
|
95
96
|
tsConfig: normalizedOptions.tsConfig,
|
|
96
97
|
entryPoints,
|
|
97
|
-
externalDependencies: [
|
|
98
|
+
externalDependencies: [
|
|
99
|
+
'vitest',
|
|
100
|
+
'@vitest/browser/context',
|
|
101
|
+
...(buildTargetOptions.externalDependencies ?? []),
|
|
102
|
+
],
|
|
98
103
|
};
|
|
99
104
|
extensions ??= {};
|
|
100
105
|
extensions.codePlugins ??= [];
|
|
@@ -108,10 +113,9 @@ async function* execute(options, context, extensions = {}) {
|
|
|
108
113
|
`import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';`,
|
|
109
114
|
'',
|
|
110
115
|
normalizedOptions.providersFile
|
|
111
|
-
? `import providers from './${node_path_1.default
|
|
116
|
+
? `import providers from './${(0, path_1.toPosixPath)(node_path_1.default
|
|
112
117
|
.relative(projectSourceRoot, normalizedOptions.providersFile)
|
|
113
|
-
.replace(/.[mc]?ts$/, '')
|
|
114
|
-
.replace(/\\/g, '/')}'`
|
|
118
|
+
.replace(/.[mc]?ts$/, ''))}'`
|
|
115
119
|
: 'const providers = [];',
|
|
116
120
|
'',
|
|
117
121
|
// Same as https://github.com/angular/angular/blob/05a03d3f975771bb59c7eefd37c01fa127ee2229/packages/core/testing/src/test_hooks.ts#L21-L29
|
|
@@ -144,9 +148,11 @@ async function* execute(options, context, extensions = {}) {
|
|
|
144
148
|
return { success: false };
|
|
145
149
|
}
|
|
146
150
|
// Add setup file entries for TestBed initialization and project polyfills
|
|
147
|
-
const setupFiles = ['init-testbed.js'];
|
|
151
|
+
const setupFiles = ['init-testbed.js', ...normalizedOptions.setupFiles];
|
|
148
152
|
if (buildTargetOptions?.polyfills?.length) {
|
|
149
|
-
|
|
153
|
+
// Placed first as polyfills may be required by the Testbed initialization
|
|
154
|
+
// or other project provided setup files (e.g., zone.js, ECMAScript polyfills).
|
|
155
|
+
setupFiles.unshift('polyfills.js');
|
|
150
156
|
}
|
|
151
157
|
const debugOptions = normalizedOptions.debug
|
|
152
158
|
? {
|
|
@@ -302,7 +308,7 @@ function generateCoverageOption(codeCoverage, workspaceRoot, outputPath) {
|
|
|
302
308
|
return {
|
|
303
309
|
enabled: true,
|
|
304
310
|
excludeAfterRemap: true,
|
|
305
|
-
include: [`${node_path_1.default.relative(workspaceRoot, outputPath)}/**`],
|
|
311
|
+
include: [`${(0, path_1.toPosixPath)(node_path_1.default.relative(workspaceRoot, outputPath))}/**`],
|
|
306
312
|
// Special handling for `reporter` due to an undefined value causing upstream failures
|
|
307
313
|
...(codeCoverage.reporters
|
|
308
314
|
? { reporter: codeCoverage.reporters }
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import { type Builder } from '@angular-devkit/architect';
|
|
9
|
-
import { type
|
|
10
|
-
export { type
|
|
11
|
-
declare const builder: Builder<
|
|
9
|
+
import { type UnitTestBuilderOptions, execute } from './builder';
|
|
10
|
+
export { type UnitTestBuilderOptions, execute };
|
|
11
|
+
declare const builder: Builder<UnitTestBuilderOptions>;
|
|
12
12
|
export default builder;
|
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import type { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
|
|
9
|
-
import { type
|
|
10
|
-
export declare function useKarmaBuilder(context: BuilderContext, unitTestOptions:
|
|
9
|
+
import { type NormalizedUnitTestBuilderOptions } from './options';
|
|
10
|
+
export declare function useKarmaBuilder(context: BuilderContext, unitTestOptions: NormalizedUnitTestBuilderOptions): Promise<AsyncIterable<BuilderOutput>>;
|
|
@@ -46,6 +46,9 @@ async function useKarmaBuilder(context, unitTestOptions) {
|
|
|
46
46
|
if (unitTestOptions.debug) {
|
|
47
47
|
context.logger.warn('The "karma" test runner does not support the "debug" option. The option will be ignored.');
|
|
48
48
|
}
|
|
49
|
+
if (unitTestOptions.setupFiles.length) {
|
|
50
|
+
context.logger.warn('The "karma" test runner does not support the "setupFiles" option. The option will be ignored.');
|
|
51
|
+
}
|
|
49
52
|
const buildTargetOptions = (await context.validateOptions(await context.getTargetOptions(unitTestOptions.buildTarget), await context.getBuilderNameForTarget(unitTestOptions.buildTarget)));
|
|
50
53
|
buildTargetOptions.polyfills = (0, options_1.injectTestingPolyfills)(buildTargetOptions.polyfills);
|
|
51
54
|
const options = {
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import { type BuilderContext } from '@angular-devkit/architect';
|
|
9
|
-
import type { Schema as
|
|
10
|
-
export type
|
|
11
|
-
export declare function normalizeOptions(context: BuilderContext, projectName: string, options:
|
|
9
|
+
import type { Schema as UnitTestBuilderOptions } from './schema';
|
|
10
|
+
export type NormalizedUnitTestBuilderOptions = Awaited<ReturnType<typeof normalizeOptions>>;
|
|
11
|
+
export declare function normalizeOptions(context: BuilderContext, projectName: string, options: UnitTestBuilderOptions): Promise<{
|
|
12
12
|
workspaceRoot: string;
|
|
13
13
|
projectRoot: string;
|
|
14
14
|
projectSourceRoot: string;
|
|
@@ -27,5 +27,6 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
27
27
|
watch: boolean;
|
|
28
28
|
debug: boolean;
|
|
29
29
|
providersFile: string | undefined;
|
|
30
|
+
setupFiles: string[];
|
|
30
31
|
}>;
|
|
31
32
|
export declare function injectTestingPolyfills(polyfills?: string[]): string[];
|
|
@@ -54,6 +54,9 @@ async function normalizeOptions(context, projectName, options) {
|
|
|
54
54
|
watch: options.watch ?? (0, tty_1.isTTY)(),
|
|
55
55
|
debug: options.debug ?? false,
|
|
56
56
|
providersFile: options.providersFile && node_path_1.default.join(workspaceRoot, options.providersFile),
|
|
57
|
+
setupFiles: options.setupFiles
|
|
58
|
+
? options.setupFiles.map((setupFile) => node_path_1.default.join(workspaceRoot, setupFile))
|
|
59
|
+
: [],
|
|
57
60
|
};
|
|
58
61
|
}
|
|
59
62
|
function injectTestingPolyfills(polyfills = []) {
|
|
@@ -55,12 +55,19 @@ export type Schema = {
|
|
|
55
55
|
* The name of the test runner to use for test execution.
|
|
56
56
|
*/
|
|
57
57
|
runner: Runner;
|
|
58
|
+
/**
|
|
59
|
+
* A list of global setup and configuration files that are included before the test files.
|
|
60
|
+
* The application's polyfills are always included before these files. The Angular Testbed
|
|
61
|
+
* is also initialized prior to the execution of these files.
|
|
62
|
+
*/
|
|
63
|
+
setupFiles?: string[];
|
|
58
64
|
/**
|
|
59
65
|
* The name of the TypeScript configuration file.
|
|
60
66
|
*/
|
|
61
67
|
tsConfig: string;
|
|
62
68
|
/**
|
|
63
|
-
*
|
|
69
|
+
* Re-run tests when source files change. Defaults to `true` in TTY environments and `false`
|
|
70
|
+
* otherwise.
|
|
64
71
|
*/
|
|
65
72
|
watch?: boolean;
|
|
66
73
|
};
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"watch": {
|
|
46
46
|
"type": "boolean",
|
|
47
|
-
"description": "
|
|
47
|
+
"description": "Re-run tests when source files change. Defaults to `true` in TTY environments and `false` otherwise."
|
|
48
48
|
},
|
|
49
49
|
"debug": {
|
|
50
50
|
"type": "boolean",
|
|
@@ -76,7 +76,14 @@
|
|
|
76
76
|
"type": "array",
|
|
77
77
|
"minItems": 1,
|
|
78
78
|
"maxItems": 2,
|
|
79
|
-
"items": [
|
|
79
|
+
"items": [
|
|
80
|
+
{
|
|
81
|
+
"$ref": "#/definitions/coverage-reporters"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"type": "object"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
80
87
|
}
|
|
81
88
|
]
|
|
82
89
|
}
|
|
@@ -92,6 +99,13 @@
|
|
|
92
99
|
"type": "string",
|
|
93
100
|
"description": "TypeScript file that exports an array of Angular providers to use during test execution. The array must be a default export.",
|
|
94
101
|
"minLength": 1
|
|
102
|
+
},
|
|
103
|
+
"setupFiles": {
|
|
104
|
+
"type": "array",
|
|
105
|
+
"items": {
|
|
106
|
+
"type": "string"
|
|
107
|
+
},
|
|
108
|
+
"description": "A list of global setup and configuration files that are included before the test files. The application's polyfills are always included before these files. The Angular Testbed is also initialized prior to the execution of these files."
|
|
95
109
|
}
|
|
96
110
|
},
|
|
97
111
|
"additionalProperties": false,
|
package/src/index.d.ts
CHANGED
|
@@ -12,3 +12,5 @@ export type { BuildOutputAsset } from './tools/esbuild/bundler-execution-result'
|
|
|
12
12
|
export { executeDevServerBuilder, type DevServerBuilderOptions, type DevServerBuilderOutput, } from './builders/dev-server';
|
|
13
13
|
export { execute as executeExtractI18nBuilder, type ExtractI18nBuilderOptions, } from './builders/extract-i18n';
|
|
14
14
|
export { execute as executeNgPackagrBuilder, type NgPackagrBuilderOptions, } from './builders/ng-packagr';
|
|
15
|
+
export { execute as executeUnitTestBuilder, type UnitTestBuilderOptions, } from './builders/unit-test';
|
|
16
|
+
export { execute as executeKarmaBuilder, type KarmaBuilderOptions } from './builders/karma';
|
package/src/index.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* found in the LICENSE file at https://angular.dev/license
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.executeNgPackagrBuilder = exports.executeExtractI18nBuilder = exports.executeDevServerBuilder = exports.BuildOutputFileType = exports.buildApplication = void 0;
|
|
10
|
+
exports.executeKarmaBuilder = exports.executeUnitTestBuilder = exports.executeNgPackagrBuilder = exports.executeExtractI18nBuilder = exports.executeDevServerBuilder = exports.BuildOutputFileType = exports.buildApplication = void 0;
|
|
11
11
|
var application_1 = require("./builders/application");
|
|
12
12
|
Object.defineProperty(exports, "buildApplication", { enumerable: true, get: function () { return application_1.buildApplication; } });
|
|
13
13
|
var bundler_context_1 = require("./tools/esbuild/bundler-context");
|
|
@@ -18,3 +18,7 @@ var extract_i18n_1 = require("./builders/extract-i18n");
|
|
|
18
18
|
Object.defineProperty(exports, "executeExtractI18nBuilder", { enumerable: true, get: function () { return extract_i18n_1.execute; } });
|
|
19
19
|
var ng_packagr_1 = require("./builders/ng-packagr");
|
|
20
20
|
Object.defineProperty(exports, "executeNgPackagrBuilder", { enumerable: true, get: function () { return ng_packagr_1.execute; } });
|
|
21
|
+
var unit_test_1 = require("./builders/unit-test");
|
|
22
|
+
Object.defineProperty(exports, "executeUnitTestBuilder", { enumerable: true, get: function () { return unit_test_1.execute; } });
|
|
23
|
+
var karma_1 = require("./builders/karma");
|
|
24
|
+
Object.defineProperty(exports, "executeKarmaBuilder", { enumerable: true, get: function () { return karma_1.execute; } });
|
package/src/private.d.ts
CHANGED
|
@@ -5,13 +5,19 @@
|
|
|
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
|
+
/**
|
|
9
|
+
* @fileoverview
|
|
10
|
+
* Private exports intended only for use with the @angular-devkit/build-angular package.
|
|
11
|
+
* All exports are not supported for external use, do not provide SemVer guarantees, and
|
|
12
|
+
* their existence may change in any future version.
|
|
13
|
+
*/
|
|
14
|
+
import { createAngularCompilation } from './tools/angular/compilation';
|
|
8
15
|
import { CompilerPluginOptions } from './tools/esbuild/angular/compiler-plugin';
|
|
9
16
|
import { BundleStylesheetOptions } from './tools/esbuild/stylesheets/bundle-options';
|
|
10
17
|
export { buildApplicationInternal } from './builders/application';
|
|
11
18
|
export type { ApplicationBuilderInternalOptions } from './builders/application/options';
|
|
12
19
|
export { type Result, type ResultFile, ResultKind } from './builders/application/results';
|
|
13
20
|
export { serveWithVite } from './builders/dev-server/vite-server';
|
|
14
|
-
export { execute as executeKarmaInternal } from './builders/karma/application_builder';
|
|
15
21
|
export * from './tools/babel/plugins';
|
|
16
22
|
export type { ExternalResultMetadata } from './tools/esbuild/bundler-execution-result';
|
|
17
23
|
export { emitFilesToDisk } from './tools/esbuild/utils';
|
|
@@ -26,6 +32,8 @@ export declare function createCompilerPlugin(pluginOptions: CompilerPluginOption
|
|
|
26
32
|
}, styleOptions: BundleStylesheetOptions & {
|
|
27
33
|
inlineStyleLanguage: string;
|
|
28
34
|
}): import('esbuild').Plugin;
|
|
35
|
+
export type { AngularCompilation } from './tools/angular/compilation';
|
|
36
|
+
export { createAngularCompilation };
|
|
29
37
|
export * from './utils/bundle-calculator';
|
|
30
38
|
export { checkPort } from './utils/check-port';
|
|
31
39
|
export { deleteOutputDir } from './utils/delete-output-dir';
|
package/src/private.js
CHANGED
|
@@ -21,7 +21,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
21
21
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
22
22
|
};
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.loadPostcssConfiguration = exports.generateSearchDirectories = exports.findTailwindConfiguration = exports.getTestEntrypoints = exports.findTests = exports.assertCompatibleAngularVersion = exports.getSupportedBrowsers = exports.generateBuildStatsTable = exports.augmentAppWithServiceWorker = exports.purgeStaleBuildCache = exports.createTranslationLoader = exports.loadProxyConfiguration = exports.InlineCriticalCssProcessor = exports.IndexHtmlGenerator = exports.loadTranslations = exports.createI18nOptions = exports.deleteOutputDir = exports.checkPort = exports.JavaScriptTransformer = exports.createJitResourceTransformer = exports.SourceFileCache = exports.SassWorkerImplementation = exports.transformSupportedBrowsersToTargets = exports.emitFilesToDisk = exports.
|
|
24
|
+
exports.loadPostcssConfiguration = exports.generateSearchDirectories = exports.findTailwindConfiguration = exports.getTestEntrypoints = exports.findTests = exports.assertCompatibleAngularVersion = exports.getSupportedBrowsers = exports.generateBuildStatsTable = exports.augmentAppWithServiceWorker = exports.purgeStaleBuildCache = exports.createTranslationLoader = exports.loadProxyConfiguration = exports.InlineCriticalCssProcessor = exports.IndexHtmlGenerator = exports.loadTranslations = exports.createI18nOptions = exports.deleteOutputDir = exports.checkPort = exports.createAngularCompilation = exports.JavaScriptTransformer = exports.createJitResourceTransformer = exports.SourceFileCache = exports.SassWorkerImplementation = exports.transformSupportedBrowsersToTargets = exports.emitFilesToDisk = exports.serveWithVite = exports.ResultKind = exports.buildApplicationInternal = void 0;
|
|
25
25
|
exports.createCompilerPlugin = createCompilerPlugin;
|
|
26
26
|
/**
|
|
27
27
|
* @fileoverview
|
|
@@ -30,6 +30,7 @@ exports.createCompilerPlugin = createCompilerPlugin;
|
|
|
30
30
|
* their existence may change in any future version.
|
|
31
31
|
*/
|
|
32
32
|
const compilation_1 = require("./tools/angular/compilation");
|
|
33
|
+
Object.defineProperty(exports, "createAngularCompilation", { enumerable: true, get: function () { return compilation_1.createAngularCompilation; } });
|
|
33
34
|
const compiler_plugin_1 = require("./tools/esbuild/angular/compiler-plugin");
|
|
34
35
|
const component_stylesheets_1 = require("./tools/esbuild/angular/component-stylesheets");
|
|
35
36
|
// Builders
|
|
@@ -39,8 +40,6 @@ var results_1 = require("./builders/application/results");
|
|
|
39
40
|
Object.defineProperty(exports, "ResultKind", { enumerable: true, get: function () { return results_1.ResultKind; } });
|
|
40
41
|
var vite_server_1 = require("./builders/dev-server/vite-server");
|
|
41
42
|
Object.defineProperty(exports, "serveWithVite", { enumerable: true, get: function () { return vite_server_1.serveWithVite; } });
|
|
42
|
-
var application_builder_1 = require("./builders/karma/application_builder");
|
|
43
|
-
Object.defineProperty(exports, "executeKarmaInternal", { enumerable: true, get: function () { return application_builder_1.execute; } });
|
|
44
43
|
// Tools
|
|
45
44
|
__exportStar(require("./tools/babel/plugins"), exports);
|
|
46
45
|
var utils_1 = require("./tools/esbuild/utils");
|
|
@@ -14,4 +14,4 @@ import type { AngularCompilation } from './angular-compilation';
|
|
|
14
14
|
* @param browserOnlyBuild True, for browser only builds; False, for browser and server builds.
|
|
15
15
|
* @returns An instance of an Angular compilation object.
|
|
16
16
|
*/
|
|
17
|
-
export declare function createAngularCompilation(jit: boolean, browserOnlyBuild: boolean): Promise<AngularCompilation>;
|
|
17
|
+
export declare function createAngularCompilation(jit: boolean, browserOnlyBuild: boolean, parallel?: boolean): Promise<AngularCompilation>;
|
|
@@ -50,8 +50,8 @@ const environment_options_1 = require("../../../utils/environment-options");
|
|
|
50
50
|
* @param browserOnlyBuild True, for browser only builds; False, for browser and server builds.
|
|
51
51
|
* @returns An instance of an Angular compilation object.
|
|
52
52
|
*/
|
|
53
|
-
async function createAngularCompilation(jit, browserOnlyBuild) {
|
|
54
|
-
if (
|
|
53
|
+
async function createAngularCompilation(jit, browserOnlyBuild, parallel = environment_options_1.useParallelTs) {
|
|
54
|
+
if (parallel) {
|
|
55
55
|
const { ParallelCompilation } = await Promise.resolve().then(() => __importStar(require('./parallel-compilation')));
|
|
56
56
|
return new ParallelCompilation(jit, browserOnlyBuild);
|
|
57
57
|
}
|
|
@@ -55,9 +55,12 @@ function convertTypeScriptDiagnosticInfo(typescript, info, textPrefix) {
|
|
|
55
55
|
function convertTypeScriptDiagnostic(typescript, diagnostic) {
|
|
56
56
|
let codePrefix = 'TS';
|
|
57
57
|
let code = `${diagnostic.code}`;
|
|
58
|
-
|
|
58
|
+
// Custom ngtsc diagnostics are prefixed with -99 which isn't a valid TypeScript diagnostic code.
|
|
59
|
+
// Strip it and mark the diagnostic as coming from Angular. Note that we can't rely on
|
|
60
|
+
// `diagnostic.source`, because it isn't always produced. This is identical to:
|
|
61
|
+
// https://github.com/angular/angular/blob/main/packages/compiler-cli/src/ngtsc/diagnostics/src/util.ts
|
|
62
|
+
if (code.startsWith('-99')) {
|
|
59
63
|
codePrefix = 'NG';
|
|
60
|
-
// Remove `-99` Angular prefix from diagnostic code
|
|
61
64
|
code = code.slice(3);
|
|
62
65
|
}
|
|
63
66
|
const message = convertTypeScriptDiagnosticInfo(typescript, diagnostic, `${codePrefix}${code}: `);
|
|
@@ -20,6 +20,7 @@ const node_crypto_1 = require("node:crypto");
|
|
|
20
20
|
const node_path_1 = require("node:path");
|
|
21
21
|
const schema_1 = require("../../builders/application/schema");
|
|
22
22
|
const environment_options_1 = require("../../utils/environment-options");
|
|
23
|
+
const path_1 = require("../../utils/path");
|
|
23
24
|
const manifest_1 = require("../../utils/server-rendering/manifest");
|
|
24
25
|
const compilation_1 = require("../angular/compilation");
|
|
25
26
|
const compiler_plugin_1 = require("./angular/compiler-plugin");
|
|
@@ -511,9 +512,7 @@ function getEsBuildCommonPolyfillsOptions(options, namespace, tryToResolvePolyfi
|
|
|
511
512
|
}));
|
|
512
513
|
}
|
|
513
514
|
// Generate module contents with an import statement per defined polyfill
|
|
514
|
-
let contents = polyfillPaths
|
|
515
|
-
.map((file) => `import '${file.replace(/\\/g, '/')}';`)
|
|
516
|
-
.join('\n');
|
|
515
|
+
let contents = polyfillPaths.map((file) => `import '${(0, path_1.toPosixPath)(file)}';`).join('\n');
|
|
517
516
|
// The below should be done after loading `$localize` as otherwise the locale will be overridden.
|
|
518
517
|
if (i18nOptions.shouldInline) {
|
|
519
518
|
// When inlining, a placeholder is used to allow the post-processing step to inject the $localize locale identifier.
|
|
@@ -534,8 +533,5 @@ function getEsBuildCommonPolyfillsOptions(options, namespace, tryToResolvePolyfi
|
|
|
534
533
|
return buildOptions;
|
|
535
534
|
}
|
|
536
535
|
function entryFileToWorkspaceRelative(workspaceRoot, entryFile) {
|
|
537
|
-
return
|
|
538
|
-
(0, node_path_1.relative)(workspaceRoot, entryFile)
|
|
539
|
-
.replace(/.[mc]?ts$/, '')
|
|
540
|
-
.replace(/\\/g, '/'));
|
|
536
|
+
return './' + (0, path_1.toPosixPath)((0, node_path_1.relative)(workspaceRoot, entryFile).replace(/.[mc]?ts$/, ''));
|
|
541
537
|
}
|
|
@@ -12,6 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.createGlobalStylesBundleOptions = createGlobalStylesBundleOptions;
|
|
14
14
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
15
|
+
const path_1 = require("../../utils/path");
|
|
15
16
|
const bundle_options_1 = require("./stylesheets/bundle-options");
|
|
16
17
|
const virtual_module_plugin_1 = require("./virtual-module-plugin");
|
|
17
18
|
function createGlobalStylesBundleOptions(options, target, initial) {
|
|
@@ -66,7 +67,7 @@ function createGlobalStylesBundleOptions(options, target, initial) {
|
|
|
66
67
|
const files = globalStyles.find(({ name }) => name === args.path)?.files;
|
|
67
68
|
(0, node_assert_1.default)(files, `global style name should always be found [${args.path}]`);
|
|
68
69
|
return {
|
|
69
|
-
contents: files.map((file) => `@import '${
|
|
70
|
+
contents: files.map((file) => `@import '${(0, path_1.toPosixPath)(file)}';`).join('\n'),
|
|
70
71
|
loader: 'css',
|
|
71
72
|
resolveDir: workspaceRoot,
|
|
72
73
|
};
|
|
@@ -17,6 +17,7 @@ const node_fs_1 = require("node:fs");
|
|
|
17
17
|
const node_path_1 = require("node:path");
|
|
18
18
|
const node_url_1 = require("node:url");
|
|
19
19
|
const error_1 = require("../../utils/error");
|
|
20
|
+
const path_1 = require("../../utils/path");
|
|
20
21
|
const lexer_1 = require("./lexer");
|
|
21
22
|
/**
|
|
22
23
|
* A Sass Importer base class that provides the load logic to rebase all `url()` functions
|
|
@@ -69,7 +70,7 @@ class UrlRebasingImporter {
|
|
|
69
70
|
const rebasedPath = (0, node_path_1.relative)(this.entryDirectory, stylesheetDirectory);
|
|
70
71
|
// Normalize path separators and escape characters
|
|
71
72
|
// https://developer.mozilla.org/en-US/docs/Web/CSS/url#syntax
|
|
72
|
-
const rebasedUrl =
|
|
73
|
+
const rebasedUrl = (0, path_1.toPosixPath)(rebasedPath).replace(/[()\s'"]/g, '\\$&');
|
|
73
74
|
updatedContents ??= new magic_string_1.default(contents);
|
|
74
75
|
// Always quote the URL to avoid potential downstream parsing problems
|
|
75
76
|
updatedContents.update(start, end, `"${rebasedUrl}||file:${valueNormalized}"`);
|
|
@@ -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 = '20.1.
|
|
13
|
+
const VERSION = '20.1.1';
|
|
14
14
|
function hasCacheMetadata(value) {
|
|
15
15
|
return (!!value &&
|
|
16
16
|
typeof value === 'object' &&
|
|
@@ -0,0 +1,29 @@
|
|
|
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.dev/license
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Converts a Windows-style file path to a POSIX-compliant path.
|
|
10
|
+
*
|
|
11
|
+
* This function replaces all backslashes (`\`) with forward slashes (`/`).
|
|
12
|
+
* It is a no-op on POSIX systems (e.g., Linux, macOS), as the conversion
|
|
13
|
+
* only runs on Windows (`win32`).
|
|
14
|
+
*
|
|
15
|
+
* @param path - The file path to convert.
|
|
16
|
+
* @returns The POSIX-compliant file path.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* // On a Windows system:
|
|
21
|
+
* toPosixPath('C:\\Users\\Test\\file.txt');
|
|
22
|
+
* // => 'C:/Users/Test/file.txt'
|
|
23
|
+
*
|
|
24
|
+
* // On a POSIX system (Linux/macOS):
|
|
25
|
+
* toPosixPath('/home/user/file.txt');
|
|
26
|
+
* // => '/home/user/file.txt'
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function toPosixPath(path: string): string;
|
|
@@ -0,0 +1,37 @@
|
|
|
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.dev/license
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.toPosixPath = toPosixPath;
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
const node_process_1 = require("node:process");
|
|
13
|
+
const WINDOWS_PATH_SEPERATOR_REGEXP = /\\/g;
|
|
14
|
+
/**
|
|
15
|
+
* Converts a Windows-style file path to a POSIX-compliant path.
|
|
16
|
+
*
|
|
17
|
+
* This function replaces all backslashes (`\`) with forward slashes (`/`).
|
|
18
|
+
* It is a no-op on POSIX systems (e.g., Linux, macOS), as the conversion
|
|
19
|
+
* only runs on Windows (`win32`).
|
|
20
|
+
*
|
|
21
|
+
* @param path - The file path to convert.
|
|
22
|
+
* @returns The POSIX-compliant file path.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* // On a Windows system:
|
|
27
|
+
* toPosixPath('C:\\Users\\Test\\file.txt');
|
|
28
|
+
* // => 'C:/Users/Test/file.txt'
|
|
29
|
+
*
|
|
30
|
+
* // On a POSIX system (Linux/macOS):
|
|
31
|
+
* toPosixPath('/home/user/file.txt');
|
|
32
|
+
* // => '/home/user/file.txt'
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
function toPosixPath(path) {
|
|
36
|
+
return node_process_1.platform === 'win32' ? path.replace(WINDOWS_PATH_SEPERATOR_REGEXP, node_path_1.posix.sep) : path;
|
|
37
|
+
}
|
|
@@ -13,6 +13,7 @@ const node_path_1 = require("node:path");
|
|
|
13
13
|
const schema_1 = require("../../builders/application/schema");
|
|
14
14
|
const bundler_context_1 = require("../../tools/esbuild/bundler-context");
|
|
15
15
|
const error_1 = require("../error");
|
|
16
|
+
const path_1 = require("../path");
|
|
16
17
|
const url_1 = require("../url");
|
|
17
18
|
const worker_pool_1 = require("../worker-pool");
|
|
18
19
|
const utils_1 = require("./esm-in-memory-loader/utils");
|
|
@@ -49,7 +50,7 @@ async function prerenderPages(workspaceRoot, baseHref, appShellOptions, prerende
|
|
|
49
50
|
serverBundlesSourceMaps.clear();
|
|
50
51
|
const assetsReversed = {};
|
|
51
52
|
for (const { source, destination } of assets) {
|
|
52
|
-
assetsReversed[addLeadingSlash(
|
|
53
|
+
assetsReversed[addLeadingSlash((0, path_1.toPosixPath)(destination))] = source;
|
|
53
54
|
}
|
|
54
55
|
// Get routes to prerender
|
|
55
56
|
const { errors: extractionErrors, serializedRouteTree: serializableRouteTreeNode, appShellRoute, } = await getAllRoutes(workspaceRoot, baseHref, outputFilesForWorker, assetsReversed, appShellOptions, prerenderOptions, sourcemap, outputMode).catch((err) => {
|
|
@@ -49,6 +49,7 @@ const path = __importStar(require("node:path"));
|
|
|
49
49
|
const bundler_context_1 = require("../tools/esbuild/bundler-context");
|
|
50
50
|
const error_1 = require("./error");
|
|
51
51
|
const load_esm_1 = require("./load-esm");
|
|
52
|
+
const path_1 = require("./path");
|
|
52
53
|
class CliFilesystem {
|
|
53
54
|
fs;
|
|
54
55
|
base;
|
|
@@ -81,7 +82,7 @@ class CliFilesystem {
|
|
|
81
82
|
const stats = await this.fs.stat(entryPath);
|
|
82
83
|
if (stats.isFile()) {
|
|
83
84
|
// Uses posix paths since the service worker expects URLs
|
|
84
|
-
items.push('/' + path.relative(this.base, entryPath)
|
|
85
|
+
items.push('/' + (0, path_1.toPosixPath)(path.relative(this.base, entryPath)));
|
|
85
86
|
}
|
|
86
87
|
else if (stats.isDirectory()) {
|
|
87
88
|
subdirectories.push(entryPath);
|
|
@@ -98,11 +99,11 @@ class ResultFilesystem {
|
|
|
98
99
|
constructor(outputFiles, assetFiles) {
|
|
99
100
|
for (const file of outputFiles) {
|
|
100
101
|
if (file.type === bundler_context_1.BuildOutputFileType.Media || file.type === bundler_context_1.BuildOutputFileType.Browser) {
|
|
101
|
-
this.fileReaders.set('/' +
|
|
102
|
+
this.fileReaders.set('/' + (0, path_1.toPosixPath)(file.path), async () => file.contents);
|
|
102
103
|
}
|
|
103
104
|
}
|
|
104
105
|
for (const file of assetFiles) {
|
|
105
|
-
this.fileReaders.set('/' +
|
|
106
|
+
this.fileReaders.set('/' + (0, path_1.toPosixPath)(file.destination), () => node_fs_1.promises.readFile(file.source));
|
|
106
107
|
}
|
|
107
108
|
}
|
|
108
109
|
async list(dir) {
|
package/src/utils/version.js
CHANGED
|
@@ -28,7 +28,7 @@ function assertCompatibleAngularVersion(projectRoot) {
|
|
|
28
28
|
'This likely indicates a corrupted local installation. Please try reinstalling your packages.');
|
|
29
29
|
process.exit(2);
|
|
30
30
|
}
|
|
31
|
-
const supportedAngularSemver = '^20.0.0
|
|
31
|
+
const supportedAngularSemver = '^20.0.0';
|
|
32
32
|
if (angularPkgJson['version'] === '0.0.0' || supportedAngularSemver.startsWith('0.0.0')) {
|
|
33
33
|
// Internal CLI and FW testing version.
|
|
34
34
|
return;
|