1 | import {
|
2 | getManager, HookContextData, HookManager, HookMap, HOOKS, hooks, Middleware
|
3 | } from '../dependencies';
|
4 | import {
|
5 | Service, ServiceOptions, HookContext, FeathersService, Application
|
6 | } from '../declarations';
|
7 | import { defaultServiceArguments, getHookMethods } from '../service';
|
8 | import {
|
9 | collectRegularHooks,
|
10 | enableRegularHooks
|
11 | } from './regular';
|
12 |
|
13 | export {
|
14 | fromBeforeHook,
|
15 | fromBeforeHooks,
|
16 | fromAfterHook,
|
17 | fromAfterHooks,
|
18 | fromErrorHook,
|
19 | fromErrorHooks
|
20 | } from './regular';
|
21 |
|
22 | export 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 |
|
32 | export 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 |
|
62 | export 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 | }
|