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 | Object.defineProperty(exports, "__esModule", { value: true });
|
---|
10 | exports.SchematicEngine = exports.TaskScheduler = exports.CollectionImpl = exports.UnknownTaskDependencyException = exports.UnregisteredTaskException = exports.SchematicEngineConflictingException = exports.PrivateSchematicException = exports.UnknownSchematicException = exports.CircularCollectionException = exports.UnknownCollectionException = exports.UnknownUrlSourceProtocol = void 0;
|
---|
11 | const core_1 = require("@angular-devkit/core");
|
---|
12 | const rxjs_1 = require("rxjs");
|
---|
13 | const operators_1 = require("rxjs/operators");
|
---|
14 | const interface_1 = require("../tree/interface");
|
---|
15 | const null_1 = require("../tree/null");
|
---|
16 | const static_1 = require("../tree/static");
|
---|
17 | const schematic_1 = require("./schematic");
|
---|
18 | class UnknownUrlSourceProtocol extends core_1.BaseException {
|
---|
19 | constructor(url) {
|
---|
20 | super(`Unknown Protocol on url "${url}".`);
|
---|
21 | }
|
---|
22 | }
|
---|
23 | exports.UnknownUrlSourceProtocol = UnknownUrlSourceProtocol;
|
---|
24 | class UnknownCollectionException extends core_1.BaseException {
|
---|
25 | constructor(name) {
|
---|
26 | super(`Unknown collection "${name}".`);
|
---|
27 | }
|
---|
28 | }
|
---|
29 | exports.UnknownCollectionException = UnknownCollectionException;
|
---|
30 | class CircularCollectionException extends core_1.BaseException {
|
---|
31 | constructor(name) {
|
---|
32 | super(`Circular collection reference "${name}".`);
|
---|
33 | }
|
---|
34 | }
|
---|
35 | exports.CircularCollectionException = CircularCollectionException;
|
---|
36 | class UnknownSchematicException extends core_1.BaseException {
|
---|
37 | constructor(name, collection) {
|
---|
38 | super(`Schematic "${name}" not found in collection "${collection.name}".`);
|
---|
39 | }
|
---|
40 | }
|
---|
41 | exports.UnknownSchematicException = UnknownSchematicException;
|
---|
42 | class PrivateSchematicException extends core_1.BaseException {
|
---|
43 | constructor(name, collection) {
|
---|
44 | super(`Schematic "${name}" not found in collection "${collection.name}".`);
|
---|
45 | }
|
---|
46 | }
|
---|
47 | exports.PrivateSchematicException = PrivateSchematicException;
|
---|
48 | class SchematicEngineConflictingException extends core_1.BaseException {
|
---|
49 | constructor() {
|
---|
50 | super(`A schematic was called from a different engine as its parent.`);
|
---|
51 | }
|
---|
52 | }
|
---|
53 | exports.SchematicEngineConflictingException = SchematicEngineConflictingException;
|
---|
54 | class 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 | }
|
---|
60 | exports.UnregisteredTaskException = UnregisteredTaskException;
|
---|
61 | class UnknownTaskDependencyException extends core_1.BaseException {
|
---|
62 | constructor(id) {
|
---|
63 | super(`Unknown task dependency [ID: ${id.id}].`);
|
---|
64 | }
|
---|
65 | }
|
---|
66 | exports.UnknownTaskDependencyException = UnknownTaskDependencyException;
|
---|
67 | class 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() {
|
---|
83 | return this._engine.listSchematicNames(this);
|
---|
84 | }
|
---|
85 | }
|
---|
86 | exports.CollectionImpl = CollectionImpl;
|
---|
87 | class 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 | }
|
---|
134 | exports.TaskScheduler = TaskScheduler;
|
---|
135 | TaskScheduler._taskIdCounter = 1;
|
---|
136 | class 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) {
|
---|
253 | const names = this._host.listSchematicNames(collection.description);
|
---|
254 | if (collection.baseDescriptions) {
|
---|
255 | for (const base of collection.baseDescriptions) {
|
---|
256 | names.push(...this._host.listSchematicNames(base));
|
---|
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 () => 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 = rxjs_1.from(this._taskSchedulers).pipe(operators_1.concatMap((scheduler) => scheduler.finalize()), 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(operators_1.concatMap((executor) => {
|
---|
288 | executors.set(name, executor);
|
---|
289 | return executor(options, task.context);
|
---|
290 | }));
|
---|
291 | }));
|
---|
292 | return taskObservable;
|
---|
293 | }
|
---|
294 | }
|
---|
295 | exports.SchematicEngine = SchematicEngine;
|
---|