UNPKG

38.7 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay5zZXF1ZW5jZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90YXNrLnNlcXVlbmNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwrQ0FBdUQ7QUFDdkQsSUFBTSxDQUFDLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUM7QUFDdEMsSUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ3pCLElBQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUM7QUFFakMscUNBQXVDO0FBQ3ZDLHFDQUF3QztBQUl4QyxxRUFPbUM7QUFFbkMsNkNBQStFO0FBRS9FLDJDQUF3QztBQUV4QyxpQ0FBd0MsS0FBYSxFQUFFLE9BQXVCO0lBRTFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRTFCLGlCQUFpQixLQUFhLEVBQUUsT0FBdUIsRUFBRSxPQUFRLEVBQUUsT0FBUTtRQUV2RSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQUFDLEdBQUcsRUFBRSxJQUFVO1lBRWhDOzs7O2VBSUc7WUFDSCxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLHdCQUFTLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssd0JBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO2dCQUUzRTs7OzttQkFJRztnQkFDSCxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7b0JBRTVDOzs7dUJBR0c7b0JBQ0gsSUFBTSxNQUFNLEdBQUcsbUJBQW1CLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFFeEQ7O3VCQUVHO29CQUNILEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLEtBQUssMkJBQVksQ0FBQyxRQUFR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
\No newline at end of file