Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

taskgroup

Package Overview
Dependencies
Maintainers
2
Versions
135
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

taskgroup - npm Package Compare versions

Comparing version 7.19.0 to 7.20.0-next.1698928880.db5de7cfdbe1bb9f2eadd99ee44e3a5dafbce45d

.prettierignore

16

edition-browsers/index.js
'use strict';
var _require = require('./task.js'),
Task = _require.Task;
var _require2 = require('./taskgroup.js'),
TaskGroup = _require2.TaskGroup;
const {
Task
} = require('./task.js');
const {
TaskGroup
} = require('./taskgroup.js');
module.exports = {
Task: Task,
TaskGroup: TaskGroup
Task,
TaskGroup
};
'use strict';
/**

@@ -22,61 +23,18 @@ Base class containing common functionality for {@link Task} and {@link TaskGroup}.

*/
class BaseInterface extends require('events').EventEmitter {
constructor() {
super();
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
// Allow extensions of this class to prepare the class instance before anything else fires
if (this.prepare) {
this.prepare();
}
function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
// Set state and config
if (this.state == null) this.state = {};
if (this.config == null) this.config = {};
if (this.config.nameSeparator == null) this.config.nameSeparator = ' ➞ ';
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
var BaseInterface = /*#__PURE__*/function (_require$EventEmitter) {
_inherits(BaseInterface, _require$EventEmitter);
var _super = _createSuper(BaseInterface);
function BaseInterface() {
var _this;
_classCallCheck(this, BaseInterface);
_this = _super.call(this); // Allow extensions of this class to prepare the class instance before anything else fires
if (_this.prepare) {
_this.prepare();
} // Set state and config
if (_this.state == null) _this.state = {};
if (_this.config == null) _this.config = {};
if (_this.config.nameSeparator == null) _this.config.nameSeparator = ' ➞ '; // Generate our listener method that we will beind to different events
// Generate our listener method that we will beind to different events
// to add support for the `done` event and better error/event handling
function listener(event) {

@@ -86,9 +44,11 @@ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {

}
// Prepare
var error = args[0]; // has done listener, forward to that
const error = args[0];
// has done listener, forward to that
if (this.listeners('done').length !== 0) {
this.emit.apply(this, ['done'].concat(args));
} // has error, but no done listener and no event listener, throw error
this.emit('done', ...args);
}
// has error, but no done listener and no event listener, throw error
else if (error && this.listeners(event).length === 1) {

@@ -101,13 +61,11 @@ if (event === 'error') {

}
} // Listen to the different events without listener
}
_this.on('error', listener.bind(_assertThisInitialized(_this), 'error'));
_this.on('completed', listener.bind(_assertThisInitialized(_this), 'completed')); // this.on('halted', listener.bind(this, 'halted'))
// Listen to the different events without listener
this.on('error', listener.bind(this, 'error'));
this.on('completed', listener.bind(this, 'completed'));
// this.on('halted', listener.bind(this, 'halted'))
// ^ @TODO not yet implemented, would be an alternative to pausing
}
return _this;
}
/**

@@ -120,146 +78,114 @@ Creates and returns new instance of the current class.

*/
_createClass(BaseInterface, [{
key: "whenDone",
value:
/**
Attaches the listener to the `done` event to be emitted each time.
@param {Function} listener - Attaches to the `done` event.
@chainable
@returns {BaseInterface} this
@access public
*/
function whenDone(listener) {
// Attach the listener
this.on('done', listener.bind(this)); // Chain
return this;
static create() {
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
/**
Attaches the listener to the `done` event to be emitted only once, then removed to not fire again.
@param {Function} listener - Attaches to the `done` event.
@chainable
@returns {BaseInterface} this
@access public
*/
return new this(...args);
}
}, {
key: "onceDone",
value: function onceDone(listener) {
// Attach the listener
this.once('done', listener.bind(this)); // Chain
/**
Attaches the listener to the `done` event to be emitted each time.
@param {Function} listener - Attaches to the `done` event.
@chainable
@returns {BaseInterface} this
@access public
*/
whenDone(listener) {
// Attach the listener
this.on('done', listener.bind(this));
return this;
}
/**
Alias for {@link BaseInterface#onceDone}
@param {Function} listener - Attaches to the `done` event.
@chainable
@returns {BaseInterface} this
@access public
*/
// Chain
return this;
}
}, {
key: "done",
value: function done(listener) {
return this.onceDone(listener);
}
/**
Gets our name prepended by all of our parents names
@type {Array}
@access public
*/
/**
Attaches the listener to the `done` event to be emitted only once, then removed to not fire again.
@param {Function} listener - Attaches to the `done` event.
@chainable
@returns {BaseInterface} this
@access public
*/
onceDone(listener) {
// Attach the listener
this.once('done', listener.bind(this));
}, {
key: "names",
get: function get() {
// Fetch
var names = [],
_this$config = this.config,
name = _this$config.name,
parent = _this$config.parent,
nameSeparator = _this$config.nameSeparator;
if (parent) names.push.apply(names, _toConsumableArray(parent.names));
if (name !== false) names.push(this.name);
// Chain
return this;
}
names.toString = function () {
return names.join(nameSeparator);
}; // Return
/**
Alias for {@link BaseInterface#onceDone}
@param {Function} listener - Attaches to the `done` event.
@chainable
@returns {BaseInterface} this
@access public
*/
done(listener) {
return this.onceDone(listener);
}
/**
Gets our name prepended by all of our parents names
@type {Array}
@access public
*/
get names() {
// Fetch
const names = [],
{
name,
parent,
nameSeparator
} = this.config;
if (parent) names.push(...parent.names);
if (name !== false) names.push(this.name);
names.toString = () => names.join(nameSeparator);
return names;
}
/**
Get the name of our instance.
If the name was never configured, then return the name in the format of `'${this.type} ${Math.random()}'` to output something like `task 0.2123`
@type {String}
@access public
*/
// Return
return names;
}
}, {
key: "name",
get: function get() {
return this.config.name || this.state.name || (this.state.name = "".concat(this.type, " ").concat(Math.random()));
} // ---------------------------------
// Backwards compatability helpers
/**
Get the name of our instance.
If the name was never configured, then return the name in the format of `'${this.type} ${Math.random()}'` to output something like `task 0.2123`
@type {String}
@access public
*/
get name() {
return this.config.name || this.state.name || (this.state.name = `${this.type} ${Math.random()}`);
}
}, {
key: "getNames",
value: function getNames(opts) {
return opts && opts.separator ? this.names.join(opts.separator) : this.names;
}
}, {
key: "getConfig",
value: function getConfig() {
return this.config;
}
}, {
key: "getTotalItems",
value: function getTotalItems() {
return this.totalItems;
}
}, {
key: "getItemTotals",
value: function getItemTotals() {
return this.itemTotals;
}
}, {
key: "isCompleted",
value: function isCompleted() {
return this.completed;
}
}, {
key: "hasStarted",
value: function hasStarted() {
return this.started;
}
}, {
key: "addGroup",
value: function addGroup() {
return this.addTaskGroup.apply(this, arguments);
}
}, {
key: "clear",
value: function clear() {
this.clearRemaining.apply(this, arguments);
return this;
}
}], [{
key: "create",
value: function create() {
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
// ---------------------------------
// Backwards compatability helpers
return _construct(this, args);
}
}]);
getNames(opts) {
return opts && opts.separator ? this.names.join(opts.separator) : this.names;
}
getConfig() {
return this.config;
}
getTotalItems() {
return this.totalItems;
}
getItemTotals() {
return this.itemTotals;
}
isCompleted() {
return this.completed;
}
hasStarted() {
return this.started;
}
addGroup() {
return this.addTaskGroup(...arguments);
}
clear() {
this.clearRemaining(...arguments);
return this;
}
}
return BaseInterface;
}(require('events').EventEmitter); // Exports
// Exports
module.exports = {
BaseInterface: BaseInterface
BaseInterface
};
/* eslint no-extra-parens:0 func-style:0 */
'use strict'; // Imports
'use strict';
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
// Imports
const {
BaseInterface
} = require('./interface.js');
const {
queue,
domain
} = require('./util.js');
const ambi = require('ambi');
const extendr = require('extendr');
const eachr = require('eachr');
const unbounded = require('unbounded');
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
var _require = require('./interface.js'),
BaseInterface = _require.BaseInterface;
var _require2 = require('./util.js'),
queue = _require2.queue,
domain = _require2.domain;
var ambi = require('ambi');
var extendr = require('extendr');
var eachr = require('eachr');
var unbounded = require('unbounded');
/**

@@ -102,26 +67,16 @@ Our Task Class

*/
var Task = /*#__PURE__*/function (_BaseInterface) {
_inherits(Task, _BaseInterface);
var _super = _createSuper(Task);
function Task() {
var _this2;
var _this;
_classCallCheck(this, Task);
class Task extends BaseInterface {
constructor() {
// Initialise BaseInterface
_this = _super.call(this); // State defaults
super();
extendr.defaults(_this.state, {
// State defaults
extendr.defaults(this.state, {
result: null,
error: null,
status: 'created'
}); // Configuration defaults
});
extendr.defaults(_this.config, {
// Configuration defaults
extendr.defaults(this.config, {
// Standard

@@ -137,8 +92,9 @@ storeResult: null,

args: null
}); // Apply user configuration
});
(_this2 = _this).setConfig.apply(_this2, arguments);
// Apply user configuration
this.setConfig(...arguments);
}
return _this;
} // ===================================
// ===================================
// Typing Helpers

@@ -155,518 +111,473 @@

*/
get type() {
return 'task';
}
/**
A helper method to check if the passed argument is a {Task} via instanceof and duck typing.
@param {Task} item - The possible instance of the {Task} that we want to check
@return {Boolean} Whether or not the item is a {Task} instance.
@static
@access public
*/
static isTask(item) {
return item && item.type === 'task' || item instanceof this;
}
_createClass(Task, [{
key: "type",
get: function get() {
return 'task';
}
/**
A helper method to check if the passed argument is a {Task} via instanceof and duck typing.
@param {Task} item - The possible instance of the {Task} that we want to check
@return {Boolean} Whether or not the item is a {Task} instance.
@static
@access public
*/
// ===================================
// Accessors
}, {
key: "events",
get: // ===================================
// Accessors
/**
An {Array} of the events that we may emit.
@type {Array}
@default ['events', 'error', 'pending', 'running', 'failed', 'passed', 'completed', 'done', 'destroyed']
@access protected
*/
get events() {
return ['events', 'error', 'pending', 'running', 'failed', 'passed', 'completed', 'done', 'destroyed'];
}
/**
An {Array} of the events that we may emit.
@type {Array}
@default ['events', 'error', 'pending', 'running', 'failed', 'passed', 'completed', 'done', 'destroyed']
@access protected
*/
function get() {
return ['events', 'error', 'pending', 'running', 'failed', 'passed', 'completed', 'done', 'destroyed'];
}
/**
Fetches the interpreted value of storeResult
@type {boolean}
@access private
*/
/**
Fetches the interpreted value of storeResult
@type {boolean}
@access private
*/
get storeResult() {
return this.config.storeResult !== false;
}
}, {
key: "storeResult",
get: function get() {
return this.config.storeResult !== false;
} // -----------------------------------
// State Accessors
// -----------------------------------
// State Accessors
/**
The first {Error} that has occured.
@type {Error}
@access protected
*/
/**
The first {Error} that has occured.
@type {Error}
@access protected
*/
get error() {
return this.state.error;
}
}, {
key: "error",
get: function get() {
return this.state.error;
}
/**
A {String} containing our current status. See our {Task} description for available values.
@type {String}
@access protected
*/
/**
A {String} containing our current status. See our {Task} description for available values.
@type {String}
@access protected
*/
get status() {
return this.state.status;
}
}, {
key: "status",
get: function get() {
return this.state.status;
}
/**
An {Array} representing the returned result or the passed {Arguments} of our method (minus the first error argument).
If no result has occured yet, or we don't care, it is null.
@type {?Array}
@access protected
*/
/**
An {Array} representing the returned result or the passed {Arguments} of our method (minus the first error argument).
If no result has occured yet, or we don't care, it is null.
@type {?Array}
@access protected
*/
get result() {
return this.state.result;
}
}, {
key: "result",
get: function get() {
return this.state.result;
} // ---------------------------------
// Status Accessors
// ---------------------------------
// Status Accessors
/**
Have we started execution yet?
@type {Boolean}
@access private
*/
/**
Have we started execution yet?
@type {Boolean}
@access private
*/
get started() {
return this.state.status !== 'created';
}
}, {
key: "started",
get: function get() {
return this.state.status !== 'created';
/**
Have we finished execution yet?
@type {Boolean}
@access private
*/
get exited() {
switch (this.state.status) {
case 'failed':
case 'passed':
case 'destroyed':
return true;
default:
return false;
}
/**
Have we finished execution yet?
@type {Boolean}
@access private
*/
}
}, {
key: "exited",
get: function get() {
switch (this.state.status) {
case 'failed':
case 'passed':
case 'destroyed':
return true;
default:
return false;
}
/**
Have we completed execution yet?
@type {Boolean}
@access private
*/
get completed() {
switch (this.state.status) {
case 'failed':
case 'passed':
return true;
default:
return false;
}
/**
Have we completed execution yet?
@type {Boolean}
@access private
*/
}
}, {
key: "completed",
get: function get() {
switch (this.state.status) {
case 'failed':
case 'passed':
return true;
// ---------------------------------
// State Changers
default:
return false;
}
} // ---------------------------------
// State Changers
/**
Reset the result.
At this point this method is internal, as it's functionality may change in the future, and it's outside use is not yet confirmed. If you need such an ability, let us know via the issue tracker.
@chainable
@returns {this}
@access private
*/
resetResult() {
this.state.result = null;
return this;
}
/**
Reset the result.
At this point this method is internal, as it's functionality may change in the future, and it's outside use is not yet confirmed. If you need such an ability, let us know via the issue tracker.
@chainable
@returns {this}
@access private
*/
}, {
key: "resetResult",
value: function resetResult() {
this.state.result = null;
return this;
/**
Clear the domain
@chainable
@returns {this}
@access private
*/
clearDomain() {
const taskDomain = this.state.taskDomain;
if (taskDomain) {
taskDomain.exit();
taskDomain.removeAllListeners();
this.state.taskDomain = null;
}
/**
Clear the domain
@chainable
@returns {this}
@access private
*/
return this;
}
}, {
key: "clearDomain",
value: function clearDomain() {
var taskDomain = this.state.taskDomain;
// ===================================
// Initialization
if (taskDomain) {
taskDomain.exit();
taskDomain.removeAllListeners();
this.state.taskDomain = null;
/**
Set the configuration for our instance.
@param {Object} [config]
@param {String} [config.name] - What we would like our name to be, useful for debugging.
@param {Function} [config.done] - Passed to {@link Task#onceDone} (aliases are `onceDone`, and `next`)
@param {Function} [config.whenDone] - Passed to {@link Task#whenDone}
@param {Object} [config.on] - A map of event names linking to listener functions that we would like bounded via {EventEmitter.on}
@param {Object} [config.once] - A map of event names linking to listener functions that we would like bounded via {EventEmitter.once}
@param {Boolean} [config.storeResult] - Whether or not to store the result, if `false` will not store
@param {Boolean} [config.destroyOnceDone=true] - Whether or not to automatically destroy the task once it's done to free up resources
@param {TaskGroup} [config.parent] - A parent {@link TaskGroup} that we may be attached to
@param {Function} [config.method] - The {Function} to execute for our {Task}
@param {Boolean} [config.errorOnExcessCompletions=true] - Whether or not to error if the task completes more than once
@param {Boolean} [config.ambi=true] - Whether or not to use bevry/ambi to determine if the method is asynchronous or synchronous and execute it appropriately
@param {Boolean} [config.domain] - If not `false` will wrap the task execution in a domain to attempt to catch background errors (aka errors that are occuring in other ticks than the initial execution), if `true` will fail if domains aren't available
@param {Array} [config.args] - Arguments that we would like to forward onto our method when we execute it
@chainable
@returns {this}
@access public
*/
setConfig() {
const opts = {};
// Extract the configuration from the arguments
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
args.forEach(function (arg) {
if (arg == null) return;
const type = typeof arg;
switch (type) {
case 'string':
opts.name = arg;
break;
case 'function':
opts.method = arg;
break;
case 'object':
extendr.deep(opts, arg);
break;
default:
{
throw new Error(`Unknown argument type of [${type}] given to Task::setConfig()`);
}
}
});
return this;
} // ===================================
// Initialization
// Apply the configuration directly to our instance
eachr(opts, (value, key) => {
if (value == null) return;
switch (key) {
case 'on':
eachr(value, (value, key) => {
if (value) this.on(key, value);
});
break;
case 'once':
eachr(value, (value, key) => {
if (value) this.once(key, value);
});
break;
case 'whenDone':
this.whenDone(value);
break;
case 'onceDone':
case 'done':
case 'next':
this.onceDone(value);
break;
case 'onError':
case 'pauseOnError':
case 'includeInResults':
case 'sync':
case 'timeout':
case 'exit':
throw new Error(`Deprecated configuration property [${key}] given to Task::setConfig()`);
default:
this.config[key] = value;
break;
}
});
/**
Set the configuration for our instance.
@param {Object} [config]
@param {String} [config.name] - What we would like our name to be, useful for debugging.
@param {Function} [config.done] - Passed to {@link Task#onceDone} (aliases are `onceDone`, and `next`)
@param {Function} [config.whenDone] - Passed to {@link Task#whenDone}
@param {Object} [config.on] - A map of event names linking to listener functions that we would like bounded via {EventEmitter.on}
@param {Object} [config.once] - A map of event names linking to listener functions that we would like bounded via {EventEmitter.once}
@param {Boolean} [config.storeResult] - Whether or not to store the result, if `false` will not store
@param {Boolean} [config.destroyOnceDone=true] - Whether or not to automatically destroy the task once it's done to free up resources
@param {TaskGroup} [config.parent] - A parent {@link TaskGroup} that we may be attached to
@param {Function} [config.method] - The {Function} to execute for our {Task}
@param {Boolean} [config.errorOnExcessCompletions=true] - Whether or not to error if the task completes more than once
@param {Boolean} [config.ambi=true] - Whether or not to use bevry/ambi to determine if the method is asynchronous or synchronous and execute it appropriately
@param {Boolean} [config.domain] - If not `false` will wrap the task execution in a domain to attempt to catch background errors (aka errors that are occuring in other ticks than the initial execution), if `true` will fail if domains aren't available
@param {Array} [config.args] - Arguments that we would like to forward onto our method when we execute it
@chainable
@returns {this}
@access public
*/
// Chain
return this;
}
}, {
key: "setConfig",
value: function setConfig() {
var _this3 = this;
// ===================================
// Workflow
var opts = {}; // Extract the configuration from the arguments
/**
What to do when our task method completes.
Should only ever execute once, if it executes more than once, then we error.
@param {...*} args - The arguments that will be applied to the {@link Task#result} variable. First argument is the {Error} if it exists.
@chainable
@returns {this}
@access private
*/
itemCompletionCallback() {
// Store the first error
let error = this.state.error;
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
if (args[0] && !error) {
this.state.error = error = args[0];
}
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
// Complete for the first (and hopefully only) time
if (!this.exited) {
// Apply the result if we want to and it exists
if (this.storeResult) {
this.state.result = args.slice(1);
}
}
args.forEach(function (arg) {
if (arg == null) return;
// Finish up
this.finish();
var type = _typeof(arg);
// Chain
return this;
}
switch (type) {
case 'string':
opts.name = arg;
break;
/**
@NOTE Perhaps at some point, we can add abort/exit functionality, but these things have to be considered:
What will happen to currently running items?
What will happen to remaining items?
Should it be two methods? .halt() and .abort(error?)
Should it be a state?
Should it alter the state?
Should it clear or destroy?
What is the definition of pausing with this?
Perhaps we need to update the definition of pausing to be halted instead?
How can we apply this to Task and TaskGroup consistently?
@access private
@returns {void}
*/
abort() {
throw new Error('not yet implemented');
}
case 'function':
opts.method = arg;
break;
/**
Set our task to the completed state.
@chainable
@returns {this}
@access private
*/
finish() {
const error = this.state.error;
case 'object':
extendr.deep(opts, arg);
break;
// Complete for the first (and hopefully only) time
if (!this.exited) {
// Set the status and emit depending on success or failure status
const status = error ? 'failed' : 'passed';
this.state.status = status;
this.emit(status, error);
default:
{
throw new Error("Unknown argument type of [".concat(type, "] given to Task::setConfig()"));
}
}
}); // Apply the configuration directly to our instance
// Notify our listeners we have completed
const args = [error];
if (this.state.result) args.push(...this.state.result);
this.emit('completed', ...args);
eachr(opts, function (value, key) {
if (value == null) return;
// Prevent the error from persisting
this.state.error = null;
switch (key) {
case 'on':
eachr(value, function (value, key) {
if (value) _this3.on(key, value);
});
break;
case 'once':
eachr(value, function (value, key) {
if (value) _this3.once(key, value);
});
break;
case 'whenDone':
_this3.whenDone(value);
break;
case 'onceDone':
case 'done':
case 'next':
_this3.onceDone(value);
break;
case 'onError':
case 'pauseOnError':
case 'includeInResults':
case 'sync':
case 'timeout':
case 'exit':
throw new Error("Deprecated configuration property [".concat(key, "] given to Task::setConfig()"));
default:
_this3.config[key] = value;
break;
}
}); // Chain
return this;
} // ===================================
// Workflow
/**
What to do when our task method completes.
Should only ever execute once, if it executes more than once, then we error.
@param {...*} args - The arguments that will be applied to the {@link Task#result} variable. First argument is the {Error} if it exists.
@chainable
@returns {this}
@access private
*/
}, {
key: "itemCompletionCallback",
value: function itemCompletionCallback() {
// Store the first error
var error = this.state.error;
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
// Destroy if desired
if (this.config.destroyOnceDone) {
this.destroy();
}
if (args[0] && !error) {
this.state.error = error = args[0];
} // Complete for the first (and hopefully only) time
if (!this.exited) {
// Apply the result if we want to and it exists
if (this.storeResult) {
this.state.result = args.slice(1);
}
} // Finish up
this.finish(); // Chain
return this;
}
/**
@NOTE Perhaps at some point, we can add abort/exit functionality, but these things have to be considered:
What will happen to currently running items?
What will happen to remaining items?
Should it be two methods? .halt() and .abort(error?)
Should it be a state?
Should it alter the state?
Should it clear or destroy?
What is the definition of pausing with this?
Perhaps we need to update the definition of pausing to be halted instead?
How can we apply this to Task and TaskGroup consistently?
@access private
@returns {void}
*/
}, {
key: "abort",
value: function abort() {
throw new Error('not yet implemented');
// Error as we have already completed before
else if (this.config.errorOnExcessCompletions) {
const source = (this.config.method.unbounded || this.config.method || 'no longer present').toString();
const completedError = new Error(`The task [${this.names}] just completed, but it had already completed earlier, this is unexpected.\nTask Source: ${source}`);
this.emit('error', completedError);
}
/**
Set our task to the completed state.
@chainable
@returns {this}
@access private
*/
}, {
key: "finish",
value: function finish() {
var error = this.state.error; // Complete for the first (and hopefully only) time
// Chain
return this;
}
if (!this.exited) {
// Set the status and emit depending on success or failure status
var status = error ? 'failed' : 'passed';
this.state.status = status;
this.emit(status, error); // Notify our listeners we have completed
/**
Destroy ourself and prevent ourself from executing ever again.
@chainable
@returns {this}
@access public
*/
destroy() {
// Update our status and notify our listeners
this.state.status = 'destroyed';
this.emit('destroyed');
var args = [error];
if (this.state.result) args.push.apply(args, _toConsumableArray(this.state.result));
this.emit.apply(this, ['completed'].concat(args)); // Prevent the error from persisting
// Clear the domain
this.clearDomain();
this.state.error = null; // Destroy if desired
// Clear result, in case it keeps references to something
this.resetResult();
if (this.config.destroyOnceDone) {
this.destroy();
}
} // Error as we have already completed before
else if (this.config.errorOnExcessCompletions) {
var source = (this.config.method.unbounded || this.config.method || 'no longer present').toString();
var completedError = new Error("The task [".concat(this.names, "] just completed, but it had already completed earlier, this is unexpected.\nTask Source: ").concat(source));
this.emit('error', completedError);
} // Chain
// Remove all listeners
this.removeAllListeners();
// Chain
return this;
}
/**
Fire the task method with our config arguments and wrapped in a domain.
@chainable
@returns {this}
@access private
*/
fire() {
var _this = this;
// Prepare
const taskArgs = (this.config.args || []).slice();
let taskDomain = this.state.taskDomain;
const exitMethod = unbounded.binder.call(this.itemCompletionCallback, this);
let method = this.config.method;
// Check that we have a method to fire
if (!method) {
const error = new Error(`The task [${this.names}] failed to run as no method was defined for it.`);
this.emit('error', error);
return this;
}
/**
Destroy ourself and prevent ourself from executing ever again.
@chainable
@returns {this}
@access public
*/
}, {
key: "destroy",
value: function destroy() {
// Update our status and notify our listeners
this.state.status = 'destroyed';
this.emit('destroyed'); // Clear the domain
// Bind method
method = unbounded.binder.call(method, this);
this.clearDomain(); // Clear result, in case it keeps references to something
this.resetResult(); // Remove all listeners
this.removeAllListeners(); // Chain
// Handle domains
if (domain) {
// Prepare the task domain if we want to and if it doesn't already exist
if (!taskDomain && this.config.domain !== false) {
this.state.taskDomain = taskDomain = domain.create();
taskDomain.on('error', exitMethod);
}
} else if (this.config.domain === true) {
const error = new Error(`The task [${this.names}] failed to run as it requested to use domains but domains are not available.`);
this.emit('error', error);
return this;
}
/**
Fire the task method with our config arguments and wrapped in a domain.
@chainable
@returns {this}
@access private
*/
}, {
key: "fire",
value: function fire() {
var _this4 = this;
// Prepare
var taskArgs = (this.config.args || []).slice();
var taskDomain = this.state.taskDomain;
var exitMethod = unbounded.binder.call(this.itemCompletionCallback, this);
var method = this.config.method; // Check that we have a method to fire
if (!method) {
var error = new Error("The task [".concat(this.names, "] failed to run as no method was defined for it."));
this.emit('error', error);
return this;
} // Bind method
method = unbounded.binder.call(method, this); // Handle domains
if (domain) {
// Prepare the task domain if we want to and if it doesn't already exist
if (!taskDomain && this.config.domain !== false) {
this.state.taskDomain = taskDomain = domain.create();
taskDomain.on('error', exitMethod);
}
} else if (this.config.domain === true) {
var _error = new Error("The task [".concat(this.names, "] failed to run as it requested to use domains but domains are not available."));
this.emit('error', _error);
return this;
} // Domains, as well as process.nextTick, make it so we can't just use exitMethod directly
// Instead we cover it up like so, to ensure the domain exits, as well to ensure the arguments are passed
var completeMethod = function completeMethod() {
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
if (taskDomain) {
_this4.clearDomain();
taskDomain = null;
exitMethod.apply(void 0, args);
} else {
// Use the next tick workaround to escape the try...catch scope
// Which would otherwise catch errors inside our code when it shouldn't therefore suppressing errors
queue(function () {
exitMethod.apply(void 0, args);
});
}
}; // Our fire function that will be wrapped in a domain or executed directly
var fireMethod = function fireMethod() {
// Execute with ambi if appropriate
if (_this4.config.ambi !== false) {
ambi.apply(void 0, [method].concat(_toConsumableArray(taskArgs)));
} // Otherwise execute directly if appropriate
else {
method.apply(void 0, _toConsumableArray(taskArgs));
}
}; // Add the competion callback to the arguments our method will receive
taskArgs.push(completeMethod); // Notify that we are now running
this.state.status = 'running';
this.emit('running'); // Fire the method within the domain if desired, otherwise execute directly
// Domains, as well as process.nextTick, make it so we can't just use exitMethod directly
// Instead we cover it up like so, to ensure the domain exits, as well to ensure the arguments are passed
const completeMethod = function () {
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
if (taskDomain) {
taskDomain.run(fireMethod);
_this.clearDomain();
taskDomain = null;
exitMethod(...args);
} else {
try {
fireMethod();
} catch (error) {
exitMethod(error);
}
} // Chain
// Use the next tick workaround to escape the try...catch scope
// Which would otherwise catch errors inside our code when it shouldn't therefore suppressing errors
queue(function () {
exitMethod(...args);
});
}
};
// Our fire function that will be wrapped in a domain or executed directly
const fireMethod = () => {
// Execute with ambi if appropriate
if (this.config.ambi !== false) {
ambi(method, ...taskArgs);
}
return this;
}
/**
Start the execution of the task.
Will emit an `error` event if the task has already started before.
@chainable
@returns {this}
@access public
*/
// Otherwise execute directly if appropriate
else {
method(...taskArgs);
}
};
}, {
key: "run",
value: function run() {
var _this5 = this;
// Add the competion callback to the arguments our method will receive
taskArgs.push(completeMethod);
// Already started?
if (this.state.status !== 'created') {
var error = new Error("Invalid run status for the Task [".concat(this.names, "], it was [").concat(this.state.status, "] instead of [created]."));
this.emit('error', error);
return this;
} // Put it into pending state
// Notify that we are now running
this.state.status = 'running';
this.emit('running');
// Fire the method within the domain if desired, otherwise execute directly
if (taskDomain) {
taskDomain.run(fireMethod);
} else {
try {
fireMethod();
} catch (error) {
exitMethod(error);
}
}
this.state.status = 'pending';
this.emit('pending'); // Queue the actual running so we can give time for the listeners to complete before continuing
// Chain
return this;
}
queue(function () {
return _this5.fire();
}); // Chain
/**
Start the execution of the task.
Will emit an `error` event if the task has already started before.
@chainable
@returns {this}
@access public
*/
run() {
// Already started?
if (this.state.status !== 'created') {
const error = new Error(`Invalid run status for the Task [${this.names}], it was [${this.state.status}] instead of [created].`);
this.emit('error', error);
return this;
}
}], [{
key: "isTask",
value: function isTask(item) {
return item && item.type === 'task' || item instanceof this;
}
}]);
return Task;
}(BaseInterface); // Exports
// Put it into pending state
this.state.status = 'pending';
this.emit('pending');
// Queue the actual running so we can give time for the listeners to complete before continuing
queue(() => this.fire());
// Chain
return this;
}
}
// Exports
module.exports = {
Task: Task
Task
};
/* eslint no-extra-parens:0 no-warning-comments:0 */
'use strict'; // Imports
'use strict';
function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
// Imports
const {
BaseInterface
} = require('./interface.js');
const {
Task
} = require('./task.js');
const {
queue,
ensureArray
} = require('./util.js');
const extendr = require('extendr');
const eachr = require('eachr');
const unbounded = require('unbounded');
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
var _require = require('./interface.js'),
BaseInterface = _require.BaseInterface;
var _require2 = require('./task.js'),
Task = _require2.Task;
var _require3 = require('./util.js'),
queue = _require3.queue,
ensureArray = _require3.ensureArray;
var extendr = require('extendr');
var eachr = require('eachr');
var unbounded = require('unbounded');
/**

@@ -87,26 +51,13 @@ Our TaskGroup class.

*/
class TaskGroup extends BaseInterface {
constructor() {
super();
// Prepare (used for class extensions)
if (this.prepare) {
this.prepare(...arguments);
}
var TaskGroup = /*#__PURE__*/function (_BaseInterface) {
_inherits(TaskGroup, _BaseInterface);
var _super = _createSuper(TaskGroup);
function TaskGroup() {
var _this3;
var _this;
_classCallCheck(this, TaskGroup);
_this = _super.call(this); // Prepare (used for class extensions)
if (_this.prepare) {
var _this2;
(_this2 = _this).prepare.apply(_this2, arguments);
} // State defaults
extendr.defaults(_this.state, {
// State defaults
extendr.defaults(this.state, {
result: null,

@@ -118,5 +69,6 @@ error: null,

itemsDoneCount: 0
}); // Configuration defaults
});
extendr.defaults(_this.config, {
// Configuration defaults
extendr.defaults(this.config, {
// Standard

@@ -135,12 +87,14 @@ storeResult: null,

run: null
}); // Apply user configuration
});
(_this3 = _this).setConfig.apply(_this3, arguments); // Give setConfig enough chance to fire
// Apply user configuration
this.setConfig(...arguments);
// Give setConfig enough chance to fire
// Changing this to setImmediate breaks a lot of things
// As tasks inside nested taskgroups will fire in any order
queue(unbounded.binder.call(this.autoRun, this));
}
queue(unbounded.binder.call(_this.autoRun, _assertThisInitialized(_this)));
return _this;
} // ===================================
// ===================================
// Typing Helpers

@@ -156,1098 +110,990 @@

*/
get type() {
return 'taskgroup';
}
/**
A helper method to check if the passed argument is a {TaskGroup} via instanceof and duck typing.
@param {TaskGroup} group - The possible instance of the {TaskGroup} that we want to check
@return {Boolean} Whether or not the item is a {TaskGroup} instance.
@static
@access public
*/
static isTaskGroup(group) {
return group && group.type === 'taskgroup' || group instanceof this;
}
_createClass(TaskGroup, [{
key: "type",
get: function get() {
return 'taskgroup';
}
/**
A helper method to check if the passed argument is a {TaskGroup} via instanceof and duck typing.
@param {TaskGroup} group - The possible instance of the {TaskGroup} that we want to check
@return {Boolean} Whether or not the item is a {TaskGroup} instance.
@static
@access public
*/
/**
A reference to the {Task} class for use in {@link TaskGroup#createTask} if we want to override it.
@type {Task}
@default Task
@access public
*/
get Task() {
return Task;
}
}, {
key: "Task",
get:
/**
A reference to the {Task} class for use in {@link TaskGroup#createTask} if we want to override it.
@type {Task}
@default Task
@access public
*/
function get() {
return Task;
}
/**
A reference to the {TaskGroup} class for use in {@link TaskGroup#createTaskGroup} if we want to override it.
@type {TaskGroup}
@default TaskGroup
@access public
*/
/**
A reference to the {TaskGroup} class for use in {@link TaskGroup#createTaskGroup} if we want to override it.
@type {TaskGroup}
@default TaskGroup
@access public
*/
get TaskGroup() {
return TaskGroup;
}
}, {
key: "TaskGroup",
get: function get() {
return TaskGroup;
} // ===================================
// Accessors
// ===================================
// Accessors
/**
An {Array} of the events that we may emit.
@type {Array}
@access protected
*/
/**
An {Array} of the events that we may emit.
@type {Array}
@access protected
*/
get events() {
return ['error', 'pending', 'running', 'passed', 'failed', 'completed', 'done', 'destroyed'];
}
}, {
key: "events",
get: function get() {
return ['error', 'pending', 'running', 'passed', 'failed', 'completed', 'done', 'destroyed'];
}
/**
Fetches the interpreted value of storeResult
@type {boolean}
@access private
*/
/**
Fetches the interpreted value of storeResult
@type {boolean}
@access private
*/
get storeResult() {
const {
storeResult,
destroyOnceDone
} = this.config;
return storeResult == null ? destroyOnceDone : storeResult !== false;
}
}, {
key: "storeResult",
get: function get() {
var _this$config = this.config,
storeResult = _this$config.storeResult,
destroyOnceDone = _this$config.destroyOnceDone;
return storeResult == null ? destroyOnceDone : storeResult !== false;
} // -----------------------------------
// State Accessors
// -----------------------------------
// State Accessors
/**
The first {Error} that has occured.
@type {Error}
@access protected
*/
/**
The first {Error} that has occured.
@type {Error}
@access protected
*/
get error() {
return this.state.error;
}
}, {
key: "error",
get: function get() {
return this.state.error;
}
/**
A {String} containing our current status. See our {TaskGroup} description for available values.
@type {String}
@access protected
*/
/**
A {String} containing our current status. See our {TaskGroup} description for available values.
@type {String}
@access protected
*/
get status() {
return this.state.status;
}
}, {
key: "status",
get: function get() {
return this.state.status;
}
/**
An {Array} that contains the result property for each completed {Task} and {TaskGroup}.
If no result has occured yet, or we don't care, it is null.
@type {?Array}
@access protected
*/
/**
An {Array} that contains the result property for each completed {Task} and {TaskGroup}.
If no result has occured yet, or we don't care, it is null.
@type {?Array}
@access protected
*/
get result() {
return this.state.result;
}
}, {
key: "result",
get: function get() {
return this.state.result;
} // ---------------------------------
// Status Accessors
// ---------------------------------
// Status Accessors
/**
Gets the total number of items inside our task group.
@type {Number}
@access public
*/
/**
Gets the total number of items inside our task group.
@type {Number}
@access public
*/
get totalItems() {
const remaining = this.state.itemsRemaining.length;
const executing = this.state.itemsExecutingCount;
const done = this.state.itemsDoneCount;
const total = executing + remaining + done;
return total;
}
}, {
key: "totalItems",
get: function get() {
var remaining = this.state.itemsRemaining.length;
var executing = this.state.itemsExecutingCount;
var done = this.state.itemsDoneCount;
var total = executing + remaining + done;
return total;
}
/**
Gets the total number count of each of our item lists.
Returns an {Object} containg the hashes:
- remaining - A {Number} of the names of the remaining items.
- executing - A {Number} of the names of the executing items.
- done - A {Number} of the names of the done items.
- total - A {Number} of the total items we have.
- result - A {Number} of the total results we have.
@type {Object}
@access public
*/
/**
Gets the total number count of each of our item lists.
Returns an {Object} containg the hashes:
- remaining - A {Number} of the names of the remaining items.
- executing - A {Number} of the names of the executing items.
- done - A {Number} of the names of the done items.
- total - A {Number} of the total items we have.
- result - A {Number} of the total results we have.
@type {Object}
@access public
*/
get itemTotals() {
const remaining = this.state.itemsRemaining.length;
const executing = this.state.itemsExecutingCount;
const done = this.state.itemsDoneCount;
const result = this.state.result && this.state.result.length;
const total = executing + remaining + done;
return {
remaining,
executing,
done,
total,
result
};
}
}, {
key: "itemTotals",
get: function get() {
var remaining = this.state.itemsRemaining.length;
var executing = this.state.itemsExecutingCount;
var done = this.state.itemsDoneCount;
var result = this.state.result && this.state.result.length;
var total = executing + remaining + done;
return {
remaining: remaining,
executing: executing,
done: done,
total: total,
result: result
};
}
/**
Whether or not we have any items yet to execute.
@type {Boolean}
@access private
*/
/**
Whether or not we have any items yet to execute.
@type {Boolean}
@access private
*/
get hasRemaining() {
return this.state.itemsRemaining.length !== 0;
}
}, {
key: "hasRemaining",
get: function get() {
return this.state.itemsRemaining.length !== 0;
}
/**
Whether or not we have any running items.
@type {Boolean}
@access private
*/
/**
Whether or not we have any running items.
@type {Boolean}
@access private
*/
get hasRunning() {
return this.state.itemsExecutingCount !== 0;
}
}, {
key: "hasRunning",
get: function get() {
return this.state.itemsExecutingCount !== 0;
}
/**
Whether or not we have any items running or remaining.
@type {Boolean}
@access private
*/
/**
Whether or not we have any items running or remaining.
@type {Boolean}
@access private
*/
get hasItems() {
return this.hasRunning || this.hasRemaining;
}
}, {
key: "hasItems",
get: function get() {
return this.hasRunning || this.hasRemaining;
}
/**
Whether or not we have an error.
@type {Boolean}
@access private
*/
/**
Whether or not we have an error.
@type {Boolean}
@access private
*/
get hasError() {
return this.state.error != null;
}
}, {
key: "hasError",
get: function get() {
return this.state.error != null;
}
/**
Whether or not we have an error or a result.
@type {Boolean}
@access private
*/
/**
Whether or not we have an error or a result.
@type {Boolean}
@access private
*/
get hasResult() {
return this.hasError || this.state.result.length !== 0;
}
}, {
key: "hasResult",
get: function get() {
return this.hasError || this.state.result.length !== 0;
}
/**
Whether or not we have any available slots to execute more items.
@type {Boolean}
@access private
*/
/**
Whether or not we have any available slots to execute more items.
@type {Boolean}
@access private
*/
get hasSlots() {
const concurrency = this.config.concurrency;
return concurrency === 0 || this.state.itemsExecutingCount < concurrency;
}
}, {
key: "hasSlots",
get: function get() {
var concurrency = this.config.concurrency;
return concurrency === 0 || this.state.itemsExecutingCount < concurrency;
}
/**
Whether or not we are capable of firing more items.
This is determined whether or not we are not paused, and we have remaning items, and we have slots able to execute those remaning items.
@type {Boolean}
@access private
*/
/**
Whether or not we are capable of firing more items.
This is determined whether or not we are not paused, and we have remaning items, and we have slots able to execute those remaning items.
@type {Boolean}
@access private
*/
get shouldFire() {
return !this.shouldPause && this.hasRemaining && this.hasSlots;
}
}, {
key: "shouldFire",
get: function get() {
return !this.shouldPause && this.hasRemaining && this.hasSlots;
}
/**
Whether or not we have errord and want to pause when we have an error.
@type {Boolean}
@access private
*/
/**
Whether or not we have errord and want to pause when we have an error.
@type {Boolean}
@access private
*/
get shouldPause() {
return this.config.abortOnError && this.hasError;
}
}, {
key: "shouldPause",
get: function get() {
return this.config.abortOnError && this.hasError;
}
/**
Whether or not we execution is currently paused.
@type {Boolean}
@access private
*/
/**
Whether or not we execution is currently paused.
@type {Boolean}
@access private
*/
get paused() {
return this.shouldPause && !this.hasRunning;
}
}, {
key: "paused",
get: function get() {
return this.shouldPause && !this.hasRunning;
}
/**
Whether or not we have no running or remaining items left.
@type {Boolean}
@access private
*/
/**
Whether or not we have no running or remaining items left.
@type {Boolean}
@access private
*/
get empty() {
return !this.hasItems;
}
}, {
key: "empty",
get: function get() {
return !this.hasItems;
/**
Whether or not we have finished execution.
@type {Boolean}
@access private
*/
get exited() {
switch (this.state.status) {
case 'passed':
case 'failed':
case 'destroyed':
return true;
default:
return false;
}
/**
Whether or not we have finished execution.
@type {Boolean}
@access private
*/
}
}, {
key: "exited",
get: function get() {
switch (this.state.status) {
case 'passed':
case 'failed':
case 'destroyed':
return true;
/**
Whether or not we have started execution.
@type {Boolean}
@access private
*/
get started() {
return this.state.status !== 'created';
}
default:
return false;
}
}
/**
Whether or not we have started execution.
@type {Boolean}
@access private
*/
/**
Whether or not we execution has completed.
Completion of executed is determined of whether or not we have started, and whether or not we are currently paused or have no remaining and running items left
@type {Boolean}
@access private
*/
get completed() {
return this.started && (this.paused || this.empty);
}
}, {
key: "started",
get: function get() {
return this.state.status !== 'created';
}
/**
Whether or not we execution has completed.
Completion of executed is determined of whether or not we have started, and whether or not we are currently paused or have no remaining and running items left
@type {Boolean}
@access private
*/
// ---------------------------------
// State Changers
}, {
key: "completed",
get: function get() {
return this.started && (this.paused || this.empty);
} // ---------------------------------
// State Changers
/**
Reset the result.
At this point this method is internal, as it's functionality may change in the future, and it's outside use is not yet confirmed. If you need such an ability, let us know via the issue tracker.
@chainable
@returns {this}
@access private
*/
resetResult() {
this.state.result = null;
/**
Reset the result.
At this point this method is internal, as it's functionality may change in the future, and it's outside use is not yet confirmed. If you need such an ability, let us know via the issue tracker.
@chainable
@returns {this}
@access private
*/
// Chain
return this;
}
}, {
key: "resetResult",
value: function resetResult() {
this.state.result = null; // Chain
return this;
/**
Remove and destroy the remaining items.
@chainable
@returns {number} the amount of items that were dropped
@access public
*/
clearRemaining() {
let dropped = 0;
const itemsRemaining = this.state.itemsRemaining;
while (itemsRemaining.length !== 0) {
itemsRemaining.pop().destroy();
++dropped;
}
/**
Remove and destroy the remaining items.
@chainable
@returns {number} the amount of items that were dropped
@access public
*/
}, {
key: "clearRemaining",
value: function clearRemaining() {
var dropped = 0;
var itemsRemaining = this.state.itemsRemaining;
// Return
return dropped;
}
while (itemsRemaining.length !== 0) {
itemsRemaining.pop().destroy();
++dropped;
} // Return
/**
Remove and destroy the running items. Here for verboseness.
@chainable
@returns {this}
@access private
*/
clearRunning() {
const error = new Error('Clearing running items is not possible. Instead remaining items and wait for running items to complete.');
this.emit('error', error);
return this;
}
// ===================================
// Initialization
return dropped;
}
/**
Remove and destroy the running items. Here for verboseness.
@chainable
@returns {this}
@access private
*/
/**
Autorun ourself under certain conditions.
Those conditions being:
- if we the :method configuration is defined, and we have no :parent
- if we the :run configuration is `true`
Used primarily to cause the :method to fire at the appropriate time when using inline style.
@chainable
@returns {this}
@access private
*/
autoRun() {
// Prepare
const method = this.config.method;
let run = this.config.run;
}, {
key: "clearRunning",
value: function clearRunning() {
var error = new Error('Clearing running items is not possible. Instead remaining items and wait for running items to complete.');
this.emit('error', error);
return this;
} // ===================================
// Initialization
// Auto run if we are going the inline style and have no parent
if (method) {
// Add the function as our first unamed task with the extra arguments
this.addMethod(method);
/**
Autorun ourself under certain conditions.
Those conditions being:
- if we the :method configuration is defined, and we have no :parent
- if we the :run configuration is `true`
Used primarily to cause the :method to fire at the appropriate time when using inline style.
@chainable
@returns {this}
@access private
*/
// If we are the topmost group default run to true
if (!this.config.parent && run == null) {
this.state.run = run = true;
}
}
}, {
key: "autoRun",
value: function autoRun() {
// Prepare
var method = this.config.method;
var run = this.config.run; // Auto run if we are going the inline style and have no parent
// Auto run if we are configured to
if (run) {
this.run();
}
if (method) {
// Add the function as our first unamed task with the extra arguments
this.addMethod(method); // If we are the topmost group default run to true
// Chain
return this;
}
if (!this.config.parent && run == null) {
this.state.run = run = true;
}
} // Auto run if we are configured to
/**
Set the configuration for our instance.
Despite accepting an {Object} of configuration, we can also accept an {Array} of configuration.
When using an array, a {String} becomes the :name, a {Function} becomes the :method, and an {Object} becomes the :config
@param {Object} [config]
@param {String} [config.name] - What we would like our name to be, useful for debugging
@param {Function} [config.done] - Passed to {@link TaskGroup#onceDone} (aliases are `onceDone`, and `next`)
@param {Function} [config.whenDone] - Passed to {@link TaskGroup#whenDone}
@param {Object} [config.on] - An object of event names linking to listener functions that we would like bounded via {@link EventEmitter#on}
@param {Object} [config.once] - An object of event names linking to listener functions that we would like bounded via {@link EventEmitter#once}
@param {Boolean} [config.storeResult] - Whether or not to store the result, if `false` will not store, defaults to `false` if `destroyOnceDone` is `true`
@param {Boolean} [config.destroyOnceDone=true] - Whether or not we should automatically destroy the {TaskGroup} once done to free up resources
@param {TaskGroup} [config.parent] - A parent {TaskGroup} that we may be attached to
@param {Function} [config.method] - The {Function} to execute for our {TaskGroup} when using inline execution style
@param {Boolean} [config.abortOnError=true] - Whether or not we should abort execution of the {TaskGroup} and exit when an error occurs
@param {Boolean} [config.destroyDoneItems=true] - Whether or not we should automatically destroy done items to free up resources
@param {Object} [config.nestedTaskGroupConfig] - The nested configuration to be applied to all {TaskGroup} descendants of this group
@param {Object} [config.nestedTaskConfig] - The nested configuration to be applied to all {Task} descendants of this group
@param {Boolean} [config.emitNestedEvents=false] - Whether or not we should emit nested item events @TODO remove this, there are not tests for it, can be accomplished via item.add listener like TaskGroupDebug
@param {Number} [config.concurrency=1] - The amount of items that we would like to execute at the same time. Use `0` for unlimited. `1` accomplishes serial execution, everything else accomplishes parallel execution
@param {Boolean} [config.run] - A {Boolean} for whether or not to run the TaskGroup automatically, by default will be enabled if config.method is defined
@param {Array} [config.tasks] - An {Array} of {Task} instances to be added to this group
@param {Array} [config.taskgroups] - An {Array} of {TaskGroup} instances to be added to this group
@param {Array} [config.items] - An {Array} of {Task} and/or {TaskGroup} instances to be added to this group
@chainable
@returns {this}
@access public
*/
setConfig() {
const opts = {};
if (run) {
this.run();
} // Chain
return this;
// Extract the configuration from the arguments
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
/**
Set the configuration for our instance.
Despite accepting an {Object} of configuration, we can also accept an {Array} of configuration.
When using an array, a {String} becomes the :name, a {Function} becomes the :method, and an {Object} becomes the :config
@param {Object} [config]
@param {String} [config.name] - What we would like our name to be, useful for debugging
@param {Function} [config.done] - Passed to {@link TaskGroup#onceDone} (aliases are `onceDone`, and `next`)
@param {Function} [config.whenDone] - Passed to {@link TaskGroup#whenDone}
@param {Object} [config.on] - An object of event names linking to listener functions that we would like bounded via {@link EventEmitter#on}
@param {Object} [config.once] - An object of event names linking to listener functions that we would like bounded via {@link EventEmitter#once}
@param {Boolean} [config.storeResult] - Whether or not to store the result, if `false` will not store, defaults to `false` if `destroyOnceDone` is `true`
@param {Boolean} [config.destroyOnceDone=true] - Whether or not we should automatically destroy the {TaskGroup} once done to free up resources
@param {TaskGroup} [config.parent] - A parent {TaskGroup} that we may be attached to
@param {Function} [config.method] - The {Function} to execute for our {TaskGroup} when using inline execution style
@param {Boolean} [config.abortOnError=true] - Whether or not we should abort execution of the {TaskGroup} and exit when an error occurs
@param {Boolean} [config.destroyDoneItems=true] - Whether or not we should automatically destroy done items to free up resources
@param {Object} [config.nestedTaskGroupConfig] - The nested configuration to be applied to all {TaskGroup} descendants of this group
@param {Object} [config.nestedTaskConfig] - The nested configuration to be applied to all {Task} descendants of this group
@param {Boolean} [config.emitNestedEvents=false] - Whether or not we should emit nested item events @TODO remove this, there are not tests for it, can be accomplished via item.add listener like TaskGroupDebug
@param {Number} [config.concurrency=1] - The amount of items that we would like to execute at the same time. Use `0` for unlimited. `1` accomplishes serial execution, everything else accomplishes parallel execution
@param {Boolean} [config.run] - A {Boolean} for whether or not to run the TaskGroup automatically, by default will be enabled if config.method is defined
@param {Array} [config.tasks] - An {Array} of {Task} instances to be added to this group
@param {Array} [config.taskgroups] - An {Array} of {TaskGroup} instances to be added to this group
@param {Array} [config.items] - An {Array} of {Task} and/or {TaskGroup} instances to be added to this group
@chainable
@returns {this}
@access public
*/
args.forEach(function (arg) {
if (arg == null) return;
const type = typeof arg;
switch (type) {
case 'string':
opts.name = arg;
break;
case 'function':
opts.method = arg;
break;
case 'object':
extendr.deep(opts, arg); // @TODO why deep?
break;
default:
{
throw new Error(`Unknown argument type of [${type}] given to TaskGroup::setConfig()`);
}
}
});
}, {
key: "setConfig",
value: function setConfig() {
var _this4 = this;
var opts = {}; // Extract the configuration from the arguments
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
// Apply the configuration directly to our instance
eachr(opts, (value, key) => {
if (value == null) return;
switch (key) {
case 'on':
eachr(value, (value, key) => {
if (value) this.on(key, value);
});
break;
case 'once':
eachr(value, (value, key) => {
if (value) this.once(key, value);
});
break;
case 'whenDone':
this.whenDone(value);
break;
case 'onceDone':
case 'done':
case 'next':
this.done(value);
break;
case 'task':
case 'tasks':
this.addTasks(value);
break;
case 'group':
case 'groups':
case 'taskgroup':
case 'taskgroups':
this.addTaskGroups(value);
break;
case 'item':
case 'items':
this.addItems(value);
break;
case 'onError':
case 'pauseOnError':
case 'includeInResults':
case 'sync':
case 'timeout':
case 'exit':
case 'nestedConfig':
throw new Error(`Deprecated configuration property [${key}] given to TaskGroup::setConfig()`);
default:
this.config[key] = value;
break;
}
});
args.forEach(function (arg) {
if (arg == null) return;
// Chain
return this;
}
var type = _typeof(arg);
/**
Merge passed configuration into {config.nestedTaskConfig}.
@param {Object} opts - The configuration to merge.
@chainable
@returns {this}
@access public
*/
setNestedTaskConfig(opts) {
// Fetch and copy options to the state's nested task configuration
extendr.deep(this.state.nestedTaskConfig, opts);
switch (type) {
case 'string':
opts.name = arg;
break;
// Chain
return this;
}
case 'function':
opts.method = arg;
break;
/**
Merge passed configuration into {config.nestedTaskGroupConfig}.
@param {Object} opts - The configuration to merge.
@chainable
@returns {this}
@access public
*/
setNestedTaskGroupConfig(opts) {
// Fetch and copy options to the state's nested configuration
extendr.deep(this.state.nestedTaskGroupConfig, opts);
case 'object':
extendr.deep(opts, arg); // @TODO why deep?
// Chain
return this;
}
break;
// ===================================
// Items
default:
{
throw new Error("Unknown argument type of [".concat(type, "] given to TaskGroup::setConfig()"));
}
}
}); // Apply the configuration directly to our instance
// ---------------------------------
// TaskGroup Method
eachr(opts, function (value, key) {
if (value == null) return;
/**
Prepare the method and it's configuration, and add it as a task to be executed.
@param {Function} method - The function we want to execute as the method of this TaskGroup.
@param {Object} opts - Optional configuration for the task to be created for the method.
@chainable
@returns {this}
@access private
*/
addMethod(method) {
let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
method = unbounded.binder.call(method, this); // run the taskgroup method on the group, rather than itself
method.isTaskGroupMethod = true;
if (!opts.name) opts.name = 'taskgroup method for ' + this.name;
if (!opts.args) opts.args = [this.addTaskGroup.bind(this), this.addTask.bind(this)];
if (opts.storeResult == null) opts.storeResult = false; // by default, hide result for methods
this.addTask(method, opts);
return this;
}
switch (key) {
case 'on':
eachr(value, function (value, key) {
if (value) _this4.on(key, value);
});
break;
// ---------------------------------
// Add Item
case 'once':
eachr(value, function (value, key) {
if (value) _this4.once(key, value);
});
break;
/**
Adds a {Task|TaskGroup} instance and configures it from the arguments.
@param {Task|TaskGroup} item - The instance to add.
@param {...*} args - Arguments used to configure the {Task|TaskGroup} instance.
@chainable
@returns {this}
@access public
*/
addItem(item) {
// Prepare
const me = this;
case 'whenDone':
_this4.whenDone(value);
// Only add the item if it exists
if (!item) return null;
break;
// Link our item to ourself
const itemConfig = {
parent: this
};
case 'onceDone':
case 'done':
case 'next':
_this4.done(value);
// Extract
const nestedTaskGroupConfig = this.config.nestedTaskGroupConfig;
const nestedTaskConfig = this.config.nestedTaskConfig;
const emitNestedEvents = this.config.emitNestedEvents;
const isTask = Task.isTask(item);
const isTaskGroup = TaskGroup.isTaskGroup(item);
break;
case 'task':
case 'tasks':
_this4.addTasks(value);
break;
case 'group':
case 'groups':
case 'taskgroup':
case 'taskgroups':
_this4.addTaskGroups(value);
break;
case 'item':
case 'items':
_this4.addItems(value);
break;
case 'onError':
case 'pauseOnError':
case 'includeInResults':
case 'sync':
case 'timeout':
case 'exit':
case 'nestedConfig':
throw new Error("Deprecated configuration property [".concat(key, "] given to TaskGroup::setConfig()"));
default:
_this4.config[key] = value;
break;
}
}); // Chain
// Check
if (!isTask && !isTaskGroup) {
const error = new Error('Unknown item type');
this.emit('error', error);
return this;
}
/**
Merge passed configuration into {config.nestedTaskConfig}.
@param {Object} opts - The configuration to merge.
@chainable
@returns {this}
@access public
*/
}, {
key: "setNestedTaskConfig",
value: function setNestedTaskConfig(opts) {
// Fetch and copy options to the state's nested task configuration
extendr.deep(this.state.nestedTaskConfig, opts); // Chain
// Nested configuration
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
if (isTask) item.setConfig(itemConfig, nestedTaskConfig, ...args);else if (isTaskGroup) item.setConfig(itemConfig, {
nestedTaskConfig,
nestedTaskGroupConfig
}, nestedTaskGroupConfig, ...args);
return this;
// Name default
// @todo perhaps this can come after item.add emissions, in case the user wants to set the item name there,
// however that is signficant complexity to test, so for now won't bother
if (!item.config.name) {
item.config.name = `${item.type} ${this.totalItems + 1} for [${this.name}]`;
}
/**
Merge passed configuration into {config.nestedTaskGroupConfig}.
@param {Object} opts - The configuration to merge.
@chainable
@returns {this}
@access public
*/
}, {
key: "setNestedTaskGroupConfig",
value: function setNestedTaskGroupConfig(opts) {
// Fetch and copy options to the state's nested configuration
extendr.deep(this.state.nestedTaskGroupConfig, opts); // Chain
// Store Result Default
// if the item is undecided, then inherit from our decision
// @todo perhaps this can come after item.add emissions, in case the user wants to set the item name there,
// however that is signficant complexity to test, so for now won't bother
if (item.config.storeResult == null) {
item.config.storeResult = this.config.storeResult;
}
return this;
} // ===================================
// Items
// ---------------------------------
// TaskGroup Method
// Add the item
this.state.itemsRemaining.push(item);
/**
Prepare the method and it's configuration, and add it as a task to be executed.
@param {Function} method - The function we want to execute as the method of this TaskGroup.
@param {Object} opts - Optional configuration for the task to be created for the method.
@chainable
@returns {this}
@access private
*/
// When the item completes, update our state
item.done(this.itemDoneCallbackUpdateState.bind(this, item));
}, {
key: "addMethod",
value: function addMethod(method) {
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
method = unbounded.binder.call(method, this); // run the taskgroup method on the group, rather than itself
// Bubble the nested events if desired
if (emitNestedEvents) {
item.events.forEach(function (event) {
item.on(event, function () {
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
if (isTask) me.emit(`task.${event}`, item, ...args);else if (isTaskGroup) me.emit(`task.${event}`, item, ...args);
me.emit(`item.${event}`, item, ...args);
});
});
}
method.isTaskGroupMethod = true;
if (!opts.name) opts.name = 'taskgroup method for ' + this.name;
if (!opts.args) opts.args = [this.addTaskGroup.bind(this), this.addTask.bind(this)];
if (opts.storeResult == null) opts.storeResult = false; // by default, hide result for methods
// Emit
if (isTask) this.emit('task.add', item);else if (isTaskGroup) this.emit('group.add', item);
this.emit('item.add', item);
this.addTask(method, opts);
return this;
} // ---------------------------------
// Add Item
// When the item completes, after user events have fired, continue with the next state
item.done(this.itemDoneCallbackNextState.bind(this, item));
/**
Adds a {Task|TaskGroup} instance and configures it from the arguments.
@param {Task|TaskGroup} item - The instance to add.
@param {...*} args - Arguments used to configure the {Task|TaskGroup} instance.
@chainable
@returns {this}
@access public
*/
// We may be running and expecting items, if so, fire
// @TODO determine if this should require a new run
this.fire();
}, {
key: "addItem",
value: function addItem(item) {
// Prepare
var me = this; // Only add the item if it exists
// Chain
return this;
}
if (!item) return null; // Link our item to ourself
/**
Adds {Task|TaskGroup} instances and configures them from the arguments.
@param {Array} items - Array of {Task|TaskGroup} instances to add to this task group.
@param {...*} args - Arguments used to configure the {Task|TaskGroup} instances.
@chainable
@returns {this}
@access public
*/
addItems(items) {
for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
args[_key4 - 1] = arguments[_key4];
}
ensureArray(items).forEach(item => this.addItem(item, ...args));
return this;
}
var itemConfig = {
parent: this
}; // Extract
// ---------------------------------
// Add Task
var nestedTaskGroupConfig = this.config.nestedTaskGroupConfig;
var nestedTaskConfig = this.config.nestedTaskConfig;
var emitNestedEvents = this.config.emitNestedEvents;
var isTask = Task.isTask(item);
var isTaskGroup = TaskGroup.isTaskGroup(item); // Check
/**
Creates a {Task} instance and configures it from the arguments.
If the first argument is already a {Task} instance, then we configure it with the remaining arguments, instead of creating a new {Task} instance.
@param {...*} args - Arguments used to configure the {Task} instance.
@return {Task}
@access public
*/
createTask() {
// Prepare
let task;
if (!isTask && !isTaskGroup) {
var error = new Error('Unknown item type');
this.emit('error', error);
return this;
} // Nested configuration
// Support receiving an existing task instance
for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
args[_key5] = arguments[_key5];
}
if (Task.isTask(args[0])) {
task = args[0];
task.setConfig(...args.slice(1));
}
// Support receiving arguments to create a task instance
else {
task = new this.Task(...args);
}
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
// Return the new task
return task;
}
if (isTask) item.setConfig.apply(item, [itemConfig, nestedTaskConfig].concat(args));else if (isTaskGroup) item.setConfig.apply(item, [itemConfig, {
nestedTaskConfig: nestedTaskConfig,
nestedTaskGroupConfig: nestedTaskGroupConfig
}, nestedTaskGroupConfig].concat(args)); // Name default
// @todo perhaps this can come after item.add emissions, in case the user wants to set the item name there,
// however that is signficant complexity to test, so for now won't bother
/**
Adds a {Task} instance and configures it from the arguments.
If a {Task} instance is not supplied, a {Task} instance is created from the arguments.
@param {...*} args - Arguments used to configure the {Task} instance.
@chainable
@returns {this}
@access public
*/
addTask() {
const task = this.createTask(...arguments);
this.addItem(task);
return this;
}
if (!item.config.name) {
item.config.name = "".concat(item.type, " ").concat(this.totalItems + 1, " for [").concat(this.name, "]");
} // Store Result Default
// if the item is undecided, then inherit from our decision
// @todo perhaps this can come after item.add emissions, in case the user wants to set the item name there,
// however that is signficant complexity to test, so for now won't bother
/**
Adds {Task} instances and configures them from the arguments.
@param {Array} items - Array of {Task} instances to add to this task group.
@param {...*} args - Arguments used to configure the {Task} instances.
@chainable
@returns {this}
@access public
*/
addTasks(items) {
for (var _len6 = arguments.length, args = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) {
args[_key6 - 1] = arguments[_key6];
}
ensureArray(items).forEach(item => this.addTask(item, ...args));
return this;
}
// ---------------------------------
// Add Group
if (item.config.storeResult == null) {
item.config.storeResult = this.config.storeResult;
} // Add the item
/**
Creates a {TaskGroup} instance and configures it from the arguments.
If the first argument is already a {TaskGroup} instance, then we configure it with the remaining arguments, instead of creating a new {TaskGroup} instance.
@param {...*} args - Arguments used to configure the {TaskGroup} instance.
@return {TaskGroup}
@access public
*/
createTaskGroup() {
// Prepare
let group;
// Support receiving an existing group instance
for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
args[_key7] = arguments[_key7];
}
if (TaskGroup.isTaskGroup(args[0])) {
group = args[0];
group.setConfig(...args.slice(1));
}
this.state.itemsRemaining.push(item); // When the item completes, update our state
// Support receiving arguments to create a group instance
else {
group = new this.TaskGroup(...args);
}
item.done(this.itemDoneCallbackUpdateState.bind(this, item)); // Bubble the nested events if desired
// Return the new group
return group;
}
if (emitNestedEvents) {
item.events.forEach(function (event) {
item.on(event, function () {
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
/**
Adds a {TaskGroup} instance and configures it from the arguments.
If a {TaskGroup} instance is not supplied, a {TaskGroup} instance is created from the arguments.
@param {...*} args - Arguments used to configure the {TaskGroup} instance.
@chainable
@returns {this}
@access public
*/
addTaskGroup() {
const group = this.createTaskGroup(...arguments);
this.addItem(group);
return this;
}
if (isTask) me.emit.apply(me, ["task.".concat(event), item].concat(args));else if (isTaskGroup) me.emit.apply(me, ["task.".concat(event), item].concat(args));
me.emit.apply(me, ["item.".concat(event), item].concat(args));
});
});
} // Emit
if (isTask) this.emit('task.add', item);else if (isTaskGroup) this.emit('group.add', item);
this.emit('item.add', item); // When the item completes, after user events have fired, continue with the next state
item.done(this.itemDoneCallbackNextState.bind(this, item)); // We may be running and expecting items, if so, fire
// @TODO determine if this should require a new run
this.fire(); // Chain
return this;
/**
Adds {TaskGroup} instances and configures them from the arguments.
@param {Array} items - Array of {TaskGroup} instances to add to this task group.
@param {...*} args - Arguments used to configure the {TaskGroup} instances.
@chainable
@returns {this}
@access public
*/
addTaskGroups(items) {
for (var _len8 = arguments.length, args = new Array(_len8 > 1 ? _len8 - 1 : 0), _key8 = 1; _key8 < _len8; _key8++) {
args[_key8 - 1] = arguments[_key8];
}
/**
Adds {Task|TaskGroup} instances and configures them from the arguments.
@param {Array} items - Array of {Task|TaskGroup} instances to add to this task group.
@param {...*} args - Arguments used to configure the {Task|TaskGroup} instances.
@chainable
@returns {this}
@access public
*/
ensureArray(items).forEach(item => this.addTaskGroup(item, ...args));
return this;
}
}, {
key: "addItems",
value: function addItems(items) {
var _this5 = this;
// ===================================
// Workflow
for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
args[_key4 - 1] = arguments[_key4];
}
/**
Fire the next items.
@return {Array|false} Either an {Array} of items that were fired or `false` if no items were fired.
@access private
*/
fireNextItems() {
// Prepare
const items = [];
ensureArray(items).forEach(function (item) {
return _this5.addItem.apply(_this5, [item].concat(args));
});
return this;
} // ---------------------------------
// Add Task
/**
Creates a {Task} instance and configures it from the arguments.
If the first argument is already a {Task} instance, then we configure it with the remaining arguments, instead of creating a new {Task} instance.
@param {...*} args - Arguments used to configure the {Task} instance.
@return {Task}
@access public
*/
}, {
key: "createTask",
value: function createTask() {
// Prepare
var task; // Support receiving an existing task instance
for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
args[_key5] = arguments[_key5];
// Fire the next items
/* eslint no-constant-condition:0 */
while (true) {
const item = this.fireNextItem();
if (item) {
items.push(item);
} else {
break;
}
if (Task.isTask(args[0])) {
var _task;
task = args[0];
(_task = task).setConfig.apply(_task, _toConsumableArray(args.slice(1)));
} // Support receiving arguments to create a task instance
else {
task = _construct(this.Task, args);
} // Return the new task
return task;
}
/**
Adds a {Task} instance and configures it from the arguments.
If a {Task} instance is not supplied, a {Task} instance is created from the arguments.
@param {...*} args - Arguments used to configure the {Task} instance.
@chainable
@returns {this}
@access public
*/
}, {
key: "addTask",
value: function addTask() {
var task = this.createTask.apply(this, arguments);
this.addItem(task);
return this;
}
/**
Adds {Task} instances and configures them from the arguments.
@param {Array} items - Array of {Task} instances to add to this task group.
@param {...*} args - Arguments used to configure the {Task} instances.
@chainable
@returns {this}
@access public
*/
// Return the items or false if no items
const result = items.length !== 0 ? items : false;
return result;
}
}, {
key: "addTasks",
value: function addTasks(items) {
var _this6 = this;
/**
Fire the next item.
@return {Task|TaskGroup|false} Either the {Task|TaskGroup} item that was fired or `false` if no item was fired.
@access private
*/
fireNextItem() {
// Prepare
let result = false;
for (var _len6 = arguments.length, args = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) {
args[_key6 - 1] = arguments[_key6];
}
// Can we run the next item?
if (this.shouldFire) {
// Fire the next item
ensureArray(items).forEach(function (item) {
return _this6.addTask.apply(_this6, [item].concat(args));
});
return this;
} // ---------------------------------
// Add Group
/**
Creates a {TaskGroup} instance and configures it from the arguments.
If the first argument is already a {TaskGroup} instance, then we configure it with the remaining arguments, instead of creating a new {TaskGroup} instance.
@param {...*} args - Arguments used to configure the {TaskGroup} instance.
@return {TaskGroup}
@access public
*/
}, {
key: "createTaskGroup",
value: function createTaskGroup() {
// Prepare
var group; // Support receiving an existing group instance
for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
args[_key7] = arguments[_key7];
// Update our status and notify our listeners
if (this.state.status !== 'running') {
this.state.status = 'running';
this.emit('running');
}
if (TaskGroup.isTaskGroup(args[0])) {
var _group;
// Get the next item and bump the running count
const item = this.state.itemsRemaining.shift();
++this.state.itemsExecutingCount;
item.run();
group = args[0];
// Return the item
result = item;
}
(_group = group).setConfig.apply(_group, _toConsumableArray(args.slice(1)));
} // Support receiving arguments to create a group instance
else {
group = _construct(this.TaskGroup, args);
} // Return the new group
// Return
return result;
}
/**
What to do when an item is done. Run before user events.
@chainable
@returns {this}
@param {Task|TaskGroup} item - The item that has completed
@param {...*} args - The arguments that the item completed with.
@access private
*/
itemDoneCallbackUpdateState(item) {
// Prepare
const result = this.state.result;
return group;
// Update error if it exists
for (var _len9 = arguments.length, args = new Array(_len9 > 1 ? _len9 - 1 : 0), _key9 = 1; _key9 < _len9; _key9++) {
args[_key9 - 1] = arguments[_key9];
}
/**
Adds a {TaskGroup} instance and configures it from the arguments.
If a {TaskGroup} instance is not supplied, a {TaskGroup} instance is created from the arguments.
@param {...*} args - Arguments used to configure the {TaskGroup} instance.
@chainable
@returns {this}
@access public
*/
}, {
key: "addTaskGroup",
value: function addTaskGroup() {
var group = this.createTaskGroup.apply(this, arguments);
this.addItem(group);
return this;
if (this.config.abortOnError && args[0]) {
if (!this.state.error) {
this.state.error = args[0];
}
}
/**
Adds {TaskGroup} instances and configures them from the arguments.
@param {Array} items - Array of {TaskGroup} instances to add to this task group.
@param {...*} args - Arguments used to configure the {TaskGroup} instances.
@chainable
@returns {this}
@access public
*/
}, {
key: "addTaskGroups",
value: function addTaskGroups(items) {
var _this7 = this;
for (var _len8 = arguments.length, args = new Array(_len8 > 1 ? _len8 - 1 : 0), _key8 = 1; _key8 < _len8; _key8++) {
args[_key8 - 1] = arguments[_key8];
}
ensureArray(items).forEach(function (item) {
return _this7.addTaskGroup.apply(_this7, [item].concat(args));
});
return this;
} // ===================================
// Workflow
/**
Fire the next items.
@return {Array|false} Either an {Array} of items that were fired or `false` if no items were fired.
@access private
*/
}, {
key: "fireNextItems",
value: function fireNextItems() {
// Prepare
var items = []; // Fire the next items
/* eslint no-constant-condition:0 */
while (true) {
var item = this.fireNextItem();
if (item) {
items.push(item);
} else {
break;
}
} // Return the items or false if no items
var result = items.length !== 0 ? items : false;
return result;
// Add the result if desired
if (this.storeResult && item.storeResult) {
result.push(args);
}
/**
Fire the next item.
@return {Task|TaskGroup|false} Either the {Task|TaskGroup} item that was fired or `false` if no item was fired.
@access private
*/
}, {
key: "fireNextItem",
value: function fireNextItem() {
// Prepare
var result = false; // Can we run the next item?
// Mark that one less item is running and one more item done
--this.state.itemsExecutingCount;
++this.state.itemsDoneCount;
if (this.shouldFire) {
// Fire the next item
// Update our status and notify our listeners
if (this.state.status !== 'running') {
this.state.status = 'running';
this.emit('running');
} // Get the next item and bump the running count
// Chain
return this;
}
var item = this.state.itemsRemaining.shift();
++this.state.itemsExecutingCount;
item.run(); // Return the item
result = item;
} // Return
return result;
/**
What to do when an item is done. Run after user events.
@chainable
@returns {this}
@param {Task|TaskGroup} item - The item that has completed
@access private
*/
itemDoneCallbackNextState(item) {
// As we no longer have any use for this item, as it has completed, destroy the item if desired
if (this.config.destroyDoneItems) {
item.destroy();
}
/**
What to do when an item is done. Run before user events.
@chainable
@returns {this}
@param {Task|TaskGroup} item - The item that has completed
@param {...*} args - The arguments that the item completed with.
@access private
*/
}, {
key: "itemDoneCallbackUpdateState",
value: function itemDoneCallbackUpdateState(item) {
// Prepare
var result = this.state.result; // Update error if it exists
// Fire
this.fire();
for (var _len9 = arguments.length, args = new Array(_len9 > 1 ? _len9 - 1 : 0), _key9 = 1; _key9 < _len9; _key9++) {
args[_key9 - 1] = arguments[_key9];
}
// Chain
return this;
}
if (this.config.abortOnError && args[0]) {
if (!this.state.error) {
this.state.error = args[0];
}
} // Add the result if desired
/**
Set our task to the completed state.
@NOTE This doesn't have to be a separate method, it could just go inside `fire` however, it is nice to have here to keep `fire` simple
@chainable
@returns {this}
@access private
*/
finish() {
// Set and emmit the appropriate status for our error or non-error
const error = this.state.error;
const status = error ? 'failed' : 'passed';
this.state.status = status;
this.emit(status, error);
// Notity our listners we have completed
const args = [error];
if (this.state.result) args.push(this.state.result);
this.emit('completed', ...args);
if (this.storeResult && item.storeResult) {
result.push(args);
} // Mark that one less item is running and one more item done
// Prevent the error from persisting
this.state.error = null;
--this.state.itemsExecutingCount;
++this.state.itemsDoneCount; // Chain
return this;
// Destroy if desired
if (this.config.destroyOnceDone) {
this.destroy();
}
/**
What to do when an item is done. Run after user events.
@chainable
@returns {this}
@param {Task|TaskGroup} item - The item that has completed
@access private
*/
}
}, {
key: "itemDoneCallbackNextState",
value: function itemDoneCallbackNextState(item) {
// As we no longer have any use for this item, as it has completed, destroy the item if desired
if (this.config.destroyDoneItems) {
item.destroy();
} // Fire
/**
@NOTE Perhaps at some point, we can add abort/exit functionality, but these things have to be considered:
What will happen to currently running items?
What will happen to remaining items?
Should it be two methods? .halt() and .abort(error?)
Should it be a state?
Should it alter the state?
Should it clear or destroy?
What is the definition of pausing with this?
Perhaps we need to update the definition of pausing to be halted instead?
How can we apply this to Task and TaskGroup consistently?
@access private
@returns {void}
*/
abort() {
throw new Error('not yet implemented');
}
/**
Destroy ourself and prevent ourself from executing ever again.
@chainable
@returns {this}
@access public
*/
destroy() {
// Update our status and notify our listeners
this.state.status = 'destroyed';
this.emit('destroyed');
this.fire(); // Chain
// Clear remaining items to prevent them from running
this.clearRemaining();
return this;
}
/**
Set our task to the completed state.
@NOTE This doesn't have to be a separate method, it could just go inside `fire` however, it is nice to have here to keep `fire` simple
@chainable
@returns {this}
@access private
*/
// Clear result
this.resetResult();
}, {
key: "finish",
value: function finish() {
// Set and emmit the appropriate status for our error or non-error
var error = this.state.error;
var status = error ? 'failed' : 'passed';
this.state.status = status;
this.emit(status, error); // Notity our listners we have completed
// Remove listeners
this.removeAllListeners();
var args = [error];
if (this.state.result) args.push(this.state.result);
this.emit.apply(this, ['completed'].concat(args)); // Prevent the error from persisting
// Chain
return this;
}
this.state.error = null; // Destroy if desired
/**
Internal: Either execute the reamining items we are not paused, or complete execution by exiting.
@chainable
@returns {this}
@access private
*/
fire() {
// Have we started are not destroyed?
if (this.started && this.state.status !== 'destroyed') {
// Check if we are complete, if so, exit
if (this.completed) {
// Finish up
this.finish();
}
if (this.config.destroyOnceDone) {
this.destroy();
// Otherwise continue firing items if we are wanting to pause
else if (!this.shouldPause) {
this.fireNextItems();
}
}
/**
@NOTE Perhaps at some point, we can add abort/exit functionality, but these things have to be considered:
What will happen to currently running items?
What will happen to remaining items?
Should it be two methods? .halt() and .abort(error?)
Should it be a state?
Should it alter the state?
Should it clear or destroy?
What is the definition of pausing with this?
Perhaps we need to update the definition of pausing to be halted instead?
How can we apply this to Task and TaskGroup consistently?
@access private
@returns {void}
*/
}, {
key: "abort",
value: function abort() {
throw new Error('not yet implemented');
}
/**
Destroy ourself and prevent ourself from executing ever again.
@chainable
@returns {this}
@access public
*/
// Chain
return this;
}
}, {
key: "destroy",
value: function destroy() {
// Update our status and notify our listeners
this.state.status = 'destroyed';
this.emit('destroyed'); // Clear remaining items to prevent them from running
this.clearRemaining(); // Clear result
this.resetResult(); // Remove listeners
this.removeAllListeners(); // Chain
/**
Start/restart/resume the execution of the TaskGroup.
@chainable
@returns {this}
@access public
*/
run() {
// Prevent running on destroy
if (this.state.status === 'destroyed') {
const error = new Error(`Invalid run status for the TaskGroup [${this.names}], it was [${this.state.status}].`);
this.emit('error', error);
return this;
}
/**
Internal: Either execute the reamining items we are not paused, or complete execution by exiting.
@chainable
@returns {this}
@access private
*/
}, {
key: "fire",
value: function fire() {
// Have we started are not destroyed?
if (this.started && this.state.status !== 'destroyed') {
// Check if we are complete, if so, exit
if (this.completed) {
// Finish up
this.finish();
} // Otherwise continue firing items if we are wanting to pause
else if (!this.shouldPause) {
this.fireNextItems();
}
} // Chain
// Put it into pending state
this.state.status = 'pending';
this.emit('pending');
return this;
// Prepare result, if it doesn't exist
if (this.storeResult && this.state.result == null) {
this.state.result = [];
}
/**
Start/restart/resume the execution of the TaskGroup.
@chainable
@returns {this}
@access public
*/
}, {
key: "run",
value: function run() {
var _this8 = this;
// Queue the actual running so we can give time for the listeners to complete before continuing
queue(() => this.fire());
// Prevent running on destroy
if (this.state.status === 'destroyed') {
var error = new Error("Invalid run status for the TaskGroup [".concat(this.names, "], it was [").concat(this.state.status, "]."));
this.emit('error', error);
return this;
} // Put it into pending state
// Chain
return this;
}
}
this.state.status = 'pending';
this.emit('pending'); // Prepare result, if it doesn't exist
if (this.storeResult && this.state.result == null) {
this.state.result = [];
} // Queue the actual running so we can give time for the listeners to complete before continuing
queue(function () {
return _this8.fire();
}); // Chain
return this;
}
}], [{
key: "isTaskGroup",
value: function isTaskGroup(group) {
return group && group.type === 'taskgroup' || group instanceof this;
}
}]);
return TaskGroup;
}(BaseInterface); // Export
// Export
module.exports = {
TaskGroup: TaskGroup
TaskGroup
};
/* eslint no-extra-parens:0 */
'use strict'; // Domains are crippled in the browser and on node 0.8, so don't use domains in those environments
'use strict';
var domain = process.browser || process.versions.node.substr(0, 3) === '0.8' ? null : require('domain'); // Cross-platform (node 0.10+, node 0.8+, browser) compatible setImmediate
// Domains are crippled in the browser and on node 0.8, so don't use domains in those environments
const domain = process.browser || process.versions.node.substr(0, 3) === '0.8' ? null : require('domain');
var queue = (global || window).setImmediate || process && process.nextTick || function (fn) {
// Cross-platform (node 0.10+, node 0.8+, browser) compatible setImmediate
const queue = (global || window).setImmediate || process && process.nextTick || function (fn) {
setTimeout(fn, 0);
}; // Convert an error to a string
};
// Convert an error to a string
function errorToString(error) {

@@ -21,16 +23,16 @@ if (!error) {

}
} // Ensure that the passed array is actually an array
}
// Ensure that the passed array is actually an array
function ensureArray(arr) {
if (!Array.isArray(arr)) arr = [arr];
return arr;
} // Exports
}
// Exports
module.exports = {
domain: domain,
queue: queue,
errorToString: errorToString,
ensureArray: ensureArray
domain,
queue,
errorToString,
ensureArray
};

@@ -12,14 +12,92 @@ <!-- LICENSEFILE/ -->

<ul><li><a href="http://spdx.org/licenses/MIT.html">MIT License</a></li></ul>
<ul><li><a href="http://spdx.org/licenses/Artistic-2.0.html">Artistic License 2.0</a></li></ul>
<h2>MIT License</h2>
<h2>The Artistic License 2.0</h2>
<pre>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
Copyright (c) 2000-2006, The Perl Foundation.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Preamble
This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software.
You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement.
Definitions
"Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package.
"Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures.
"You" and "your" means any person who would like to copy, distribute, or modify the Package.
"Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version.
"Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization.
"Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees.
"Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder.
"Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder.
"Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future.
"Source" form means the source code, documentation source, and configuration files for the Package.
"Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form.
Permission for Use and Modification Without Distribution
(1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version.
Permissions for Redistribution of the Standard Version
(2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package.
(3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License.
Distribution of Modified Versions of the Package as Source
(4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following:
(a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version.
(b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version.
(c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under
(i) the Original License or
(ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed.
Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source
(5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license.
(6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version.
Aggregating or Linking the Package
(7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation.
(8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package.
Items That are Not Considered Part of a Modified Version
(9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license.
General Provisions
(10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.
(11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.
(12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.
(13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.
(14) Disclaimer of Warranty:
THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre>
<!-- /LICENSEFILE -->
{
"title": "TaskGroup",
"name": "taskgroup",
"version": "7.19.0",
"version": "7.20.0-next.1698928880.db5de7cfdbe1bb9f2eadd99ee44e3a5dafbce45d",
"description": "Group together synchronous and asynchronous tasks and execute them with support for concurrency, naming, and nesting.",
"homepage": "https://github.com/bevry/taskgroup",
"license": "MIT",
"license": "Artistic-2.0",
"keywords": [

@@ -27,6 +27,5 @@ "async",

"npmdownloads",
"daviddm",
"daviddmdev",
"---",
"githubsponsors",
"thanksdev",
"patreon",

@@ -44,2 +43,3 @@ "flattr",

"githubSponsorsUsername": "balupton",
"thanksdevGithubUsername": "balupton",
"buymeacoffeeUsername": "balupton",

@@ -82,3 +82,3 @@ "cryptoURL": "https://bevry.me/crypto",

{
"description": "ESNext source code for Node.js 10 || 12 || 14 || 16 with Require for modules",
"description": "ESNext source code for Node.js 10 || 12 || 14 || 16 || 18 || 20 || 21 with Require for modules",
"directory": "source",

@@ -93,3 +93,3 @@ "entry": "index.js",

"engines": {
"node": "10 || 12 || 14 || 16",
"node": "10 || 12 || 14 || 16 || 18 || 20 || 21",
"browsers": false

@@ -119,23 +119,23 @@ }

"eachr": "^4.5.0",
"extendr": "^5.19.0",
"unbounded": "^3.14.0"
"extendr": "^5.20.0",
"unbounded": "^3.15.0"
},
"devDependencies": {
"@babel/cli": "^7.14.8",
"@babel/core": "^7.14.8",
"@babel/plugin-proposal-object-rest-spread": "^7.14.7",
"@babel/preset-env": "^7.14.8",
"@bevry/update-contributors": "^1.19.0",
"@babel/cli": "^7.23.0",
"@babel/core": "^7.23.2",
"@babel/plugin-proposal-object-rest-spread": "^7.20.7",
"@babel/preset-env": "^7.23.2",
"@bevry/update-contributors": "^1.22.0",
"assert-helpers": "^8.4.0",
"eslint": "^7.31.0",
"eslint-config-bevry": "^3.27.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"jsdoc": "^3.6.7",
"kava": "^5.15.0",
"prettier": "^2.3.2",
"projectz": "^2.22.0",
"safeps": "^10.17.0",
"surge": "^0.23.0",
"valid-directory": "^3.7.0"
"eslint": "^8.52.0",
"eslint-config-bevry": "^3.28.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.1",
"jsdoc": "^4.0.2",
"kava": "^5.17.0",
"prettier": "^3.0.3",
"projectz": "^2.23.0",
"safeps": "^10.18.0",
"surge": "^0.23.1",
"valid-directory": "^4.0.0"
},

@@ -146,3 +146,3 @@ "scripts": {

"our:compile:edition-browsers": "env BABEL_ENV=edition-browsers babel --out-dir ./edition-browsers ./source",
"our:deploy": "echo no need for this project",
"our:deploy": "printf '%s\n' 'no need for this project'",
"our:meta": "npm run our:meta:contributors && npm run our:meta:docs && npm run our:meta:projectz",

@@ -154,7 +154,7 @@ "our:meta:contributors": "update-contributors",

"our:release": "npm run our:release:prepare && npm run our:release:check-changelog && npm run our:release:check-dirty && npm run our:release:tag && npm run our:release:push",
"our:release:check-changelog": "cat ./HISTORY.md | grep v$npm_package_version || (echo add a changelog entry for v$npm_package_version && exit -1)",
"our:release:check-changelog": "cat ./HISTORY.md | grep \"v$npm_package_version\" || (printf '%s\n' \"add a changelog entry for v$npm_package_version\" && exit -1)",
"our:release:check-dirty": "git diff --exit-code",
"our:release:prepare": "npm run our:clean && npm run our:compile && npm run our:test && npm run our:meta",
"our:release:push": "git push origin && git push origin --tags",
"our:release:tag": "export MESSAGE=$(cat ./HISTORY.md | sed -n \"/## v$npm_package_version/,/##/p\" | sed 's/## //' | awk 'NR>1{print buf}{buf = $0}') && test \"$MESSAGE\" || (echo 'proper changelog entry not found' && exit -1) && git tag v$npm_package_version -am \"$MESSAGE\"",
"our:release:tag": "export MESSAGE=$(cat ./HISTORY.md | sed -n \"/## v$npm_package_version/,/##/p\" | sed 's/## //' | awk 'NR>1{print buf}{buf = $0}') && test \"$MESSAGE\" || (printf '%s\n' 'proper changelog entry not found' && exit -1) && git tag \"v$npm_package_version\" -am \"$MESSAGE\"",
"our:setup": "npm run our:setup:install",

@@ -205,2 +205,2 @@ "our:setup:install": "npm install",

}
}
}

@@ -13,6 +13,5 @@ <!-- TITLE/ -->

<span class="badge-npmdownloads"><a href="https://npmjs.org/package/taskgroup" title="View this project on NPM"><img src="https://img.shields.io/npm/dm/taskgroup.svg" alt="NPM downloads" /></a></span>
<span class="badge-daviddm"><a href="https://david-dm.org/bevry/taskgroup" title="View the status of this project's dependencies on DavidDM"><img src="https://img.shields.io/david/bevry/taskgroup.svg" alt="Dependency Status" /></a></span>
<span class="badge-daviddmdev"><a href="https://david-dm.org/bevry/taskgroup#info=devDependencies" title="View the status of this project's development dependencies on DavidDM"><img src="https://img.shields.io/david/dev/bevry/taskgroup.svg" alt="Dev Dependency Status" /></a></span>
<br class="badge-separator" />
<span class="badge-githubsponsors"><a href="https://github.com/sponsors/balupton" title="Donate to this project using GitHub Sponsors"><img src="https://img.shields.io/badge/github-donate-yellow.svg" alt="GitHub Sponsors donate button" /></a></span>
<span class="badge-thanksdev"><a href="https://thanks.dev/u/gh/balupton" title="Donate to this project using ThanksDev"><img src="https://img.shields.io/badge/thanksdev-donate-yellow.svg" alt="ThanksDev donate button" /></a></span>
<span class="badge-patreon"><a href="https://patreon.com/bevry" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span>

@@ -60,3 +59,3 @@ <span class="badge-flattr"><a href="https://flattr.com/profile/balupton" title="Donate to this project using Flattr"><img src="https://img.shields.io/badge/flattr-donate-yellow.svg" alt="Flattr donate button" /></a></span>

<script type="module">
import * as pkg from '//dev.jspm.io/taskgroup@7.19.0'
import * as pkg from '//dev.jspm.io/taskgroup@7.20.0'
</script>

@@ -70,3 +69,3 @@ ```

<ul><li><code>taskgroup</code> aliases <code>taskgroup/source/index.js</code></li>
<li><code>taskgroup/source/index.js</code> is <a href="https://en.wikipedia.org/wiki/ECMAScript#ES.Next" title="ECMAScript Next">ESNext</a> source code for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 10 || 12 || 14 || 16 with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li>
<li><code>taskgroup/source/index.js</code> is <a href="https://en.wikipedia.org/wiki/ECMAScript#ES.Next" title="ECMAScript Next">ESNext</a> source code for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 10 || 12 || 14 || 16 || 18 || 20 || 21 with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li>
<li><code>taskgroup/edition-browsers/index.js</code> is <a href="https://en.wikipedia.org/wiki/ECMAScript#ES.Next" title="ECMAScript Next">ESNext</a> compiled for web browsers with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li></ul>

@@ -122,2 +121,3 @@

<span class="badge-githubsponsors"><a href="https://github.com/sponsors/balupton" title="Donate to this project using GitHub Sponsors"><img src="https://img.shields.io/badge/github-donate-yellow.svg" alt="GitHub Sponsors donate button" /></a></span>
<span class="badge-thanksdev"><a href="https://thanks.dev/u/gh/balupton" title="Donate to this project using ThanksDev"><img src="https://img.shields.io/badge/thanksdev-donate-yellow.svg" alt="ThanksDev donate button" /></a></span>
<span class="badge-patreon"><a href="https://patreon.com/bevry" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span>

@@ -157,4 +157,4 @@ <span class="badge-flattr"><a href="https://flattr.com/profile/balupton" title="Donate to this project using Flattr"><img src="https://img.shields.io/badge/flattr-donate-yellow.svg" alt="Flattr donate button" /></a></span>

<ul><li><a href="http://spdx.org/licenses/MIT.html">MIT License</a></li></ul>
<ul><li><a href="http://spdx.org/licenses/Artistic-2.0.html">Artistic License 2.0</a></li></ul>
<!-- /LICENSE -->

@@ -308,3 +308,3 @@ /* eslint no-extra-parens:0 func-style:0 */

throw new Error(
`Unknown argument type of [${type}] given to Task::setConfig()`
`Unknown argument type of [${type}] given to Task::setConfig()`,
)

@@ -348,3 +348,3 @@ }

throw new Error(
`Deprecated configuration property [${key}] given to Task::setConfig()`
`Deprecated configuration property [${key}] given to Task::setConfig()`,
)

@@ -451,3 +451,3 @@

const completedError = new Error(
`The task [${this.names}] just completed, but it had already completed earlier, this is unexpected.\nTask Source: ${source}`
`The task [${this.names}] just completed, but it had already completed earlier, this is unexpected.\nTask Source: ${source}`,
)

@@ -501,3 +501,3 @@ this.emit('error', completedError)

const error = new Error(
`The task [${this.names}] failed to run as no method was defined for it.`
`The task [${this.names}] failed to run as no method was defined for it.`,
)

@@ -520,3 +520,3 @@ this.emit('error', error)

const error = new Error(
`The task [${this.names}] failed to run as it requested to use domains but domains are not available.`
`The task [${this.names}] failed to run as it requested to use domains but domains are not available.`,
)

@@ -589,3 +589,3 @@ this.emit('error', error)

const error = new Error(
`Invalid run status for the Task [${this.names}], it was [${this.state.status}] instead of [created].`
`Invalid run status for the Task [${this.names}], it was [${this.state.status}] instead of [created].`,
)

@@ -592,0 +592,0 @@ this.emit('error', error)

@@ -414,3 +414,3 @@ /* eslint no-extra-parens:0 no-warning-comments:0 */

const error = new Error(
'Clearing running items is not possible. Instead remaining items and wait for running items to complete.'
'Clearing running items is not possible. Instead remaining items and wait for running items to complete.',
)

@@ -517,3 +517,3 @@ this.emit('error', error)

throw new Error(
`Unknown argument type of [${type}] given to TaskGroup::setConfig()`
`Unknown argument type of [${type}] given to TaskGroup::setConfig()`,
)

@@ -575,3 +575,3 @@ }

throw new Error(
`Deprecated configuration property [${key}] given to TaskGroup::setConfig()`
`Deprecated configuration property [${key}] given to TaskGroup::setConfig()`,
)

@@ -688,3 +688,3 @@

nestedTaskGroupConfig,
...args
...args,
)

@@ -1084,3 +1084,3 @@

const error = new Error(
`Invalid run status for the TaskGroup [${this.names}], it was [${this.state.status}].`
`Invalid run status for the TaskGroup [${this.names}], it was [${this.state.status}].`,
)

@@ -1087,0 +1087,0 @@ this.emit('error', error)

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc