UNPKG

12.1 kBJavaScriptView Raw
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.SchematicEngine = exports.TaskScheduler = exports.CollectionImpl = exports.UnknownTaskDependencyException = exports.UnregisteredTaskException = exports.SchematicEngineConflictingException = exports.PrivateSchematicException = exports.UnknownSchematicException = exports.CircularCollectionException = exports.UnknownCollectionException = exports.UnknownUrlSourceProtocol = void 0;
11const core_1 = require("@angular-devkit/core");
12const rxjs_1 = require("rxjs");
13const operators_1 = require("rxjs/operators");
14const interface_1 = require("../tree/interface");
15const null_1 = require("../tree/null");
16const static_1 = require("../tree/static");
17const schematic_1 = require("./schematic");
18class UnknownUrlSourceProtocol extends core_1.BaseException {
19 constructor(url) {
20 super(`Unknown Protocol on url "${url}".`);
21 }
22}
23exports.UnknownUrlSourceProtocol = UnknownUrlSourceProtocol;
24class UnknownCollectionException extends core_1.BaseException {
25 constructor(name) {
26 super(`Unknown collection "${name}".`);
27 }
28}
29exports.UnknownCollectionException = UnknownCollectionException;
30class CircularCollectionException extends core_1.BaseException {
31 constructor(name) {
32 super(`Circular collection reference "${name}".`);
33 }
34}
35exports.CircularCollectionException = CircularCollectionException;
36class UnknownSchematicException extends core_1.BaseException {
37 constructor(name, collection) {
38 super(`Schematic "${name}" not found in collection "${collection.name}".`);
39 }
40}
41exports.UnknownSchematicException = UnknownSchematicException;
42class PrivateSchematicException extends core_1.BaseException {
43 constructor(name, collection) {
44 super(`Schematic "${name}" not found in collection "${collection.name}".`);
45 }
46}
47exports.PrivateSchematicException = PrivateSchematicException;
48class SchematicEngineConflictingException extends core_1.BaseException {
49 constructor() {
50 super(`A schematic was called from a different engine as its parent.`);
51 }
52}
53exports.SchematicEngineConflictingException = SchematicEngineConflictingException;
54class UnregisteredTaskException extends core_1.BaseException {
55 constructor(name, schematic) {
56 const addendum = schematic ? ` in schematic "${schematic.name}"` : '';
57 super(`Unregistered task "${name}"${addendum}.`);
58 }
59}
60exports.UnregisteredTaskException = UnregisteredTaskException;
61class UnknownTaskDependencyException extends core_1.BaseException {
62 constructor(id) {
63 super(`Unknown task dependency [ID: ${id.id}].`);
64 }
65}
66exports.UnknownTaskDependencyException = UnknownTaskDependencyException;
67class CollectionImpl {
68 constructor(_description, _engine, baseDescriptions) {
69 this._description = _description;
70 this._engine = _engine;
71 this.baseDescriptions = baseDescriptions;
72 }
73 get description() {
74 return this._description;
75 }
76 get name() {
77 return this.description.name || '<unknown>';
78 }
79 createSchematic(name, allowPrivate = false) {
80 return this._engine.createSchematic(name, this, allowPrivate);
81 }
82 listSchematicNames(includeHidden) {
83 return this._engine.listSchematicNames(this, includeHidden);
84 }
85}
86exports.CollectionImpl = CollectionImpl;
87class TaskScheduler {
88 constructor(_context) {
89 this._context = _context;
90 this._queue = new core_1.PriorityQueue((x, y) => x.priority - y.priority);
91 this._taskIds = new Map();
92 }
93 _calculatePriority(dependencies) {
94 if (dependencies.size === 0) {
95 return 0;
96 }
97 const prio = [...dependencies].reduce((prio, task) => prio + task.priority, 1);
98 return prio;
99 }
100 _mapDependencies(dependencies) {
101 if (!dependencies) {
102 return new Set();
103 }
104 const tasks = dependencies.map((dep) => {
105 const task = this._taskIds.get(dep);
106 if (!task) {
107 throw new UnknownTaskDependencyException(dep);
108 }
109 return task;
110 });
111 return new Set(tasks);
112 }
113 schedule(taskConfiguration) {
114 const dependencies = this._mapDependencies(taskConfiguration.dependencies);
115 const priority = this._calculatePriority(dependencies);
116 const task = {
117 id: TaskScheduler._taskIdCounter++,
118 priority,
119 configuration: taskConfiguration,
120 context: this._context,
121 };
122 this._queue.push(task);
123 const id = { id: task.id };
124 this._taskIds.set(id, task);
125 return id;
126 }
127 finalize() {
128 const tasks = this._queue.toArray();
129 this._queue.clear();
130 this._taskIds.clear();
131 return tasks;
132 }
133}
134exports.TaskScheduler = TaskScheduler;
135TaskScheduler._taskIdCounter = 1;
136class SchematicEngine {
137 constructor(_host, _workflow) {
138 this._host = _host;
139 this._workflow = _workflow;
140 this._collectionCache = new Map();
141 this._schematicCache = new WeakMap();
142 this._taskSchedulers = new Array();
143 }
144 get workflow() {
145 return this._workflow || null;
146 }
147 get defaultMergeStrategy() {
148 return this._host.defaultMergeStrategy || interface_1.MergeStrategy.Default;
149 }
150 createCollection(name, requester) {
151 let collection = this._collectionCache.get(name);
152 if (collection) {
153 return collection;
154 }
155 const [description, bases] = this._createCollectionDescription(name, requester === null || requester === void 0 ? void 0 : requester.description);
156 collection = new CollectionImpl(description, this, bases);
157 this._collectionCache.set(name, collection);
158 this._schematicCache.set(collection, new Map());
159 return collection;
160 }
161 _createCollectionDescription(name, requester, parentNames) {
162 const description = this._host.createCollectionDescription(name, requester);
163 if (!description) {
164 throw new UnknownCollectionException(name);
165 }
166 if (parentNames && parentNames.has(description.name)) {
167 throw new CircularCollectionException(name);
168 }
169 const bases = new Array();
170 if (description.extends) {
171 parentNames = (parentNames || new Set()).add(description.name);
172 for (const baseName of description.extends) {
173 const [base, baseBases] = this._createCollectionDescription(baseName, description, new Set(parentNames));
174 bases.unshift(base, ...baseBases);
175 }
176 }
177 return [description, bases];
178 }
179 createContext(schematic, parent, executionOptions) {
180 // Check for inconsistencies.
181 if (parent && parent.engine && parent.engine !== this) {
182 throw new SchematicEngineConflictingException();
183 }
184 let interactive = true;
185 if (executionOptions && executionOptions.interactive != undefined) {
186 interactive = executionOptions.interactive;
187 }
188 else if (parent && parent.interactive != undefined) {
189 interactive = parent.interactive;
190 }
191 let context = {
192 debug: (parent && parent.debug) || false,
193 engine: this,
194 logger: (parent && parent.logger && parent.logger.createChild(schematic.description.name)) ||
195 new core_1.logging.NullLogger(),
196 schematic,
197 strategy: parent && parent.strategy !== undefined ? parent.strategy : this.defaultMergeStrategy,
198 interactive,
199 addTask,
200 };
201 const maybeNewContext = this._host.transformContext(context);
202 if (maybeNewContext) {
203 context = maybeNewContext;
204 }
205 const taskScheduler = new TaskScheduler(context);
206 const host = this._host;
207 this._taskSchedulers.push(taskScheduler);
208 function addTask(task, dependencies) {
209 const config = task.toConfiguration();
210 if (!host.hasTaskExecutor(config.name)) {
211 throw new UnregisteredTaskException(config.name, schematic.description);
212 }
213 config.dependencies = config.dependencies || [];
214 if (dependencies) {
215 config.dependencies.unshift(...dependencies);
216 }
217 return taskScheduler.schedule(config);
218 }
219 return context;
220 }
221 createSchematic(name, collection, allowPrivate = false) {
222 const schematicMap = this._schematicCache.get(collection);
223 let schematic = schematicMap === null || schematicMap === void 0 ? void 0 : schematicMap.get(name);
224 if (schematic) {
225 return schematic;
226 }
227 let collectionDescription = collection.description;
228 let description = this._host.createSchematicDescription(name, collection.description);
229 if (!description) {
230 if (collection.baseDescriptions) {
231 for (const base of collection.baseDescriptions) {
232 description = this._host.createSchematicDescription(name, base);
233 if (description) {
234 collectionDescription = base;
235 break;
236 }
237 }
238 }
239 if (!description) {
240 // Report the error for the top level schematic collection
241 throw new UnknownSchematicException(name, collection.description);
242 }
243 }
244 if (description.private && !allowPrivate) {
245 throw new PrivateSchematicException(name, collection.description);
246 }
247 const factory = this._host.getSchematicRuleFactory(description, collectionDescription);
248 schematic = new schematic_1.SchematicImpl(description, factory, collection, this);
249 schematicMap === null || schematicMap === void 0 ? void 0 : schematicMap.set(name, schematic);
250 return schematic;
251 }
252 listSchematicNames(collection, includeHidden) {
253 const names = this._host.listSchematicNames(collection.description, includeHidden);
254 if (collection.baseDescriptions) {
255 for (const base of collection.baseDescriptions) {
256 names.push(...this._host.listSchematicNames(base, includeHidden));
257 }
258 }
259 // remove duplicates
260 return [...new Set(names)].sort();
261 }
262 transformOptions(schematic, options, context) {
263 return this._host.transformOptions(schematic.description, options, context);
264 }
265 createSourceFromUrl(url, context) {
266 switch (url.protocol) {
267 case 'null:':
268 return () => new null_1.NullTree();
269 case 'empty:':
270 return () => (0, static_1.empty)();
271 default:
272 const hostSource = this._host.createSourceFromUrl(url, context);
273 if (!hostSource) {
274 throw new UnknownUrlSourceProtocol(url.toString());
275 }
276 return hostSource;
277 }
278 }
279 executePostTasks() {
280 const executors = new Map();
281 const taskObservable = (0, rxjs_1.from)(this._taskSchedulers).pipe((0, operators_1.concatMap)((scheduler) => scheduler.finalize()), (0, operators_1.concatMap)((task) => {
282 const { name, options } = task.configuration;
283 const executor = executors.get(name);
284 if (executor) {
285 return executor(options, task.context);
286 }
287 return this._host.createTaskExecutor(name).pipe((0, operators_1.concatMap)((executor) => {
288 executors.set(name, executor);
289 return executor(options, task.context);
290 }));
291 }));
292 return taskObservable;
293 }
294}
295exports.SchematicEngine = SchematicEngine;