UNPKG

3.31 kBPlain TextView Raw
1import {
2 getManager, HookContextData, HookManager, HookMap, HOOKS, hooks, Middleware
3} from '../dependencies';
4import {
5 Service, ServiceOptions, HookContext, FeathersService, Application
6} from '../declarations';
7import { defaultServiceArguments, getHookMethods } from '../service';
8import {
9 collectRegularHooks,
10 enableRegularHooks
11} from './regular';
12
13export {
14 fromBeforeHook,
15 fromBeforeHooks,
16 fromAfterHook,
17 fromAfterHooks,
18 fromErrorHook,
19 fromErrorHooks
20} from './regular';
21
22export function createContext (service: Service, method: string, data: HookContextData = {}) {
23 const createContext = (service as any)[method].createContext;
24
25 if (typeof createContext !== 'function') {
26 throw new Error(`Can not create context for method ${method}`);
27 }
28
29 return createContext(data) as HookContext;
30}
31
32export class FeathersHookManager<A> extends HookManager {
33 constructor (public app: A, public method: string) {
34 super();
35 this._middleware = [];
36 }
37
38 collectMiddleware (self: any, args: any[]): Middleware[] {
39 const app = this.app as any as Application;
40 const appHooks = app.appHooks[HOOKS].concat(app.appHooks[this.method] || []);
41 const regularAppHooks = collectRegularHooks(this.app, this.method);
42 const middleware = super.collectMiddleware(self, args);
43 const regularHooks = collectRegularHooks(self, this.method);
44
45 return [...appHooks, ...regularAppHooks, ...middleware, ...regularHooks];
46 }
47
48 initializeContext (self: any, args: any[], context: HookContext) {
49 const ctx = super.initializeContext(self, args, context);
50
51 ctx.params = ctx.params || {};
52
53 return ctx;
54 }
55
56 middleware (mw: Middleware[]) {
57 this._middleware.push(...mw);
58 return this;
59 }
60}
61
62export function hookMixin<A> (
63 this: A, service: FeathersService<A>, path: string, options: ServiceOptions
64) {
65 if (typeof service.hooks === 'function') {
66 return service;
67 }
68
69 const app = this;
70 const hookMethods = getHookMethods(service, options);
71
72 const serviceMethodHooks = hookMethods.reduce((res, method) => {
73 const params = (defaultServiceArguments as any)[method] || [ 'data', 'params' ];
74
75 res[method] = new FeathersHookManager<A>(app, method)
76 .params(...params)
77 .props({
78 app,
79 path,
80 method,
81 service,
82 event: null,
83 type: null,
84 get statusCode () {
85 return this.http?.status;
86 },
87 set statusCode (value: number) {
88 (this.http ||= {}).status = value;
89 }
90 });
91
92 return res;
93 }, {} as HookMap);
94
95 const handleRegularHooks = enableRegularHooks(service, hookMethods);
96
97 hooks(service, serviceMethodHooks);
98
99 service.hooks = function (this: any, hookOptions: any) {
100 if (hookOptions.before || hookOptions.after || hookOptions.error) {
101 return handleRegularHooks.call(this, hookOptions);
102 }
103
104 if (Array.isArray(hookOptions)) {
105 return hooks(this, hookOptions);
106 }
107
108 Object.keys(hookOptions).forEach(method => {
109 const manager = getManager(this[method]);
110
111 if (!(manager instanceof FeathersHookManager)) {
112 throw new Error(`Method ${method} is not a Feathers hooks enabled service method`);
113 }
114
115 manager.middleware(hookOptions[method]);
116 });
117
118 return this;
119 }
120
121 return service;
122}