PK˥|[8!Elib/AsyncParallelBailHook.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Hook = require("./Hook"); 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 { compile(options) { factory.setup(this, options); return factory.create(options); } } Object.defineProperties(AsyncParallelBailHook.prototype, { _call: { value: undefined, configurable: true, writable: true } }); module.exports = AsyncParallelBailHook; PK˥|[lib/AsyncParallelHook.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Hook = require("./Hook"); 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 { compile(options) { factory.setup(this, options); return factory.create(options); } } Object.defineProperties(AsyncParallelHook.prototype, { _call: { value: undefined, configurable: true, writable: true } }); module.exports = AsyncParallelHook; PK˥|[q$lib/AsyncSeriesBailHook.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Hook = require("./Hook"); const HookCodeFactory = require("./HookCodeFactory"); class AsyncSeriesBailHookCodeFactory extends HookCodeFactory { content({ onError, onResult, resultReturns, 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`, resultReturns, onDone }); } } const factory = new AsyncSeriesBailHookCodeFactory(); class AsyncSeriesBailHook extends Hook { compile(options) { factory.setup(this, options); return factory.create(options); } } Object.defineProperties(AsyncSeriesBailHook.prototype, { _call: { value: undefined, configurable: true, writable: true } }); module.exports = AsyncSeriesBailHook; PK˥|[}lib/AsyncSeriesHook.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Hook = require("./Hook"); 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 { compile(options) { factory.setup(this, options); return factory.create(options); } } Object.defineProperties(AsyncSeriesHook.prototype, { _call: { value: undefined, configurable: true, writable: true } }); module.exports = AsyncSeriesHook; PK˥|[EH<  lib/AsyncSeriesLoopHook.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Hook = require("./Hook"); 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 { compile(options) { factory.setup(this, options); return factory.create(options); } } Object.defineProperties(AsyncSeriesLoopHook.prototype, { _call: { value: undefined, configurable: true, writable: true } }); module.exports = AsyncSeriesLoopHook; PK˥|[yglib/AsyncSeriesWaterfallHook.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Hook = require("./Hook"); 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 { constructor(args) { super(args); if (args.length < 1) throw new Error("Waterfall hooks must have at least one argument"); } compile(options) { factory.setup(this, options); return factory.create(options); } } Object.defineProperties(AsyncSeriesWaterfallHook.prototype, { _call: { value: undefined, configurable: true, writable: true } }); module.exports = AsyncSeriesWaterfallHook; PK˥|[' lib/Hook.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; class Hook { constructor(args) { if (!Array.isArray(args)) args = []; this._args = args; this.taps = []; this.interceptors = []; this.call = this._call; this.promise = this._promise; this.callAsync = this._callAsync; this._x = undefined; } compile(options) { throw new Error("Abstract: should be overriden"); } _createCall(type) { return this.compile({ taps: this.taps, interceptors: this.interceptors, args: this._args, type: type }); } tap(options, fn) { if (typeof options === "string") options = { name: options }; if (typeof options !== "object" || options === null) throw new Error( "Invalid arguments to tap(options: Object, fn: function)" ); options = Object.assign({ type: "sync", fn: fn }, options); if (typeof options.name !== "string" || options.name === "") throw new Error("Missing name for tap"); options = this._runRegisterInterceptors(options); this._insert(options); } tapAsync(options, fn) { if (typeof options === "string") options = { name: options }; if (typeof options !== "object" || options === null) throw new Error( "Invalid arguments to tapAsync(options: Object, fn: function)" ); options = Object.assign({ type: "async", fn: fn }, options); if (typeof options.name !== "string" || options.name === "") throw new Error("Missing name for tapAsync"); options = this._runRegisterInterceptors(options); this._insert(options); } tapPromise(options, fn) { if (typeof options === "string") options = { name: options }; if (typeof options !== "object" || options === null) throw new Error( "Invalid arguments to tapPromise(options: Object, fn: function)" ); options = Object.assign({ type: "promise", fn: fn }, options); if (typeof options.name !== "string" || options.name === "") 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) { const mergeOptions = opt => Object.assign({}, options, typeof opt === "string" ? { name: opt } : opt); // Prevent creating endless prototype chains options = Object.assign({}, options, this._withOptions); const base = this._withOptionsBase || this; const newHook = Object.create(base); (newHook.tapAsync = (opt, fn) => base.tapAsync(mergeOptions(opt), fn)), (newHook.tap = (opt, fn) => base.tap(mergeOptions(opt), fn)); newHook.tapPromise = (opt, fn) => base.tapPromise(mergeOptions(opt), fn); newHook._withOptions = options; newHook._withOptionsBase = base; return newHook; } isUsed() { return this.taps.length > 0 || this.interceptors.length > 0; } intercept(interceptor) { this._resetCompilation(); 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]); } } _resetCompilation() { this.call = this._call; this.callAsync = this._callAsync; this.promise = this._promise; } _insert(item) { this._resetCompilation(); let before; if (typeof item.before === "string") before = new Set([item.before]); else if (Array.isArray(item.before)) { before = new Set(item.before); } let stage = 0; if (typeof item.stage === "number") stage = item.stage; let i = this.taps.length; while (i > 0) { i--; const x = this.taps[i]; this.taps[i + 1] = x; const xStage = x.stage || 0; if (before) { if (before.has(x.name)) { before.delete(x.name); continue; } if (before.size > 0) { continue; } } if (xStage > stage) { continue; } i++; break; } this.taps[i] = item; } } function createCompileDelegate(name, type) { return function lazyCompileHook(...args) { this[name] = this._createCall(type); return this[name](...args); }; } Object.defineProperties(Hook.prototype, { _call: { value: createCompileDelegate("call", "sync"), configurable: true, writable: true }, _promise: { value: createCompileDelegate("promise", "promise"), configurable: true, writable: true }, _callAsync: { value: createCompileDelegate("callAsync", "async"), configurable: true, writable: true } }); module.exports = Hook; PK˥|[%?(?(lib/HookCodeFactory.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; class HookCodeFactory { constructor(config) { this.config = config; this.options = undefined; this._args = undefined; } create(options) { this.init(options); let fn; switch (this.options.type) { case "sync": fn = new Function( this.args(), '"use strict";\n' + this.header() + this.content({ onError: err => `throw ${err};\n`, onResult: result => `return ${result};\n`, resultReturns: true, onDone: () => "", rethrowIfPossible: true }) ); break; case "async": fn = new Function( this.args({ after: "_callback" }), '"use strict";\n' + this.header() + this.content({ onError: err => `_callback(${err});\n`, onResult: result => `_callback(null, ${result});\n`, onDone: () => "_callback();\n" }) ); break; case "promise": let errorHelperUsed = false; const content = this.content({ onError: err => { errorHelperUsed = true; return `_error(${err});\n`; }, onResult: result => `_resolve(${result});\n`, onDone: () => "_resolve();\n" }); let code = ""; code += '"use strict";\n'; code += "return new Promise((_resolve, _reject) => {\n"; if (errorHelperUsed) { code += "var _sync = true;\n"; code += "function _error(_err) {\n"; code += "if(_sync)\n"; code += "_resolve(Promise.resolve().then(() => { throw _err; }));\n"; code += "else\n"; code += "_reject(_err);\n"; code += "};\n"; } code += this.header(); code += content; if (errorHelperUsed) { code += "_sync = false;\n"; } code += "});\n"; fn = new Function(this.args(), code); break; } this.deinit(); return fn; } setup(instance, options) { instance._x = options.taps.map(t => t.fn); } /** * @param {{ type: "sync" | "promise" | "async", taps: Array, interceptors: Array }} options */ init(options) { this.options = options; this._args = options.args.slice(); } deinit() { this.options = undefined; this._args = undefined; } header() { let code = ""; if (this.needContext()) { code += "var _context = {};\n"; } else { code += "var _context;\n"; } code += "var _x = this._x;\n"; if (this.options.interceptors.length > 0) { code += "var _taps = this.taps;\n"; code += "var _interceptors = this.interceptors;\n"; } for (let i = 0; i < this.options.interceptors.length; i++) { const interceptor = this.options.interceptors[i]; if (interceptor.call) { code += `${this.getInterceptor(i)}.call(${this.args({ before: interceptor.context ? "_context" : undefined })});\n`; } } return code; } needContext() { for (const tap of this.options.taps) if (tap.context) return true; return false; } callTap(tapIndex, { onError, onResult, onDone, rethrowIfPossible }) { let code = ""; let hasTapCached = false; for (let i = 0; i < this.options.interceptors.length; i++) { const interceptor = this.options.interceptors[i]; if (interceptor.tap) { if (!hasTapCached) { code += `var _tap${tapIndex} = ${this.getTap(tapIndex)};\n`; hasTapCached = true; } code += `${this.getInterceptor(i)}.tap(${ interceptor.context ? "_context, " : "" }_tap${tapIndex});\n`; } } code += `var _fn${tapIndex} = ${this.getTapFn(tapIndex)};\n`; const tap = this.options.taps[tapIndex]; switch (tap.type) { case "sync": if (!rethrowIfPossible) { code += `var _hasError${tapIndex} = false;\n`; code += "try {\n"; } if (onResult) { code += `var _result${tapIndex} = _fn${tapIndex}(${this.args({ before: tap.context ? "_context" : undefined })});\n`; } else { code += `_fn${tapIndex}(${this.args({ before: tap.context ? "_context" : undefined })});\n`; } if (!rethrowIfPossible) { code += "} catch(_err) {\n"; code += `_hasError${tapIndex} = true;\n`; code += onError("_err"); code += "}\n"; code += `if(!_hasError${tapIndex}) {\n`; } if (onResult) { code += onResult(`_result${tapIndex}`); } if (onDone) { code += onDone(); } if (!rethrowIfPossible) { code += "}\n"; } break; case "async": let cbCode = ""; if (onResult) cbCode += `(_err${tapIndex}, _result${tapIndex}) => {\n`; else cbCode += `_err${tapIndex} => {\n`; cbCode += `if(_err${tapIndex}) {\n`; cbCode += onError(`_err${tapIndex}`); cbCode += "} else {\n"; if (onResult) { cbCode += onResult(`_result${tapIndex}`); } if (onDone) { cbCode += onDone(); } cbCode += "}\n"; cbCode += "}"; code += `_fn${tapIndex}(${this.args({ before: tap.context ? "_context" : undefined, after: cbCode })});\n`; break; case "promise": code += `var _hasResult${tapIndex} = false;\n`; code += `var _promise${tapIndex} = _fn${tapIndex}(${this.args({ before: tap.context ? "_context" : undefined })});\n`; code += `if (!_promise${tapIndex} || !_promise${tapIndex}.then)\n`; code += ` throw new Error('Tap function (tapPromise) did not return promise (returned ' + _promise${tapIndex} + ')');\n`; code += `_promise${tapIndex}.then(_result${tapIndex} => {\n`; code += `_hasResult${tapIndex} = true;\n`; if (onResult) { code += onResult(`_result${tapIndex}`); } if (onDone) { code += onDone(); } code += `}, _err${tapIndex} => {\n`; code += `if(_hasResult${tapIndex}) throw _err${tapIndex};\n`; code += onError(`_err${tapIndex}`); code += "});\n"; break; } return code; } callTapsSeries({ onError, onResult, resultReturns, onDone, doneReturns, rethrowIfPossible }) { if (this.options.taps.length === 0) return onDone(); const firstAsync = this.options.taps.findIndex(t => t.type !== "sync"); const somethingReturns = resultReturns || doneReturns || false; let code = ""; let current = onDone; for (let j = this.options.taps.length - 1; j >= 0; j--) { const i = j; const unroll = current !== onDone && this.options.taps[i].type !== "sync"; if (unroll) { code += `function _next${i}() {\n`; code += current(); code += `}\n`; current = () => `${somethingReturns ? "return " : ""}_next${i}();\n`; } const done = current; const doneBreak = skipDone => { if (skipDone) return ""; return onDone(); }; const content = this.callTap(i, { onError: error => onError(i, error, done, doneBreak), onResult: onResult && (result => { return onResult(i, result, done, doneBreak); }), onDone: !onResult && done, rethrowIfPossible: rethrowIfPossible && (firstAsync < 0 || i < firstAsync) }); current = () => content; } code += current(); return code; } callTapsLooping({ onError, onDone, rethrowIfPossible }) { if (this.options.taps.length === 0) return onDone(); const syncOnly = this.options.taps.every(t => t.type === "sync"); let code = ""; if (!syncOnly) { code += "var _looper = () => {\n"; code += "var _loopAsync = false;\n"; } code += "var _loop;\n"; code += "do {\n"; code += "_loop = false;\n"; for (let i = 0; i < this.options.interceptors.length; i++) { const interceptor = this.options.interceptors[i]; if (interceptor.loop) { code += `${this.getInterceptor(i)}.loop(${this.args({ before: interceptor.context ? "_context" : undefined })});\n`; } } code += this.callTapsSeries({ onError, onResult: (i, result, next, doneBreak) => { let code = ""; code += `if(${result} !== undefined) {\n`; code += "_loop = true;\n"; if (!syncOnly) code += "if(_loopAsync) _looper();\n"; code += doneBreak(true); code += `} else {\n`; code += next(); code += `}\n`; return code; }, onDone: onDone && (() => { let code = ""; code += "if(!_loop) {\n"; code += onDone(); code += "}\n"; return code; }), rethrowIfPossible: rethrowIfPossible && syncOnly }); code += "} while(_loop);\n"; if (!syncOnly) { code += "_loopAsync = true;\n"; code += "};\n"; code += "_looper();\n"; } return code; } callTapsParallel({ onError, onResult, onDone, rethrowIfPossible, onTap = (i, run) => run() }) { if (this.options.taps.length <= 1) { return this.callTapsSeries({ onError, onResult, onDone, rethrowIfPossible }); } let code = ""; code += "do {\n"; code += `var _counter = ${this.options.taps.length};\n`; if (onDone) { code += "var _done = () => {\n"; code += onDone(); code += "};\n"; } for (let i = 0; i < this.options.taps.length; i++) { const done = () => { if (onDone) return "if(--_counter === 0) _done();\n"; else return "--_counter;"; }; const doneBreak = skipDone => { if (skipDone || !onDone) return "_counter = 0;\n"; else return "_counter = 0;\n_done();\n"; }; code += "if(_counter <= 0) break;\n"; code += onTap( i, () => this.callTap(i, { onError: error => { let code = ""; code += "if(_counter > 0) {\n"; code += onError(i, error, done, doneBreak); code += "}\n"; return code; }, onResult: onResult && (result => { let code = ""; code += "if(_counter > 0) {\n"; code += onResult(i, result, done, doneBreak); code += "}\n"; return code; }), onDone: !onResult && (() => { return done(); }), rethrowIfPossible }), done, doneBreak ); } code += "} while(false);\n"; return code; } args({ before, after } = {}) { let allArgs = this._args; if (before) allArgs = [before].concat(allArgs); if (after) allArgs = allArgs.concat(after); if (allArgs.length === 0) { return ""; } else { return allArgs.join(", "); } } getTapFn(idx) { return `_x[${idx}]`; } getTap(idx) { return `_taps[${idx}]`; } getInterceptor(idx) { return `_interceptors[${idx}]`; } } module.exports = HookCodeFactory; PK˥|[ỗlib/HookMap.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; class HookMap { constructor(factory) { this._map = new Map(); this._factory = factory; this._interceptors = []; } get(key) { return this._map.get(key); } for(key) { const hook = this.get(key); if (hook !== undefined) { return hook; } let newHook = this._factory(key); const interceptors = this._interceptors; for (let i = 0; i < interceptors.length; i++) { newHook = interceptors[i].factory(key, newHook); } this._map.set(key, newHook); return newHook; } intercept(interceptor) { this._interceptors.push( Object.assign( { factory: (key, hook) => hook }, interceptor ) ); } tap(key, options, fn) { return this.for(key).tap(options, fn); } tapAsync(key, options, fn) { return this.for(key).tapAsync(options, fn); } tapPromise(key, options, fn) { return this.for(key).tapPromise(options, fn); } } module.exports = HookMap; PK˥|[zfGGlib/MultiHook.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Hook = require("./Hook"); class MultiHook { constructor(hooks) { this.hooks = hooks; } tap(options, fn) { for (const hook of this.hooks) { hook.tap(options, fn); } } tapAsync(options, fn) { for (const hook of this.hooks) { hook.tapAsync(options, fn); } } tapPromise(options, fn) { for (const hook of this.hooks) { hook.tapPromise(options, fn); } } isUsed() { for (const hook of this.hooks) { if (hook.isUsed()) return true; } return false; } intercept(interceptor) { for (const hook of this.hooks) { hook.intercept(interceptor); } } withOptions(options) { return new MultiHook(this.hooks.map(h => h.withOptions(options))); } } module.exports = MultiHook; PK˥|[;lib/SyncBailHook.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Hook = require("./Hook"); const HookCodeFactory = require("./HookCodeFactory"); class SyncBailHookCodeFactory extends HookCodeFactory { content({ onError, onResult, resultReturns, 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`, resultReturns, onDone, rethrowIfPossible }); } } const factory = new SyncBailHookCodeFactory(); class SyncBailHook extends Hook { tapAsync() { throw new Error("tapAsync is not supported on a SyncBailHook"); } tapPromise() { throw new Error("tapPromise is not supported on a SyncBailHook"); } compile(options) { factory.setup(this, options); return factory.create(options); } } module.exports = SyncBailHook; PK˥|[ 35lib/SyncHook.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Hook = require("./Hook"); const HookCodeFactory = require("./HookCodeFactory"); class SyncHookCodeFactory extends HookCodeFactory { content({ onError, onDone, rethrowIfPossible }) { return this.callTapsSeries({ onError: (i, err) => onError(err), onDone, rethrowIfPossible }); } } const factory = new SyncHookCodeFactory(); class SyncHook extends Hook { tapAsync() { throw new Error("tapAsync is not supported on a SyncHook"); } tapPromise() { throw new Error("tapPromise is not supported on a SyncHook"); } compile(options) { factory.setup(this, options); return factory.create(options); } } module.exports = SyncHook; PK˥|[ING  lib/SyncLoopHook.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Hook = require("./Hook"); const HookCodeFactory = require("./HookCodeFactory"); class SyncLoopHookCodeFactory extends HookCodeFactory { content({ onError, onDone, rethrowIfPossible }) { return this.callTapsLooping({ onError: (i, err) => onError(err), onDone, rethrowIfPossible }); } } const factory = new SyncLoopHookCodeFactory(); class SyncLoopHook extends Hook { tapAsync() { throw new Error("tapAsync is not supported on a SyncLoopHook"); } tapPromise() { throw new Error("tapPromise is not supported on a SyncLoopHook"); } compile(options) { factory.setup(this, options); return factory.create(options); } } module.exports = SyncLoopHook; PK˥|[-vlib/SyncWaterfallHook.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Hook = require("./Hook"); const HookCodeFactory = require("./HookCodeFactory"); class SyncWaterfallHookCodeFactory extends HookCodeFactory { content({ onError, onResult, resultReturns, 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]), doneReturns: resultReturns, rethrowIfPossible }); } } const factory = new SyncWaterfallHookCodeFactory(); class SyncWaterfallHook extends Hook { constructor(args) { super(args); if (args.length < 1) throw new Error("Waterfall hooks must have at least one argument"); } tapAsync() { throw new Error("tapAsync is not supported on a SyncWaterfallHook"); } tapPromise() { throw new Error("tapPromise is not supported on a SyncWaterfallHook"); } compile(options) { factory.setup(this, options); return factory.create(options); } } module.exports = SyncWaterfallHook; PK˥|[5lib/Tapable.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const util = require("util"); const SyncBailHook = require("./SyncBailHook"); function Tapable() { this._pluginCompat = new SyncBailHook(["options"]); this._pluginCompat.tap( { name: "Tapable camelCase", stage: 100 }, options => { options.names.add( options.name.replace(/[- ]([a-z])/g, (str, ch) => ch.toUpperCase()) ); } ); this._pluginCompat.tap( { name: "Tapable this.hooks", stage: 200 }, options => { let hook; for (const name of options.names) { hook = this.hooks[name]; if (hook !== undefined) { break; } } if (hook !== undefined) { const tapOpt = { name: options.fn.name || "unnamed compat plugin", stage: options.stage || 0 }; if (options.async) hook.tapAsync(tapOpt, options.fn); else hook.tap(tapOpt, options.fn); return true; } } ); } module.exports = Tapable; Tapable.addCompatLayer = function addCompatLayer(instance) { Tapable.call(instance); instance.plugin = Tapable.prototype.plugin; instance.apply = Tapable.prototype.apply; }; Tapable.prototype.plugin = util.deprecate(function plugin(name, fn) { if (Array.isArray(name)) { name.forEach(function(name) { this.plugin(name, fn); }, this); return; } const result = this._pluginCompat.call({ name: name, fn: fn, names: new Set([name]) }); if (!result) { throw new Error( `Plugin could not be registered at '${name}'. Hook was not found.\n` + "BREAKING CHANGE: There need to exist a hook at 'this.hooks'. " + "To create a compatibility layer for this hook, hook into 'this._pluginCompat'." ); } }, "Tapable.plugin is deprecated. Use new API on `.hooks` instead"); Tapable.prototype.apply = util.deprecate(function apply() { for (var i = 0; i < arguments.length; i++) { arguments[i].apply(this); } }, "Tapable.apply is deprecated. Call apply on the plugin directly instead"); PK˥|[P lib/index.jsnuIw/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; exports.__esModule = true; exports.Tapable = require("./Tapable"); exports.SyncHook = require("./SyncHook"); exports.SyncBailHook = require("./SyncBailHook"); exports.SyncWaterfallHook = require("./SyncWaterfallHook"); exports.SyncLoopHook = require("./SyncLoopHook"); exports.AsyncParallelHook = require("./AsyncParallelHook"); exports.AsyncParallelBailHook = require("./AsyncParallelBailHook"); exports.AsyncSeriesHook = require("./AsyncSeriesHook"); exports.AsyncSeriesBailHook = require("./AsyncSeriesBailHook"); exports.AsyncSeriesWaterfallHook = require("./AsyncSeriesWaterfallHook"); exports.HookMap = require("./HookMap"); exports.MultiHook = require("./MultiHook"); PK˥|[55LICENSEnuIwThe MIT License Copyright (c) Tobias Koppers @sokra Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK˥|[Lw!! README.mdnuIw# Tapable The tapable package expose many Hook classes, which can be used to create hooks for plugins. ``` javascript const { SyncHook, SyncBailHook, SyncWaterfallHook, SyncLoopHook, AsyncParallelHook, AsyncParallelBailHook, AsyncSeriesHook, AsyncSeriesBailHook, AsyncSeriesWaterfallHook } = require("tapable"); ``` ## Installation ``` shell npm install --save tapable ``` ## Usage All Hook constructors take one optional argument, which is a list of argument names as strings. ``` js const hook = new SyncHook(["arg1", "arg2", "arg3"]); ``` The best practice is to expose all hooks of a class in a `hooks` property: ``` js class Car { constructor() { this.hooks = { accelerate: new SyncHook(["newSpeed"]), brake: new SyncHook(), calculateRoutes: new AsyncParallelHook(["source", "target", "routesList"]) }; } /* ... */ } ``` Other people can now use these hooks: ``` js const myCar = new Car(); // Use the tap method to add a consument myCar.hooks.brake.tap("WarningLampPlugin", () => warningLamp.on()); ``` It's required to pass a name to identify the plugin/reason. You may receive arguments: ``` js myCar.hooks.accelerate.tap("LoggerPlugin", newSpeed => console.log(`Accelerating to ${newSpeed}`)); ``` For sync hooks, `tap` is the only valid method to add a plugin. Async hooks also support async plugins: ``` js myCar.hooks.calculateRoutes.tapPromise("GoogleMapsPlugin", (source, target, routesList) => { // return a promise return google.maps.findRoute(source, target).then(route => { routesList.add(route); }); }); myCar.hooks.calculateRoutes.tapAsync("BingMapsPlugin", (source, target, routesList, callback) => { bing.findRoute(source, target, (err, route) => { if(err) return callback(err); routesList.add(route); // call the callback callback(); }); }); // You can still use sync plugins myCar.hooks.calculateRoutes.tap("CachedRoutesPlugin", (source, target, routesList) => { const cachedRoute = cache.get(source, target); if(cachedRoute) routesList.add(cachedRoute); }) ``` The class declaring these hooks need to call them: ``` js class Car { /* ... */ setSpeed(newSpeed) { this.hooks.accelerate.call(newSpeed); } useNavigationSystemPromise(source, target) { const routesList = new List(); return this.hooks.calculateRoutes.promise(source, target, routesList).then(() => { return routesList.getRoutes(); }); } useNavigationSystemAsync(source, target, callback) { const routesList = new List(); this.hooks.calculateRoutes.callAsync(source, target, routesList, err => { if(err) return callback(err); callback(null, routesList.getRoutes()); }); } } ``` The Hook will compile a method with the most efficient way of running your plugins. It generates code depending on: * The number of registered plugins (none, one, many) * The kind of registered plugins (sync, async, promise) * The used call method (sync, async, promise) * The number of arguments * Whether interception is used This ensures fastest possible execution. ## Hook types Each hook can be tapped with one or several functions. How they are executed depends on the hook type: * Basic hook (without “Waterfall”, “Bail” or “Loop” in its name). This hook simply calls every function it tapped in a row. * __Waterfall__. A waterfall hook also calls each tapped function in a row. Unlike the basic hook, it passes a return value from each function to the next function. * __Bail__. A bail hook allows exiting early. When any of the tapped function returns anything, the bail hook will stop executing the remaining ones. * __Loop__. TODO Additionally, hooks can be synchronous or asynchronous. To reflect this, there’re “Sync”, “AsyncSeries”, and “AsyncParallel” hook classes: * __Sync__. A sync hook can only be tapped with synchronous functions (using `myHook.tap()`). * __AsyncSeries__. An async-series hook can be tapped with synchronous, callback-based and promise-based functions (using `myHook.tap()`, `myHook.tapAsync()` and `myHook.tapPromise()`). They call each async method in a row. * __AsyncParallel__. An async-parallel hook can also be tapped with synchronous, callback-based and promise-based functions (using `myHook.tap()`, `myHook.tapAsync()` and `myHook.tapPromise()`). However, they run each async method in parallel. The hook type is reflected in its class name. E.g., `AsyncSeriesWaterfallHook` allows asynchronous functions and runs them in series, passing each function’s return value into the next function. ## Interception All Hooks offer an additional interception API: ``` js myCar.hooks.calculateRoutes.intercept({ call: (source, target, routesList) => { console.log("Starting to calculate routes"); }, register: (tapInfo) => { // tapInfo = { type: "promise", name: "GoogleMapsPlugin", fn: ... } console.log(`${tapInfo.name} is doing its job`); return tapInfo; // may return a new tapInfo object } }) ``` **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. ## Context Plugins and interceptors can opt-in to access an optional `context` object, which can be used to pass arbitrary values to subsequent plugins and interceptors. ``` js myCar.hooks.accelerate.intercept({ context: true, tap: (context, tapInfo) => { // tapInfo = { type: "sync", name: "NoisePlugin", fn: ... } console.log(`${tapInfo.name} is doing it's job`); // `context` starts as an empty object if at least one plugin uses `context: true`. // If no plugins use `context: true`, then `context` is undefined. if (context) { // Arbitrary properties can be added to `context`, which plugins can then access. context.hasMuffler = true; } } }); myCar.hooks.accelerate.tap({ name: "NoisePlugin", context: true }, (context, newSpeed) => { if (context && context.hasMuffler) { console.log("Silence..."); } else { console.log("Vroom!"); } }); ``` ## 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) => 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) => 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, 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]); ``` PK˥|[ % package.jsonnuIw{ "_args": [ [ "tapable@1.1.3", "/home/freeclou/app.optimyar.com/backend" ] ], "_from": "tapable@1.1.3", "_id": "tapable@1.1.3", "_inBundle": false, "_integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "_location": "/tapable", "_phantomChildren": {}, "_requested": { "type": "version", "registry": true, "raw": "tapable@1.1.3", "name": "tapable", "escapedName": "tapable", "rawSpec": "1.1.3", "saveSpec": null, "fetchSpec": "1.1.3" }, "_requiredBy": [ "/enhanced-resolve", "/html-webpack-plugin", "/webpack" ], "_resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", "_spec": "1.1.3", "_where": "/home/freeclou/app.optimyar.com/backend", "author": { "name": "Tobias Koppers @sokra" }, "bugs": { "url": "https://github.com/webpack/tapable/issues" }, "description": "Just a little module for plugins.", "devDependencies": { "babel-core": "^6.26.0", "babel-jest": "^21.0.2", "babel-polyfill": "^6.26.0", "babel-preset-env": "^1.6.0", "codecov": "^2.3.0", "jest": "^21.0.4", "prettier": "^1.13.2" }, "engines": { "node": ">=6" }, "files": [ "lib", "!lib/__tests__" ], "homepage": "https://github.com/webpack/tapable", "jest": { "transform": { "__tests__[\\\\/].+\\.js$": "babel-jest" } }, "license": "MIT", "main": "lib/index.js", "name": "tapable", "repository": { "type": "git", "url": "git+ssh://git@github.com/webpack/tapable.git" }, "scripts": { "pretty": "prettier --write lib/*.js lib/__tests__/*.js", "test": "jest", "travis": "jest --coverage && codecov" }, "version": "1.1.3" } PK˥|[8!Elib/AsyncParallelBailHook.jsnuIwPK˥|[ lib/AsyncParallelHook.jsnuIwPK˥|[q$O lib/AsyncSeriesBailHook.jsnuIwPK˥|[}Llib/AsyncSeriesHook.jsnuIwPK˥|[EH<  lib/AsyncSeriesLoopHook.jsnuIwPK˥|[yglib/AsyncSeriesWaterfallHook.jsnuIwPK˥|[' lib/Hook.jsnuIwPK˥|[%?(?(.lib/HookCodeFactory.jsnuIwPK˥|[ỗVlib/HookMap.jsnuIwPK˥|[zfGGZlib/MultiHook.jsnuIwPK˥|[;d^lib/SyncBailHook.jsnuIwPK˥|[ 35qblib/SyncHook.jsnuIwPK˥|[ING  elib/SyncLoopHook.jsnuIwPK˥|[-vilib/SyncWaterfallHook.jsnuIwPK˥|[5Gnlib/Tapable.jsnuIwPK˥|[P ]vlib/index.jsnuIwPK˥|[55yLICENSEnuIwPK˥|[Lw!! ~README.mdnuIwPK˥|[ % package.jsonnuIwPK