@angular-devkit/build-angular 14.0.0-next.9 → 14.0.0-rc.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/builders.json +5 -0
- package/package.json +29 -29
- package/src/babel/presets/application.d.ts +3 -2
- package/src/babel/presets/application.js +2 -3
- package/src/babel/webpack-loader.d.ts +1 -0
- package/src/babel/webpack-loader.js +29 -15
- package/src/builders/app-shell/index.js +1 -1
- package/src/builders/browser/index.js +1 -1
- package/src/builders/browser-esbuild/compiler-plugin.d.ts +14 -0
- package/src/builders/browser-esbuild/compiler-plugin.js +338 -0
- package/src/builders/browser-esbuild/esbuild.d.ts +36 -0
- package/src/builders/browser-esbuild/esbuild.js +62 -0
- package/src/builders/browser-esbuild/experimental-warnings.d.ts +10 -0
- package/src/builders/browser-esbuild/experimental-warnings.js +65 -0
- package/src/builders/browser-esbuild/index.d.ts +19 -0
- package/src/builders/browser-esbuild/index.js +262 -0
- package/src/builders/browser-esbuild/options.d.ts +34 -0
- package/src/builders/browser-esbuild/options.js +87 -0
- package/src/builders/browser-esbuild/stylesheets.d.ts +52 -0
- package/src/builders/browser-esbuild/stylesheets.js +119 -0
- package/src/builders/protractor/index.js +50 -52
- package/src/utils/service-worker.d.ts +1 -1
- package/src/utils/service-worker.js +2 -2
- package/src/webpack/configs/common.js +1 -0
- package/src/webpack/configs/styles.d.ts +6 -0
- package/src/webpack/configs/styles.js +2 -1
- package/src/webpack/plugins/css-optimizer-plugin.js +7 -0
- package/src/webpack/plugins/javascript-optimizer-plugin.js +6 -0
- package/src/webpack/plugins/karma/karma.js +7 -27
- package/src/webpack/plugins/typescript.js +5 -0
package/builders.json
CHANGED
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
"schema": "./src/builders/browser/schema.json",
|
|
12
12
|
"description": "Build a browser application."
|
|
13
13
|
},
|
|
14
|
+
"browser-esbuild": {
|
|
15
|
+
"implementation": "./src/builders/browser-esbuild",
|
|
16
|
+
"schema": "./src/builders/browser/schema.json",
|
|
17
|
+
"description": "Build a browser application."
|
|
18
|
+
},
|
|
14
19
|
"dev-server": {
|
|
15
20
|
"implementation": "./src/builders/dev-server",
|
|
16
21
|
"schema": "./src/builders/dev-server/schema.json",
|
package/package.json
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-devkit/build-angular",
|
|
3
|
-
"version": "14.0.0-
|
|
3
|
+
"version": "14.0.0-rc.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
|
-
"@ampproject/remapping": "2.
|
|
10
|
-
"@angular-devkit/architect": "0.1400.0-
|
|
11
|
-
"@angular-devkit/build-webpack": "0.1400.0-
|
|
12
|
-
"@angular-devkit/core": "14.0.0-
|
|
13
|
-
"@babel/core": "7.17.
|
|
14
|
-
"@babel/generator": "7.17.
|
|
9
|
+
"@ampproject/remapping": "2.2.0",
|
|
10
|
+
"@angular-devkit/architect": "0.1400.0-rc.2",
|
|
11
|
+
"@angular-devkit/build-webpack": "0.1400.0-rc.2",
|
|
12
|
+
"@angular-devkit/core": "14.0.0-rc.2",
|
|
13
|
+
"@babel/core": "7.17.10",
|
|
14
|
+
"@babel/generator": "7.17.10",
|
|
15
15
|
"@babel/helper-annotate-as-pure": "7.16.7",
|
|
16
16
|
"@babel/plugin-proposal-async-generator-functions": "7.16.8",
|
|
17
17
|
"@babel/plugin-transform-async-to-generator": "7.16.8",
|
|
18
|
-
"@babel/plugin-transform-runtime": "7.17.
|
|
19
|
-
"@babel/preset-env": "7.
|
|
18
|
+
"@babel/plugin-transform-runtime": "7.17.10",
|
|
19
|
+
"@babel/preset-env": "7.17.10",
|
|
20
20
|
"@babel/runtime": "7.17.9",
|
|
21
21
|
"@babel/template": "7.16.7",
|
|
22
22
|
"@discoveryjs/json-ext": "0.5.7",
|
|
23
|
-
"@ngtools/webpack": "14.0.0-
|
|
23
|
+
"@ngtools/webpack": "14.0.0-rc.2",
|
|
24
24
|
"ansi-colors": "4.1.1",
|
|
25
|
-
"babel-loader": "8.2.
|
|
25
|
+
"babel-loader": "8.2.5",
|
|
26
26
|
"babel-plugin-istanbul": "6.1.1",
|
|
27
27
|
"browserslist": "^4.9.1",
|
|
28
|
-
"cacache": "16.0.
|
|
28
|
+
"cacache": "16.0.7",
|
|
29
29
|
"copy-webpack-plugin": "10.2.4",
|
|
30
30
|
"critters": "0.0.16",
|
|
31
31
|
"css-loader": "6.7.1",
|
|
32
|
-
"esbuild-wasm": "0.14.
|
|
33
|
-
"glob": "
|
|
34
|
-
"https-proxy-agent": "5.0.
|
|
35
|
-
"inquirer": "8.2.
|
|
32
|
+
"esbuild-wasm": "0.14.38",
|
|
33
|
+
"glob": "8.0.1",
|
|
34
|
+
"https-proxy-agent": "5.0.1",
|
|
35
|
+
"inquirer": "8.2.4",
|
|
36
36
|
"jsonc-parser": "3.0.0",
|
|
37
37
|
"karma-source-map-support": "1.4.0",
|
|
38
38
|
"less": "4.1.2",
|
|
@@ -45,42 +45,42 @@
|
|
|
45
45
|
"ora": "5.4.1",
|
|
46
46
|
"parse5-html-rewriting-stream": "6.0.1",
|
|
47
47
|
"piscina": "3.2.0",
|
|
48
|
-
"postcss": "8.4.
|
|
48
|
+
"postcss": "8.4.13",
|
|
49
49
|
"postcss-import": "14.1.0",
|
|
50
50
|
"postcss-loader": "6.2.1",
|
|
51
|
-
"postcss-preset-env": "7.
|
|
51
|
+
"postcss-preset-env": "7.5.0",
|
|
52
52
|
"regenerator-runtime": "0.13.9",
|
|
53
53
|
"resolve-url-loader": "5.0.0",
|
|
54
54
|
"rxjs": "6.6.7",
|
|
55
|
-
"sass": "1.
|
|
55
|
+
"sass": "1.51.0",
|
|
56
56
|
"sass-loader": "12.6.0",
|
|
57
|
-
"semver": "7.3.
|
|
57
|
+
"semver": "7.3.7",
|
|
58
58
|
"source-map-loader": "3.0.1",
|
|
59
59
|
"source-map-support": "0.5.21",
|
|
60
60
|
"stylus": "0.57.0",
|
|
61
61
|
"stylus-loader": "6.2.0",
|
|
62
|
-
"terser": "5.
|
|
62
|
+
"terser": "5.13.1",
|
|
63
63
|
"text-table": "0.2.0",
|
|
64
64
|
"tree-kill": "1.2.2",
|
|
65
|
-
"tslib": "2.
|
|
66
|
-
"webpack": "5.72.
|
|
65
|
+
"tslib": "2.4.0",
|
|
66
|
+
"webpack": "5.72.1",
|
|
67
67
|
"webpack-dev-middleware": "5.3.1",
|
|
68
|
-
"webpack-dev-server": "4.
|
|
68
|
+
"webpack-dev-server": "4.9.0",
|
|
69
69
|
"webpack-merge": "5.8.0",
|
|
70
70
|
"webpack-subresource-integrity": "5.1.0"
|
|
71
71
|
},
|
|
72
72
|
"optionalDependencies": {
|
|
73
|
-
"esbuild": "0.14.
|
|
73
|
+
"esbuild": "0.14.38"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
|
-
"@angular/compiler-cli": "^14.0.0 || ^14.0.0-
|
|
77
|
-
"@angular/localize": "^14.0.0 || ^14.0.0-
|
|
78
|
-
"@angular/service-worker": "^14.0.0 || ^14.0.0-
|
|
76
|
+
"@angular/compiler-cli": "^14.0.0 || ^14.0.0-rc",
|
|
77
|
+
"@angular/localize": "^14.0.0 || ^14.0.0-rc",
|
|
78
|
+
"@angular/service-worker": "^14.0.0 || ^14.0.0-rc",
|
|
79
79
|
"karma": "^6.3.0",
|
|
80
80
|
"ng-packagr": "^14.0.0 || ^14.0.0-next",
|
|
81
81
|
"protractor": "^7.0.0",
|
|
82
82
|
"tailwindcss": "^2.0.0 || ^3.0.0",
|
|
83
|
-
"typescript": "
|
|
83
|
+
"typescript": ">=4.6.2 <4.8"
|
|
84
84
|
},
|
|
85
85
|
"peerDependenciesMeta": {
|
|
86
86
|
"@angular/localize": {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
-
import type { ɵParsedTranslation } from '@angular/localize
|
|
8
|
+
import type { ɵParsedTranslation } from '@angular/localize';
|
|
9
9
|
import type { makeEs2015TranslatePlugin, makeEs5TranslatePlugin, makeLocalePlugin } from '@angular/localize/tools';
|
|
10
10
|
export declare type DiagnosticReporter = (type: 'error' | 'warning' | 'info', message: string) => void;
|
|
11
11
|
/**
|
|
@@ -32,7 +32,7 @@ export interface ApplicationPresetOptions {
|
|
|
32
32
|
jitMode: boolean;
|
|
33
33
|
linkerPluginCreator: typeof import('@angular/compiler-cli/linker/babel').createEs2015LinkerPlugin;
|
|
34
34
|
};
|
|
35
|
-
|
|
35
|
+
forcePresetEnv?: boolean;
|
|
36
36
|
forceAsyncTransformation?: boolean;
|
|
37
37
|
instrumentCode?: {
|
|
38
38
|
includedBasePath: string;
|
|
@@ -43,6 +43,7 @@ export interface ApplicationPresetOptions {
|
|
|
43
43
|
pureTopLevel: boolean;
|
|
44
44
|
wrapDecorators: boolean;
|
|
45
45
|
};
|
|
46
|
+
supportedBrowsers?: string[];
|
|
46
47
|
diagnosticReporter?: DiagnosticReporter;
|
|
47
48
|
}
|
|
48
49
|
export default function (api: unknown, options: ApplicationPresetOptions): {
|
|
@@ -116,14 +116,13 @@ function default_1(api, options) {
|
|
|
116
116
|
},
|
|
117
117
|
}));
|
|
118
118
|
}
|
|
119
|
-
if (options.
|
|
119
|
+
if (options.forcePresetEnv) {
|
|
120
120
|
presets.push([
|
|
121
121
|
require('@babel/preset-env').default,
|
|
122
122
|
{
|
|
123
123
|
bugfixes: true,
|
|
124
124
|
modules: false,
|
|
125
|
-
|
|
126
|
-
targets: { ie: 9 },
|
|
125
|
+
targets: options.supportedBrowsers,
|
|
127
126
|
exclude: ['transform-typeof-symbol'],
|
|
128
127
|
},
|
|
129
128
|
]);
|
|
@@ -14,5 +14,6 @@ interface AngularCustomOptions extends Omit<ApplicationPresetOptions, 'instrumen
|
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
export declare type AngularBabelLoaderOptions = AngularCustomOptions & Record<string, unknown>;
|
|
17
|
+
export declare function requiresLinking(path: string, source: string): Promise<boolean>;
|
|
17
18
|
declare const _default: any;
|
|
18
19
|
export default _default;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* found in the LICENSE file at https://angular.io/license
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.requiresLinking = void 0;
|
|
10
11
|
const babel_loader_1 = require("babel-loader");
|
|
11
12
|
const typescript_1 = require("typescript");
|
|
12
13
|
const load_esm_1 = require("../utils/load-esm");
|
|
@@ -38,6 +39,7 @@ async function requiresLinking(path, source) {
|
|
|
38
39
|
}
|
|
39
40
|
return needsLinking(path, source);
|
|
40
41
|
}
|
|
42
|
+
exports.requiresLinking = requiresLinking;
|
|
41
43
|
// eslint-disable-next-line max-lines-per-function
|
|
42
44
|
exports.default = (0, babel_loader_1.custom)(() => {
|
|
43
45
|
const baseOptions = Object.freeze({
|
|
@@ -51,15 +53,16 @@ exports.default = (0, babel_loader_1.custom)(() => {
|
|
|
51
53
|
return {
|
|
52
54
|
async customOptions(options, { source, map }) {
|
|
53
55
|
var _a, _b;
|
|
54
|
-
const { i18n, scriptTarget, aot, optimize, instrumentCode, ...rawOptions } = options;
|
|
56
|
+
const { i18n, scriptTarget, aot, optimize, instrumentCode, supportedBrowsers, ...rawOptions } = options;
|
|
55
57
|
// Must process file if plugins are added
|
|
56
58
|
let shouldProcess = Array.isArray(rawOptions.plugins) && rawOptions.plugins.length > 0;
|
|
57
59
|
const customOptions = {
|
|
58
60
|
forceAsyncTransformation: false,
|
|
59
|
-
|
|
61
|
+
forcePresetEnv: false,
|
|
60
62
|
angularLinker: undefined,
|
|
61
63
|
i18n: undefined,
|
|
62
64
|
instrumentCode: undefined,
|
|
65
|
+
supportedBrowsers,
|
|
63
66
|
};
|
|
64
67
|
// Analyze file for linking
|
|
65
68
|
if (await requiresLinking(this.resourcePath, source)) {
|
|
@@ -76,20 +79,31 @@ exports.default = (0, babel_loader_1.custom)(() => {
|
|
|
76
79
|
}
|
|
77
80
|
// Analyze for ES target processing
|
|
78
81
|
const esTarget = scriptTarget;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
82
|
+
const isJsFile = /\.[cm]?js$/.test(this.resourcePath);
|
|
83
|
+
// The below should be dropped when we no longer support ES5 TypeScript output.
|
|
84
|
+
if (esTarget === typescript_1.ScriptTarget.ES5) {
|
|
85
|
+
// This is needed because when target is ES5 we change the TypeScript target to ES2015
|
|
86
|
+
// because it simplifies build-optimization passes.
|
|
87
|
+
// @see https://github.com/angular/angular-cli/blob/22af6520834171d01413d4c7e4a9f13fb752252e/packages/angular_devkit/build_angular/src/webpack/plugins/typescript.ts#L51-L56
|
|
88
|
+
customOptions.forcePresetEnv = true;
|
|
89
|
+
// Comparable behavior to tsconfig target of ES5
|
|
90
|
+
customOptions.supportedBrowsers = ['IE 9'];
|
|
91
|
+
}
|
|
92
|
+
else if (isJsFile) {
|
|
93
|
+
// Applications code ES version can be controlled using TypeScript's `target` option.
|
|
94
|
+
// However, this doesn't effect libraries and hence we use preset-env to downlevel ES fetaures
|
|
95
|
+
// based on the supported browsers in browserlist.
|
|
96
|
+
customOptions.forcePresetEnv = true;
|
|
97
|
+
}
|
|
98
|
+
if ((esTarget !== undefined && esTarget >= typescript_1.ScriptTarget.ES2017) || isJsFile) {
|
|
99
|
+
// Application code (TS files) will only contain native async if target is ES2017+.
|
|
100
|
+
// However, third-party libraries can regardless of the target option.
|
|
101
|
+
// APF packages with code in [f]esm2015 directories is downlevelled to ES2015 and
|
|
102
|
+
// will not have native async.
|
|
103
|
+
customOptions.forceAsyncTransformation =
|
|
104
|
+
!/[\\/][_f]?esm2015[\\/]/.test(this.resourcePath) && source.includes('async');
|
|
92
105
|
}
|
|
106
|
+
shouldProcess || (shouldProcess = customOptions.forceAsyncTransformation || customOptions.forcePresetEnv || false);
|
|
93
107
|
// Analyze for i18n inlining
|
|
94
108
|
if (i18n &&
|
|
95
109
|
!/[\\/]@angular[\\/](?:compiler|localize)/.test(this.resourcePath) &&
|
|
@@ -95,7 +95,7 @@ async function _renderUniversal(options, context, browserResult, serverResult, s
|
|
|
95
95
|
}
|
|
96
96
|
await fs.promises.writeFile(outputIndexPath, html);
|
|
97
97
|
if (browserOptions.serviceWorker) {
|
|
98
|
-
await (0, service_worker_1.augmentAppWithServiceWorker)(projectRoot, outputPath, browserOptions.baseHref || '/', browserOptions.ngswConfigPath);
|
|
98
|
+
await (0, service_worker_1.augmentAppWithServiceWorker)(projectRoot, root, outputPath, browserOptions.baseHref || '/', browserOptions.ngswConfigPath);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
return browserResult;
|
|
@@ -252,7 +252,7 @@ function buildWebpackBrowser(options, context, transforms = {}) {
|
|
|
252
252
|
spinner.start('Generating service worker...');
|
|
253
253
|
for (const [locale, outputPath] of outputPaths.entries()) {
|
|
254
254
|
try {
|
|
255
|
-
await (0, service_worker_1.augmentAppWithServiceWorker)(projectRoot, outputPath, getLocaleBaseHref(i18n, locale) || options.baseHref || '/', options.ngswConfigPath);
|
|
255
|
+
await (0, service_worker_1.augmentAppWithServiceWorker)(projectRoot, context.workspaceRoot, outputPath, getLocaleBaseHref(i18n, locale) || options.baseHref || '/', options.ngswConfigPath);
|
|
256
256
|
}
|
|
257
257
|
catch (error) {
|
|
258
258
|
spinner.fail('Service worker generation failed.');
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
import type { Plugin } from 'esbuild';
|
|
9
|
+
import { BundleStylesheetOptions } from './stylesheets';
|
|
10
|
+
export declare function createCompilerPlugin(pluginOptions: {
|
|
11
|
+
sourcemap: boolean;
|
|
12
|
+
tsconfig: string;
|
|
13
|
+
advancedOptimizations?: boolean;
|
|
14
|
+
}, styleOptions: BundleStylesheetOptions): Plugin;
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://angular.io/license
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
26
|
+
if (mod && mod.__esModule) return mod;
|
|
27
|
+
var result = {};
|
|
28
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
29
|
+
__setModuleDefault(result, mod);
|
|
30
|
+
return result;
|
|
31
|
+
};
|
|
32
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
33
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
34
|
+
};
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.createCompilerPlugin = void 0;
|
|
37
|
+
const core_1 = require("@babel/core");
|
|
38
|
+
const assert = __importStar(require("assert"));
|
|
39
|
+
const fs_1 = require("fs");
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
42
|
+
const application_1 = __importDefault(require("../../babel/presets/application"));
|
|
43
|
+
const webpack_loader_1 = require("../../babel/webpack-loader");
|
|
44
|
+
const load_esm_1 = require("../../utils/load-esm");
|
|
45
|
+
const stylesheets_1 = require("./stylesheets");
|
|
46
|
+
/**
|
|
47
|
+
* Converts TypeScript Diagnostic related information into an esbuild compatible note object.
|
|
48
|
+
* Related information is a subset of a full TypeScript Diagnostic and also used for diagnostic
|
|
49
|
+
* notes associated with the main Diagnostic.
|
|
50
|
+
* @param diagnostic The TypeScript diagnostic relative information to convert.
|
|
51
|
+
* @param host A TypeScript FormatDiagnosticsHost instance to use during conversion.
|
|
52
|
+
* @returns An esbuild diagnostic message as a PartialMessage object
|
|
53
|
+
*/
|
|
54
|
+
function convertTypeScriptDiagnosticInfo(info, host, textPrefix) {
|
|
55
|
+
let text = typescript_1.default.flattenDiagnosticMessageText(info.messageText, host.getNewLine());
|
|
56
|
+
if (textPrefix) {
|
|
57
|
+
text = textPrefix + text;
|
|
58
|
+
}
|
|
59
|
+
const note = { text };
|
|
60
|
+
if (info.file) {
|
|
61
|
+
note.location = {
|
|
62
|
+
file: info.file.fileName,
|
|
63
|
+
length: info.length,
|
|
64
|
+
};
|
|
65
|
+
// Calculate the line/column location and extract the full line text that has the diagnostic
|
|
66
|
+
if (info.start) {
|
|
67
|
+
const { line, character } = typescript_1.default.getLineAndCharacterOfPosition(info.file, info.start);
|
|
68
|
+
note.location.line = line + 1;
|
|
69
|
+
note.location.column = character;
|
|
70
|
+
// The start position for the slice is the first character of the error line
|
|
71
|
+
const lineStartPosition = typescript_1.default.getPositionOfLineAndCharacter(info.file, line, 0);
|
|
72
|
+
// The end position for the slice is the first character of the next line or the length of
|
|
73
|
+
// the entire file if the line is the last line of the file (getPositionOfLineAndCharacter
|
|
74
|
+
// will error if a nonexistent line is passed).
|
|
75
|
+
const { line: lastLineOfFile } = typescript_1.default.getLineAndCharacterOfPosition(info.file, info.file.text.length - 1);
|
|
76
|
+
const lineEndPosition = line < lastLineOfFile
|
|
77
|
+
? typescript_1.default.getPositionOfLineAndCharacter(info.file, line + 1, 0)
|
|
78
|
+
: info.file.text.length;
|
|
79
|
+
note.location.lineText = info.file.text.slice(lineStartPosition, lineEndPosition).trimEnd();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return note;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Converts a TypeScript Diagnostic message into an esbuild compatible message object.
|
|
86
|
+
* @param diagnostic The TypeScript diagnostic to convert.
|
|
87
|
+
* @param host A TypeScript FormatDiagnosticsHost instance to use during conversion.
|
|
88
|
+
* @returns An esbuild diagnostic message as a PartialMessage object
|
|
89
|
+
*/
|
|
90
|
+
function convertTypeScriptDiagnostic(diagnostic, host) {
|
|
91
|
+
var _a;
|
|
92
|
+
let codePrefix = 'TS';
|
|
93
|
+
let code = `${diagnostic.code}`;
|
|
94
|
+
if (diagnostic.source === 'ngtsc') {
|
|
95
|
+
codePrefix = 'NG';
|
|
96
|
+
// Remove `-99` Angular prefix from diagnostic code
|
|
97
|
+
code = code.slice(3);
|
|
98
|
+
}
|
|
99
|
+
const message = {
|
|
100
|
+
...convertTypeScriptDiagnosticInfo(diagnostic, host, `${codePrefix}${code}: `),
|
|
101
|
+
// Store original diagnostic for reference if needed downstream
|
|
102
|
+
detail: diagnostic,
|
|
103
|
+
};
|
|
104
|
+
if ((_a = diagnostic.relatedInformation) === null || _a === void 0 ? void 0 : _a.length) {
|
|
105
|
+
message.notes = diagnostic.relatedInformation.map((info) => convertTypeScriptDiagnosticInfo(info, host));
|
|
106
|
+
}
|
|
107
|
+
return message;
|
|
108
|
+
}
|
|
109
|
+
// This is a non-watch version of the compiler code from `@ngtools/webpack` augmented for esbuild
|
|
110
|
+
// eslint-disable-next-line max-lines-per-function
|
|
111
|
+
function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
112
|
+
return {
|
|
113
|
+
name: 'angular-compiler',
|
|
114
|
+
// eslint-disable-next-line max-lines-per-function
|
|
115
|
+
async setup(build) {
|
|
116
|
+
var _a;
|
|
117
|
+
var _b;
|
|
118
|
+
// This uses a wrapped dynamic import to load `@angular/compiler-cli` which is ESM.
|
|
119
|
+
// Once TypeScript provides support for retaining dynamic imports this workaround can be dropped.
|
|
120
|
+
const compilerCli = await (0, load_esm_1.loadEsmModule)('@angular/compiler-cli');
|
|
121
|
+
// Temporary deep import for transformer support
|
|
122
|
+
const { createAotTransformers, mergeTransformers, } = require('@ngtools/webpack/src/ivy/transformation');
|
|
123
|
+
// Setup defines based on the values provided by the Angular compiler-cli
|
|
124
|
+
(_a = (_b = build.initialOptions).define) !== null && _a !== void 0 ? _a : (_b.define = {});
|
|
125
|
+
for (const [key, value] of Object.entries(compilerCli.GLOBAL_DEFS_FOR_TERSER_WITH_AOT)) {
|
|
126
|
+
if (key in build.initialOptions.define) {
|
|
127
|
+
// Skip keys that have been manually provided
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
// esbuild requires values to be a string (actual strings need to be quoted).
|
|
131
|
+
// In this case, all provided values are booleans.
|
|
132
|
+
build.initialOptions.define[key] = value.toString();
|
|
133
|
+
}
|
|
134
|
+
// The tsconfig is loaded in setup instead of in start to allow the esbuild target build option to be modified.
|
|
135
|
+
// esbuild build options can only be modified in setup prior to starting the build.
|
|
136
|
+
const { options: compilerOptions, rootNames, errors: configurationDiagnostics, } = compilerCli.readConfiguration(pluginOptions.tsconfig, {
|
|
137
|
+
enableIvy: true,
|
|
138
|
+
noEmitOnError: false,
|
|
139
|
+
suppressOutputPathCheck: true,
|
|
140
|
+
outDir: undefined,
|
|
141
|
+
inlineSources: pluginOptions.sourcemap,
|
|
142
|
+
inlineSourceMap: pluginOptions.sourcemap,
|
|
143
|
+
sourceMap: false,
|
|
144
|
+
mapRoot: undefined,
|
|
145
|
+
sourceRoot: undefined,
|
|
146
|
+
declaration: false,
|
|
147
|
+
declarationMap: false,
|
|
148
|
+
allowEmptyCodegenFiles: false,
|
|
149
|
+
annotationsAs: 'decorators',
|
|
150
|
+
enableResourceInlining: false,
|
|
151
|
+
});
|
|
152
|
+
// Adjust the esbuild output target based on the tsconfig target
|
|
153
|
+
if (compilerOptions.target === undefined ||
|
|
154
|
+
compilerOptions.target <= typescript_1.default.ScriptTarget.ES2015) {
|
|
155
|
+
build.initialOptions.target = 'es2015';
|
|
156
|
+
}
|
|
157
|
+
else if (compilerOptions.target >= typescript_1.default.ScriptTarget.ESNext) {
|
|
158
|
+
build.initialOptions.target = 'esnext';
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
build.initialOptions.target = typescript_1.default.ScriptTarget[compilerOptions.target].toLowerCase();
|
|
162
|
+
}
|
|
163
|
+
// The file emitter created during `onStart` that will be used during the build in `onLoad` callbacks for TS files
|
|
164
|
+
let fileEmitter;
|
|
165
|
+
build.onStart(async () => {
|
|
166
|
+
var _a, _b;
|
|
167
|
+
const result = {};
|
|
168
|
+
// Create TypeScript compiler host
|
|
169
|
+
const host = typescript_1.default.createIncrementalCompilerHost(compilerOptions);
|
|
170
|
+
// Temporarily add a readResource hook to allow for a transformResource hook.
|
|
171
|
+
// Once the AOT compiler allows only a transformResource hook this can be removed.
|
|
172
|
+
host.readResource = function (fileName) {
|
|
173
|
+
var _a;
|
|
174
|
+
// Provide same no file found behavior as @ngtools/webpack
|
|
175
|
+
return (_a = this.readFile(fileName)) !== null && _a !== void 0 ? _a : '';
|
|
176
|
+
};
|
|
177
|
+
// Add an AOT compiler resource transform hook
|
|
178
|
+
host.transformResource = async function (data, context) {
|
|
179
|
+
var _a, _b, _c;
|
|
180
|
+
// Only style resources are transformed currently
|
|
181
|
+
if (context.type !== 'style') {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
// The file with the resource content will either be an actual file (resourceFile)
|
|
185
|
+
// or the file containing the inline component style text (containingFile).
|
|
186
|
+
const file = (_a = context.resourceFile) !== null && _a !== void 0 ? _a : context.containingFile;
|
|
187
|
+
const { contents, errors, warnings } = await (0, stylesheets_1.bundleStylesheetText)(data, {
|
|
188
|
+
resolvePath: path.dirname(file),
|
|
189
|
+
virtualName: file,
|
|
190
|
+
}, styleOptions);
|
|
191
|
+
((_b = result.errors) !== null && _b !== void 0 ? _b : (result.errors = [])).push(...errors);
|
|
192
|
+
((_c = result.warnings) !== null && _c !== void 0 ? _c : (result.warnings = [])).push(...warnings);
|
|
193
|
+
return { content: contents };
|
|
194
|
+
};
|
|
195
|
+
// Create the Angular specific program that contains the Angular compiler
|
|
196
|
+
const angularProgram = new compilerCli.NgtscProgram(rootNames, compilerOptions, host);
|
|
197
|
+
const angularCompiler = angularProgram.compiler;
|
|
198
|
+
const { ignoreForDiagnostics, ignoreForEmit } = angularCompiler;
|
|
199
|
+
const typeScriptProgram = angularProgram.getTsProgram();
|
|
200
|
+
const builder = typescript_1.default.createAbstractBuilder(typeScriptProgram, host);
|
|
201
|
+
await angularCompiler.analyzeAsync();
|
|
202
|
+
function* collectDiagnostics() {
|
|
203
|
+
// Collect program level diagnostics
|
|
204
|
+
yield* configurationDiagnostics;
|
|
205
|
+
yield* angularCompiler.getOptionDiagnostics();
|
|
206
|
+
yield* builder.getOptionsDiagnostics();
|
|
207
|
+
yield* builder.getGlobalDiagnostics();
|
|
208
|
+
// Collect source file specific diagnostics
|
|
209
|
+
const OptimizeFor = compilerCli.OptimizeFor;
|
|
210
|
+
for (const sourceFile of builder.getSourceFiles()) {
|
|
211
|
+
if (ignoreForDiagnostics.has(sourceFile)) {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
yield* builder.getSyntacticDiagnostics(sourceFile);
|
|
215
|
+
yield* builder.getSemanticDiagnostics(sourceFile);
|
|
216
|
+
const angularDiagnostics = angularCompiler.getDiagnosticsForFile(sourceFile, OptimizeFor.WholeProgram);
|
|
217
|
+
yield* angularDiagnostics;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
for (const diagnostic of collectDiagnostics()) {
|
|
221
|
+
const message = convertTypeScriptDiagnostic(diagnostic, host);
|
|
222
|
+
if (diagnostic.category === typescript_1.default.DiagnosticCategory.Error) {
|
|
223
|
+
((_a = result.errors) !== null && _a !== void 0 ? _a : (result.errors = [])).push(message);
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
((_b = result.warnings) !== null && _b !== void 0 ? _b : (result.warnings = [])).push(message);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
fileEmitter = createFileEmitter(builder, mergeTransformers(angularCompiler.prepareEmit().transformers, createAotTransformers(builder, {})), () => []);
|
|
230
|
+
return result;
|
|
231
|
+
});
|
|
232
|
+
build.onLoad({ filter: compilerOptions.allowJs ? /\.[cm]?[jt]sx?$/ : /\.[cm]?tsx?$/ }, async (args) => {
|
|
233
|
+
var _a, _b;
|
|
234
|
+
assert.ok(fileEmitter, 'Invalid plugin execution order');
|
|
235
|
+
const typescriptResult = await fileEmitter(args.path);
|
|
236
|
+
if (!typescriptResult) {
|
|
237
|
+
// No TS result indicates the file is not part of the TypeScript program.
|
|
238
|
+
// If allowJs is enabled and the file is JS then defer to the next load hook.
|
|
239
|
+
if (compilerOptions.allowJs && /\.[cm]?js$/.test(args.path)) {
|
|
240
|
+
return undefined;
|
|
241
|
+
}
|
|
242
|
+
// Otherwise return an error
|
|
243
|
+
return {
|
|
244
|
+
errors: [
|
|
245
|
+
{
|
|
246
|
+
text: 'File is missing from the TypeScript compilation.',
|
|
247
|
+
location: { file: args.path },
|
|
248
|
+
notes: [
|
|
249
|
+
{
|
|
250
|
+
text: `Ensure the file is part of the TypeScript program via the 'files' or 'include' property.`,
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
const data = (_a = typescriptResult.content) !== null && _a !== void 0 ? _a : '';
|
|
258
|
+
const babelResult = await (0, core_1.transformAsync)(data, {
|
|
259
|
+
filename: args.path,
|
|
260
|
+
inputSourceMap: (pluginOptions.sourcemap ? undefined : false),
|
|
261
|
+
sourceMaps: pluginOptions.sourcemap ? 'inline' : false,
|
|
262
|
+
compact: false,
|
|
263
|
+
configFile: false,
|
|
264
|
+
babelrc: false,
|
|
265
|
+
browserslistConfigFile: false,
|
|
266
|
+
plugins: [],
|
|
267
|
+
presets: [
|
|
268
|
+
[
|
|
269
|
+
application_1.default,
|
|
270
|
+
{
|
|
271
|
+
forceAsyncTransformation: data.includes('async'),
|
|
272
|
+
optimize: pluginOptions.advancedOptimizations && {},
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
],
|
|
276
|
+
});
|
|
277
|
+
return {
|
|
278
|
+
contents: (_b = babelResult === null || babelResult === void 0 ? void 0 : babelResult.code) !== null && _b !== void 0 ? _b : '',
|
|
279
|
+
loader: 'js',
|
|
280
|
+
};
|
|
281
|
+
});
|
|
282
|
+
build.onLoad({ filter: /\.[cm]?js$/ }, async (args) => {
|
|
283
|
+
var _a;
|
|
284
|
+
const angularPackage = /[\\/]node_modules[\\/]@angular[\\/]/.test(args.path);
|
|
285
|
+
const linkerPluginCreator = (await (0, load_esm_1.loadEsmModule)('@angular/compiler-cli/linker/babel')).createEs2015LinkerPlugin;
|
|
286
|
+
const data = await fs_1.promises.readFile(args.path, 'utf-8');
|
|
287
|
+
const result = await (0, core_1.transformAsync)(data, {
|
|
288
|
+
filename: args.path,
|
|
289
|
+
inputSourceMap: (pluginOptions.sourcemap ? undefined : false),
|
|
290
|
+
sourceMaps: pluginOptions.sourcemap ? 'inline' : false,
|
|
291
|
+
compact: false,
|
|
292
|
+
configFile: false,
|
|
293
|
+
babelrc: false,
|
|
294
|
+
browserslistConfigFile: false,
|
|
295
|
+
plugins: [],
|
|
296
|
+
presets: [
|
|
297
|
+
[
|
|
298
|
+
application_1.default,
|
|
299
|
+
{
|
|
300
|
+
angularLinker: {
|
|
301
|
+
shouldLink: await (0, webpack_loader_1.requiresLinking)(args.path, data),
|
|
302
|
+
jitMode: false,
|
|
303
|
+
linkerPluginCreator,
|
|
304
|
+
},
|
|
305
|
+
forceAsyncTransformation: !/[\\/][_f]?esm2015[\\/]/.test(args.path) && data.includes('async'),
|
|
306
|
+
optimize: pluginOptions.advancedOptimizations && {
|
|
307
|
+
looseEnums: angularPackage,
|
|
308
|
+
pureTopLevel: angularPackage,
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
],
|
|
312
|
+
],
|
|
313
|
+
});
|
|
314
|
+
return {
|
|
315
|
+
contents: (_a = result === null || result === void 0 ? void 0 : result.code) !== null && _a !== void 0 ? _a : data,
|
|
316
|
+
loader: 'js',
|
|
317
|
+
};
|
|
318
|
+
});
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
exports.createCompilerPlugin = createCompilerPlugin;
|
|
323
|
+
function createFileEmitter(program, transformers = {}, onAfterEmit) {
|
|
324
|
+
return async (file) => {
|
|
325
|
+
const sourceFile = program.getSourceFile(file);
|
|
326
|
+
if (!sourceFile) {
|
|
327
|
+
return undefined;
|
|
328
|
+
}
|
|
329
|
+
let content;
|
|
330
|
+
program.emit(sourceFile, (filename, data) => {
|
|
331
|
+
if (/\.[cm]?js$/.test(filename)) {
|
|
332
|
+
content = data;
|
|
333
|
+
}
|
|
334
|
+
}, undefined /* cancellationToken */, undefined /* emitOnlyDtsFiles */, transformers);
|
|
335
|
+
onAfterEmit === null || onAfterEmit === void 0 ? void 0 : onAfterEmit(sourceFile);
|
|
336
|
+
return { content, dependencies: [] };
|
|
337
|
+
};
|
|
338
|
+
}
|