@feathersjs/hooks
Version:
Async middleware for JavaScript and TypeScript
106 lines (105 loc) • 4.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.legacyDecorator = exports.hookDecorator = exports.objectHooks = exports.functionHooks = exports.getOriginal = void 0;
const compose_js_1 = require("./compose.js");
const base_js_1 = require("./base.js");
const utils_js_1 = require("./utils.js");
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 = (0, base_js_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 (0, compose_js_1.compose)(hookChain).call(this, context);
};
(0, utils_js_1.copyFnProperties)(wrapper, fn);
(0, utils_js_1.copyProperties)(wrapper, fn);
(0, base_js_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) {
if (Array.isArray(hooks)) {
return (0, base_js_1.setMiddleware)(obj, hooks);
}
for (const method of Object.keys(hooks)) {
const target = typeof obj[method] === 'function' ? obj : obj.prototype;
const fn = target && target[method];
if (typeof fn !== 'function') {
throw new Error(`Can not apply hooks. '${method}' is not a function`);
}
const manager = (0, base_js_1.convertOptions)(hooks[method]);
target[method] = functionHooks(fn, manager.props({ method }));
}
return obj;
}
exports.objectHooks = objectHooks;
const hookDecorator = (managerOrMiddleware) => {
return (target, context) => {
const manager = (0, base_js_1.convertOptions)(managerOrMiddleware);
if (context.kind === 'class') {
(0, base_js_1.setManager)(target.prototype, manager);
return target;
}
else if (context.kind === 'method') {
const method = String(context.name);
return functionHooks(target, manager.props({ method }));
}
throw new Error('Can not apply hooks.');
};
};
exports.hookDecorator = hookDecorator;
const legacyDecorator = (managerOrMiddleware) => {
const wrapper = (_target, method, descriptor) => {
const manager = (0, base_js_1.convertOptions)(managerOrMiddleware);
if (!descriptor) {
(0, base_js_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.legacyDecorator = legacyDecorator;