source: trip-planner-front/node_modules/@ngtools/webpack/src/ngcc_processor.js@ 8d391a1

Last change on this file since 8d391a1 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 10.7 KB
Line 
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 */
9var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10 if (k2 === undefined) k2 = k;
11 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
12}) : (function(o, m, k, k2) {
13 if (k2 === undefined) k2 = k;
14 o[k2] = m[k];
15}));
16var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17 Object.defineProperty(o, "default", { enumerable: true, value: v });
18}) : function(o, v) {
19 o["default"] = v;
20});
21var __importStar = (this && this.__importStar) || function (mod) {
22 if (mod && mod.__esModule) return mod;
23 var result = {};
24 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
25 __setModuleDefault(result, mod);
26 return result;
27};
28Object.defineProperty(exports, "__esModule", { value: true });
29exports.NgccProcessor = void 0;
30const ngcc_1 = require("@angular/compiler-cli/ngcc");
31const child_process_1 = require("child_process");
32const crypto_1 = require("crypto");
33const fs_1 = require("fs");
34const path = __importStar(require("path"));
35const benchmark_1 = require("./benchmark");
36// We cannot create a plugin for this, because NGTSC requires addition type
37// information which ngcc creates when processing a package which was compiled with NGC.
38// Example of such errors:
39// ERROR in node_modules/@angular/platform-browser/platform-browser.d.ts(42,22):
40// error TS-996002: Appears in the NgModule.imports of AppModule,
41// but could not be resolved to an NgModule class
42// We now transform a package and it's typings when NGTSC is resolving a module.
43class NgccProcessor {
44 constructor(propertiesToConsider, compilationWarnings, compilationErrors, basePath, tsConfigPath, inputFileSystem, resolver) {
45 this.propertiesToConsider = propertiesToConsider;
46 this.compilationWarnings = compilationWarnings;
47 this.compilationErrors = compilationErrors;
48 this.basePath = basePath;
49 this.tsConfigPath = tsConfigPath;
50 this.inputFileSystem = inputFileSystem;
51 this.resolver = resolver;
52 this._processedModules = new Set();
53 this._logger = new NgccLogger(this.compilationWarnings, this.compilationErrors);
54 this._nodeModulesDirectory = this.findNodeModulesDirectory(this.basePath);
55 }
56 /** Process the entire node modules tree. */
57 process() {
58 // Under Bazel when running in sandbox mode parts of the filesystem is read-only.
59 if (process.env.BAZEL_TARGET) {
60 return;
61 }
62 // Skip if node_modules are read-only
63 const corePackage = this.tryResolvePackage('@angular/core', this._nodeModulesDirectory);
64 if (corePackage && isReadOnlyFile(corePackage)) {
65 return;
66 }
67 // Perform a ngcc run check to determine if an initial execution is required.
68 // If a run hash file exists that matches the current package manager lock file and the
69 // project's tsconfig, then an initial ngcc run has already been performed.
70 let skipProcessing = false;
71 let runHashFilePath;
72 const runHashBasePath = path.join(this._nodeModulesDirectory, '.cli-ngcc');
73 const projectBasePath = path.join(this._nodeModulesDirectory, '..');
74 try {
75 let lockData;
76 let lockFile = 'yarn.lock';
77 try {
78 lockData = fs_1.readFileSync(path.join(projectBasePath, lockFile));
79 }
80 catch {
81 lockFile = 'package-lock.json';
82 lockData = fs_1.readFileSync(path.join(projectBasePath, lockFile));
83 }
84 let ngccConfigData;
85 try {
86 ngccConfigData = fs_1.readFileSync(path.join(projectBasePath, 'ngcc.config.js'));
87 }
88 catch {
89 ngccConfigData = '';
90 }
91 const relativeTsconfigPath = path.relative(projectBasePath, this.tsConfigPath);
92 const tsconfigData = fs_1.readFileSync(this.tsConfigPath);
93 // Generate a hash that represents the state of the package lock file and used tsconfig
94 const runHash = crypto_1.createHash('sha256')
95 .update(lockData)
96 .update(lockFile)
97 .update(ngccConfigData)
98 .update(tsconfigData)
99 .update(relativeTsconfigPath)
100 .digest('hex');
101 // The hash is used directly in the file name to mitigate potential read/write race
102 // conditions as well as to only require a file existence check
103 runHashFilePath = path.join(runHashBasePath, runHash + '.lock');
104 // If the run hash lock file exists, then ngcc was already run against this project state
105 if (fs_1.existsSync(runHashFilePath)) {
106 skipProcessing = true;
107 }
108 }
109 catch {
110 // Any error means an ngcc execution is needed
111 }
112 if (skipProcessing) {
113 return;
114 }
115 const timeLabel = 'NgccProcessor.process';
116 benchmark_1.time(timeLabel);
117 // We spawn instead of using the API because:
118 // - NGCC Async uses clustering which is problematic when used via the API which means
119 // that we cannot setup multiple cluster masters with different options.
120 // - We will not be able to have concurrent builds otherwise Ex: App-Shell,
121 // as NGCC will create a lock file for both builds and it will cause builds to fails.
122 const { status, error } = child_process_1.spawnSync(process.execPath, [
123 require.resolve('@angular/compiler-cli/ngcc/main-ngcc.js'),
124 '--source' /** basePath */,
125 this._nodeModulesDirectory,
126 '--properties' /** propertiesToConsider */,
127 ...this.propertiesToConsider,
128 '--first-only' /** compileAllFormats */,
129 '--create-ivy-entry-points' /** createNewEntryPointFormats */,
130 '--async',
131 '--tsconfig' /** tsConfigPath */,
132 this.tsConfigPath,
133 '--use-program-dependencies',
134 ], {
135 stdio: ['inherit', process.stderr, process.stderr],
136 });
137 if (status !== 0) {
138 const errorMessage = (error === null || error === void 0 ? void 0 : error.message) || '';
139 throw new Error(errorMessage + `NGCC failed${errorMessage ? ', see above' : ''}.`);
140 }
141 benchmark_1.timeEnd(timeLabel);
142 // ngcc was successful so if a run hash was generated, write it for next time
143 if (runHashFilePath) {
144 try {
145 if (!fs_1.existsSync(runHashBasePath)) {
146 fs_1.mkdirSync(runHashBasePath, { recursive: true });
147 }
148 fs_1.writeFileSync(runHashFilePath, '');
149 }
150 catch {
151 // Errors are non-fatal
152 }
153 }
154 }
155 /** Process a module and it's depedencies. */
156 processModule(moduleName, resolvedModule) {
157 var _a, _b;
158 const resolvedFileName = resolvedModule.resolvedFileName;
159 if (!resolvedFileName ||
160 moduleName.startsWith('.') ||
161 this._processedModules.has(resolvedFileName)) {
162 // Skip when module is unknown, relative or NGCC compiler is not found or already processed.
163 return;
164 }
165 const packageJsonPath = this.tryResolvePackage(moduleName, resolvedFileName);
166 // If the package.json is read only we should skip calling NGCC.
167 // With Bazel when running under sandbox the filesystem is read-only.
168 if (!packageJsonPath || isReadOnlyFile(packageJsonPath)) {
169 // add it to processed so the second time round we skip this.
170 this._processedModules.add(resolvedFileName);
171 return;
172 }
173 const timeLabel = `NgccProcessor.processModule.ngcc.process+${moduleName}`;
174 benchmark_1.time(timeLabel);
175 ngcc_1.process({
176 basePath: this._nodeModulesDirectory,
177 targetEntryPointPath: path.dirname(packageJsonPath),
178 propertiesToConsider: this.propertiesToConsider,
179 compileAllFormats: false,
180 createNewEntryPointFormats: true,
181 logger: this._logger,
182 tsConfigPath: this.tsConfigPath,
183 });
184 benchmark_1.timeEnd(timeLabel);
185 // Purge this file from cache, since NGCC add new mainFields. Ex: module_ivy_ngcc
186 // which are unknown in the cached file.
187 (_b = (_a = this.inputFileSystem).purge) === null || _b === void 0 ? void 0 : _b.call(_a, packageJsonPath);
188 this._processedModules.add(resolvedFileName);
189 }
190 invalidate(fileName) {
191 this._processedModules.delete(fileName);
192 }
193 /**
194 * Try resolve a package.json file from the resolved .d.ts file.
195 */
196 tryResolvePackage(moduleName, resolvedFileName) {
197 try {
198 const resolvedPath = this.resolver.resolveSync({}, resolvedFileName, `${moduleName}/package.json`);
199 return resolvedPath || undefined;
200 }
201 catch {
202 // Ex: @angular/compiler/src/i18n/i18n_ast/package.json
203 // or local libraries which don't reside in node_modules
204 const packageJsonPath = path.resolve(resolvedFileName, '../package.json');
205 return fs_1.existsSync(packageJsonPath) ? packageJsonPath : undefined;
206 }
207 }
208 findNodeModulesDirectory(startPoint) {
209 let current = startPoint;
210 while (path.dirname(current) !== current) {
211 const nodePath = path.join(current, 'node_modules');
212 if (fs_1.existsSync(nodePath)) {
213 return nodePath;
214 }
215 current = path.dirname(current);
216 }
217 throw new Error(`Cannot locate the 'node_modules' directory.`);
218 }
219}
220exports.NgccProcessor = NgccProcessor;
221class NgccLogger {
222 constructor(compilationWarnings, compilationErrors) {
223 this.compilationWarnings = compilationWarnings;
224 this.compilationErrors = compilationErrors;
225 this.level = ngcc_1.LogLevel.info;
226 }
227 // eslint-disable-next-line @typescript-eslint/no-empty-function
228 debug() { }
229 info(...args) {
230 // Log to stderr because it's a progress-like info message.
231 process.stderr.write(`\n${args.join(' ')}\n`);
232 }
233 warn(...args) {
234 this.compilationWarnings.push(args.join(' '));
235 }
236 error(...args) {
237 this.compilationErrors.push(new Error(args.join(' ')));
238 }
239}
240function isReadOnlyFile(fileName) {
241 try {
242 fs_1.accessSync(fileName, fs_1.constants.W_OK);
243 return false;
244 }
245 catch {
246 return true;
247 }
248}
Note: See TracBrowser for help on using the repository browser.