Socket
Socket
Sign inDemoInstall

tapable

Package Overview
Dependencies
0
Maintainers
1
Versions
48
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.0-beta.4 to 1.0.0-beta.5

lib/__tests__/__snapshots__/HookCodeFactory.js.snap

4

lib/__tests__/AsyncParallelHooks.js

@@ -18,3 +18,3 @@ /*

expect(result).toMatchSnapshot();
})
}, 15000)
})

@@ -29,3 +29,3 @@

expect(result).toMatchSnapshot();
})
}, 15000)
})

@@ -204,3 +204,2 @@ /*

result[`${method}InterceptedSyncCalledTap`] = (result[`${method}InterceptedSyncCalledTap`] || 0) + 1
return tap;
},

@@ -338,3 +337,2 @@ })

result[`${method}InterceptedTap1`] = Object.assign({}, tap, { fn: tap.fn.length });
return tap;
}

@@ -349,3 +347,2 @@ });

result[`${method}InterceptedTap2`] = Object.assign({}, tap, { fn: tap.fn.length });
return tap;
}

@@ -871,3 +868,2 @@ });

result[`${type}InterceptedTap1`] = Object.assign({}, tap, { fn: tap.fn.length });
return tap;
}

@@ -882,3 +878,2 @@ });

result[`${type}InterceptedTap2`] = Object.assign({}, tap, { fn: tap.fn.length });
return tap;
}

@@ -890,2 +885,50 @@ });

}
{
const hook = this.createHook(["a", "b", "c"], `${type}ContextIntercepted`);
hook.intercept({
call: (context, a, b, c) => {
context.number = 42;
result[`${type}ContextInterceptedCall1`] = [context, a, b, c];
},
loop: (context, a, b, c) => {
context.number2 = 88;
result[`${type}ContextInterceptedLoop1`] = [context, a, b, c];
},
tap: (context, tap) => {
result[`${type}ContextInterceptedTap1`] = context;
},
context: true
});
hook.intercept({
call: (a, b, c) => {
result[`${type}ContextInterceptedCall2`] = [a, b, c];
}
});
hook.tap({
name: "sync",
context: true
}, (context, a, b, c) => context.number + a + b + c);
result[`${type}ContextIntercepted`] = await this.gainResult((cb) => hook[type](1, 2, 3, cb));
}
{
const hook = this.createHook(["a", "b", "c"], `${type}UnusedContextIntercepted`);
hook.intercept({
call: (context, a, b, c) => {
result[`${type}UnusedContextInterceptedCall1`] = [context, a, b, c];
},
tap: (context, tap) => {
result[`${type}UnusedContextInterceptedTap1`] = context;
},
context: true
});
hook.intercept({
call: (a, b, c) => {
result[`${type}UnusedContextInterceptedCall2`] = [a, b, c];
}
});
hook.tap("sync", (a, b, c) => a + b + c);
result[`${type}UnusedContextIntercepted`] = await this.gainResult((cb) => hook[type](1, 2, 3, cb));
}
}

@@ -892,0 +935,0 @@

@@ -75,16 +75,17 @@ /*

const mock0 = jest.fn();
const mockTap = jest.fn(x => ({
const mockRegister = jest.fn(x => ({
name: "huh",
type: "sync",
fn: mock0
}));
const mock1 = jest.fn();
hook.tap("Test1", mock1);
hook.intercept({
call: mockCall,
tap: mockTap
register: mockRegister
});
const mock1 = jest.fn();
const mock2 = jest.fn();
hook.tap("Test1", mock1);
hook.tap("Test2", mock2);

@@ -95,3 +96,3 @@

expect(mockCall).toHaveBeenLastCalledWith(1, 2);
expect(mockTap).toHaveBeenLastCalledWith({
expect(mockRegister).toHaveBeenLastCalledWith({
type: "sync",

@@ -98,0 +99,0 @@ name: "Test2",

@@ -8,4 +8,61 @@ /*

const Hook = require("./Hook");
const simpleAsyncCases = require("./simpleAsyncCases");
const HookCodeFactory = require("./HookCodeFactory");
class AsyncParallelBailHookCodeFactory extends HookCodeFactory {
content({ onError, onResult, onDone }) {
let code = "";
code += `var _results = new Array(${this.options.taps.length});\n`;
code += "var _checkDone = () => {\n";
code += "for(var i = 0; i < _results.length; i++) {\n";
code += "var item = _results[i];\n";
code += "if(item === undefined) return false;\n";
code += "if(item.result !== undefined) {\n";
code += onResult("item.result");
code += "return true;\n";
code += "}\n";
code += "if(item.error) {\n";
code += onError("item.error");
code += "return true;\n";
code += "}\n";
code += "}\n";
code += "return false;\n";
code += "}\n";
code += this.callTapsParallel({
onError: (i, err, done, doneBreak) => {
let code = "";
code += `if(${i} < _results.length && ((_results.length = ${i + 1}), (_results[${i}] = { error: ${err} }), _checkDone())) {\n`;
code += doneBreak(true);
code += "} else {\n";
code += done();
code += "}\n";
return code;
},
onResult: (i, result, done, doneBreak) => {
let code = "";
code += `if(${i} < _results.length && (${result} !== undefined && (_results.length = ${i + 1}), (_results[${i}] = { result: ${result} }), _checkDone())) {\n`;
code += doneBreak(true);
code += "} else {\n";
code += done();
code += "}\n";
return code;
},
onTap: (i, run, done, doneBreak) => {
let code = "";
if(i > 0) {
code += `if(${i} >= _results.length) {\n`;
code += done();
code += "} else {\n";
}
code += run();
if(i > 0) code += "}\n";
return code;
},
onDone
});
return code;
}
}
const factory = new AsyncParallelBailHookCodeFactory();
class AsyncParallelBailHook extends Hook {

@@ -17,215 +74,5 @@ constructor(args) {

template(options) {
const simpleCase = simpleAsyncCases.bailing(options);
if(simpleCase) return simpleCase;
const args = options.args.join(", ");
const argsWithCallback = args ? `${args}, _callback` : "_callback";
const argsWithComma = args ? `${args}, ` : "";
const tap = options.tap;
const type = options.type;
const isIntercept = tap == "intercept";
switch(`${tap} ${type}`) {
case "multiple-async async":
return `function(${argsWithCallback}) {
const _fns = this._x;
let _done = new Set();
let _currentPos = _fns.length;
let _currentError, _currentResult;
for(let _i = 0; _i < _fns.length; _i++) {
if(_i >= _currentPos) return; // early ignore
_fns[_i](${argsWithComma}((_i) => (_err, _result) => {
if(_i >= _currentPos) return; // ignore
if(_err || _result !== undefined) {
_currentPos = _i;
for(const _k of _done)
if(_k >= _i)
_done.delete(_k);
_currentError = _err;
_currentResult = _result;
} else {
_done.add(_i);
}
if(_done.size === _currentPos) {
_currentPos = 0;
_callback(_currentError, _currentResult);
}
})(_i));
}
}`;
case "multiple-async promise":
return `function(${args}) {
return new Promise((_resolve, _reject) => {
const _fns = this._x;
let _done = new Set();
let _currentPos = _fns.length;
let _currentError, _currentResult;
for(let _i = 0; _i < _fns.length; _i++) {
if(_i >= _currentPos) return; // early ignore
_fns[_i](${argsWithComma}((_i) => (_err, _result) => {
if(_i >= _currentPos) return; // ignore
if(_err || _result !== undefined) {
_currentPos = _i;
for(const _k of _done)
if(_k >= _i)
_done.delete(_k);
_currentError = _err;
_currentResult = _result;
} else {
_done.add(_i);
}
if(_done.size === _currentPos) {
_currentPos = 0;
if(_currentError) {
_reject(_currentError);
return;
}
_resolve(_currentResult);
}
})(_i));
}
});
}`;
case "multiple-promise async":
return `function(${argsWithCallback}) {
const _fns = this._x;
const _promises = _fns.map(_fn => _fn(${args}));
Promise.race(_promises).catch(() => {}); // prevent unhandled rejections
let _i = 0;
(function _next() {
_promises[_i].then(_result => {
if(_result !== undefined) {
_callback(null, _result);
return;
}
if(++_i >= _promises.length) {
_callback();
return;
}
_next();
}, _err => {
_callback(_err);
});
}());
}`;
case "multiple-promise promise":
return `function(${args}) {
const _fns = this._x;
const _promises = _fns.map(_fn => _fn(${args}));
Promise.race(_promises).catch(() => {}); // prevent unhandled rejections
let _i = 0;
return (function _next() {
return _promises[_i].then(_result => {
if(_result !== undefined) {
return _result;
}
if(++_i >= _promises.length) {
return;
}
return _next();
});
}());
}`;
case "multiple async":
case "intercept async":
return `function(${argsWithCallback}) {
const _taps = this._x;
${isIntercept ? `const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
` : ""}
const _promises = _taps.map(_tap => {
${isIntercept ? `for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
` : ""}
switch(_tap.type) {
case "sync":
try {
return Promise.resolve(_tap.fn(${args}));
} catch(_err) {
return Promise.resolve().then(() => { throw _err; });
}
case "async":
return new Promise((_resolve, _reject) => {
_tap.fn(${argsWithComma}(_err, _result) => {
if(_err) {
_reject(_err);
return;
}
_resolve(_result);
});
});
case "promise":
return Promise.resolve(_tap.fn(${args}));
}
});
Promise.race(_promises).catch(() => {}); // prevent unhandled rejections
let _i = 0;
(function _next() {
_promises[_i].then(_result => {
if(_result !== undefined) {
_callback(null, _result);
return;
}
if(++_i >= _promises.length) {
_callback();
return;
}
_next();
}, _err => {
_callback(_err);
});
}());
}`;
case "multiple promise":
case "intercept promise":
return `function(${args}) {
const _taps = this._x;
${isIntercept ? `const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
` : ""}
const _promises = _taps.map(_tap => {
${isIntercept ? `for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
` : ""}
switch(_tap.type) {
case "sync":
try {
return Promise.resolve(_tap.fn(${args}));
} catch(_err) {
return Promise.resolve().then(() => { throw _err; });
}
case "async":
return new Promise((_resolve, _reject) => {
_tap.fn(${argsWithComma}(_err, _result) => {
if(_err) {
_reject(_err);
return;
}
_resolve(_result);
});
});
case "promise":
return Promise.resolve(_tap.fn(${args}));
}
});
Promise.race(_promises).catch(() => {}); // prevent unhandled rejections
let _i = 0;
return (function _next() {
return _promises[_i].then(_result => {
if(_result !== undefined) {
return _result;
}
if(++_i >= _promises.length) {
return;
}
return _next();
});
}());
}`;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported tap '${tap}' or type '${type}'`);
}
compile(options) {
factory.setup(this, options);
return factory.create(options);
}

@@ -232,0 +79,0 @@ }

@@ -8,4 +8,15 @@ /*

const Hook = require("./Hook");
const simpleAsyncCases = require("./simpleAsyncCases");
const HookCodeFactory = require("./HookCodeFactory");
class AsyncParallelHookCodeFactory extends HookCodeFactory {
content({ onError, onDone }) {
return this.callTapsParallel({
onError: (i, err, done, doneBreak) => onError(err) + doneBreak(true),
onDone
});
}
}
const factory = new AsyncParallelHookCodeFactory();
class AsyncParallelHook extends Hook {

@@ -17,174 +28,5 @@ constructor(args) {

template(options) {
const simpleCase = simpleAsyncCases.notBailing(options);
if(simpleCase) return simpleCase;
const args = options.args.join(", ");
const argsWithCallback = args ? `${args}, _callback` : "_callback";
const argsWithComma = args ? `${args}, ` : "";
const tap = options.tap;
const type = options.type;
const isIntercept = tap == "intercept";
switch(`${tap} ${type}`) {
case "multiple-async async":
return `function(${argsWithCallback}) {
const _fns = this._x;
let _remaining = _fns.length;
const _handler = (_err) => {
if(_err && _remaining > 0) {
_remaining = -1;
_callback(_err);
return;
}
if(--_remaining === 0) {
_callback();
}
};
for(let _i = 0; _i < _fns.length; _i++) {
_fns[_i](${argsWithComma}_handler);
}
}`;
case "multiple-async promise":
return `function(${args}) {
return new Promise((_resolve, _reject) => {
const _fns = this._x;
let _remaining = _fns.length;
const _handler = (_err) => {
if(_err && _remaining > 0) {
_remaining = -1;
_reject(_err);
return;
}
if(--_remaining === 0) {
_resolve();
}
};
for(let _i = 0; _i < _fns.length; _i++) {
_fns[_i](${argsWithComma}_handler);
}
});
}`;
case "multiple-promise async":
return `function(${argsWithCallback}) {
const _fns = this._x;
let _remaining = _fns.length;
const _handler = () => {
if(--_remaining === 0) {
_callback();
}
}
const _handlerErr = (_err) => {
if(_remaining > 0) {
_remaining = -1;
_callback(_err);
}
}
for(let _i = 0; _i < _fns.length; _i++) {
Promise.resolve(_fns[_i](${args})).then(_handler, _handlerErr);
}
}`;
case "multiple-promise promise":
return `function(${args}) {
const _fns = this._x;
return Promise.all(_fns.map(_fn => _fn(${args}))).then(() => {});
}`;
case "multiple async":
case "intercept async":
return `function(${argsWithCallback}) {
const _taps = this._x;
${isIntercept ? `const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
` : ""}
let _remaining = _taps.length;
const _handler = (_err) => {
if(_err && _remaining > 0) {
_remaining = -1;
_callback(_err);
return;
}
if(--_remaining === 0) {
_callback();
}
};
const _handlerSuccess = () => {
if(--_remaining === 0) {
_callback();
}
}
const _handlerErr = (_err) => {
if(_remaining > 0) {
_remaining = -1;
_callback(_err);
}
}
for(let _i = 0; _i < _taps.length; _i++) {
${isIntercept ? `let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
` : `const _tap = _taps[_i];`}
switch(_tap.type) {
case "sync":
try {
_tap.fn(${args});
} catch(_err) {
_handlerErr(_err);
break;
}
_handlerSuccess();
break;
case "async":
_tap.fn(${argsWithComma}_handler);
break;
case "promise":
Promise.resolve(_tap.fn(${args})).then(_handlerSuccess, _handlerErr);
break;
}
}
}`;
case "multiple promise":
case "intercept promise":
return `function(${args}) {
const _taps = this._x;
${isIntercept ? `const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
` : ""}
let _earlyAbort = false;
return Promise.all(_taps.map(_tap => {
if(_earlyAbort) return;
${isIntercept ? `for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
` : ""}
switch(_tap.type) {
case "sync":
try {
_tap.fn(${args});
} catch(_err) {
_earlyAbort = true;
return Promise.reject(_err);
}
return Promise.resolve();
case "async":
return new Promise((_resolve, _reject) => {
_tap.fn(${argsWithComma}_err => {
if(_err) {
_earlyAbort = true;
_reject(_err);
return;
}
_resolve();
});
});
break;
case "promise":
return _tap.fn(${args});
break;
}
})).then(() => {});
}`;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported tap '${tap}' or type '${type}'`);
}
compile(options) {
factory.setup(this, options);
return factory.create(options);
}

@@ -191,0 +33,0 @@ }

@@ -8,4 +8,16 @@ /*

const Hook = require("./Hook");
const simpleAsyncCases = require("./simpleAsyncCases");
const HookCodeFactory = require("./HookCodeFactory");
class AsyncSeriesBailHookCodeFactory extends HookCodeFactory {
content({ onError, onResult, onDone }) {
return this.callTapsSeries({
onError: (i, err, next, doneBreak) => onError(err) + doneBreak(true),
onResult: (i, result, next) => `if(${result} !== undefined) {\n${onResult(result)};\n} else {\n${next()}}\n`,
onDone
});
}
}
const factory = new AsyncSeriesBailHookCodeFactory();
class AsyncSeriesBailHook extends Hook {

@@ -17,219 +29,6 @@ constructor(args) {

template(options) {
const simpleCase = simpleAsyncCases.bailing(options);
if(simpleCase) return simpleCase;
const args = options.args.join(", ");
const argsWithCallback = args ? `${args}, _callback` : "_callback";
const argsWithComma = args ? `${args}, ` : "";
const tap = options.tap;
const type = options.type;
const isIntercept = tap == "intercept";
switch(`${tap} ${type}`) {
case "multiple-async async":
return `function(${argsWithCallback}) {
const _fns = this._x;
let _i = 0;
const _handler = (_err, _result) => {
if(_err) {
_callback(_err);
return;
}
if(_result !== undefined) {
_callback(null, _result);
return;
}
if(++_i >= _fns.length) {
_callback();
return;
}
_next();
};
function _next() {
_fns[_i](${argsWithComma}_handler);
}
_next();
}`;
case "multiple-async promise":
return `function(${args}) {
return new Promise((_resolve, _reject) => {
const _fns = this._x;
let _i = 0;
let _isSync;
const _handler = (_err, _result) => {
if(_err) {
if(_isSync)
Promise.resolve().then(() => _reject(_err));
else
_reject(_err);
return;
}
if(_result !== undefined) {
_resolve(_result);
return;
}
if(++_i >= _fns.length) {
_resolve();
return;
}
_next();
};
function _next() {
_isSync = true;
_fns[_i](${argsWithComma}_handler);
_isSync = false;
}
_next();
});
}`;
case "multiple-promise async":
return `function(${argsWithCallback}) {
const _fns = this._x;
let _i = 0;
const _handler = (_result) => {
if(_result !== undefined) {
_callback(null, _result);
return;
}
if(++_i >= _fns.length) {
_callback();
return;
}
_next();
};
const _handlerErr = (_err) => {
_callback(_err);
};
function _next() {
Promise.resolve(_fns[_i](${args})).then(_handler, _handlerErr);
}
_next();
}`;
case "multiple-promise promise":
return `function(${args}) {
const _fns = this._x;
let _i = 0;
function _next() {
return Promise.resolve(_fns[_i](${args})).then(_result => {
if(_result !== undefined) {
return _result;
}
if(++_i >= _fns.length) {
return;
}
return _next();
});
}
return _next();
}`;
case "multiple async":
case "intercept async":
return `function(${argsWithCallback}) {
const _taps = this._x;
${isIntercept ? `const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
` : ""}
let _i = 0;
const _handler = (_err, _result) => {
if(_err) {
_callback(_err);
return;
}
_handlerSuccess(_result);
};
const _handlerErr = (_err) => {
_callback(_err);
};
const _handlerSuccess = (_result) => {
if(_result !== undefined) {
_callback(null, _result);
return;
}
if(++_i >= _taps.length) {
_callback();
return;
}
_next();
};
function _next() {
${isIntercept ? `let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
` : `const _tap = _taps[_i];`}
switch(_tap.type) {
case "sync":
let _result;
try {
_result = _tap.fn(${args});
} catch(_err) {
_handlerErr(_err);
}
_handlerSuccess(_result);
break;
case "async":
_tap.fn(${argsWithComma}_handler);
break;
case "promise":
Promise.resolve(_tap.fn(${args})).then(_handlerSuccess, _handlerErr);
break;
}
}
_next();
}`;
case "multiple promise":
case "intercept promise":
return `function(${args}) {
const _taps = this._x;
${isIntercept ? `const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
` : ""}
let _i = 0;
function _getPromise() {
${isIntercept ? `let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
` : `const _tap = _taps[_i];`}
switch(_tap.type) {
case "sync":
return Promise.resolve().then(() => {
return _tap.fn(${args});
});
case "async":
return new Promise((_resolve, _reject) => {
let _isSync = true;
_tap.fn(${argsWithComma}(_err, _result) => {
if(_err) {
if(_isSync)
Promise.resolve().then(() => _reject(_err));
else
_reject(_err);
return;
}
_resolve(_result);
});
_isSync = false;
});
case "promise":
return Promise.resolve(_tap.fn(${args}));
}
}
function _next() {
return _getPromise().then(_result => {
if(_result !== undefined) {
return _result;
}
if(++_i >= _taps.length) {
return;
}
return _next();
});
}
return _next();
}`;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported tap '${tap}' or type '${type}'`);
}
compile(options) {
factory.setup(this, options);
return factory.create(options);
}

@@ -236,0 +35,0 @@ }

@@ -8,4 +8,15 @@ /*

const Hook = require("./Hook");
const simpleAsyncCases = require("./simpleAsyncCases");
const HookCodeFactory = require("./HookCodeFactory");
class AsyncSeriesHookCodeFactory extends HookCodeFactory {
content({ onError, onDone }) {
return this.callTapsSeries({
onError: (i, err, next, doneBreak) => onError(err) + doneBreak(true),
onDone
});
}
}
const factory = new AsyncSeriesHookCodeFactory();
class AsyncSeriesHook extends Hook {

@@ -17,196 +28,5 @@ constructor(args) {

template(options) {
const simpleCase = simpleAsyncCases.notBailing(options);
if(simpleCase) return simpleCase;
const args = options.args.join(", ");
const argsWithCallback = args ? `${args}, _callback` : "_callback";
const argsWithComma = args ? `${args}, ` : "";
const tap = options.tap;
const type = options.type;
const isIntercept = tap == "intercept";
switch(`${tap} ${type}`) {
case "multiple-async async":
return `function(${argsWithCallback}) {
const _fns = this._x;
let _i = 0;
const _handler = (_err) => {
if(_err) {
_callback(_err);
return;
}
if(++_i >= _fns.length) {
_callback();
return;
}
_next();
};
function _next() {
_fns[_i](${argsWithComma}_handler);
}
_next();
}`;
case "multiple-async promise":
return `function(${args}) {
return new Promise((_resolve, _reject) => {
const _fns = this._x;
let _i = 0;
let _isSync;
const _handler = (_err) => {
if(_err) {
if(_isSync)
Promise.resolve().then(() => _reject(_err));
else
_reject(_err);
return;
}
if(++_i >= _fns.length) {
_resolve();
return;
}
_next();
};
function _next() {
_isSync = true;
_fns[_i](${argsWithComma}_handler);
_isSync = false;
}
_next();
});
}`;
case "multiple-promise async":
return `function(${argsWithCallback}) {
const _fns = this._x;
let _i = 0;
const _handler = () => {
if(++_i >= _fns.length) {
_callback();
return;
}
_next();
};
const _handlerErr = (_err) => {
_callback(_err);
};
function _next() {
Promise.resolve(_fns[_i](${args})).then(_handler, _handlerErr);
}
_next();
}`;
case "multiple-promise promise":
return `function(${args}) {
const _fns = this._x;
let _i = 0;
function _next() {
return Promise.resolve(_fns[_i](${args})).then(() => {
if(++_i >= _fns.length) {
return;
}
return _next();
});
}
return _next();
}`;
case "multiple async":
case "intercept async":
return `function(${argsWithCallback}) {
const _taps = this._x;
${isIntercept ? `const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
` : ""}
let _i = 0;
const _handler = (_err) => {
if(_err) {
_callback(_err);
return;
}
_handlerSuccess();
};
const _handlerErr = (_err) => {
_callback(_err);
};
const _handlerSuccess = () => {
if(++_i >= _taps.length) {
_callback();
return;
}
_next();
};
function _next() {
${isIntercept ? `let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
` : `const _tap = _taps[_i];`}
switch(_tap.type) {
case "sync":
try {
_tap.fn(${args});
} catch(_err) {
_handlerErr(_err);
}
_handlerSuccess();
break;
case "async":
_tap.fn(${argsWithComma}_handler);
break;
case "promise":
Promise.resolve(_tap.fn(${args})).then(_handlerSuccess, _handlerErr);
break;
}
}
_next();
}`;
case "multiple promise":
case "intercept promise":
return `function(${args}) {
const _taps = this._x;
${isIntercept ? `const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
` : ""}
let _i = 0;
function _getPromise() {
${isIntercept ? `let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
` : `const _tap = _taps[_i];`}
switch(_tap.type) {
case "sync":
return Promise.resolve().then(() => {
_tap.fn(${args});
});
case "async":
return new Promise((_resolve, _reject) => {
let _isSync = true;
_tap.fn(${argsWithComma}(_err) => {
if(_err) {
if(_isSync)
Promise.resolve().then(() => _reject(_err));
else
_reject(_err);
return;
}
_resolve();
});
_isSync = false;
});
case "promise":
return Promise.resolve(_tap.fn(${args}));
}
}
function _next() {
return _getPromise().then(() => {
if(++_i >= _taps.length) {
return;
}
return _next();
});
}
return _next();
}`;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported tap '${tap}' or type '${type}'`);
}
compile(options) {
factory.setup(this, options);
return factory.create(options);
}

@@ -213,0 +33,0 @@ }

@@ -8,4 +8,15 @@ /*

const Hook = require("./Hook");
const simpleAsyncCases = require("./simpleAsyncCases");
const HookCodeFactory = require("./HookCodeFactory");
class AsyncSeriesLoopHookCodeFactory extends HookCodeFactory {
content({ onError, onDone }) {
return this.callTapsLooping({
onError: (i, err, next, doneBreak) => onError(err) + doneBreak(true),
onDone
});
}
}
const factory = new AsyncSeriesLoopHookCodeFactory();
class AsyncSeriesLoopHook extends Hook {

@@ -17,352 +28,5 @@ constructor(args) {

template(options) {
const args = options.args.join(", ");
const argsWithCallback = args ? `${args}, _callback` : "_callback";
const argsWithComma = args ? `${args}, ` : "";
const tap = options.tap;
const type = options.type;
const isIntercept = tap == "intercept";
switch(`${tap} ${type}`) {
case "none async":
return `function(${argsWithCallback}) {
_callback();
}`;
case "none promise":
return `function(${args}) {
return Promise.resolve();
}`;
case "sync async":
return `function(${argsWithCallback}) {
try {
while(this._x(${args}) !== undefined);
} catch(_e) {
_callback(_e);
return;
}
_callback();
}`;
case "sync promise":
return `function(${args}) {
return Promise.resolve().then(() => {
while(this._x(${args}) !== undefined);
});
}`;
case "async async":
return `function(${argsWithCallback}) {
const _next = () => {
this._x(${argsWithComma}(_err, _result) => {
if(_err) {
_callback(_err);
return;
}
if(_result !== undefined) {
_next();
return;
}
_callback();
});
};
_next();
}`;
case "async promise":
return `function(${args}) {
return new Promise((_resolve, _reject) => {
let _isSync = true;
const _next = () => {
this._x(${argsWithComma}(_err, _result) => {
if(_err) {
if(_isSync)
Promise.resolve().then(() => _reject(_err));
else
_reject(_err);
return;
}
if(_result !== undefined) {
_next();
return;
}
_resolve();
});
};
_next();
_isSync = false;
});
}`;
case "promise async":
return `function(${argsWithCallback}) {
const _next = () => {
Promise.resolve(this._x(${args})).then(_result => {
if(_result !== undefined)
_next();
else
_callback();
}, _err => {
_callback(_err);
});
}
_next();
}`;
case "promise promise":
return `function(${args}) {
const _next = () => Promise.resolve(this._x(${args})).then(_result => {
if(_result !== undefined)
return _next();
});
return _next();
}`;
case "multiple-sync async":
return `function(${argsWithCallback}) {
try {
const _fns = this._x;
for(let _i = 0; _i < _fns.length; _i++) {
const _result = _fns[_i](${args});
if(_result !== undefined)
_i = -1;
}
} catch(_err) {
_callback(_err);
return;
}
_callback();
}`;
case "multiple-sync promise":
return `function(${args}) {
return Promise.resolve().then(() => {
const _fns = this._x;
for(let _i = 0; _i < _fns.length; _i++) {
const _result = _fns[_i](${args});
if(_result !== undefined)
_i = -1;
}
});
}`;
case "multiple-async async":
return `function(${argsWithCallback}) {
const _fns = this._x;
let _i = 0;
const _handler = (_err, _result) => {
if(_err) {
_callback(_err);
return;
}
if(_result !== undefined) {
_i = 0;
_next();
return;
}
if(++_i >= _fns.length) {
_callback();
return;
}
_next();
};
function _next() {
_fns[_i](${argsWithComma}_handler);
}
_next();
}`;
case "multiple-async promise":
return `function(${args}) {
return new Promise((_resolve, _reject) => {
const _fns = this._x;
let _i = 0;
let _isSync;
const _handler = (_err, _result) => {
if(_err) {
if(_isSync)
Promise.resolve().then(() => _reject(_err));
else
_reject(_err);
return;
}
if(_result !== undefined) {
_i = 0;
_next();
return;
}
if(++_i >= _fns.length) {
_resolve();
return;
}
_next();
};
function _next() {
_isSync = true;
_fns[_i](${argsWithComma}_handler);
_isSync = false;
}
_next();
});
}`;
case "multiple-promise async":
return `function(${argsWithCallback}) {
const _fns = this._x;
let _i = 0;
const _handler = (_result) => {
if(_result !== undefined) {
_i = 0;
_next();
return;
}
if(++_i >= _fns.length) {
_callback();
return;
}
_next();
};
const _handlerErr = (_err) => {
_callback(_err);
};
function _next() {
Promise.resolve(_fns[_i](${args})).then(_handler, _handlerErr);
}
_next();
}`;
case "multiple-promise promise":
return `function(${args}) {
const _fns = this._x;
let _i = 0;
function _next() {
return Promise.resolve(_fns[_i](${args})).then(_result => {
if(_result !== undefined) {
_i = 0;
return _next();
}
if(++_i >= _fns.length) {
return;
}
return _next();
});
}
return _next();
}`;
case "multiple async":
case "intercept async":
return `function(${argsWithCallback}) {
const _taps = this._x;
${isIntercept ? `const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
` : ""}
${isIntercept ? `
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].loop(${args});
` : ""}
let _i = 0;
const _handler = (_err, _result) => {
if(_err) {
_callback(_err);
return;
}
_handlerSuccess(_result);
};
const _handlerErr = (_err) => {
_callback(_err);
};
const _handlerSuccess = (_result) => {
if(_result !== undefined) {
_i = 0;
${isIntercept ? `
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].loop(${args});
` : ""}
_next();
return;
}
if(++_i >= _taps.length) {
_callback();
return;
}
_next();
};
function _next() {
${isIntercept ? `let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
` : `const _tap = _taps[_i];`}
switch(_tap.type) {
case "sync":
let _result;
try {
_result = _tap.fn(${args});
} catch(_err) {
_handlerErr(_err);
}
_handlerSuccess(_result);
break;
case "async":
_tap.fn(${argsWithComma}_handler);
break;
case "promise":
Promise.resolve(_tap.fn(${args})).then(_handlerSuccess, _handlerErr);
break;
}
}
_next();
}`;
case "multiple promise":
case "intercept promise":
return `function(${args}) {
const _taps = this._x;
${isIntercept ? `const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
` : ""}
${isIntercept ? `
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].loop(${args});
` : ""}
let _i = 0;
function _getPromise() {
${isIntercept ? `let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
` : `const _tap = _taps[_i];`}
switch(_tap.type) {
case "sync":
return Promise.resolve().then(() => {
return _tap.fn(${args});
});
case "async":
return new Promise((_resolve, _reject) => {
let _isSync = true;
_tap.fn(${argsWithComma}(_err, _result) => {
if(_err) {
if(_isSync)
Promise.resolve().then(() => _reject(_err));
else
_reject(_err);
return;
}
_resolve(_result);
});
_isSync = false;
});
case "promise":
return Promise.resolve(_tap.fn(${args}));
}
}
function _next() {
return _getPromise().then(_result => {
if(_result !== undefined) {
${isIntercept ? `
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].loop(${args});
` : ""}
_i = 0;
return _next();
}
if(++_i >= _taps.length) {
return;
}
return _next();
});
}
return _next();
}`;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported tap '${tap}' or type '${type}'`);
}
compile(options) {
factory.setup(this, options);
return factory.create(options);
}

@@ -369,0 +33,0 @@ }

@@ -8,4 +8,23 @@ /*

const Hook = require("./Hook");
const simpleAsyncCases = require("./simpleAsyncCases");
const HookCodeFactory = require("./HookCodeFactory");
class AsyncSeriesWaterfallHookCodeFactory extends HookCodeFactory {
content({ onError, onResult, onDone }) {
return this.callTapsSeries({
onError: (i, err, next, doneBreak) => onError(err) + doneBreak(true),
onResult: (i, result, next) => {
let code = "";
code += `if(${result} !== undefined) {\n`;
code += `${this._args[0]} = ${result};\n`;
code += `}\n`;
code += next();
return code;
},
onDone: () => onResult(this._args[0])
});
}
}
const factory = new AsyncSeriesWaterfallHookCodeFactory();
class AsyncSeriesWaterfallHook extends Hook {

@@ -18,318 +37,5 @@ constructor(args) {

template(options) {
const args = options.args.join(", ");
const firstArg = options.args[0];
const argsWithCurrent = ["_current"].concat(options.args.slice(1)).join(", ");
const argsWithCallback = `${args}, _callback`;
const tap = options.tap;
const type = options.type;
const isIntercept = tap == "intercept";
switch(`${tap} ${type}`) {
case "none async":
return `function(${argsWithCallback}) {
_callback(null, ${firstArg});
}`;
case "none promise":
return `function(${args}) {
return Promise.resolve(${firstArg});
}`;
case "sync async":
return `function(${argsWithCallback}) {
let _result;
try {
_result = this._x(${args});
} catch(_e) {
_callback(_e);
return;
}
_callback(null, _result !== undefined ? _result : ${firstArg});
}`;
case "sync promise":
return `function(${args}) {
return Promise.resolve().then(() => {
const _result = this._x(${args});
return _result !== undefined ? _result : ${firstArg};
});
}`;
case "async async":
return `function(${argsWithCallback}) {
this._x(${args}, (_err, _result) => {
if(_err) {
_callback(_err);
return;
}
_callback(null, _result !== undefined ? _result : ${firstArg});
});
}`;
case "async promise":
return `function(${args}) {
return new Promise((_resolve, _reject) => {
let _isSync = true;
this._x(${args}, (_err, _result) => {
if(_err) {
if(_isSync)
Promise.resolve().then(() => _reject(_err));
else
_reject(_err);
return;
}
_resolve(_result !== undefined ? _result : ${firstArg});
});
_isSync = false;
});
}`;
case "promise async":
return `function(${argsWithCallback}) {
Promise.resolve(this._x(${args})).then(_result => {
_callback(null, _result !== undefined ? _result : ${firstArg});
}, _err => {
_callback(_err);
});
}`;
case "promise promise":
return `function(${args}) {
return Promise.resolve(this._x(${args})).then(_result => {
return _result !== undefined ? _result : ${firstArg};
});
}`;
case "multiple-sync async":
return `function(${argsWithCallback}) {
let _current = ${firstArg};
try {
const _fns = this._x;
for(let _i = 0; _i < _fns.length; _i++) {
const _result = _fns[_i](${argsWithCurrent});
if(_result !== undefined) {
_current = _result;
}
}
} catch(_err) {
_callback(_err);
return;
}
_callback(null, _current);
}`;
case "multiple-sync promise":
return `function(${args}) {
return new Promise(_resolve => {
let _current = ${firstArg};
const _fns = this._x;
for(let _i = 0; _i < _fns.length; _i++) {
const _result = _fns[_i](${argsWithCurrent});
if(_result !== undefined) {
_current = _result;
}
}
_resolve(_current);
});
}`;
case "multiple-async async":
return `function(${argsWithCallback}) {
const _fns = this._x;
let _i = 0;
let _current = ${firstArg};
const _handler = (_err, _result) => {
if(_err) {
_callback(_err);
return;
}
if(_result !== undefined) {
_current = _result;
}
if(++_i >= _fns.length) {
_callback(null, _current);
return;
}
_next();
};
function _next() {
_fns[_i](${argsWithCurrent}, _handler);
}
_next();
}`;
case "multiple-async promise":
return `function(${args}) {
return new Promise((_resolve, _reject) => {
const _fns = this._x;
let _i = 0;
let _current = ${firstArg};
let _isSync;
const _handler = (_err, _result) => {
if(_err) {
if(_isSync)
Promise.resolve().then(() => _reject(_err));
else
_reject(_err);
return;
}
if(_result !== undefined) {
_current = _result;
}
if(++_i >= _fns.length) {
_resolve(_current);
return;
}
_next();
};
function _next() {
_isSync = true;
_fns[_i](${argsWithCurrent}, _handler);
_isSync = false;
}
_next();
});
}`;
case "multiple-promise async":
return `function(${argsWithCallback}) {
const _fns = this._x;
let _i = 0;
let _current = ${firstArg};
const _handler = (_result) => {
if(_result !== undefined) {
_current = _result;
}
if(++_i >= _fns.length) {
_callback(null, _current);
return;
}
_next();
};
const _handlerErr = (_err) => {
_callback(_err);
};
function _next() {
Promise.resolve(_fns[_i](${argsWithCurrent})).then(_handler, _handlerErr);
}
_next();
}`;
case "multiple-promise promise":
return `function(${args}) {
const _fns = this._x;
let _i = 0;
let _current = ${firstArg};
function _next() {
return Promise.resolve(_fns[_i](${argsWithCurrent})).then(_result => {
if(_result !== undefined) {
_current = _result;
}
if(++_i >= _fns.length) {
return _current;
}
return _next();
});
}
return _next();
}`;
case "multiple async":
case "intercept async":
return `function(${argsWithCallback}) {
const _taps = this._x;
${isIntercept ? `const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
` : ""}
let _i = 0;
let _current = ${firstArg};
const _handler = (_err, _result) => {
if(_err) {
_callback(_err);
return;
}
_handlerSuccess(_result);
};
const _handlerErr = (_err) => {
_callback(_err);
};
const _handlerSuccess = (_result) => {
if(_result !== undefined) {
_current = _result;
}
if(++_i >= _taps.length) {
_callback(null, _current);
return;
}
_next();
};
function _next() {
${isIntercept ? `let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
` : `const _tap = _taps[_i];`}
switch(_tap.type) {
case "sync":
let _result;
try {
_result = _tap.fn(${argsWithCurrent});
} catch(_err) {
_handlerErr(_err);
}
_handlerSuccess(_result);
break;
case "async":
_tap.fn(${argsWithCurrent}, _handler);
break;
case "promise":
Promise.resolve(_tap.fn(${argsWithCurrent})).then(_handlerSuccess, _handlerErr);
break;
}
}
_next();
}`;
case "multiple promise":
case "intercept promise":
return `function(${args}) {
const _taps = this._x;
${isIntercept ? `const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
` : ""}
let _i = 0;
let _current = ${firstArg};
function _getPromise() {
${isIntercept ? `let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
` : `const _tap = _taps[_i];`}
switch(_tap.type) {
case "sync":
return Promise.resolve().then(() => {
return _tap.fn(${argsWithCurrent});
});
case "async":
return new Promise((_resolve, _reject) => {
let _isSync = true;
_tap.fn(${argsWithCurrent}, (_err, _result) => {
if(_err) {
if(_isSync)
Promise.resolve().then(() => _reject(_err));
else
_reject(_err);
return;
}
_resolve(_result);
});
_isSync = false;
});
case "promise":
return Promise.resolve(_tap.fn(${argsWithCurrent}));
}
}
function _next() {
return _getPromise().then(_result => {
if(_result !== undefined) {
_current = _result;
}
if(++_i >= _taps.length) {
return _current;
}
return _next();
});
}
return _next();
}`;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported tap '${tap}' or type '${type}'`);
}
compile(options) {
factory.setup(this, options);
return factory.create(options);
}

@@ -336,0 +42,0 @@ }

@@ -13,5 +13,5 @@ /*

this.interceptors = [];
this.call = this._call = this.createCompileDelegate("call", "sync");
this.promise = this._promise = this.createCompileDelegate("promise", "promise");
this.callAsync = this._callAsync = this.createCompileDelegate("callAsync", "async");
this.call = this._call = this._createCompileDelegate("call", "sync");
this.promise = this._promise = this._createCompileDelegate("promise", "promise");
this.callAsync = this._callAsync = this._createCompileDelegate("callAsync", "async");
this._x = undefined;

@@ -21,32 +21,10 @@ }

compile(options) {
const source = this.template(options);
return new Function(`"use strict"; const compiledHookHandler = ${source}; return compiledHookHandler; `)();
throw new Error("Abstract: should be overriden");
}
getTapType() {
if(this.interceptors.length > 0) return "intercept";
if(this.taps.length === 0) return "none";
if(this.taps.length === 1) {
const tap = this.taps[0];
return tap.type;
}
let type = this.taps[0].type;
for(let i = 1; i < this.taps.length; i++) {
const tap = this.taps[i];
if(tap.type !== type) return "multiple";
}
return "multiple-" + type;
}
createCall(type) {
const tap = this.getTapType();
if(tap === "sync" || tap === "async" || tap === "promise")
this._x = this.taps[0].fn;
else if(tap === "multiple-sync" || tap === "multiple-async" || tap === "multiple-promise")
this._x = this.taps.map(t => t.fn);
else
this._x = this.taps;
_createCall(type) {
return this.compile({
taps: this.taps,
interceptors: this.interceptors,
args: this._args,
tap: tap,
type: type

@@ -56,5 +34,5 @@ });

createCompileDelegate(name, type) {
_createCompileDelegate(name, type) {
const lazyCompileHook = (...args) => {
this[name] = this.createCall(type);
this[name] = this._createCall(type);
return this[name](...args);

@@ -73,2 +51,3 @@ };

throw new Error("Missing name for tap");
options = this._runRegisterInterceptors(options);
this._insert(options);

@@ -85,2 +64,3 @@ }

throw new Error("Missing name for tapAsync");
options = this._runRegisterInterceptors(options);
this._insert(options);

@@ -97,5 +77,17 @@ }

throw new Error("Missing name for tapPromise");
options = this._runRegisterInterceptors(options);
this._insert(options);
}
_runRegisterInterceptors(options) {
for(const interceptor of this.interceptors) {
if(interceptor.register) {
const newOptions = interceptor.register(options);
if(newOptions !== undefined)
options = newOptions;
}
}
return options;
}
withOptions(options) {

@@ -123,7 +115,7 @@ const mergeOptions = opt => Object.assign({}, options, typeof opt === "string" ? { name: opt } : opt);

this._resetCompilation();
this.interceptors.push(Object.assign({
call: () => {},
loop: () => {},
tap: tap => tap,
}, interceptor));
this.interceptors.push(Object.assign({}, interceptor));
if(interceptor.register) {
for(let i = 0; i < this.taps.length; i++)
this.taps[i] = interceptor.register(this.taps[i]);
}
}

@@ -130,0 +122,0 @@

@@ -19,1 +19,2 @@ /*

exports.HookMap = require("./HookMap");
exports.MultiHook = require("./MultiHook");

@@ -8,3 +8,17 @@ /*

const Hook = require("./Hook");
const HookCodeFactory = require("./HookCodeFactory");
class SyncBailHookCodeFactory extends HookCodeFactory {
content({ onError, onResult, onDone, rethrowIfPossible }) {
return this.callTapsSeries({
onError: (i, err) => onError(err),
onResult: (i, result, next) => `if(${result} !== undefined) {\n${onResult(result)};\n} else {\n${next()}}\n`,
onDone,
rethrowIfPossible
});
}
}
const factory = new SyncBailHookCodeFactory();
class SyncBailHook extends Hook {

@@ -19,79 +33,5 @@ tapAsync() {

template(options) {
const args = options.args.join(", ");
const argsWithCallback = args ? `${args}, _callback` : "_callback";
const tap = options.tap;
const type = options.type;
let emitResult;
switch(type) {
case "async":
emitResult = value => `return _callback(null, ${value});`;
break;
case "promise":
emitResult = value => `return Promise.resolve(${value});`;
break;
case "sync":
emitResult = value => `return ${value};`;
break;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported type ${tap}`);
}
let content;
switch(tap) {
case "none":
content = emitResult("undefined");
break;
case "sync":
content = emitResult(`this._x(${args})`);
break;
case "multiple-sync":
content = `
const _taps = this._x;
for(let _i = 0; _i < _taps.length; _i++) {
const _result = _taps[_i](${args});
if(_result !== undefined)
${emitResult("_result")}
}
${emitResult("undefined")}
`;
break;
case "intercept":
content = `
const _taps = this._x;
const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
for(let _i = 0; _i < _taps.length; _i++) {
let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
const _result = _tap.fn(${args});
if(_result !== undefined)
${emitResult("_result")}
}
${emitResult("undefined")}
`;
break;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported tap type ${tap}`);
}
switch(type) {
case "async":
return `function(${argsWithCallback}) {
${content}
}`;
case "promise":
case "sync":
return `function(${args}) {
${content}
}`;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported type ${tap}`);
}
compile(options) {
factory.setup(this, options);
return factory.create(options);
}

@@ -98,0 +38,0 @@ }

@@ -8,3 +8,16 @@ /*

const Hook = require("./Hook");
const HookCodeFactory = require("./HookCodeFactory");
class SyncHookCodeFactory extends HookCodeFactory {
content({ onError, onResult, onDone, rethrowIfPossible }) {
return this.callTapsSeries({
onError: (i, err) => onError(err),
onDone,
rethrowIfPossible
});
}
}
const factory = new SyncHookCodeFactory();
class SyncHook extends Hook {

@@ -19,61 +32,5 @@ tapAsync() {

template(options) {
const args = options.args.join(", ");
const argsWithCallback = args ? `${args}, _callback` : "_callback";
const tap = options.tap;
const type = options.type;
let content;
switch(tap) {
case "none":
content = "";
break;
case "sync":
content = `this._x(${args});`;
break;
case "multiple-sync":
content = `
const _taps = this._x;
for(let _i = 0; _i < _taps.length; _i++)
_taps[_i](${args});
`;
break;
case "intercept":
content = `
const _taps = this._x;
const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
for(let _i = 0; _i < _taps.length; _i++) {
let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
_tap.fn(${args});
}
`;
break;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported tap type ${tap}`);
}
switch(type) {
case "async":
return `function(${argsWithCallback}) {
${content}
_callback();
}`;
case "promise":
return `function(${args}) {
${content}
return Promise.resolve();
}`;
case "sync":
return `function(${args}) {
${content}
}`;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported type ${tap}`);
}
compile(options) {
factory.setup(this, options);
return factory.create(options);
}

@@ -80,0 +37,0 @@ }

@@ -8,3 +8,16 @@ /*

const Hook = require("./Hook");
const HookCodeFactory = require("./HookCodeFactory");
class SyncLoopHookCodeFactory extends HookCodeFactory {
content({ onError, onResult, onDone, rethrowIfPossible }) {
return this.callTapsLooping({
onError: (i, err) => onError(err),
onDone,
rethrowIfPossible
});
}
}
const factory = new SyncLoopHookCodeFactory();
class SyncLoopHook extends Hook {

@@ -19,71 +32,5 @@ tapAsync() {

template(options) {
const args = options.args.join(", ");
const argsWithCallback = args ? `${args}, _callback` : "_callback";
const tap = options.tap;
const type = options.type;
let content;
switch(tap) {
case "none":
content = "";
break;
case "sync":
content = `while(this._x(${args}) !== undefined);`;
break;
case "multiple-sync":
content = `
const _taps = this._x;
for(let _i = 0; _i < _taps.length; _i++) {
const _result = _taps[_i](${args});
if(_result !== undefined)
_i = -1;
}
`;
break;
case "intercept":
content = `
const _taps = this._x;
const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].loop(${args});
for(let _i = 0; _i < _taps.length; _i++) {
let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
const _result = _tap.fn(${args});
if(_result !== undefined) {
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].loop(${args});
_i = -1;
}
}
`;
break;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported tap type ${tap}`);
}
switch(type) {
case "async":
return `function(${argsWithCallback}) {
${content}
_callback();
}`;
case "promise":
return `function(${args}) {
${content}
return Promise.resolve();
}`;
case "sync":
return `function(${args}) {
${content}
}`;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported type ${tap}`);
}
compile(options) {
factory.setup(this, options);
return factory.create(options);
}

@@ -90,0 +37,0 @@ }

@@ -8,3 +8,24 @@ /*

const Hook = require("./Hook");
const HookCodeFactory = require("./HookCodeFactory");
class SyncWaterfallHookCodeFactory extends HookCodeFactory {
content({ onError, onResult, onDone, rethrowIfPossible }) {
return this.callTapsSeries({
onError: (i, err) => onError(err),
onResult: (i, result, next) => {
let code = "";
code += `if(${result} !== undefined) {\n`;
code += `${this._args[0]} = ${result};\n`;
code += `}\n`;
code += next();
return code;
},
onDone: () => onResult(this._args[0]),
rethrowIfPossible
});
}
}
const factory = new SyncWaterfallHookCodeFactory();
class SyncWaterfallHook extends Hook {

@@ -24,87 +45,5 @@ constructor(args) {

template(options) {
const args = options.args.join(", ");
const firstArg = options.args[0];
const argsWithCurrent = ["_current"].concat(options.args.slice(1)).join(", ");
const argsWithCallback = `${args}, _callback`;
const tap = options.tap;
const type = options.type;
let emitResult;
switch(type) {
case "async":
emitResult = value => `return _callback(null, ${value});`;
break;
case "promise":
case "sync":
emitResult = value => `return ${value};`;
break;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported type ${tap}`);
}
let content;
switch(tap) {
case "none":
content = emitResult(firstArg);
break;
case "sync":
content = `const _result = this._x(${args});
${emitResult(`_result !== undefined ? _result : ${firstArg}`)}`;
break;
case "multiple-sync":
content = `
const _taps = this._x;
let _current = ${firstArg};
for(let _i = 0; _i < _taps.length; _i++) {
const _result = _taps[_i](${argsWithCurrent});
if(_result !== undefined)
_current = _result;
}
${emitResult("_current")}
`;
break;
case "intercept":
content = `
const _taps = this._x;
let _current = ${firstArg};
const _intercept = this.interceptors;
for(let _j = 0; _j < _intercept.length; _j++)
_intercept[_j].call(${args});
for(let _i = 0; _i < _taps.length; _i++) {
let _tap = _taps[_i];
for(let _j = 0; _j < _intercept.length; _j++)
_tap = _intercept[_j].tap(_tap);
const _result = _tap.fn(${argsWithCurrent});
if(_result !== undefined)
_current = _result;
}
${emitResult("_current")}
`;
break;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported tap type ${tap}`);
}
switch(type) {
case "async":
return `function(${argsWithCallback}) {
${content}
}`;
case "promise":
return `function(${args}) {
return Promise.resolve().then(() => {
${content}
});
}`;
case "sync":
return `function(${args}) {
${content}
}`;
/* istanbul ignore next */
default:
/* istanbul ignore next */
throw new Error(`Unsupported type ${tap}`);
}
compile(options) {
factory.setup(this, options);
return factory.create(options);
}

