Update to NPM version
This commit is contained in:
68
ProjectSourceCode/node_modules/spex/lib/adapter.js
generated
vendored
Normal file
68
ProjectSourceCode/node_modules/spex/lib/adapter.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @class PromiseAdapter
|
||||
* @description
|
||||
* Adapter for the primary promise operations.
|
||||
*
|
||||
* Provides compatibility with promise libraries that cannot be recognized automatically,
|
||||
* via functions that implement the primary operations with promises:
|
||||
*
|
||||
* - construct a new promise with a callback function
|
||||
* - resolve a promise with some result data
|
||||
* - reject a promise with a reason
|
||||
*
|
||||
* #### Example
|
||||
*
|
||||
* Below is an example of setting up a [client-side]{@tutorial client} adapter for AngularJS $q.
|
||||
*
|
||||
* ```js
|
||||
* const spexLib = require('spex'); // or include client-side spex.js
|
||||
*
|
||||
* const adapter = new spexLib.PromiseAdapter(
|
||||
* cb => $q(cb), // creating a new promise;
|
||||
* data => $q.when(data), // resolving a promise;
|
||||
* reason => $q.reject(reason) // rejecting a promise;
|
||||
* );
|
||||
*
|
||||
* const spex = spexLib(adapter);
|
||||
* ```
|
||||
*
|
||||
* @param {Function} create
|
||||
* A function that takes a callback parameter and returns a new promise object.
|
||||
* The callback parameter is expected to be `function(resolve, reject)`.
|
||||
*
|
||||
* Passing in anything other than a function will throw `Adapter requires a function to create a promise.`
|
||||
*
|
||||
* @param {Function} resolve
|
||||
* A function that takes an optional data parameter and resolves a promise with it.
|
||||
*
|
||||
* Passing in anything other than a function will throw `Adapter requires a function to resolve a promise.`
|
||||
*
|
||||
* @param {Function} reject
|
||||
* A function that takes an optional error parameter and rejects a promise with it.
|
||||
*
|
||||
* Passing in anything other than a function will throw `Adapter requires a function to reject a promise.`
|
||||
*
|
||||
* @see {@tutorial client}
|
||||
*
|
||||
*/
|
||||
class PromiseAdapter {
|
||||
constructor(create, resolve, reject) {
|
||||
this.create = create;
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
|
||||
if (typeof create !== 'function') {
|
||||
throw new TypeError('Adapter requires a function to create a promise.');
|
||||
}
|
||||
|
||||
if (typeof resolve !== 'function') {
|
||||
throw new TypeError('Adapter requires a function to resolve a promise.');
|
||||
}
|
||||
|
||||
if (typeof reject !== 'function') {
|
||||
throw new TypeError('Adapter requires a function to reject a promise.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PromiseAdapter;
|
||||
173
ProjectSourceCode/node_modules/spex/lib/errors/batch.js
generated
vendored
Normal file
173
ProjectSourceCode/node_modules/spex/lib/errors/batch.js
generated
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
const npm = {
|
||||
u: require('util'),
|
||||
os: require('os'),
|
||||
utils: require('../utils/static')
|
||||
};
|
||||
|
||||
/**
|
||||
* @class errors.BatchError
|
||||
* @augments external:Error
|
||||
* @description
|
||||
* This type represents all errors rejected by method {@link batch}, except for {@link external:TypeError TypeError}
|
||||
* when the method receives invalid input parameters.
|
||||
*
|
||||
* @property {string} name
|
||||
* Standard {@link external:Error Error} property - error type name = `BatchError`.
|
||||
*
|
||||
* @property {string} message
|
||||
* Standard {@link external:Error Error} property - the error message.
|
||||
*
|
||||
* It represents the message of the first error encountered in the batch, and is a safe
|
||||
* version of using `first.message`.
|
||||
*
|
||||
* @property {string} stack
|
||||
* Standard {@link external:Error Error} property - the stack trace.
|
||||
*
|
||||
* @property {array} data
|
||||
* Array of objects `{success, result, [origin]}`:
|
||||
* - `success` = true/false, indicates whether the corresponding value in the input array was resolved.
|
||||
* - `result` = resolved data, if `success`=`true`, or else the rejection reason.
|
||||
* - `origin` - set only when failed as a result of an unsuccessful call into the notification callback
|
||||
* (parameter `cb` of method {@link batch})
|
||||
*
|
||||
* The array has the same size as the input one that was passed into method {@link batch}, providing direct mapping.
|
||||
*
|
||||
* @property {} stat
|
||||
* Resolution Statistics.
|
||||
*
|
||||
* @property {number} stat.total
|
||||
* Total number of elements in the batch.
|
||||
*
|
||||
* @property {number} stat.succeeded
|
||||
* Number of resolved values in the batch.
|
||||
*
|
||||
* @property {number} stat.failed
|
||||
* Number of rejected values in the batch.
|
||||
*
|
||||
* @property {number} stat.duration
|
||||
* Time in milliseconds it took to settle all values.
|
||||
*
|
||||
* @property {} first
|
||||
* The very first error within the batch, with support for nested batch results, it is also the same error
|
||||
* as $[promise.all] would provide.
|
||||
*
|
||||
* @see {@link batch}
|
||||
*
|
||||
*/
|
||||
class BatchError extends Error {
|
||||
|
||||
constructor(result, errors, duration) {
|
||||
|
||||
function getErrors() {
|
||||
const err = new Array(errors.length);
|
||||
for (let i = 0; i < errors.length; i++) {
|
||||
err[i] = result[errors[i]].result;
|
||||
if (err[i] instanceof BatchError) {
|
||||
err[i] = err[i].getErrors();
|
||||
}
|
||||
}
|
||||
npm.utils.extend(err, '$isErrorList', true);
|
||||
return err;
|
||||
}
|
||||
|
||||
const e = getErrors();
|
||||
|
||||
let first = e[0];
|
||||
|
||||
while (first && first.$isErrorList) {
|
||||
first = first[0];
|
||||
}
|
||||
|
||||
let message;
|
||||
|
||||
if (first instanceof Error) {
|
||||
message = first.message;
|
||||
} else {
|
||||
if (typeof first !== 'string') {
|
||||
first = npm.u.inspect(first);
|
||||
}
|
||||
message = first;
|
||||
}
|
||||
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
|
||||
this.data = result;
|
||||
|
||||
// we do not show it within the inspect, because when the error
|
||||
// happens for a nested result, the output becomes a mess.
|
||||
this.first = first;
|
||||
|
||||
this.stat = {
|
||||
total: result.length,
|
||||
succeeded: result.length - e.length,
|
||||
failed: e.length,
|
||||
duration: duration
|
||||
};
|
||||
|
||||
this.getErrors = getErrors;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @method errors.BatchError.getErrors
|
||||
* @description
|
||||
* Returns the complete list of errors only.
|
||||
*
|
||||
* It supports nested batch results, presented as a sub-array.
|
||||
*
|
||||
* @returns {array}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @method errors.BatchError.toString
|
||||
* @description
|
||||
* Creates a well-formatted multi-line string that represents the error.
|
||||
*
|
||||
* It is called automatically when writing the object into the console.
|
||||
*
|
||||
* The output is an abbreviated version of the error, because the complete error
|
||||
* is often too much for displaying or even logging, as a batch can be of any size.
|
||||
* Therefore, only errors are rendered from the `data` property, alongside their indexes,
|
||||
* and only up to the first 5, to avoid polluting the screen or the log file.
|
||||
*
|
||||
* @param {number} [level=0]
|
||||
* Nested output level, to provide visual offset.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
BatchError.prototype.toString = function (level) {
|
||||
level = level > 0 ? parseInt(level) : 0;
|
||||
const gap0 = npm.utils.messageGap(level),
|
||||
gap1 = npm.utils.messageGap(level + 1),
|
||||
gap2 = npm.utils.messageGap(level + 2),
|
||||
lines = [
|
||||
'BatchError {',
|
||||
gap1 + 'stat: { total: ' + this.stat.total + ', succeeded: ' + this.stat.succeeded +
|
||||
', failed: ' + this.stat.failed + ', duration: ' + this.stat.duration + ' }',
|
||||
gap1 + 'errors: ['
|
||||
];
|
||||
|
||||
// In order to avoid polluting the error log or the console,
|
||||
// we limit the log output to the top 5 errors:
|
||||
const maxErrors = 5;
|
||||
let counter = 0;
|
||||
this.data.forEach((d, index) => {
|
||||
if (!d.success && counter < maxErrors) {
|
||||
lines.push(gap2 + index + ': ' + npm.utils.formatError(d.result, level + 2));
|
||||
counter++;
|
||||
}
|
||||
});
|
||||
lines.push(gap1 + ']');
|
||||
lines.push(gap0 + '}');
|
||||
return lines.join(npm.os.EOL);
|
||||
};
|
||||
|
||||
npm.utils.addInspection(BatchError, function () {
|
||||
return this.toString();
|
||||
});
|
||||
|
||||
module.exports = {BatchError};
|
||||
|
||||
36
ProjectSourceCode/node_modules/spex/lib/errors/index.js
generated
vendored
Normal file
36
ProjectSourceCode/node_modules/spex/lib/errors/index.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
const {BatchError} = require('./batch');
|
||||
const {PageError} = require('./page');
|
||||
const {SequenceError} = require('./sequence');
|
||||
|
||||
|
||||
/**
|
||||
* @namespace errors
|
||||
* @description
|
||||
* Namespace for all custom error types supported by the library.
|
||||
*
|
||||
* In addition to the custom error type used by each method (regular error), they can also reject with
|
||||
* {@link external:TypeError TypeError} when receiving invalid input parameters.
|
||||
*
|
||||
* @property {function} BatchError
|
||||
* {@link errors.BatchError BatchError} class.
|
||||
*
|
||||
* Represents regular errors that can be reported by method {@link batch}.
|
||||
*
|
||||
* @property {function} PageError
|
||||
* {@link errors.PageError PageError} class.
|
||||
*
|
||||
* Represents regular errors that can be reported by method {@link page}.
|
||||
*
|
||||
* @property {function} SequenceError
|
||||
* {@link errors.SequenceError SequenceError} class.
|
||||
*
|
||||
* Represents regular errors that can be reported by method {@link sequence}.
|
||||
*
|
||||
*/
|
||||
module.exports = {
|
||||
BatchError,
|
||||
PageError,
|
||||
SequenceError
|
||||
};
|
||||
|
||||
Object.freeze(module.exports);
|
||||
135
ProjectSourceCode/node_modules/spex/lib/errors/page.js
generated
vendored
Normal file
135
ProjectSourceCode/node_modules/spex/lib/errors/page.js
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
const npm = {
|
||||
u: require('util'),
|
||||
os: require('os'),
|
||||
utils: require('../utils/static')
|
||||
};
|
||||
|
||||
const errorReasons = {
|
||||
0: 'Page with index %d rejected.',
|
||||
1: 'Source %s returned a rejection at index %d.',
|
||||
2: 'Source %s threw an error at index %d.',
|
||||
3: 'Destination %s returned a rejection at index %d.',
|
||||
4: 'Destination %s threw an error at index %d.',
|
||||
5: 'Source %s returned a non-array value at index %d.'
|
||||
};
|
||||
|
||||
/**
|
||||
* @class errors.PageError
|
||||
* @augments external:Error
|
||||
* @description
|
||||
* This type represents all errors rejected by method {@link page}, except for {@link external:TypeError TypeError}
|
||||
* when the method receives invalid input parameters.
|
||||
*
|
||||
* @property {string} name
|
||||
* Standard {@link external:Error Error} property - error type name = `PageError`.
|
||||
*
|
||||
* @property {string} message
|
||||
* Standard {@link external:Error Error} property - the error message.
|
||||
*
|
||||
* @property {string} stack
|
||||
* Standard {@link external:Error Error} property - the stack trace.
|
||||
*
|
||||
* @property {} error
|
||||
* The error that was thrown, or the rejection reason.
|
||||
*
|
||||
* @property {number} index
|
||||
* Index of the element in the sequence for which the error/rejection occurred.
|
||||
*
|
||||
* @property {number} duration
|
||||
* Duration (in milliseconds) of processing until the error/rejection occurred.
|
||||
*
|
||||
* @property {string} reason
|
||||
* Textual explanation of why the method failed.
|
||||
*
|
||||
* @property {} source
|
||||
* Resolved `data` parameter that was passed into the `source` function.
|
||||
*
|
||||
* It is only set when the error/rejection occurred inside the `source` function.
|
||||
*
|
||||
* @property {} dest
|
||||
* Resolved `data` parameter that was passed into the `dest` function.
|
||||
*
|
||||
* It is only set when the error/rejection occurred inside the `dest` function.
|
||||
*
|
||||
* @see
|
||||
* {@link page},
|
||||
* {@link batch}
|
||||
*
|
||||
*/
|
||||
class PageError extends Error {
|
||||
|
||||
constructor(e, code, cbName, duration) {
|
||||
|
||||
let message;
|
||||
if (e.error instanceof Error) {
|
||||
message = e.error.message;
|
||||
} else {
|
||||
message = e.error;
|
||||
if (typeof message !== 'string') {
|
||||
message = npm.u.inspect(message);
|
||||
}
|
||||
}
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
|
||||
this.index = e.index;
|
||||
this.duration = duration;
|
||||
this.error = e.error;
|
||||
|
||||
if ('source' in e) {
|
||||
this.source = e.source;
|
||||
}
|
||||
|
||||
if ('dest' in e) {
|
||||
this.dest = e.dest;
|
||||
}
|
||||
|
||||
if (code) {
|
||||
cbName = cbName ? ('\'' + cbName + '\'') : '<anonymous>';
|
||||
this.reason = npm.u.format(errorReasons[code], cbName, e.index);
|
||||
} else {
|
||||
this.reason = npm.u.format(errorReasons[code], e.index);
|
||||
}
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @method errors.PageError.toString
|
||||
* @description
|
||||
* Creates a well-formatted multi-line string that represents the error.
|
||||
*
|
||||
* It is called automatically when writing the object into the console.
|
||||
*
|
||||
* @param {number} [level=0]
|
||||
* Nested output level, to provide visual offset.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
PageError.prototype.toString = function (level) {
|
||||
|
||||
level = level > 0 ? parseInt(level) : 0;
|
||||
|
||||
const gap0 = npm.utils.messageGap(level),
|
||||
gap1 = npm.utils.messageGap(level + 1),
|
||||
lines = [
|
||||
'PageError {',
|
||||
gap1 + 'message: ' + JSON.stringify(this.message),
|
||||
gap1 + 'reason: ' + this.reason,
|
||||
gap1 + 'index: ' + this.index,
|
||||
gap1 + 'duration: ' + this.duration
|
||||
];
|
||||
|
||||
lines.push(gap1 + 'error: ' + npm.utils.formatError(this.error, level + 1));
|
||||
lines.push(gap0 + '}');
|
||||
return lines.join(npm.os.EOL);
|
||||
};
|
||||
|
||||
npm.utils.addInspection(PageError, function () {
|
||||
return this.toString();
|
||||
});
|
||||
|
||||
module.exports = {PageError};
|
||||
|
||||
125
ProjectSourceCode/node_modules/spex/lib/errors/sequence.js
generated
vendored
Normal file
125
ProjectSourceCode/node_modules/spex/lib/errors/sequence.js
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
const npm = {
|
||||
u: require('util'),
|
||||
os: require('os'),
|
||||
utils: require('../utils/static')
|
||||
};
|
||||
|
||||
const errorReasons = {
|
||||
0: 'Source %s returned a rejection at index %d.',
|
||||
1: 'Source %s threw an error at index %d.',
|
||||
2: 'Destination %s returned a rejection at index %d.',
|
||||
3: 'Destination %s threw an error at index %d.'
|
||||
};
|
||||
|
||||
/**
|
||||
* @class errors.SequenceError
|
||||
* @augments external:Error
|
||||
* @description
|
||||
* This type represents all errors rejected by method {@link sequence}, except for {@link external:TypeError TypeError}
|
||||
* when the method receives invalid input parameters.
|
||||
*
|
||||
* @property {string} name
|
||||
* Standard {@link external:Error Error} property - error type name = `SequenceError`.
|
||||
*
|
||||
* @property {string} message
|
||||
* Standard {@link external:Error Error} property - the error message.
|
||||
*
|
||||
* @property {string} stack
|
||||
* Standard {@link external:Error Error} property - the stack trace.
|
||||
*
|
||||
* @property {} error
|
||||
* The error that was thrown or the rejection reason.
|
||||
*
|
||||
* @property {number} index
|
||||
* Index of the element in the sequence for which the error/rejection occurred.
|
||||
*
|
||||
* @property {number} duration
|
||||
* Duration (in milliseconds) of processing until the error/rejection occurred.
|
||||
*
|
||||
* @property {string} reason
|
||||
* Textual explanation of why the method failed.
|
||||
*
|
||||
* @property {} source
|
||||
* Resolved `data` parameter that was passed into the `source` function.
|
||||
*
|
||||
* It is only set when the error/rejection occurred inside the `source` function.
|
||||
*
|
||||
* @property {} dest
|
||||
* Resolved `data` parameter that was passed into the `dest` function.
|
||||
*
|
||||
* It is only set when the error/rejection occurred inside the `dest` function.
|
||||
*
|
||||
* @see {@link sequence}
|
||||
*
|
||||
*/
|
||||
class SequenceError extends Error {
|
||||
|
||||
constructor(e, code, cbName, duration) {
|
||||
|
||||
let message;
|
||||
if (e.error instanceof Error) {
|
||||
message = e.error.message;
|
||||
} else {
|
||||
message = e.error;
|
||||
if (typeof message !== 'string') {
|
||||
message = npm.u.inspect(message);
|
||||
}
|
||||
}
|
||||
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
|
||||
this.index = e.index;
|
||||
this.duration = duration;
|
||||
this.error = e.error;
|
||||
|
||||
if ('source' in e) {
|
||||
this.source = e.source;
|
||||
} else {
|
||||
this.dest = e.dest;
|
||||
}
|
||||
|
||||
cbName = cbName ? ('\'' + cbName + '\'') : '<anonymous>';
|
||||
this.reason = npm.u.format(errorReasons[code], cbName, e.index);
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @method errors.SequenceError.toString
|
||||
* @description
|
||||
* Creates a well-formatted multi-line string that represents the error.
|
||||
*
|
||||
* It is called automatically when writing the object into the console.
|
||||
*
|
||||
* @param {number} [level=0]
|
||||
* Nested output level, to provide visual offset.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
SequenceError.prototype.toString = function (level) {
|
||||
|
||||
level = level > 0 ? parseInt(level) : 0;
|
||||
|
||||
const gap0 = npm.utils.messageGap(level),
|
||||
gap1 = npm.utils.messageGap(level + 1),
|
||||
lines = [
|
||||
'SequenceError {',
|
||||
gap1 + 'message: ' + JSON.stringify(this.message),
|
||||
gap1 + 'reason: ' + this.reason,
|
||||
gap1 + 'index: ' + this.index,
|
||||
gap1 + 'duration: ' + this.duration
|
||||
];
|
||||
|
||||
lines.push(gap1 + 'error: ' + npm.utils.formatError(this.error, level + 1));
|
||||
lines.push(gap0 + '}');
|
||||
return lines.join(npm.os.EOL);
|
||||
};
|
||||
|
||||
npm.utils.addInspection(SequenceError, function () {
|
||||
return this.toString();
|
||||
});
|
||||
|
||||
module.exports = {SequenceError};
|
||||
|
||||
151
ProjectSourceCode/node_modules/spex/lib/ext/batch.js
generated
vendored
Normal file
151
ProjectSourceCode/node_modules/spex/lib/ext/batch.js
generated
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
const {BatchError} = require('../errors/batch');
|
||||
|
||||
/**
|
||||
* @method batch
|
||||
* @description
|
||||
* Settles (resolves or rejects) every [mixed value]{@tutorial mixed} in the input array.
|
||||
*
|
||||
* The method resolves with an array of results, the same as the standard $[promise.all],
|
||||
* while providing comprehensive error details in case of a reject, in the form of
|
||||
* type {@link errors.BatchError BatchError}.
|
||||
*
|
||||
* @param {Array} values
|
||||
* Array of [mixed values]{@tutorial mixed} (it can be empty), to be resolved asynchronously, in no particular order.
|
||||
*
|
||||
* Passing in anything other than an array will reject with {@link external:TypeError TypeError} =
|
||||
* `Method 'batch' requires an array of values.`
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* Optional Parameters.
|
||||
*
|
||||
* @param {Function|generator} [options.cb]
|
||||
* Optional callback (or generator) to receive the result for each settled value.
|
||||
*
|
||||
* Callback Parameters:
|
||||
* - `index` = index of the value in the source array
|
||||
* - `success` - indicates whether the value was resolved (`true`), or rejected (`false`)
|
||||
* - `result` = resolved data, if `success`=`true`, or else the rejection reason
|
||||
* - `delay` = number of milliseconds since the last call (`undefined` when `index=0`)
|
||||
*
|
||||
* The function inherits `this` context from the calling method.
|
||||
*
|
||||
* It can optionally return a promise to indicate that notifications are handled asynchronously.
|
||||
* And if the returned promise resolves, it signals a successful handling, while any resolved
|
||||
* data is ignored.
|
||||
*
|
||||
* If the function returns a rejected promise or throws an error, the entire method rejects
|
||||
* with {@link errors.BatchError BatchError} where the corresponding value in property `data`
|
||||
* is set to `{success, result, origin}`:
|
||||
* - `success` = `false`
|
||||
* - `result` = the rejection reason or the error thrown by the notification callback
|
||||
* - `origin` = the original data passed into the callback as object `{success, result}`
|
||||
*
|
||||
* @returns {external:Promise}
|
||||
*
|
||||
* The method resolves with an array of individual resolved results, the same as the standard $[promise.all].
|
||||
* In addition, the array is extended with a hidden read-only property `duration` - number of milliseconds
|
||||
* spent resolving all the data.
|
||||
*
|
||||
* The method rejects with {@link errors.BatchError BatchError} when any of the following occurs:
|
||||
* - one or more values rejected or threw an error while being resolved as a [mixed value]{@tutorial mixed}
|
||||
* - notification callback `cb` returned a rejected promise or threw an error
|
||||
*
|
||||
*/
|
||||
function batch(values, options, config) {
|
||||
|
||||
const $p = config.promise, utils = config.utils;
|
||||
|
||||
if (!Array.isArray(values)) {
|
||||
return $p.reject(new TypeError('Method \'batch\' requires an array of values.'));
|
||||
}
|
||||
|
||||
if (!values.length) {
|
||||
const empty = [];
|
||||
utils.extend(empty, 'duration', 0);
|
||||
return $p.resolve(empty);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
const cb = utils.wrap(options.cb),
|
||||
self = this, start = Date.now();
|
||||
|
||||
return $p((resolve, reject) => {
|
||||
let cbTime, remaining = values.length;
|
||||
const errors = [], result = new Array(remaining);
|
||||
values.forEach((item, i) => {
|
||||
utils.resolve.call(self, item, null, data => {
|
||||
result[i] = data;
|
||||
step(i, true, data);
|
||||
}, reason => {
|
||||
result[i] = {success: false, result: reason};
|
||||
errors.push(i);
|
||||
step(i, false, reason);
|
||||
});
|
||||
});
|
||||
|
||||
function step(idx, pass, data) {
|
||||
if (cb) {
|
||||
const cbNow = Date.now(),
|
||||
cbDelay = idx ? (cbNow - cbTime) : undefined;
|
||||
let cbResult;
|
||||
cbTime = cbNow;
|
||||
try {
|
||||
cbResult = cb.call(self, idx, pass, data, cbDelay);
|
||||
} catch (e) {
|
||||
setError(e);
|
||||
}
|
||||
if (utils.isPromise(cbResult)) {
|
||||
cbResult
|
||||
.then(check)
|
||||
.catch(error => {
|
||||
setError(error);
|
||||
check();
|
||||
});
|
||||
} else {
|
||||
check();
|
||||
}
|
||||
} else {
|
||||
check();
|
||||
}
|
||||
|
||||
function setError(e) {
|
||||
const r = pass ? {success: false} : result[idx];
|
||||
if (pass) {
|
||||
result[idx] = r;
|
||||
errors.push(idx);
|
||||
}
|
||||
r.result = e;
|
||||
r.origin = {success: pass, result: data};
|
||||
}
|
||||
|
||||
function check() {
|
||||
if (!--remaining) {
|
||||
if (errors.length) {
|
||||
errors.sort();
|
||||
if (errors.length < result.length) {
|
||||
for (let i = 0, k = 0; i < result.length; i++) {
|
||||
if (i === errors[k]) {
|
||||
k++;
|
||||
} else {
|
||||
result[i] = {success: true, result: result[i]};
|
||||
}
|
||||
}
|
||||
}
|
||||
reject(new BatchError(result, errors, Date.now() - start));
|
||||
} else {
|
||||
utils.extend(result, 'duration', Date.now() - start);
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
return null; // this dummy return is just to prevent Bluebird warnings;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function (config) {
|
||||
return function (values, options) {
|
||||
return batch.call(this, values, options, config);
|
||||
};
|
||||
};
|
||||
182
ProjectSourceCode/node_modules/spex/lib/ext/page.js
generated
vendored
Normal file
182
ProjectSourceCode/node_modules/spex/lib/ext/page.js
generated
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
const {PageError} = require('../errors/page');
|
||||
|
||||
/**
|
||||
* @method page
|
||||
* @description
|
||||
* Resolves a dynamic sequence of pages/arrays with [mixed values]{@tutorial mixed}.
|
||||
*
|
||||
* The method acquires pages (arrays of [mixed values]{@tutorial mixed}) from the `source` function, one by one,
|
||||
* and resolves each page as a {@link batch}, till no more pages left or an error/reject occurs.
|
||||
*
|
||||
* @param {Function|generator} source
|
||||
* Expected to return a [mixed value]{@tutorial mixed} that resolves with the next page of data (array of [mixed values]{@tutorial mixed}).
|
||||
* Returning or resolving with `undefined` ends the sequence, and the method resolves.
|
||||
*
|
||||
* The function inherits `this` context from the calling method.
|
||||
*
|
||||
* Parameters:
|
||||
* - `index` = index of the page being requested
|
||||
* - `data` = previously returned page, resolved as a {@link batch} (`undefined` when `index=0`)
|
||||
* - `delay` = number of milliseconds since the last call (`undefined` when `index=0`)
|
||||
*
|
||||
* If the function throws an error or returns a rejected promise, the method rejects with
|
||||
* {@link errors.PageError PageError}, which will have property `source` set.
|
||||
*
|
||||
* And if the function returns or resolves with anything other than an array or `undefined`,
|
||||
* the method rejects with the same {@link errors.PageError PageError}, but with `error` set to
|
||||
* `Unexpected data returned from the source.`
|
||||
*
|
||||
* Passing in anything other than a function will reject with {@link external:TypeError TypeError} = `Parameter 'source' must be a function.`
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* Optional Parameters.
|
||||
*
|
||||
* @param {Function|generator} [options.dest]
|
||||
* Optional destination function (or generator), to receive a resolved {@link batch} of data
|
||||
* for each page, process it and respond as required.
|
||||
*
|
||||
* Parameters:
|
||||
* - `index` = page index in the sequence
|
||||
* - `data` = page data resolved as a {@link batch}
|
||||
* - `delay` = number of milliseconds since the last call (`undefined` when `index=0`)
|
||||
*
|
||||
* The function inherits `this` context from the calling method.
|
||||
*
|
||||
* It can optionally return a promise object, if notifications are handled asynchronously.
|
||||
* And if a promise is returned, the method will not request another page from the `source`
|
||||
* function until the promise has been resolved.
|
||||
*
|
||||
* If the function throws an error or returns a rejected promise, the sequence terminates,
|
||||
* and the method rejects with {@link errors.PageError PageError}, which will have property `dest` set.
|
||||
*
|
||||
* @param {Number} [options.limit=0]
|
||||
* Limits the maximum number of pages to be requested from the `source`. If the value is greater
|
||||
* than 0, the method will successfully resolve once the specified limit has been reached.
|
||||
*
|
||||
* When `limit` isn't specified (default), the sequence is unlimited, and it will continue
|
||||
* till one of the following occurs:
|
||||
* - `source` returns or resolves with `undefined` or an invalid value (non-array)
|
||||
* - either `source` or `dest` functions throw an error or return a rejected promise
|
||||
*
|
||||
* @returns {external:Promise}
|
||||
*
|
||||
* When successful, the method resolves with object `{pages, total, duration}`:
|
||||
* - `pages` = number of pages resolved
|
||||
* - `total` = the sum of all page sizes (total number of values resolved)
|
||||
* - `duration` = number of milliseconds consumed by the method
|
||||
*
|
||||
* When the method fails, it rejects with {@link errors.PageError PageError}.
|
||||
*
|
||||
*/
|
||||
function page(source, options, config) {
|
||||
|
||||
const $p = config.promise, spex = config.spex, utils = config.utils;
|
||||
|
||||
if (typeof source !== 'function') {
|
||||
return $p.reject(new TypeError('Parameter \'source\' must be a function.'));
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
source = utils.wrap(source);
|
||||
|
||||
const limit = (options.limit > 0) ? parseInt(options.limit) : 0,
|
||||
dest = utils.wrap(options.dest), self = this, start = Date.now();
|
||||
let request, srcTime, destTime, total = 0;
|
||||
|
||||
return $p((resolve, reject) => {
|
||||
|
||||
function loop(idx) {
|
||||
const srcNow = Date.now(),
|
||||
srcDelay = idx ? (srcNow - srcTime) : undefined;
|
||||
srcTime = srcNow;
|
||||
utils.resolve.call(self, source, [idx, request, srcDelay], value => {
|
||||
if (value === undefined) {
|
||||
success();
|
||||
} else {
|
||||
if (value instanceof Array) {
|
||||
spex.batch(value)
|
||||
.then(data => {
|
||||
request = data;
|
||||
total += data.length;
|
||||
if (dest) {
|
||||
const destNow = Date.now(),
|
||||
destDelay = idx ? (destNow - destTime) : undefined;
|
||||
let destResult;
|
||||
destTime = destNow;
|
||||
try {
|
||||
destResult = dest.call(self, idx, data, destDelay);
|
||||
} catch (err) {
|
||||
fail({
|
||||
error: err,
|
||||
dest: data
|
||||
}, 4, dest.name);
|
||||
return;
|
||||
}
|
||||
if (utils.isPromise(destResult)) {
|
||||
destResult
|
||||
.then(next)
|
||||
.catch(error => {
|
||||
fail({
|
||||
error: error,
|
||||
dest: data
|
||||
}, 3, dest.name);
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
return null; // this dummy return is just to prevent Bluebird warnings;
|
||||
})
|
||||
.catch(error => {
|
||||
fail({
|
||||
error: error
|
||||
}, 0);
|
||||
});
|
||||
} else {
|
||||
fail({
|
||||
error: new Error('Unexpected data returned from the source.'),
|
||||
source: request
|
||||
}, 5, source.name);
|
||||
}
|
||||
}
|
||||
}, (reason, isRej) => {
|
||||
fail({
|
||||
error: reason,
|
||||
source: request
|
||||
}, isRej ? 1 : 2, source.name);
|
||||
});
|
||||
|
||||
function next() {
|
||||
if (limit === ++idx) {
|
||||
success();
|
||||
} else {
|
||||
loop(idx);
|
||||
}
|
||||
return null; // this dummy return is just to prevent Bluebird warnings;
|
||||
}
|
||||
|
||||
function success() {
|
||||
resolve({
|
||||
pages: idx,
|
||||
total: total,
|
||||
duration: Date.now() - start
|
||||
});
|
||||
}
|
||||
|
||||
function fail(reason, code, cbName) {
|
||||
reason.index = idx;
|
||||
reject(new PageError(reason, code, cbName, Date.now() - start));
|
||||
}
|
||||
}
|
||||
|
||||
loop(0);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function (config) {
|
||||
return function (source, options) {
|
||||
return page.call(this, source, options, config);
|
||||
};
|
||||
};
|
||||
194
ProjectSourceCode/node_modules/spex/lib/ext/sequence.js
generated
vendored
Normal file
194
ProjectSourceCode/node_modules/spex/lib/ext/sequence.js
generated
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
const {SequenceError} = require('../errors/sequence');
|
||||
|
||||
/**
|
||||
* @method sequence
|
||||
* @description
|
||||
* Resolves a dynamic sequence of [mixed values]{@tutorial mixed}.
|
||||
*
|
||||
* The method acquires [mixed values]{@tutorial mixed} from the `source` function, one at a time, and resolves them,
|
||||
* till either no more values left in the sequence or an error/reject occurs.
|
||||
*
|
||||
* It supports both [linked and detached sequencing]{@tutorial sequencing}.
|
||||
*
|
||||
* @param {Function|generator} source
|
||||
* Expected to return the next [mixed value]{@tutorial mixed} to be resolved. Returning or resolving
|
||||
* with `undefined` ends the sequence, and the method resolves.
|
||||
*
|
||||
* Parameters:
|
||||
* - `index` = current request index in the sequence
|
||||
* - `data` = resolved data from the previous call (`undefined` when `index=0`)
|
||||
* - `delay` = number of milliseconds since the last call (`undefined` when `index=0`)
|
||||
*
|
||||
* The function inherits `this` context from the calling method.
|
||||
*
|
||||
* If the function throws an error or returns a rejected promise, the sequence terminates,
|
||||
* and the method rejects with {@link errors.SequenceError SequenceError}, which will have property `source` set.
|
||||
*
|
||||
* Passing in anything other than a function will reject with {@link external:TypeError TypeError} = `Parameter 'source' must be a function.`
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* Optional Parameters.
|
||||
*
|
||||
* @param {Function|generator} [options.dest=null]
|
||||
* Optional destination function (or generator), to receive resolved data for each index,
|
||||
* process it and respond as required.
|
||||
*
|
||||
* Parameters:
|
||||
* - `index` = index of the resolved data in the sequence
|
||||
* - `data` = the data resolved
|
||||
* - `delay` = number of milliseconds since the last call (`undefined` when `index=0`)
|
||||
*
|
||||
* The function inherits `this` context from the calling method.
|
||||
*
|
||||
* It can optionally return a promise object, if data processing is done asynchronously.
|
||||
* If a promise is returned, the method will not request another value from the `source` function,
|
||||
* until the promise has been resolved (the resolved value is ignored).
|
||||
*
|
||||
* If the function throws an error or returns a rejected promise, the sequence terminates,
|
||||
* and the method rejects with {@link errors.SequenceError SequenceError}, which will have property `dest` set.
|
||||
*
|
||||
* @param {Number} [options.limit=0]
|
||||
* Limits the maximum size of the sequence. If the value is greater than 0, the method will
|
||||
* successfully resolve once the specified limit has been reached.
|
||||
*
|
||||
* When `limit` isn't specified (default), the sequence is unlimited, and it will continue
|
||||
* till one of the following occurs:
|
||||
* - `source` either returns or resolves with `undefined`
|
||||
* - either `source` or `dest` functions throw an error or return a rejected promise
|
||||
*
|
||||
* @param {Boolean} [options.track=false]
|
||||
* Changes the type of data to be resolved by this method. By default, it is `false`
|
||||
* (see the return result). When set to be `true`, the method tracks/collects all resolved data
|
||||
* into an array internally, and resolves with that array once the method has finished successfully.
|
||||
*
|
||||
* It must be used with caution, as to the size of the sequence, because accumulating data for
|
||||
* a very large sequence can result in consuming too much memory.
|
||||
*
|
||||
* @returns {external:Promise}
|
||||
*
|
||||
* When successful, the resolved data depends on parameter `track`. When `track` is `false`
|
||||
* (default), the method resolves with object `{total, duration}`:
|
||||
* - `total` = number of values resolved by the sequence
|
||||
* - `duration` = number of milliseconds consumed by the method
|
||||
*
|
||||
* When `track` is `true`, the method resolves with an array of all the data that has been resolved,
|
||||
* the same way that the standard $[promise.all] resolves. In addition, the array comes extended with
|
||||
* a hidden read-only property `duration` - number of milliseconds consumed by the method.
|
||||
*
|
||||
* When the method fails, it rejects with {@link errors.SequenceError SequenceError}.
|
||||
*/
|
||||
function sequence(source, options, config) {
|
||||
|
||||
const $p = config.promise, utils = config.utils;
|
||||
|
||||
if (typeof source !== 'function') {
|
||||
return $p.reject(new TypeError('Parameter \'source\' must be a function.'));
|
||||
}
|
||||
|
||||
source = utils.wrap(source);
|
||||
|
||||
options = options || {};
|
||||
|
||||
const limit = (options.limit > 0) ? parseInt(options.limit) : 0,
|
||||
dest = utils.wrap(options.dest),
|
||||
self = this, start = Date.now();
|
||||
let data, srcTime, destTime, result = [];
|
||||
|
||||
return $p((resolve, reject) => {
|
||||
|
||||
function loop(idx) {
|
||||
const srcNow = Date.now(),
|
||||
srcDelay = idx ? (srcNow - srcTime) : undefined;
|
||||
srcTime = srcNow;
|
||||
utils.resolve.call(self, source, [idx, data, srcDelay], (value, delayed) => {
|
||||
data = value;
|
||||
if (data === undefined) {
|
||||
success();
|
||||
} else {
|
||||
if (options.track) {
|
||||
result.push(data);
|
||||
}
|
||||
if (dest) {
|
||||
const destNow = Date.now(),
|
||||
destDelay = idx ? (destNow - destTime) : undefined;
|
||||
let destResult;
|
||||
destTime = destNow;
|
||||
try {
|
||||
destResult = dest.call(self, idx, data, destDelay);
|
||||
} catch (e) {
|
||||
fail({
|
||||
error: e,
|
||||
dest: data
|
||||
}, 3, dest.name);
|
||||
return;
|
||||
}
|
||||
if (utils.isPromise(destResult)) {
|
||||
destResult
|
||||
.then(() => {
|
||||
next(true);
|
||||
return null; // this dummy return is just to prevent Bluebird warnings;
|
||||
})
|
||||
.catch(error => {
|
||||
fail({
|
||||
error: error,
|
||||
dest: data
|
||||
}, 2, dest.name);
|
||||
});
|
||||
} else {
|
||||
next(delayed);
|
||||
}
|
||||
} else {
|
||||
next(delayed);
|
||||
}
|
||||
}
|
||||
}, (reason, isRej) => {
|
||||
fail({
|
||||
error: reason,
|
||||
source: data
|
||||
}, isRej ? 0 : 1, source.name);
|
||||
});
|
||||
|
||||
function next(delayed) {
|
||||
if (limit === ++idx) {
|
||||
success();
|
||||
} else {
|
||||
if (delayed) {
|
||||
loop(idx);
|
||||
} else {
|
||||
$p.resolve()
|
||||
.then(() => {
|
||||
loop(idx);
|
||||
return null; // this dummy return is just to prevent Bluebird warnings;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function success() {
|
||||
const length = Date.now() - start;
|
||||
if (options.track) {
|
||||
utils.extend(result, 'duration', length);
|
||||
} else {
|
||||
result = {
|
||||
total: idx,
|
||||
duration: length
|
||||
};
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
|
||||
function fail(reason, code, cbName) {
|
||||
reason.index = idx;
|
||||
reject(new SequenceError(reason, code, cbName, Date.now() - start));
|
||||
}
|
||||
}
|
||||
|
||||
loop(0);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function (config) {
|
||||
return function (source, options) {
|
||||
return sequence.call(this, source, options, config);
|
||||
};
|
||||
};
|
||||
65
ProjectSourceCode/node_modules/spex/lib/ext/stream/index.js
generated
vendored
Normal file
65
ProjectSourceCode/node_modules/spex/lib/ext/stream/index.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
const npm = {
|
||||
read: require('./read')
|
||||
};
|
||||
|
||||
/**
|
||||
* @namespace stream
|
||||
* @description
|
||||
* Namespace with methods that implement stream operations, and {@link stream.read read} is the only method currently supported.
|
||||
*
|
||||
* **Synchronous Stream Processing**
|
||||
*
|
||||
* ```js
|
||||
* const stream = require('spex')(Promise).stream;
|
||||
* const fs = require('fs');
|
||||
*
|
||||
* const rs = fs.createReadStream('values.txt');
|
||||
*
|
||||
* function receiver(index, data, delay) {
|
||||
* console.log('RECEIVED:', index, data, delay);
|
||||
* }
|
||||
*
|
||||
* stream.read(rs, receiver)
|
||||
* .then(data => {
|
||||
* console.log('DATA:', data);
|
||||
* })
|
||||
* .catch(error => {
|
||||
* console.log('ERROR:', error);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* **Asynchronous Stream Processing**
|
||||
*
|
||||
* ```js
|
||||
* const stream = require('spex')(Promise).stream;
|
||||
* const fs = require('fs');
|
||||
*
|
||||
* const rs = fs.createReadStream('values.txt');
|
||||
*
|
||||
* function receiver(index, data, delay) {
|
||||
* return new Promise(resolve => {
|
||||
* console.log('RECEIVED:', index, data, delay);
|
||||
* resolve();
|
||||
* });
|
||||
* }
|
||||
*
|
||||
* stream.read(rs, receiver)
|
||||
* .then(data => {
|
||||
* console.log('DATA:', data);
|
||||
* })
|
||||
* .catch(error => {
|
||||
* console.log('ERROR:', error);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @property {function} stream.read
|
||||
* Consumes and processes data from a $[Readable] stream.
|
||||
*
|
||||
*/
|
||||
module.exports = function (config) {
|
||||
const res = {
|
||||
read: npm.read(config)
|
||||
};
|
||||
Object.freeze(res);
|
||||
return res;
|
||||
};
|
||||
206
ProjectSourceCode/node_modules/spex/lib/ext/stream/read.js
generated
vendored
Normal file
206
ProjectSourceCode/node_modules/spex/lib/ext/stream/read.js
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
/**
|
||||
* @method stream.read
|
||||
* @description
|
||||
* Consumes and processes data from a $[Readable] stream.
|
||||
*
|
||||
* It reads the entire stream, using either **paused mode** (default), or in chunks (see `options.readChunks`)
|
||||
* with support for both synchronous and asynchronous data processing.
|
||||
*
|
||||
* **NOTE:** Once the method has finished, the onus is on the caller to release the stream
|
||||
* according to its protocol.
|
||||
*
|
||||
* @param {Object} stream
|
||||
* $[Readable] stream object.
|
||||
*
|
||||
* Passing in anything else will throw `Readable stream is required.`
|
||||
*
|
||||
* @param {Function|generator} receiver
|
||||
* Data processing callback (or generator).
|
||||
*
|
||||
* Passing in anything else will throw `Invalid stream receiver.`
|
||||
*
|
||||
* Parameters:
|
||||
* - `index` = index of the call made to the function
|
||||
* - `data` = array of all data reads from the stream's buffer
|
||||
* - `delay` = number of milliseconds since the last call (`undefined` when `index=0`)
|
||||
*
|
||||
* The function is called with the same `this` context as the calling method.
|
||||
*
|
||||
* It can optionally return a promise object, if data processing is asynchronous.
|
||||
* And if a promise is returned, the method will not read data from the stream again,
|
||||
* until the promise has been resolved.
|
||||
*
|
||||
* If the function throws an error or returns a rejected promise, the method rejects
|
||||
* with the same error / rejection reason.
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* Optional Parameters.
|
||||
*
|
||||
* @param {Boolean} [options.closable=false]
|
||||
* Instructs the method to resolve on event `close` supported by the stream, as opposed to event
|
||||
* `end` that's used by default.
|
||||
*
|
||||
* @param {Boolean} [options.readChunks=false]
|
||||
* By default, the method handles event `readable` of the stream to consume data in a simplified form,
|
||||
* item by item. If you enable this option, the method will instead handle event `data` of the stream,
|
||||
* to consume chunks of data.
|
||||
*
|
||||
* @param {Number} [options.readSize]
|
||||
* When the value is greater than 0, it sets the read size from the stream's buffer
|
||||
* when the next data is available. By default, the method uses as few reads as possible
|
||||
* to get all the data currently available in the buffer.
|
||||
*
|
||||
* NOTE: This option is ignored when option `readChunks` is enabled.
|
||||
*
|
||||
* @returns {external:Promise}
|
||||
*
|
||||
* When finished successfully, resolves with object `{calls, reads, length, duration}`:
|
||||
* - `calls` = number of calls made into the `receiver`
|
||||
* - `reads` = number of successful reads from the stream
|
||||
* - `length` = total length for all the data reads from the stream
|
||||
* - `duration` = number of milliseconds consumed by the method
|
||||
*
|
||||
* When it fails, the method rejects with the error/reject specified,
|
||||
* which can happen as a result of:
|
||||
* - event `error` emitted by the stream
|
||||
* - receiver throws an error or returns a rejected promise
|
||||
*/
|
||||
function read(stream, receiver, options, config) {
|
||||
|
||||
const $p = config.promise, utils = config.utils;
|
||||
|
||||
if (!utils.isReadableStream(stream)) {
|
||||
return $p.reject(new TypeError('Readable stream is required.'));
|
||||
}
|
||||
|
||||
if (typeof receiver !== 'function') {
|
||||
return $p.reject(new TypeError('Invalid stream receiver.'));
|
||||
}
|
||||
|
||||
receiver = utils.wrap(receiver);
|
||||
|
||||
options = options || {};
|
||||
|
||||
const readSize = (options.readSize > 0) ? parseInt(options.readSize) : null,
|
||||
self = this, start = Date.now(), receiveEvent = options.readChunks ? 'data' : 'readable';
|
||||
let cbTime, ready, waiting, stop, reads = 0, length = 0, index = 0;
|
||||
|
||||
return $p((resolve, reject) => {
|
||||
|
||||
function onReceive(data) {
|
||||
ready = true;
|
||||
process(data);
|
||||
}
|
||||
|
||||
function onEnd() {
|
||||
if (!options.closable) {
|
||||
success();
|
||||
}
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
success();
|
||||
}
|
||||
|
||||
function onError(error) {
|
||||
fail(error);
|
||||
}
|
||||
|
||||
stream.on(receiveEvent, onReceive);
|
||||
stream.on('end', onEnd);
|
||||
stream.on('close', onClose);
|
||||
stream.on('error', onError);
|
||||
|
||||
function process(data) {
|
||||
if (!ready || stop || waiting) {
|
||||
return;
|
||||
}
|
||||
ready = false;
|
||||
let cache;
|
||||
if (options.readChunks) {
|
||||
cache = data;
|
||||
// istanbul ignore else;
|
||||
// we cannot test the else condition, as it requires a special broken stream interface.
|
||||
if (!Array.isArray(cache)) {
|
||||
cache = [cache];
|
||||
}
|
||||
length += cache.length;
|
||||
reads++;
|
||||
} else {
|
||||
cache = [];
|
||||
waiting = true;
|
||||
let page;
|
||||
do {
|
||||
page = stream.read(readSize);
|
||||
if (page) {
|
||||
cache.push(page);
|
||||
// istanbul ignore next: requires a unique stream that
|
||||
// creates objects without property `length` defined.
|
||||
length += page.length || 0;
|
||||
reads++;
|
||||
}
|
||||
} while (page);
|
||||
|
||||
if (!cache.length) {
|
||||
waiting = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const cbNow = Date.now(),
|
||||
cbDelay = index ? (cbNow - cbTime) : undefined;
|
||||
let result;
|
||||
cbTime = cbNow;
|
||||
try {
|
||||
result = receiver.call(self, index++, cache, cbDelay);
|
||||
} catch (e) {
|
||||
fail(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (utils.isPromise(result)) {
|
||||
result
|
||||
.then(() => {
|
||||
waiting = false;
|
||||
process();
|
||||
return null; // this dummy return is just to prevent Bluebird warnings;
|
||||
})
|
||||
.catch(error => {
|
||||
fail(error);
|
||||
});
|
||||
} else {
|
||||
waiting = false;
|
||||
process();
|
||||
}
|
||||
}
|
||||
|
||||
function success() {
|
||||
cleanup();
|
||||
resolve({
|
||||
calls: index,
|
||||
reads: reads,
|
||||
length: length,
|
||||
duration: Date.now() - start
|
||||
});
|
||||
}
|
||||
|
||||
function fail(error) {
|
||||
stop = true;
|
||||
cleanup();
|
||||
reject(error);
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
stream.removeListener(receiveEvent, onReceive);
|
||||
stream.removeListener('close', onClose);
|
||||
stream.removeListener('error', onError);
|
||||
stream.removeListener('end', onEnd);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function (config) {
|
||||
return function (stream, receiver, options) {
|
||||
return read.call(this, stream, receiver, options, config);
|
||||
};
|
||||
};
|
||||
123
ProjectSourceCode/node_modules/spex/lib/index.js
generated
vendored
Normal file
123
ProjectSourceCode/node_modules/spex/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
const npm = {
|
||||
utils: require('./utils'),
|
||||
batch: require('./ext/batch'),
|
||||
page: require('./ext/page'),
|
||||
sequence: require('./ext/sequence'),
|
||||
stream: require('./ext/stream'),
|
||||
errors: require('./errors')
|
||||
};
|
||||
|
||||
/**
|
||||
* @module spex
|
||||
* @summary Specialized Promise Extensions
|
||||
* @author Vitaly Tomilov
|
||||
*
|
||||
* @description
|
||||
* Attaches to an external promise library and provides additional methods built solely
|
||||
* on the basic promise operations:
|
||||
* - construct a new promise with a callback function
|
||||
* - resolve a promise with some result data
|
||||
* - reject a promise with a reason
|
||||
*
|
||||
* ### usage
|
||||
* For any third-party promise library:
|
||||
* ```js
|
||||
* const promise = require('bluebird');
|
||||
* const spex = require('spex')(promise);
|
||||
* ```
|
||||
* For ES6 promises:
|
||||
* ```js
|
||||
* const spex = require('spex')(Promise);
|
||||
* ```
|
||||
*
|
||||
* @param {Object|Function} promiseLib
|
||||
* Instance of a promise library to be used by this module.
|
||||
*
|
||||
* Some implementations use `Promise` constructor to create a new promise, while
|
||||
* others use the module's function for it. Both types are supported the same.
|
||||
*
|
||||
* Alternatively, an object of type {@link PromiseAdapter} can be passed in, which provides
|
||||
* compatibility with any promise library outside of the standard.
|
||||
*
|
||||
* Passing in a promise library that cannot be recognized will throw
|
||||
* `Invalid promise library specified.`
|
||||
*
|
||||
* @returns {Object}
|
||||
* Namespace with all supported methods.
|
||||
*
|
||||
* @see {@link PromiseAdapter}, {@link batch}, {@link page}, {@link sequence}, {@link stream}
|
||||
*/
|
||||
function main(promiseLib) {
|
||||
|
||||
const spex = {}, // library instance;
|
||||
promise = parsePromiseLib(promiseLib); // promise library parsing;
|
||||
|
||||
const config = {
|
||||
spex: spex,
|
||||
promise: promise,
|
||||
utils: npm.utils(promise)
|
||||
};
|
||||
|
||||
spex.errors = npm.errors;
|
||||
spex.batch = npm.batch(config);
|
||||
spex.page = npm.page(config);
|
||||
spex.sequence = npm.sequence(config);
|
||||
spex.stream = npm.stream(config);
|
||||
|
||||
config.utils.extend(spex, '$p', promise);
|
||||
|
||||
Object.freeze(spex);
|
||||
|
||||
return spex;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// Parses and validates a promise library;
|
||||
function parsePromiseLib(lib) {
|
||||
if (lib) {
|
||||
let promise;
|
||||
if (lib instanceof main.PromiseAdapter) {
|
||||
promise = function (func) {
|
||||
return lib.create(func);
|
||||
};
|
||||
promise.resolve = lib.resolve;
|
||||
promise.reject = lib.reject;
|
||||
return promise;
|
||||
}
|
||||
const t = typeof lib;
|
||||
if (t === 'function' || t === 'object') {
|
||||
const Root = typeof lib.Promise === 'function' ? lib.Promise : lib;
|
||||
promise = function (func) {
|
||||
return new Root(func);
|
||||
};
|
||||
promise.resolve = Root.resolve;
|
||||
promise.reject = Root.reject;
|
||||
if (typeof promise.resolve === 'function' && typeof promise.reject === 'function') {
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new TypeError('Invalid promise library specified.');
|
||||
}
|
||||
|
||||
main.PromiseAdapter = require('./adapter');
|
||||
main.errors = npm.errors;
|
||||
|
||||
Object.freeze(main);
|
||||
|
||||
module.exports = main;
|
||||
|
||||
/**
|
||||
* @external Error
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external TypeError
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external Promise
|
||||
* @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
||||
*/
|
||||
94
ProjectSourceCode/node_modules/spex/lib/utils/index.js
generated
vendored
Normal file
94
ProjectSourceCode/node_modules/spex/lib/utils/index.js
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
const npm = {
|
||||
stat: require('./static')
|
||||
};
|
||||
|
||||
module.exports = function ($p) {
|
||||
|
||||
const exp = {
|
||||
formatError: npm.stat.formatError,
|
||||
isPromise: npm.stat.isPromise,
|
||||
isReadableStream: npm.stat.isReadableStream,
|
||||
messageGap: npm.stat.messageGap,
|
||||
extend: npm.stat.extend,
|
||||
resolve: resolve,
|
||||
wrap: wrap
|
||||
};
|
||||
|
||||
return exp;
|
||||
|
||||
//////////////////////////////////////////
|
||||
// Checks if the function is a generator,
|
||||
// and if so - wraps it up into a promise;
|
||||
function wrap(func) {
|
||||
if (typeof func === 'function') {
|
||||
if (func.constructor.name === 'GeneratorFunction') {
|
||||
return asyncAdapter(func);
|
||||
}
|
||||
return func;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Resolves a mixed value into the actual value,
|
||||
// consistent with the way mixed values are defined:
|
||||
// https://github.com/vitaly-t/spex/wiki/Mixed-Values
|
||||
function resolve(value, params, onSuccess, onError) {
|
||||
|
||||
const self = this;
|
||||
let delayed = false;
|
||||
|
||||
function loop() {
|
||||
while (typeof value === 'function') {
|
||||
if (value.constructor.name === 'GeneratorFunction') {
|
||||
value = asyncAdapter(value);
|
||||
}
|
||||
try {
|
||||
value = params ? value.apply(self, params) : value.call(self);
|
||||
} catch (e) {
|
||||
onError(e, false); // false means 'threw an error'
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (exp.isPromise(value)) {
|
||||
value
|
||||
.then(data => {
|
||||
delayed = true;
|
||||
value = data;
|
||||
loop();
|
||||
return null; // this dummy return is just to prevent Bluebird warnings;
|
||||
})
|
||||
.catch(error => {
|
||||
onError(error, true); // true means 'rejected'
|
||||
});
|
||||
} else {
|
||||
onSuccess(value, delayed);
|
||||
}
|
||||
}
|
||||
|
||||
loop();
|
||||
}
|
||||
|
||||
// Generator-to-Promise adapter;
|
||||
// Based on: https://www.promisejs.org/generators/#both
|
||||
function asyncAdapter(generator) {
|
||||
return function () {
|
||||
const g = generator.apply(this, arguments);
|
||||
|
||||
function handle(result) {
|
||||
if (result.done) {
|
||||
return $p.resolve(result.value);
|
||||
}
|
||||
return $p.resolve(result.value)
|
||||
.then(res => {
|
||||
return handle(g.next(res));
|
||||
}, err => {
|
||||
return handle(g.throw(err));
|
||||
});
|
||||
}
|
||||
|
||||
return handle(g.next());
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
75
ProjectSourceCode/node_modules/spex/lib/utils/static.js
generated
vendored
Normal file
75
ProjectSourceCode/node_modules/spex/lib/utils/static.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
const npm = {
|
||||
stream: require('stream'),
|
||||
util: require('util')
|
||||
};
|
||||
|
||||
/////////////////////////////////////
|
||||
// Checks if the value is a promise;
|
||||
function isPromise(value) {
|
||||
return value && typeof value.then === 'function';
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Checks object for being a readable stream;
|
||||
|
||||
function isReadableStream(obj) {
|
||||
return obj instanceof npm.stream.Stream &&
|
||||
typeof obj._read === 'function' &&
|
||||
typeof obj._readableState === 'object';
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Sets an object property as read-only and non-enumerable.
|
||||
function extend(obj, name, value) {
|
||||
Object.defineProperty(obj, name, {
|
||||
value: value,
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: false
|
||||
});
|
||||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Returns a space gap for console output;
|
||||
function messageGap(level) {
|
||||
return ' '.repeat(level * 4);
|
||||
}
|
||||
|
||||
function formatError(error, level) {
|
||||
const names = ['BatchError', 'PageError', 'SequenceError'];
|
||||
let msg = npm.util.inspect(error);
|
||||
if (error instanceof Error) {
|
||||
if (names.indexOf(error.name) === -1) {
|
||||
const gap = messageGap(level);
|
||||
msg = msg.split('\n').map((line, index) => {
|
||||
return (index ? gap : '') + line;
|
||||
}).join('\n');
|
||||
} else {
|
||||
msg = error.toString(level);
|
||||
}
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Adds prototype inspection, with support of the newer
|
||||
// Custom Inspection, which was added in Node.js 6.x
|
||||
function addInspection(type, cb) {
|
||||
// istanbul ignore next;
|
||||
if (npm.util.inspect.custom) {
|
||||
// Custom inspection is supported:
|
||||
type.prototype[npm.util.inspect.custom] = cb;
|
||||
} else {
|
||||
// Use classic inspection:
|
||||
type.prototype.inspect = cb;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addInspection: addInspection,
|
||||
formatError: formatError,
|
||||
isPromise: isPromise,
|
||||
isReadableStream: isReadableStream,
|
||||
messageGap: messageGap,
|
||||
extend: extend
|
||||
};
|
||||
Reference in New Issue
Block a user