UNPKG

39 kBJavaScriptView Raw
1"use strict";
2var task_resolve_1 = require("./task.resolve");
3var _ = require("../lodash.custom");
4var Rx = require("rx");
5var Observable = Rx.Observable;
6var adaptors = require("./adaptors");
7var Immutable = require("immutable");
8var task_sequence_factories_1 = require("./task.sequence.factories");
9var task_runner_1 = require("./task.runner");
10var task_utils_1 = require("./task.utils");
11function createFlattenedSequence(tasks, trigger) {
12 return flatten(tasks, []);
13 function flatten(items, initial, options, viaName) {
14 return items.reduce(function (all, task) {
15 /**
16 * If the current task has child tasks, we build a tree of
17 * nested observables for it (a task with children cannot itself
18 * be a task that should be run)
19 */
20 if (task.type === task_resolve_1.TaskTypes.TaskGroup || task.type === task_resolve_1.TaskTypes.ParentGroup) {
21 /**
22 * If we're looking at a group of tasks that was run
23 * with sub-tasks, we need to resolve differently to
24 * allow things such as parallel running to work as expected
25 */
26 if (task.subTasks.length && task.tasks.length) {
27 /**
28 * Build the list of tasks/groups
29 * @type {Array}
30 */
31 var output = resolveGroupOfTasks(task, trigger.input);
32 /**
33 * Wrap as parallel group if this task has a runMode of 'parallel'
34 */
35 if (task.runMode === task_resolve_1.TaskRunModes.parallel) {
36 return all.concat(task_sequence_factories_1.createSequenceParallelGroup({
37 taskName: task.taskName,
38 items: output,
39 skipped: task.skipped
40 }));
41 }
42 /**
43 * Wrap as a series group if this task has a runMode of 'series'
44 */
45 if (task.runMode === task_resolve_1.TaskRunModes.series) {
46 return all.concat(task_sequence_factories_1.createSequenceSeriesGroup({
47 taskName: task.taskName,
48 items: output,
49 skipped: task.skipped
50 }));
51 }
52 }
53 /**
54 * If the current task was marked as `parallel`, all immediate children
55 * of (this task) will be run in `parallel`
56 */
57 if (task.runMode === task_resolve_1.TaskRunModes.parallel) {
58 return all.concat(resolveGroup(task, task_sequence_factories_1.createSequenceParallelGroup));
59 }
60 /**
61 * If the current task was marked as `series`, all immediate child tasks
62 * will be queued and run in series - each waiting until the previous
63 * one has completed
64 */
65 if (task.runMode === task_resolve_1.TaskRunModes.series) {
66 return all.concat(resolveGroup(task, task_sequence_factories_1.createSequenceSeriesGroup));
67 }
68 }
69 /**
70 * At this point, we must be dealing with a task that should be run,
71 * so we first check if it's an adaptor @ task first
72 */
73 if (task.type === task_resolve_1.TaskTypes.Adaptor) {
74 return all.concat(getSequenceItemWithOptions(task, trigger, adaptors[task.adaptor].create(task, trigger), {}));
75 }
76 /**
77 * Finally, if the does not have children tasks & is not an
78 * adaptor task it must have at least 1 associated module
79 * (or an inline function) so we can begin working with it
80 * by first resolving the top-level options object for it.
81 */
82 var localOptions = _.assign({}, loadTopLevelOptions(task, trigger), options);
83 /**
84 * Decide where the callable function is coming from
85 * (inline function, external task etc)
86 * @type {CBFunction}
87 */
88 var callable = (function () {
89 if (task.type === task_resolve_1.TaskTypes.InlineFunction) {
90 return task.inlineFunctions[0];
91 }
92 return require(task.externalTasks[0].resolved);
93 })();
94 /**
95 * Take the callable and create items with it + options
96 */
97 return all.concat(resolveFromFunction(task, callable, trigger, localOptions, viaName));
98 }, initial);
99 }
100 /**
101 * Resolve a group of tasks
102 * @param task
103 * @param groupCreatorFn
104 * @param continueFn
105 * @returns {any}
106 */
107 function resolveGroup(task, groupCreatorFn) {
108 /**
109 * If the group contains no subtasks
110 */
111 if (!task.subTasks.length) {
112 /**
113 * If a group has _default options,
114 * but here no 'subTasks' were given, use the
115 * default options always
116 */
117 var parentOptions = (function () {
118 if (task.options._default !== undefined) {
119 return _.merge({}, task.options._default, task.query, task.flags);
120 }
121 return task.options;
122 })();
123 /**
124 * Here the group had no direct 'sub tasks', so just return the item
125 */
126 return [groupCreatorFn({
127 taskName: task.taskName,
128 items: flatten(task.tasks, [], parentOptions),
129 skipped: task.skipped
130 })];
131 }
132 /**
133 * Use either subtasks directly, or if '*' was given, use
134 * each key in the object to create a task
135 */
136 var lookupKeys = getLookupKeys(task.subTasks, task.options);
137 /**
138 * Now for each sub-task create a separate task item
139 */
140 return lookupKeys.map(function (subTaskName) {
141 /**
142 * When things like options, flags or query strings
143 * were present on this task-group - pass them into the upcoming task instead
144 * Order of presedence
145 * flags -> query -> options -> shared
146 */
147 var taskOptions = _.merge({}, task.options._default, _.get(task.options, subTaskName, {}), task.query, task.flags);
148 return groupCreatorFn({
149 taskName: task.taskName,
150 items: flatten(task.tasks, [], taskOptions, task.taskName + ":" + subTaskName),
151 skipped: task.skipped,
152 subTaskName: subTaskName
153 });
154 });
155 }
156 function resolveGroupOfTasks(task, input) {
157 if (task.type === task_resolve_1.TaskTypes.ParentGroup) {
158 var opts = _.merge({}, task.options._default, task.query, task.flags);
159 return flatten(task.tasks, [], opts, task.taskName);
160 }
161 var lookupKeys = getLookupKeys(task.subTasks, task.options);
162 return lookupKeys.reduce(function (acc, subTaskName) {
163 var opts = _.merge({}, task.options._default, _.get(task.options, subTaskName, {}), _.get(input.options, [task.baseTaskName, subTaskName], {}), task.query, task.flags);
164 return acc.concat(flatten(task.tasks, [], opts, task.taskName + ":" + subTaskName));
165 }, []);
166 }
167}
168exports.createFlattenedSequence = createFlattenedSequence;
169function resolveFromFunction(task, callable, trigger, localOptions, viaName) {
170 /**
171 * If the current item has no sub-tasks, we can return early
172 * with a simple task creation using the global options
173 *
174 * eg:
175 * $ crossbow run sass
176 *
177 * options:
178 * sass:
179 * input: "core.scss"
180 * output: "core.css"
181 *
182 * -> `sass` task will be run with the options
183 * {input: "core.scss", output: "core.css"}
184 */
185 if (!task.subTasks.length) {
186 return getSequenceItemWithOptions(task, trigger, callable, localOptions, viaName);
187 }
188 /**
189 * Get lookup keys for this task
190 */
191 var lookupKeys = getLookupKeys(task.subTasks, localOptions);
192 /**
193 * Now generate 1 task per lookup key.
194 */
195 var group = lookupKeys.reduce(function (acc, optionKey) {
196 /**
197 * `optionKey` here will be a string that represented the subTask
198 * name, so we use that to try and find a child key
199 * in the options that matched it.
200 * */
201 var currentOptionObject = _.merge({}, localOptions._default, _.get(localOptions, optionKey));
202 var sequenceItems = getSequenceItemWithOptions(task, trigger, callable, currentOptionObject, optionKey)
203 .map(function (seqItem) {
204 seqItem.subTaskName = optionKey;
205 return seqItem;
206 });
207 return acc.concat(sequenceItems);
208 }, []);
209 /**
210 * Don't create a 'group' if we're only talking about 1 item
211 */
212 if (group.length === 1) {
213 return group;
214 }
215 if (task.runMode === task_resolve_1.TaskRunModes.parallel) {
216 return [task_sequence_factories_1.createSequenceParallelGroup({
217 taskName: task.taskName,
218 items: group,
219 skipped: task.skipped
220 })];
221 }
222 /**
223 * If the current task was marked as `series`, all immediate child tasks
224 * will be queued and run in series - each waiting until the previous
225 * one has completed
226 */
227 if (task.runMode === task_resolve_1.TaskRunModes.series) {
228 return [task_sequence_factories_1.createSequenceSeriesGroup({
229 taskName: task.taskName,
230 items: group,
231 skipped: task.skipped
232 })];
233 }
234}
235function getSequenceItemWithOptions(task, trigger, imported, options, viaName) {
236 /**
237 * Merge incoming options with query + flags
238 * eg:
239 * $ sass?input=css/core.css --production
240 * -> sass
241 * input: css/core.css
242 * production: true
243 */
244 var mergedOptionsWithQuery = _.merge({}, options, task.options, task.query, task.flags);
245 /**
246 * If the module did not export a function, but has a 'tasks'
247 * property that is an array, use each function from it
248 * eg:
249 * module.exports.tasks = [sass, cssmin, version-rev]
250 */
251 if (imported.tasks && Array.isArray(imported.tasks)) {
252 return imported.tasks.map(function (importedFn, i) {
253 return task_sequence_factories_1.createSequenceTaskItem({
254 fnName: getFunctionName(imported, i + 1),
255 factory: importedFn,
256 task: task,
257 options: mergedOptionsWithQuery,
258 viaName: viaName
259 });
260 });
261 }
262 /**
263 * If the module exported a function, use that as the factory
264 * and return a single task for it.
265 * eg:
266 * module.exports = function runSass() {}
267 */
268 if (typeof imported === "function") {
269 return [task_sequence_factories_1.createSequenceTaskItem({
270 fnName: getFunctionName(imported, 0),
271 factory: imported,
272 task: task,
273 options: mergedOptionsWithQuery,
274 viaName: viaName
275 })];
276 }
277}
278/**
279 * For reporting purposes, try to 'name' a function
280 */
281function getFunctionName(fn, count) {
282 if (count === void 0) { count = 0; }
283 if (fn.name === undefined) {
284 return "Anonymous Function " + count;
285 }
286 return fn.name;
287}
288/**
289 * ******************
290 * Where the **--~~Magic~~--** happens!!!
291 * ******************
292 *
293 * Creating a task runner in crossbow is really about
294 * wrapping the process of running the tasks in a way
295 * that allows comprehensive logging/reporting
296 *
297 * Series & Parallel have different semantics and are
298 * therefor handled separately.
299 *
300 * Note that everything here is completely lazy and
301 * nothing will be executed until a user calls subscribe
302 */
303function createRunner(items, trigger) {
304 return {
305 sequence: items,
306 series: function (ctx) {
307 if (!ctx)
308 ctx = Immutable.Map({});
309 var flattened = createObservableTree(items, [], false, ctx);
310 var run = Observable
311 .from(flattened)
312 .concatAll()
313 .catch(function (x) { return Rx.Observable.empty(); });
314 return run;
315 },
316 parallel: function (ctx) {
317 if (!ctx)
318 ctx = Immutable.Map({});
319 var flattened = createObservableTree(items, [], true, ctx);
320 var run = Observable.from(flattened).mergeAll();
321 return run;
322 }
323 };
324 /**
325 * Any task in 'Parallel' run mode that throws an
326 * error should not adversely affect sibling tasks
327 */
328 function shouldCatch(trigger) {
329 return trigger.config.runMode === task_resolve_1.TaskRunModes.parallel;
330 }
331 /**
332 * Create a nested tree of Observables that can contain tasks
333 * alongside parallel/series groups. To understand how this works
334 * you can think of the following to be an accurate representation of
335 * what this function produces:
336 *
337 * const out = [
338 Observable.concat(
339 task1(),
340 task2()
341 ),
342 Observable.concat(
343 task3(),
344 task4(),
345 Observable.concat(
346 task5(),
347 task6(),
348 task7()
349 )
350 )
351 ];
352 *
353 */
354 function createObservableTree(items, initial, addCatch, ctx) {
355 if (addCatch === void 0) { addCatch = false; }
356 return items.reduce(function (all, item) {
357 var output;
358 /**
359 * If the current task was marked as `parallel`, all immediate children
360 * of (this task) will be run in `parallel`
361 */
362 if (item.type === task_sequence_factories_1.SequenceItemTypes.ParallelGroup) {
363 output = Observable.merge(createObservableTree(item.items, [], shouldCatch(trigger), ctx));
364 }
365 /**
366 * If the current task was marked as `series`, all immediate child tasks
367 * will be queued and run in series - each waiting until the previous
368 * one has completed
369 */
370 if (item.type === task_sequence_factories_1.SequenceItemTypes.SeriesGroup) {
371 output = Observable.concat(createObservableTree(item.items, [], false, ctx));
372 }
373 /**
374 * Finally is item is a task, create an observable for it.
375 */
376 if (item.type === task_sequence_factories_1.SequenceItemTypes.Task && item.factory) {
377 output = task_runner_1.createObservableFromSequenceItem(item, trigger, ctx);
378 }
379 /**
380 * Should we add a catch clause to this item to enable
381 * siblings to continue when a task errors
382 */
383 if (addCatch || !trigger.config.fail) {
384 return all.concat(output.catch(function (x) { return Rx.Observable.empty(); }));
385 }
386 return all.concat(output);
387 }, initial);
388 }
389}
390exports.createRunner = createRunner;
391/**
392 * From user input, try to locate a options object
393 */
394function loadTopLevelOptions(task, trigger) {
395 // todo - more robust way of matching options -> tasks
396 var fullMatch = _.get(trigger.input.options, [task.taskName]);
397 if (fullMatch !== undefined) {
398 /**
399 * If this item was given as top-level + options
400 * just return the options here
401 */
402 if (fullMatch.options && fullMatch.tasks) {
403 return fullMatch.options;
404 }
405 /**
406 * If this task has a _default key, don't pass
407 * all the options in, just pass the stuff under default
408 */
409 if (task.subTasks.length === 0 && fullMatch._default !== undefined) {
410 return fullMatch._default;
411 }
412 return fullMatch;
413 }
414 if (task_utils_1.isInternal(task.rawInput)) {
415 var lookup = task.taskName.replace(/(.+?)_internal_fn_\d{0,10}/, "");
416 var fromInternal = _.get(trigger.input.options, [lookup]);
417 if (fromInternal !== undefined) {
418 return fromInternal;
419 }
420 }
421 return {};
422}
423/**
424 * After a bunch of tasks have run, we need to link up task-ended reports
425 * with their original position in the sequence. This will allow us to
426 * reconstruct the task render-tree but also show any tasks that errored
427 * or did not complete
428 * @param sequence
429 * @param reports
430 * @returns {*}
431 */
432function decorateSequenceWithReports(sequence, reports) {
433 return addMany(sequence, []);
434 function addMany(sequence, initial) {
435 return sequence.reduce(function (all, item) {
436 var c = _.assign({}, item);
437 if (item.type === task_sequence_factories_1.SequenceItemTypes.Task) {
438 c.stats = getMergedStats(item, reports);
439 return all.concat(c);
440 }
441 else {
442 c.items = addMany(item.items, []);
443 return all.concat(c);
444 }
445 }, initial);
446 }
447}
448exports.decorateSequenceWithReports = decorateSequenceWithReports;
449/**
450 * Look at every item in the sequence tree and count how many
451 * error have occured
452 */
453function countSequenceErrors(items) {
454 return items.reduce(function (acc, item) {
455 if (item.type === task_sequence_factories_1.SequenceItemTypes.Task) {
456 var errors = _.get(item, "stats.errors", []);
457 if (errors.length) {
458 return acc + errors.length;
459 }
460 return acc;
461 }
462 return acc + countSequenceErrors(item.items);
463 }, 0);
464}
465exports.countSequenceErrors = countSequenceErrors;
466function collectSkippedTasks(items, initial) {
467 return items.reduce(function (acc, item) {
468 if (item.type === task_sequence_factories_1.SequenceItemTypes.Task) {
469 if (item.stats.skipped) {
470 return acc.concat(item);
471 }
472 return acc;
473 }
474 return acc.concat(collectSkippedTasks(item.items, []));
475 }, initial);
476}
477exports.collectSkippedTasks = collectSkippedTasks;
478function collectRunnableTasks(items, initial) {
479 return items.reduce(function (acc, item) {
480 if (item.type === task_sequence_factories_1.SequenceItemTypes.Task) {
481 return acc.concat(item);
482 }
483 return acc.concat(collectRunnableTasks(item.items, []));
484 }, initial);
485}
486exports.collectRunnableTasks = collectRunnableTasks;
487/**
488 * Look at the reports array to find stats linked to a
489 * given task
490 */
491function getMergedStats(item, reports) {
492 var match = reports.filter(function (report) {
493 return report.item.seqUID === item.seqUID;
494 });
495 var start = match.filter(function (x) { return x.type === task_runner_1.TaskReportType.start; })[0];
496 var error = match.filter(function (x) { return x.type === task_runner_1.TaskReportType.error; })[0];
497 var end = match.filter(function (x) { return x.type === task_runner_1.TaskReportType.end; })[0];
498 if (start && end) {
499 return _.assign({}, start.stats, end.stats);
500 }
501 if (start && error) {
502 var duration = error.stats.endTime - start.stats.startTime;
503 return _.assign({}, start.stats, error.stats, { duration: duration });
504 }
505 if (start) {
506 return _.assign({}, start.stats);
507 }
508 return { item: item, errors: [] };
509}
510/**
511 * When we know a task has `subTasks` we need to check if
512 * if the first entry in the subTasks array is a `*` - then
513 * the user wants to run all tasks under this options
514 * object. So we need to get the keys and use each one as a lookup
515 * on the local options. (minus any excluded tasks)
516 *
517 * eg:
518 * $ crossbow run sass:*
519 *
520 * options:
521 * sass:
522 * site: {input: "core.scss"}
523 * debug: {input: "debug.scss"}
524 *
525 * lookupKeys = ['site', 'debug']
526 */
527var blacklistedSubTaskNames = ["_default"];
528function getLookupKeys(subTasks, topLevelObject) {
529 if (subTasks[0] === "*") {
530 return Object.keys(topLevelObject)
531 .filter(function (x) { return blacklistedSubTaskNames.indexOf(x) === -1; });
532 }
533 return subTasks;
534}
535//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay5zZXF1ZW5jZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90YXNrLnNlcXVlbmNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSw2QkFBc0MsZ0JBQWdCLENBQUMsQ0FBQTtBQUN2RCxJQUFNLENBQUMsR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUN0QyxJQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDekIsSUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQztBQUVqQyxJQUFZLFFBQVEsV0FBTSxZQUFZLENBQUMsQ0FBQTtBQUN2QyxJQUFPLFNBQVMsV0FBVyxXQUFXLENBQUMsQ0FBQztBQUl4Qyx3Q0FPTywyQkFBMkIsQ0FBQyxDQUFBO0FBRW5DLDRCQUErRCxlQUFlLENBQUMsQ0FBQTtBQUUvRSwyQkFBeUIsY0FBYyxDQUFDLENBQUE7QUFFeEMsaUNBQXdDLEtBQWEsRUFBRSxPQUF1QjtJQUUxRSxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztJQUUxQixpQkFBaUIsS0FBYSxFQUFFLE9BQXVCLEVBQUUsT0FBUSxFQUFFLE9BQVE7UUFFdkUsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsVUFBQyxHQUFHLEVBQUUsSUFBVTtZQUVoQzs7OztlQUlHO1lBQ0gsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyx3QkFBUyxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLHdCQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztnQkFFM0U7Ozs7bUJBSUc7Z0JBQ0gsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO29CQUU1Qzs7O3VCQUdHO29CQUNILElBQU0sTUFBTSxHQUFHLG1CQUFtQixD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
\No newline at end of file