source: trip-planner-front/node_modules/@angular-devkit/build-angular/src/testing/builder-harness.js@ 6a3a178

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

initial commit

  • Property mode set to 100644
File size: 13.3 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 */
9Object.defineProperty(exports, "__esModule", { value: true });
10exports.BuilderHarness = void 0;
11const architect_1 = require("@angular-devkit/architect");
12const core_1 = require("@angular-devkit/core");
13const rxjs_1 = require("rxjs");
14const operators_1 = require("rxjs/operators");
15const file_watching_1 = require("./file-watching");
16class BuilderHarness {
17 constructor(builderHandler, host, builderInfo) {
18 this.builderHandler = builderHandler;
19 this.host = host;
20 this.schemaRegistry = new core_1.json.schema.CoreSchemaRegistry();
21 this.projectName = 'test';
22 this.projectMetadata = { root: '.', sourceRoot: 'src' };
23 this.options = new Map();
24 this.builderTargets = new Map();
25 // Generate default pseudo builder info for test purposes
26 this.builderInfo = {
27 builderName: builderHandler.name,
28 description: '',
29 optionSchema: true,
30 ...builderInfo,
31 };
32 this.schemaRegistry.addPostTransform(core_1.json.schema.transforms.addUndefinedDefaults);
33 }
34 useProject(name, metadata = {}) {
35 if (!name) {
36 throw new Error('Project name cannot be an empty string.');
37 }
38 this.projectName = name;
39 this.projectMetadata = metadata;
40 return this;
41 }
42 useTarget(name, baseOptions) {
43 if (!name) {
44 throw new Error('Target name cannot be an empty string.');
45 }
46 this.targetName = name;
47 this.options.set(null, baseOptions);
48 return this;
49 }
50 withConfiguration(configuration, options) {
51 this.options.set(configuration, options);
52 return this;
53 }
54 withBuilderTarget(target, handler, options, info) {
55 this.builderTargets.set(target, {
56 handler,
57 options: options || {},
58 info: { builderName: handler.name, description: '', optionSchema: true, ...info },
59 });
60 return this;
61 }
62 execute(options = {}) {
63 var _a;
64 const { configuration, outputLogsOnException = true, outputLogsOnFailure = true, useNativeFileWatching = false, } = options;
65 const targetOptions = {
66 ...this.options.get(null),
67 ...((_a = (configuration && this.options.get(configuration))) !== null && _a !== void 0 ? _a : {}),
68 };
69 if (!useNativeFileWatching) {
70 if (this.watcherNotifier) {
71 throw new Error('Only one harness execution at a time is supported.');
72 }
73 this.watcherNotifier = new file_watching_1.WatcherNotifier();
74 }
75 const contextHost = {
76 findBuilderByTarget: async (project, target) => {
77 this.validateProjectName(project);
78 if (target === this.targetName) {
79 return {
80 info: this.builderInfo,
81 handler: this.builderHandler,
82 };
83 }
84 const builderTarget = this.builderTargets.get(target);
85 if (builderTarget) {
86 return { info: builderTarget.info, handler: builderTarget.handler };
87 }
88 throw new Error('Project target does not exist.');
89 },
90 async getBuilderName(project, target) {
91 return (await this.findBuilderByTarget(project, target)).info.builderName;
92 },
93 getMetadata: async (project) => {
94 this.validateProjectName(project);
95 return this.projectMetadata;
96 },
97 getOptions: async (project, target, configuration) => {
98 var _a, _b;
99 this.validateProjectName(project);
100 if (target === this.targetName) {
101 return (_a = this.options.get(configuration !== null && configuration !== void 0 ? configuration : null)) !== null && _a !== void 0 ? _a : {};
102 }
103 else if (configuration !== undefined) {
104 // Harness builder targets currently do not support configurations
105 return {};
106 }
107 else {
108 return ((_b = this.builderTargets.get(target)) === null || _b === void 0 ? void 0 : _b.options) || {};
109 }
110 },
111 hasTarget: async (project, target) => {
112 this.validateProjectName(project);
113 return this.targetName === target || this.builderTargets.has(target);
114 },
115 getDefaultConfigurationName: async (_project, _target) => {
116 return undefined;
117 },
118 validate: async (options, builderName) => {
119 let schema;
120 if (builderName === this.builderInfo.builderName) {
121 schema = this.builderInfo.optionSchema;
122 }
123 else {
124 for (const [, value] of this.builderTargets) {
125 if (value.info.builderName === builderName) {
126 schema = value.info.optionSchema;
127 break;
128 }
129 }
130 }
131 const validator = await this.schemaRegistry.compile(schema !== null && schema !== void 0 ? schema : true).toPromise();
132 const { data } = await validator(options).toPromise();
133 return data;
134 },
135 };
136 const context = new HarnessBuilderContext(this.builderInfo, core_1.getSystemPath(this.host.root()), contextHost, useNativeFileWatching ? undefined : this.watcherNotifier);
137 if (this.targetName !== undefined) {
138 context.target = {
139 project: this.projectName,
140 target: this.targetName,
141 configuration: configuration,
142 };
143 }
144 const logs = [];
145 context.logger.subscribe((e) => logs.push(e));
146 return this.schemaRegistry.compile(this.builderInfo.optionSchema).pipe(operators_1.mergeMap((validator) => validator(targetOptions)), operators_1.map((validationResult) => validationResult.data), operators_1.mergeMap((data) => convertBuilderOutputToObservable(this.builderHandler(data, context))), operators_1.map((buildResult) => ({ result: buildResult, error: undefined })), operators_1.catchError((error) => {
147 if (outputLogsOnException) {
148 // eslint-disable-next-line no-console
149 console.error(logs.map((entry) => entry.message).join('\n'));
150 // eslint-disable-next-line no-console
151 console.error(error);
152 }
153 return rxjs_1.of({ result: undefined, error });
154 }), operators_1.map(({ result, error }) => {
155 if (outputLogsOnFailure && (result === null || result === void 0 ? void 0 : result.success) === false && logs.length > 0) {
156 // eslint-disable-next-line no-console
157 console.error(logs.map((entry) => entry.message).join('\n'));
158 }
159 // Capture current logs and clear for next
160 const currentLogs = logs.slice();
161 logs.length = 0;
162 return { result, error, logs: currentLogs };
163 }), operators_1.finalize(() => {
164 this.watcherNotifier = undefined;
165 for (const teardown of context.teardowns) {
166 // eslint-disable-next-line @typescript-eslint/no-floating-promises
167 teardown();
168 }
169 }));
170 }
171 async executeOnce(options) {
172 // Return the first result
173 return this.execute(options).pipe(operators_1.first()).toPromise();
174 }
175 async appendToFile(path, content) {
176 await this.writeFile(path, this.readFile(path).concat(content));
177 }
178 async writeFile(path, content) {
179 var _a;
180 this.host
181 .scopedSync()
182 .write(core_1.normalize(path), typeof content === 'string' ? Buffer.from(content) : content);
183 (_a = this.watcherNotifier) === null || _a === void 0 ? void 0 : _a.notify([
184 { path: core_1.getSystemPath(core_1.join(this.host.root(), path)), type: 'modified' },
185 ]);
186 }
187 async writeFiles(files) {
188 var _a;
189 const watchEvents = this.watcherNotifier
190 ? []
191 : undefined;
192 for (const [path, content] of Object.entries(files)) {
193 this.host
194 .scopedSync()
195 .write(core_1.normalize(path), typeof content === 'string' ? Buffer.from(content) : content);
196 watchEvents === null || watchEvents === void 0 ? void 0 : watchEvents.push({ path: core_1.getSystemPath(core_1.join(this.host.root(), path)), type: 'modified' });
197 }
198 if (watchEvents) {
199 (_a = this.watcherNotifier) === null || _a === void 0 ? void 0 : _a.notify(watchEvents);
200 }
201 }
202 async removeFile(path) {
203 var _a;
204 this.host.scopedSync().delete(core_1.normalize(path));
205 (_a = this.watcherNotifier) === null || _a === void 0 ? void 0 : _a.notify([
206 { path: core_1.getSystemPath(core_1.join(this.host.root(), path)), type: 'deleted' },
207 ]);
208 }
209 async modifyFile(path, modifier) {
210 var _a;
211 const content = this.readFile(path);
212 await this.writeFile(path, await modifier(content));
213 (_a = this.watcherNotifier) === null || _a === void 0 ? void 0 : _a.notify([
214 { path: core_1.getSystemPath(core_1.join(this.host.root(), path)), type: 'modified' },
215 ]);
216 }
217 hasFile(path) {
218 return this.host.scopedSync().exists(core_1.normalize(path));
219 }
220 hasFileMatch(directory, pattern) {
221 return this.host
222 .scopedSync()
223 .list(core_1.normalize(directory))
224 .some((name) => pattern.test(name));
225 }
226 readFile(path) {
227 const content = this.host.scopedSync().read(core_1.normalize(path));
228 return Buffer.from(content).toString('utf8');
229 }
230 validateProjectName(name) {
231 if (name !== this.projectName) {
232 throw new Error(`Project "${name}" does not exist.`);
233 }
234 }
235}
236exports.BuilderHarness = BuilderHarness;
237class HarnessBuilderContext {
238 constructor(builder, basePath, contextHost, watcherFactory) {
239 this.builder = builder;
240 this.contextHost = contextHost;
241 this.watcherFactory = watcherFactory;
242 this.id = Math.trunc(Math.random() * 1000000);
243 this.logger = new core_1.logging.Logger(`builder-harness-${this.id}`);
244 this.teardowns = [];
245 this.workspaceRoot = this.currentDirectory = basePath;
246 }
247 get analytics() {
248 // Can be undefined even though interface does not allow it
249 return undefined;
250 }
251 addTeardown(teardown) {
252 this.teardowns.push(teardown);
253 }
254 async getBuilderNameForTarget(target) {
255 return this.contextHost.getBuilderName(target.project, target.target);
256 }
257 async getProjectMetadata(targetOrName) {
258 const project = typeof targetOrName === 'string' ? targetOrName : targetOrName.project;
259 return this.contextHost.getMetadata(project);
260 }
261 async getTargetOptions(target) {
262 return this.contextHost.getOptions(target.project, target.target, target.configuration);
263 }
264 // Unused by builders in this package
265 async scheduleBuilder(builderName, options, scheduleOptions) {
266 throw new Error('Not Implemented.');
267 }
268 async scheduleTarget(target, overrides, scheduleOptions) {
269 const { info, handler } = await this.contextHost.findBuilderByTarget(target.project, target.target);
270 const targetOptions = await this.validateOptions({
271 ...(await this.getTargetOptions(target)),
272 ...overrides,
273 }, info.builderName);
274 const context = new HarnessBuilderContext(info, this.workspaceRoot, this.contextHost, this.watcherFactory);
275 context.target = target;
276 context.logger = (scheduleOptions === null || scheduleOptions === void 0 ? void 0 : scheduleOptions.logger) || this.logger.createChild('');
277 const progressSubject = new rxjs_1.Subject();
278 const output = convertBuilderOutputToObservable(handler(targetOptions, context));
279 const run = {
280 id: context.id,
281 info,
282 progress: progressSubject.asObservable(),
283 async stop() {
284 for (const teardown of context.teardowns) {
285 await teardown();
286 }
287 progressSubject.complete();
288 },
289 output: output.pipe(operators_1.shareReplay()),
290 get result() {
291 return this.output.pipe(operators_1.first()).toPromise();
292 },
293 };
294 return run;
295 }
296 async validateOptions(options, builderName) {
297 return this.contextHost.validate(options, builderName);
298 }
299 // Unused report methods
300 reportRunning() { }
301 reportStatus() { }
302 reportProgress() { }
303}
304function isAsyncIterable(obj) {
305 return !!obj && typeof obj[Symbol.asyncIterator] === 'function';
306}
307function convertBuilderOutputToObservable(output) {
308 if (architect_1.isBuilderOutput(output)) {
309 return rxjs_1.of(output);
310 }
311 else if (isAsyncIterable(output)) {
312 return architect_1.fromAsyncIterable(output);
313 }
314 else {
315 return rxjs_1.from(output);
316 }
317}
Note: See TracBrowser for help on using the repository browser.