@@ -111,0 +50,0 @@ }

{
"name": "tapable",
"version": "1.0.0-beta.4",
"version": "1.0.0-beta.5",
"author": "Tobias Koppers @sokra",

@@ -5,0 +5,0 @@ "description": "Just a little module for plugins.",

@@ -13,5 +13,5 @@ # Tapable

AsyncParallelBailHook,
AsyncSequencialHook,
AsyncSequencialBailHook,
AsyncWaterfallHook
AsyncSeriesHook,
AsyncSeriesBailHook,
AsyncSeriesWaterfallHook
} = require("tapable");

@@ -139,1 +139,98 @@ ```

```
**call**: `(...args) => void` Adding `call` to your interceptor will trigger when hooks are triggered. You have access to the hooks arguments.
**tap**: `(tap: Tap) => void` Adding `tap` to your interceptor will trigger when a plugin taps into a hook. Provided is the `Tap` object. `Tap` object can't be changed.
**loop**: `(...args) => void` Adding `loop` to your interceptor will trigger for each loop of a looping hook.
**register**: `(tap: Tap) => Tap | undefined` Adding `register` to your interceptor will trigger for each added `Tap` and allows to modify it.
## HookMap
A HookMap is a helper class for a Map with Hooks
``` js
const keyedHook = new HookMap(key => new SyncHook(["arg"]))
```
``` js
keyedHook.tap("some-key", "MyPlugin", (arg) => { /* ... */ });
keyedHook.tapAsync("some-key", "MyPlugin", (arg, callback) => { /* ... */ });
keyedHook.tapPromise("some-key", "MyPlugin", (arg) => { /* ... */ });
```
``` js
const hook = keyedHook.get("some-key");
if(hook !== undefined) {
hook.callAsync("arg", err => { /* ... */ });
}
```
## Hook/HookMap interface
Public:
``` ts
interface Hook {
tap: (name: string | Tap, fn: (context?, ...args) => Result) => void,
tapAsync: (name: string | Tap, fn: (context?, ...args, callback: (err, result: Result) => void) => void) => void,
tapPromise: (name: string | Tap, fn: (context?, ...args) => Promise<Result>) => void,
intercept: (interceptor: HookInterceptor) => void
}
interface HookInterceptor {
call: (context?, ...args) => void,
loop: (context?, ...args) => void,
tap: (context?, tap: Tap) => void,
register: (tap: Tap) => Tap,
context: boolean
}
interface HookMap {
for: (key: any) => Hook,
tap: (key: any, name: string | Tap, fn: (context?, ...args) => Result) => void,
tapAsync: (key: any, name: string | Tap, fn: (context?, ...args, callback: (err, result: Result) => void) => void) => void,
tapPromise: (key: any, name: string | Tap, fn: (context?, ...args) => Promise<Result>) => void,
intercept: (interceptor: HookMapInterceptor) => void
}
interface HookMapInterceptor {
factory: (key: any, hook: Hook) => Hook
}
interface Tap {
name: string,
type: string
fn: Function,
stage: number,
context: boolean
}
```
Protected (only for the class containing the hook):
``` ts
interface Hook {
isUsed: () => boolean,
call: (...args) => Result,
promise: (...args) => Promise<Result>,
callAsync: (...args, callback: (err, result: Result) => void) => void,
}
interface HookMap {
get: (key: any) => Hook | undefined,
for: (key: any) => Hook
}
```
## MultiHook
A helper Hook-like class to redirect taps to multiple other hooks:
``` js
const { MultiHook } = require("tapable");
this.hooks.allHooks = new MultiHook([this.hooks.hookA, this.hooks.hookB]);
```

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc