@feathersjs/feathers 5.0.0-pre.14 → 5.0.0-pre.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/lib/application.d.ts +11 -11
- package/lib/application.js +5 -5
- package/lib/application.js.map +1 -1
- package/lib/declarations.d.ts +51 -33
- package/lib/hooks/index.d.ts +2 -3
- package/lib/hooks/index.js +24 -12
- package/lib/hooks/index.js.map +1 -1
- package/lib/hooks/regular.d.ts +12 -0
- package/lib/hooks/regular.js +169 -0
- package/lib/hooks/regular.js.map +1 -0
- package/lib/service.js +1 -0
- package/lib/service.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +6 -6
- package/src/application.ts +22 -22
- package/src/declarations.ts +52 -37
- package/src/hooks/index.ts +27 -14
- package/src/hooks/regular.ts +207 -0
- package/src/service.ts +1 -0
- package/src/version.ts +1 -1
- package/lib/hooks/legacy.d.ts +0 -7
- package/lib/hooks/legacy.js +0 -126
- package/lib/hooks/legacy.js.map +0 -1
- package/src/hooks/legacy.ts +0 -150
package/lib/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "5.0.0-pre.
|
|
1
|
+
declare const _default: "5.0.0-pre.15";
|
|
2
2
|
export default _default;
|
package/lib/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@feathersjs/feathers",
|
|
3
3
|
"description": "A framework for real-time applications and REST API with JavaScript and TypeScript",
|
|
4
|
-
"version": "5.0.0-pre.
|
|
4
|
+
"version": "5.0.0-pre.15",
|
|
5
5
|
"homepage": "http://feathersjs.com",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -57,17 +57,17 @@
|
|
|
57
57
|
"access": "public"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@feathersjs/commons": "^5.0.0-pre.
|
|
60
|
+
"@feathersjs/commons": "^5.0.0-pre.15",
|
|
61
61
|
"@feathersjs/hooks": "^0.6.5",
|
|
62
62
|
"events": "^3.3.0"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@types/mocha": "^9.0.0",
|
|
66
|
-
"@types/node": "^16.
|
|
67
|
-
"mocha": "^9.1.
|
|
66
|
+
"@types/node": "^16.11.6",
|
|
67
|
+
"mocha": "^9.1.3",
|
|
68
68
|
"shx": "^0.3.3",
|
|
69
|
-
"ts-node": "^10.
|
|
69
|
+
"ts-node": "^10.4.0",
|
|
70
70
|
"typescript": "^4.4.4"
|
|
71
71
|
},
|
|
72
|
-
"gitHead": "
|
|
72
|
+
"gitHead": "8008bf4f8529a2a40b6a2f976c1f43ae13675693"
|
|
73
73
|
}
|
package/src/application.ts
CHANGED
|
@@ -15,34 +15,34 @@ import {
|
|
|
15
15
|
HookOptions,
|
|
16
16
|
FeathersService,
|
|
17
17
|
HookMap,
|
|
18
|
-
|
|
18
|
+
RegularHookMap
|
|
19
19
|
} from './declarations';
|
|
20
|
-
import {
|
|
20
|
+
import { enableRegularHooks } from './hooks/regular';
|
|
21
21
|
|
|
22
22
|
const debug = createDebug('@feathersjs/feathers');
|
|
23
23
|
|
|
24
|
-
export class Feathers<
|
|
25
|
-
services:
|
|
26
|
-
settings:
|
|
27
|
-
mixins: ServiceMixin<Application<
|
|
24
|
+
export class Feathers<Services, Settings> extends EventEmitter implements FeathersApplication<Services, Settings> {
|
|
25
|
+
services: Services = ({} as Services);
|
|
26
|
+
settings: Settings = ({} as Settings);
|
|
27
|
+
mixins: ServiceMixin<Application<Services, Settings>>[] = [ hookMixin, eventMixin ];
|
|
28
28
|
version: string = version;
|
|
29
29
|
_isSetup = false;
|
|
30
|
-
appHooks: HookMap<Application<
|
|
30
|
+
appHooks: HookMap<Application<Services, Settings>, any> = {
|
|
31
31
|
[HOOKS]: [ (eventHook as any) ]
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
private
|
|
34
|
+
private regularHooks: (this: any, allHooks: any) => any;
|
|
35
35
|
|
|
36
36
|
constructor () {
|
|
37
37
|
super();
|
|
38
|
-
this.
|
|
38
|
+
this.regularHooks = enableRegularHooks(this);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
get<L extends keyof
|
|
41
|
+
get<L extends keyof Settings & string> (name: L): Settings[L] {
|
|
42
42
|
return this.settings[name];
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
set<L extends keyof
|
|
45
|
+
set<L extends keyof Settings & string> (name: L, value: Settings[L]) {
|
|
46
46
|
this.settings[name] = value;
|
|
47
47
|
return this;
|
|
48
48
|
}
|
|
@@ -53,13 +53,13 @@ export class Feathers<ServiceTypes, AppSettings> extends EventEmitter implements
|
|
|
53
53
|
return this;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
defaultService (location: string): ServiceInterface
|
|
56
|
+
defaultService (location: string): ServiceInterface {
|
|
57
57
|
throw new Error(`Can not find service '${location}'`);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
service<L extends keyof
|
|
60
|
+
service<L extends keyof Services & string> (
|
|
61
61
|
location: L
|
|
62
|
-
): FeathersService<this, keyof any extends keyof
|
|
62
|
+
): FeathersService<this, keyof any extends keyof Services ? Service : Services[L]> {
|
|
63
63
|
const path = (stripSlashes(location) || '/') as L;
|
|
64
64
|
const current = this.services[path];
|
|
65
65
|
|
|
@@ -71,9 +71,9 @@ export class Feathers<ServiceTypes, AppSettings> extends EventEmitter implements
|
|
|
71
71
|
return current as any;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
use<L extends keyof
|
|
74
|
+
use<L extends keyof Services & string> (
|
|
75
75
|
path: L,
|
|
76
|
-
service: keyof any extends keyof
|
|
76
|
+
service: keyof any extends keyof Services ? ServiceInterface | Application : Services[L],
|
|
77
77
|
options?: ServiceOptions
|
|
78
78
|
): this {
|
|
79
79
|
if (typeof path !== 'string') {
|
|
@@ -118,16 +118,16 @@ export class Feathers<ServiceTypes, AppSettings> extends EventEmitter implements
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
hooks (hookMap: HookOptions<this, any>) {
|
|
121
|
-
const
|
|
121
|
+
const regularMap = hookMap as RegularHookMap<this, any>;
|
|
122
122
|
|
|
123
|
-
if (
|
|
124
|
-
return this.
|
|
123
|
+
if (regularMap.before || regularMap.after || regularMap.error) {
|
|
124
|
+
return this.regularHooks(regularMap);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
if (Array.isArray(hookMap)) {
|
|
128
128
|
this.appHooks[HOOKS].push(...hookMap as any);
|
|
129
129
|
} else {
|
|
130
|
-
const methodHookMap = hookMap as HookMap<Application<
|
|
130
|
+
const methodHookMap = hookMap as HookMap<Application<Services, Settings>, any>;
|
|
131
131
|
|
|
132
132
|
Object.keys(methodHookMap).forEach(key => {
|
|
133
133
|
const methodHooks = this.appHooks[key] || [];
|
|
@@ -146,10 +146,10 @@ export class Feathers<ServiceTypes, AppSettings> extends EventEmitter implements
|
|
|
146
146
|
for (const path of Object.keys(this.services)) {
|
|
147
147
|
promise = promise.then(() => {
|
|
148
148
|
const service: any = this.service(path as any);
|
|
149
|
-
|
|
149
|
+
|
|
150
150
|
if (typeof service.setup === 'function') {
|
|
151
151
|
debug(`Setting up service for \`${path}\``);
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
return service.setup(this, path);
|
|
154
154
|
}
|
|
155
155
|
});
|
package/src/declarations.ts
CHANGED
|
@@ -18,9 +18,10 @@ export interface ServiceOptions {
|
|
|
18
18
|
events?: string[];
|
|
19
19
|
methods?: string[];
|
|
20
20
|
serviceEvents?: string[];
|
|
21
|
+
routeParams?: { [key: string]: any };
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
export interface ServiceMethods<T, D = Partial<T>> {
|
|
24
|
+
export interface ServiceMethods<T = any, D = Partial<T>> {
|
|
24
25
|
find (params?: Params): Promise<T | T[]>;
|
|
25
26
|
|
|
26
27
|
get (id: Id, params?: Params): Promise<T>;
|
|
@@ -36,7 +37,7 @@ export interface ServiceMethods<T, D = Partial<T>> {
|
|
|
36
37
|
setup (app: Application, path: string): Promise<void>;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
export interface ServiceOverloads<T, D
|
|
40
|
+
export interface ServiceOverloads<T = any, D = Partial<T>> {
|
|
40
41
|
create? (data: D[], params?: Params): Promise<T[]>;
|
|
41
42
|
|
|
42
43
|
update? (id: Id, data: D, params?: Params): Promise<T>;
|
|
@@ -52,14 +53,14 @@ export interface ServiceOverloads<T, D> {
|
|
|
52
53
|
remove? (id: null, params?: Params): Promise<T[]>;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
export type Service<T, D = Partial<T>> =
|
|
56
|
+
export type Service<T = any, D = Partial<T>> =
|
|
56
57
|
ServiceMethods<T, D> &
|
|
57
58
|
ServiceOverloads<T, D>;
|
|
58
59
|
|
|
59
|
-
export type ServiceInterface<T, D = Partial<T>> =
|
|
60
|
+
export type ServiceInterface<T = any, D = Partial<T>> =
|
|
60
61
|
Partial<ServiceMethods<T, D>>;
|
|
61
62
|
|
|
62
|
-
export interface ServiceAddons<A = Application, S = Service
|
|
63
|
+
export interface ServiceAddons<A = Application, S = Service> extends EventEmitter {
|
|
63
64
|
id?: string;
|
|
64
65
|
hooks (options: HookOptions<A, S>): this;
|
|
65
66
|
}
|
|
@@ -103,19 +104,19 @@ export interface ServiceHookOverloads<S> {
|
|
|
103
104
|
): Promise<HookContext>;
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
export type FeathersService<A = FeathersApplication, S = Service
|
|
107
|
+
export type FeathersService<A = FeathersApplication, S = Service> =
|
|
107
108
|
S & ServiceAddons<A, S> & OptionalPick<ServiceHookOverloads<S>, keyof S>;
|
|
108
109
|
|
|
109
|
-
export type
|
|
110
|
-
[
|
|
110
|
+
export type CustomMethods<T extends {[key: string]: [any, any]}> = {
|
|
111
|
+
[K in keyof T]: (data: T[K][0], params?: Params) => Promise<T[K][1]>;
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
export type ServiceMixin<A> = (service: FeathersService<A>, path: string, options
|
|
114
|
+
export type ServiceMixin<A> = (service: FeathersService<A>, path: string, options: ServiceOptions) => void;
|
|
114
115
|
|
|
115
116
|
export type ServiceGenericType<S> = S extends ServiceInterface<infer T> ? T : any;
|
|
116
117
|
export type ServiceGenericData<S> = S extends ServiceInterface<infer _T, infer D> ? D : any;
|
|
117
118
|
|
|
118
|
-
export interface FeathersApplication<
|
|
119
|
+
export interface FeathersApplication<Services = any, Settings = any> {
|
|
119
120
|
/**
|
|
120
121
|
* The Feathers application version
|
|
121
122
|
*/
|
|
@@ -124,7 +125,7 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
|
|
|
124
125
|
/**
|
|
125
126
|
* A list of callbacks that run when a new service is registered
|
|
126
127
|
*/
|
|
127
|
-
mixins: ServiceMixin<Application<
|
|
128
|
+
mixins: ServiceMixin<Application<Services, Settings>>[];
|
|
128
129
|
|
|
129
130
|
/**
|
|
130
131
|
* The index of all services keyed by their path.
|
|
@@ -132,13 +133,13 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
|
|
|
132
133
|
* __Important:__ Services should always be retrieved via `app.service('name')`
|
|
133
134
|
* not via `app.services`.
|
|
134
135
|
*/
|
|
135
|
-
services:
|
|
136
|
+
services: Services;
|
|
136
137
|
|
|
137
138
|
/**
|
|
138
139
|
* The application settings that can be used via
|
|
139
140
|
* `app.get` and `app.set`
|
|
140
141
|
*/
|
|
141
|
-
settings:
|
|
142
|
+
settings: Settings;
|
|
142
143
|
|
|
143
144
|
/**
|
|
144
145
|
* A private-ish indicator if `app.setup()` has been called already
|
|
@@ -148,14 +149,14 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
|
|
|
148
149
|
/**
|
|
149
150
|
* Contains all registered application level hooks.
|
|
150
151
|
*/
|
|
151
|
-
appHooks: HookMap<Application<
|
|
152
|
+
appHooks: HookMap<Application<Services, Settings>, any>;
|
|
152
153
|
|
|
153
154
|
/**
|
|
154
155
|
* Retrieve an application setting by name
|
|
155
156
|
*
|
|
156
157
|
* @param name The setting name
|
|
157
158
|
*/
|
|
158
|
-
get<L extends keyof
|
|
159
|
+
get<L extends keyof Settings & string> (name: L): Settings[L];
|
|
159
160
|
|
|
160
161
|
/**
|
|
161
162
|
* Set an application setting
|
|
@@ -163,7 +164,7 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
|
|
|
163
164
|
* @param name The setting name
|
|
164
165
|
* @param value The setting value
|
|
165
166
|
*/
|
|
166
|
-
set<L extends keyof
|
|
167
|
+
set<L extends keyof Settings & string> (name: L, value: Settings[L]): this;
|
|
167
168
|
|
|
168
169
|
/**
|
|
169
170
|
* Runs a callback configure function with the current application instance.
|
|
@@ -179,7 +180,7 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
|
|
|
179
180
|
*
|
|
180
181
|
* @param location The path of the service
|
|
181
182
|
*/
|
|
182
|
-
defaultService (location: string): ServiceInterface
|
|
183
|
+
defaultService (location: string): ServiceInterface;
|
|
183
184
|
|
|
184
185
|
/**
|
|
185
186
|
* Register a new service or a sub-app. When passed another
|
|
@@ -191,9 +192,9 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
|
|
|
191
192
|
* Feathers application to use a sub-app under the `path` prefix.
|
|
192
193
|
* @param options The options for this service
|
|
193
194
|
*/
|
|
194
|
-
use<L extends keyof
|
|
195
|
+
use<L extends keyof Services & string> (
|
|
195
196
|
path: L,
|
|
196
|
-
service: keyof any extends keyof
|
|
197
|
+
service: keyof any extends keyof Services ? ServiceInterface | Application : Services[L],
|
|
197
198
|
options?: ServiceOptions
|
|
198
199
|
): this;
|
|
199
200
|
|
|
@@ -204,9 +205,9 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
|
|
|
204
205
|
*
|
|
205
206
|
* @param path The name of the service.
|
|
206
207
|
*/
|
|
207
|
-
service<L extends keyof
|
|
208
|
+
service<L extends keyof Services & string> (
|
|
208
209
|
path: L
|
|
209
|
-
): FeathersService<this, keyof any extends keyof
|
|
210
|
+
): FeathersService<this, keyof any extends keyof Services ? Service : Services[L]>;
|
|
210
211
|
|
|
211
212
|
setup (server?: any): Promise<this>;
|
|
212
213
|
|
|
@@ -220,7 +221,7 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
|
|
|
220
221
|
|
|
221
222
|
// This needs to be an interface instead of a type
|
|
222
223
|
// so that the declaration can be extended by other modules
|
|
223
|
-
export interface Application<
|
|
224
|
+
export interface Application<Services = any, Settings = any> extends FeathersApplication<Services, Settings>, EventEmitter {
|
|
224
225
|
|
|
225
226
|
}
|
|
226
227
|
|
|
@@ -234,11 +235,19 @@ export interface Query {
|
|
|
234
235
|
export interface Params {
|
|
235
236
|
query?: Query;
|
|
236
237
|
provider?: string;
|
|
237
|
-
route?: { [key: string]:
|
|
238
|
+
route?: { [key: string]: any };
|
|
238
239
|
headers?: { [key: string]: any };
|
|
239
240
|
[key: string]: any; // (JL) not sure if we want this
|
|
240
241
|
}
|
|
241
242
|
|
|
243
|
+
export interface Http {
|
|
244
|
+
/**
|
|
245
|
+
* A writeable, optional property that allows to override the standard HTTP status
|
|
246
|
+
* code that should be returned.
|
|
247
|
+
*/
|
|
248
|
+
statusCode?: number;
|
|
249
|
+
}
|
|
250
|
+
|
|
242
251
|
export interface HookContext<A = Application, S = any> extends BaseHookContext<ServiceGenericType<S>> {
|
|
243
252
|
/**
|
|
244
253
|
* A read only property that contains the Feathers application object. This can be used to
|
|
@@ -309,35 +318,41 @@ export interface HookContext<A = Application, S = any> extends BaseHookContext<S
|
|
|
309
318
|
/**
|
|
310
319
|
* A writeable, optional property that allows to override the standard HTTP status
|
|
311
320
|
* code that should be returned.
|
|
321
|
+
*
|
|
322
|
+
* @deprecated Use `http.statusCode` instead.
|
|
312
323
|
*/
|
|
313
324
|
statusCode?: number;
|
|
325
|
+
/**
|
|
326
|
+
* A writeable, optional property that contains options specific to HTTP transports.
|
|
327
|
+
*/
|
|
328
|
+
http?: Http;
|
|
314
329
|
/**
|
|
315
330
|
* The event emitted by this method. Can be set to `null` to skip event emitting.
|
|
316
331
|
*/
|
|
317
332
|
event: string|null;
|
|
318
333
|
}
|
|
319
334
|
|
|
320
|
-
//
|
|
321
|
-
export type
|
|
335
|
+
// Regular hook typings
|
|
336
|
+
export type RegularHookFunction<A = Application, S = Service> =
|
|
322
337
|
(this: S, context: HookContext<A, S>) => (Promise<HookContext<Application, S> | void> | HookContext<Application, S> | void);
|
|
323
338
|
|
|
324
|
-
export type Hook<A = Application, S = Service
|
|
339
|
+
export type Hook<A = Application, S = Service> = RegularHookFunction<A, S>;
|
|
325
340
|
|
|
326
|
-
type
|
|
327
|
-
{ [L in keyof S]?: SelfOrArray<
|
|
328
|
-
{ all?: SelfOrArray<
|
|
341
|
+
type RegularHookMethodMap<A, S> =
|
|
342
|
+
{ [L in keyof S]?: SelfOrArray<RegularHookFunction<A, S>>; } &
|
|
343
|
+
{ all?: SelfOrArray<RegularHookFunction<A, S>> };
|
|
329
344
|
|
|
330
|
-
type
|
|
331
|
-
SelfOrArray<
|
|
345
|
+
type RegularHookTypeMap<A, S> =
|
|
346
|
+
SelfOrArray<RegularHookFunction<A, S>> | RegularHookMethodMap<A, S>;
|
|
332
347
|
|
|
333
|
-
export type
|
|
334
|
-
before?:
|
|
335
|
-
after?:
|
|
336
|
-
error?:
|
|
348
|
+
export type RegularHookMap<A, S> = {
|
|
349
|
+
before?: RegularHookTypeMap<A, S>,
|
|
350
|
+
after?: RegularHookTypeMap<A, S>,
|
|
351
|
+
error?: RegularHookTypeMap<A, S>
|
|
337
352
|
}
|
|
338
353
|
|
|
339
354
|
// New @feathersjs/hook typings
|
|
340
|
-
export type HookFunction<A = Application, S = Service
|
|
355
|
+
export type HookFunction<A = Application, S = Service> =
|
|
341
356
|
(context: HookContext<A, S>, next: NextFunction) => Promise<void>;
|
|
342
357
|
|
|
343
358
|
export type HookMap<A, S> = {
|
|
@@ -345,4 +360,4 @@ export type HookMap<A, S> = {
|
|
|
345
360
|
};
|
|
346
361
|
|
|
347
362
|
export type HookOptions<A, S> =
|
|
348
|
-
HookMap<A, S> | HookFunction<A, S>[] |
|
|
363
|
+
HookMap<A, S> | HookFunction<A, S>[] | RegularHookMap<A, S>;
|
package/src/hooks/index.ts
CHANGED
|
@@ -6,16 +6,20 @@ import {
|
|
|
6
6
|
} from '../declarations';
|
|
7
7
|
import { defaultServiceArguments, getHookMethods } from '../service';
|
|
8
8
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
collectRegularHooks,
|
|
10
|
+
enableRegularHooks
|
|
11
|
+
} from './regular';
|
|
12
|
+
|
|
13
|
+
export {
|
|
12
14
|
fromBeforeHook,
|
|
15
|
+
fromBeforeHooks,
|
|
16
|
+
fromAfterHook,
|
|
17
|
+
fromAfterHooks,
|
|
18
|
+
fromErrorHook,
|
|
13
19
|
fromErrorHooks
|
|
14
|
-
} from './
|
|
20
|
+
} from './regular';
|
|
15
21
|
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
export function createContext (service: Service<any>, method: string, data: HookContextData = {}) {
|
|
22
|
+
export function createContext (service: Service, method: string, data: HookContextData = {}) {
|
|
19
23
|
const createContext = (service as any)[method].createContext;
|
|
20
24
|
|
|
21
25
|
if (typeof createContext !== 'function') {
|
|
@@ -34,11 +38,11 @@ export class FeathersHookManager<A> extends HookManager {
|
|
|
34
38
|
collectMiddleware (self: any, args: any[]): Middleware[] {
|
|
35
39
|
const app = this.app as any as Application;
|
|
36
40
|
const appHooks = app.appHooks[HOOKS].concat(app.appHooks[this.method] || []);
|
|
37
|
-
const
|
|
41
|
+
const regularAppHooks = collectRegularHooks(this.app, this.method);
|
|
38
42
|
const middleware = super.collectMiddleware(self, args);
|
|
39
|
-
const
|
|
43
|
+
const regularHooks = collectRegularHooks(self, this.method);
|
|
40
44
|
|
|
41
|
-
return [...appHooks, ...
|
|
45
|
+
return [...appHooks, ...regularAppHooks, ...middleware, ...regularHooks];
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
initializeContext (self: any, args: any[], context: HookContext) {
|
|
@@ -63,7 +67,9 @@ export function hookMixin<A> (
|
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
const app = this;
|
|
66
|
-
const
|
|
70
|
+
const hookMethods = getHookMethods(service, options);
|
|
71
|
+
|
|
72
|
+
const serviceMethodHooks = hookMethods.reduce((res, method) => {
|
|
67
73
|
const params = (defaultServiceArguments as any)[method] || [ 'data', 'params' ];
|
|
68
74
|
|
|
69
75
|
res[method] = new FeathersHookManager<A>(app, method)
|
|
@@ -74,18 +80,25 @@ export function hookMixin<A> (
|
|
|
74
80
|
method,
|
|
75
81
|
service,
|
|
76
82
|
event: null,
|
|
77
|
-
type: null
|
|
83
|
+
type: null,
|
|
84
|
+
get statusCode() {
|
|
85
|
+
return this.http?.statusCode;
|
|
86
|
+
},
|
|
87
|
+
set statusCode(value: number) {
|
|
88
|
+
(this.http ||= {}).statusCode = value;
|
|
89
|
+
}
|
|
78
90
|
});
|
|
79
91
|
|
|
80
92
|
return res;
|
|
81
93
|
}, {} as HookMap);
|
|
82
|
-
|
|
94
|
+
|
|
95
|
+
const handleRegularHooks = enableRegularHooks(service, hookMethods);
|
|
83
96
|
|
|
84
97
|
hooks(service, serviceMethodHooks);
|
|
85
98
|
|
|
86
99
|
service.hooks = function (this: any, hookOptions: any) {
|
|
87
100
|
if (hookOptions.before || hookOptions.after || hookOptions.error) {
|
|
88
|
-
return
|
|
101
|
+
return handleRegularHooks.call(this, hookOptions);
|
|
89
102
|
}
|
|
90
103
|
|
|
91
104
|
if (Array.isArray(hookOptions)) {
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { HookFunction, RegularHookFunction, RegularHookMap } from '../declarations';
|
|
2
|
+
import { defaultServiceMethods } from '../service';
|
|
3
|
+
|
|
4
|
+
const runHook = <A, S> (hook: RegularHookFunction<A, S>, context: any, type?: string) => {
|
|
5
|
+
if (type) context.type = type;
|
|
6
|
+
return Promise.resolve(hook.call(context.self, context))
|
|
7
|
+
.then((res: any) => {
|
|
8
|
+
if (type) context.type = null;
|
|
9
|
+
if (res && res !== context) {
|
|
10
|
+
Object.assign(context, res);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function fromBeforeHook<A, S> (hook: RegularHookFunction<A, S>): HookFunction<A, S> {
|
|
16
|
+
return (context, next) => {
|
|
17
|
+
return runHook(hook, context, 'before').then(next);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function fromAfterHook<A, S> (hook: RegularHookFunction<A, S>): HookFunction<A, S> {
|
|
22
|
+
return (context, next) => {
|
|
23
|
+
return next().then(() => runHook(hook, context, 'after'));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function fromErrorHook<A, S> (hook: RegularHookFunction<A, S>): HookFunction<A, S> {
|
|
28
|
+
return (context, next) => {
|
|
29
|
+
return next().catch((error: any) => {
|
|
30
|
+
if (context.error !== error || context.result !== undefined) {
|
|
31
|
+
(context as any).original = { ...context };
|
|
32
|
+
context.error = error;
|
|
33
|
+
delete context.result;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return runHook(hook, context, 'error').then(() => {
|
|
37
|
+
if (context.result === undefined && context.error !== undefined) {
|
|
38
|
+
throw context.error;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const RunHooks = <A, S> (hooks: RegularHookFunction<A, S>[]) => (context: any) => {
|
|
46
|
+
return hooks.reduce((promise, hook) => {
|
|
47
|
+
return promise.then(() => runHook(hook, context))
|
|
48
|
+
}, Promise.resolve(undefined));
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export function fromBeforeHooks<A, S> (hooks: RegularHookFunction<A, S>[]) {
|
|
52
|
+
return fromBeforeHook(RunHooks(hooks));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function fromAfterHooks<A, S> (hooks: RegularHookFunction<A, S>[]) {
|
|
56
|
+
return fromAfterHook(RunHooks(hooks));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function fromErrorHooks<A, S> (hooks: RegularHookFunction<A, S>[]) {
|
|
60
|
+
return fromErrorHook(RunHooks(hooks));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function collectRegularHooks (target: any, method: string) {
|
|
64
|
+
return target.__hooks.hooks[method] || [];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Converts different hook registration formats into the
|
|
68
|
+
// same internal format
|
|
69
|
+
export function convertHookData (input: any) {
|
|
70
|
+
const result: { [ method: string ]: RegularHookFunction[] } = {};
|
|
71
|
+
|
|
72
|
+
if (Array.isArray(input)) {
|
|
73
|
+
result.all = input;
|
|
74
|
+
} else if (typeof input !== 'object') {
|
|
75
|
+
result.all = [ input ];
|
|
76
|
+
} else {
|
|
77
|
+
for (const key of Object.keys(input)) {
|
|
78
|
+
const value = input[key];
|
|
79
|
+
result[key] = Array.isArray(value) ? value : [ value ];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
type RegularType = 'before' | 'after' | 'error';
|
|
87
|
+
|
|
88
|
+
type RegularMap = { [ type in RegularType ]: ReturnType< typeof convertHookData > };
|
|
89
|
+
|
|
90
|
+
type RegularAdapter = HookFunction & { hooks: RegularHookFunction[] };
|
|
91
|
+
|
|
92
|
+
type RegularStore = {
|
|
93
|
+
before: { [ method: string ]: RegularAdapter },
|
|
94
|
+
after: { [ method: string ]: RegularAdapter },
|
|
95
|
+
error: { [ method: string ]: RegularAdapter },
|
|
96
|
+
hooks: { [ method: string ]: HookFunction[] }
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const types: RegularType[] = ['before', 'after', 'error'];
|
|
100
|
+
|
|
101
|
+
const isType = (value: any): value is RegularType => types.includes(value);
|
|
102
|
+
|
|
103
|
+
const wrappers = {
|
|
104
|
+
before: fromBeforeHooks,
|
|
105
|
+
after: fromAfterHooks,
|
|
106
|
+
error: fromErrorHooks
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const createStore = (methods: string[]) => {
|
|
110
|
+
const store: RegularStore = {
|
|
111
|
+
before: {},
|
|
112
|
+
after: {},
|
|
113
|
+
error: {},
|
|
114
|
+
hooks: {}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
for (const method of methods) {
|
|
118
|
+
store.hooks[method] = [];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return store;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const setStore = (object: any, store: RegularStore) => {
|
|
125
|
+
Object.defineProperty(object, '__hooks', {
|
|
126
|
+
configurable: true,
|
|
127
|
+
value: store,
|
|
128
|
+
writable: true
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const getStore = (object: any): RegularStore => object.__hooks;
|
|
133
|
+
|
|
134
|
+
const createMap = (input: RegularHookMap<any, any>, methods: string[]) => {
|
|
135
|
+
const map = {} as RegularMap;
|
|
136
|
+
|
|
137
|
+
Object.keys(input).forEach((type) => {
|
|
138
|
+
if (!isType(type)) {
|
|
139
|
+
throw new Error(`'${type}' is not a valid hook type`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const data = convertHookData(input[type]);
|
|
143
|
+
|
|
144
|
+
Object.keys(data).forEach((method) => {
|
|
145
|
+
if (method !== 'all' && !methods.includes(method)) {
|
|
146
|
+
throw new Error(`'${method}' is not a valid hook method`);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
map[type] = data;
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
return map;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const createAdapter = (type: RegularType) => {
|
|
157
|
+
const hooks: RegularHookFunction[] = [];
|
|
158
|
+
const hook = wrappers[type](hooks);
|
|
159
|
+
const adapter = Object.assign(hook, { hooks });
|
|
160
|
+
|
|
161
|
+
return adapter;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const updateStore = (store: RegularStore, map: RegularMap) => {
|
|
165
|
+
Object.keys(store.hooks).forEach((method) => {
|
|
166
|
+
let adapted = false;
|
|
167
|
+
|
|
168
|
+
Object.keys(map).forEach((key) => {
|
|
169
|
+
const type = key as RegularType;
|
|
170
|
+
const allHooks = map[type].all || [];
|
|
171
|
+
const methodHooks = map[type][method] || [];
|
|
172
|
+
|
|
173
|
+
if (allHooks.length || methodHooks.length) {
|
|
174
|
+
const adapter = store[type][method] ||= (adapted = true, createAdapter(type));
|
|
175
|
+
|
|
176
|
+
adapter.hooks.push(...allHooks, ...methodHooks);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
if (adapted) {
|
|
181
|
+
store.hooks[method] = [
|
|
182
|
+
store.error[method],
|
|
183
|
+
store.before[method],
|
|
184
|
+
store.after[method]
|
|
185
|
+
].filter(hook => hook);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// Add `.hooks` functionality to an object
|
|
191
|
+
export function enableRegularHooks (
|
|
192
|
+
object: any,
|
|
193
|
+
methods: string[] = defaultServiceMethods
|
|
194
|
+
) {
|
|
195
|
+
const store = createStore(methods);
|
|
196
|
+
|
|
197
|
+
setStore(object, store);
|
|
198
|
+
|
|
199
|
+
return function regularHooks (this: any, input: RegularHookMap<any, any>) {
|
|
200
|
+
const store = getStore(this);
|
|
201
|
+
const map = createMap(input, methods);
|
|
202
|
+
|
|
203
|
+
updateStore(store, map);
|
|
204
|
+
|
|
205
|
+
return this;
|
|
206
|
+
}
|
|
207
|
+
}
|