"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.hookDecorator = exports.objectHooks = exports.functionHooks = exports.getOriginal = void 0; const compose_1 = require("./compose"); const base_1 = require("./base"); const utils_1 = require("./utils"); function getOriginal(fn) { return typeof fn.original === 'function' ? getOriginal(fn.original) : fn; } exports.getOriginal = getOriginal; function functionHooks(fn, managerOrMiddleware) { if (typeof fn !== 'function') { throw new Error('Can not apply hooks to non-function'); } const manager = base_1.convertOptions(managerOrMiddleware); const wrapper = function (...args) { const { Context, original } = wrapper; // If we got passed an existing HookContext instance, we want to return it as well const returnContext = args[args.length - 1] instanceof Context; // Use existing context or default const base = returnContext ? args.pop() : new Context(); // Initialize the context const context = manager.initializeContext(this, args, base); // Assemble the hook chain const hookChain = [ // Return `ctx.result` or the context (ctx, next) => next().then(() => returnContext ? ctx : ctx.result) ]; // Create the hook chain by calling the `collectMiddleware function const mw = manager.collectMiddleware(this, args); if (mw) { Array.prototype.push.apply(hookChain, mw); } // Runs the actual original method if `ctx.result` is not already set hookChain.push((ctx, next) => { if (!Object.prototype.hasOwnProperty.call(context, 'result')) { return Promise.resolve(original.apply(this, ctx.arguments)).then(result => { ctx.result = result; return next(); }); } return next(); }); return compose_1.compose(hookChain).call(this, context); }; utils_1.copyFnProperties(wrapper, fn); utils_1.copyProperties(wrapper, fn); base_1.setManager(wrapper, manager); return Object.assign(wrapper, { original: getOriginal(fn), Context: manager.getContextClass(), createContext: (data = {}) => { return new wrapper.Context(data); } }); } exports.functionHooks = functionHooks; ; function objectHooks(_obj, hooks) { const obj = typeof _obj === 'function' ? _obj.prototype : _obj; if (Array.isArray(hooks)) { return base_1.setMiddleware(obj, hooks); } return Object.keys(hooks).reduce((result, method) => { const fn = obj[method]; if (typeof fn !== 'function') { throw new Error(`Can not apply hooks. '${method}' is not a function`); } const manager = base_1.convertOptions(hooks[method]); result[method] = functionHooks(fn, manager.props({ method })); return result; }, obj); } exports.objectHooks = objectHooks; ; const hookDecorator = (managerOrMiddleware) => { const wrapper = (_target, method, descriptor) => { const manager = base_1.convertOptions(managerOrMiddleware); if (!descriptor) { base_1.setManager(_target.prototype, manager); return _target; } const fn = descriptor.value; if (typeof fn !== 'function') { throw new Error(`Can not apply hooks. '${method}' is not a function`); } descriptor.value = functionHooks(fn, manager.props({ method })); return descriptor; }; return wrapper; }; exports.hookDecorator = hookDecorator; //# sourceMappingURL=hooks.js.map