@feathersjs/feathers 5.0.0-pre.2 → 5.0.0-pre.20

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.
@@ -1,115 +1,125 @@
1
- import { EventEmitter } from 'events';
2
1
  import {
3
- NextFunction, HookContext as BaseHookContext
4
- } from '@feathersjs/hooks';
2
+ EventEmitter, NextFunction, HookContext as BaseHookContext
3
+ } from './dependencies';
5
4
 
6
5
  type SelfOrArray<S> = S | S[];
7
6
  type OptionalPick<T, K extends PropertyKey> = Pick<T, Extract<keyof T, K>>
8
7
 
9
- export { NextFunction };
8
+ export type { NextFunction };
9
+
10
+ export interface Paginated<T> {
11
+ total: number;
12
+ limit: number;
13
+ skip: number;
14
+ data: T[];
15
+ }
10
16
 
11
17
  export interface ServiceOptions {
12
18
  events?: string[];
13
19
  methods?: string[];
14
20
  serviceEvents?: string[];
21
+ routeParams?: { [key: string]: any };
15
22
  }
16
23
 
17
- export interface ServiceMethods<T, D = Partial<T>> {
18
- find (params?: Params): Promise<T | T[]>;
24
+ export interface ServiceMethods<T = any, D = Partial<T>, P = Params> {
25
+ find (params?: P): Promise<T | T[]>;
19
26
 
20
- get (id: Id, params?: Params): Promise<T>;
27
+ get (id: Id, params?: P): Promise<T>;
21
28
 
22
- create (data: D, params?: Params): Promise<T>;
29
+ create (data: D, params?: P): Promise<T>;
23
30
 
24
- update (id: NullableId, data: D, params?: Params): Promise<T | T[]>;
31
+ update (id: NullableId, data: D, params?: P): Promise<T | T[]>;
25
32
 
26
- patch (id: NullableId, data: D, params?: Params): Promise<T | T[]>;
33
+ patch (id: NullableId, data: D, params?: P): Promise<T | T[]>;
27
34
 
28
- remove (id: NullableId, params?: Params): Promise<T | T[]>;
35
+ remove (id: NullableId, params?: P): Promise<T | T[]>;
29
36
 
30
- setup (app: Application, path: string): Promise<void>;
37
+ setup? (app: Application, path: string): Promise<void>;
38
+
39
+ teardown? (app: Application, path: string): Promise<void>;
31
40
  }
32
41
 
33
- export interface ServiceOverloads<T, D> {
34
- create? (data: D[], params?: Params): Promise<T[]>;
42
+ export interface ServiceOverloads<T = any, D = Partial<T>, P = Params> {
43
+ create? (data: D[], params?: P): Promise<T[]>;
35
44
 
36
- update? (id: Id, data: D, params?: Params): Promise<T>;
45
+ update? (id: Id, data: D, params?: P): Promise<T>;
37
46
 
38
- update? (id: null, data: D, params?: Params): Promise<T[]>;
47
+ update? (id: null, data: D, params?: P): Promise<T[]>;
39
48
 
40
- patch? (id: Id, data: D, params?: Params): Promise<T>;
49
+ patch? (id: Id, data: D, params?: P): Promise<T>;
41
50
 
42
- patch? (id: null, data: D, params?: Params): Promise<T[]>;
51
+ patch? (id: null, data: D, params?: P): Promise<T[]>;
43
52
 
44
- remove? (id: Id, params?: Params): Promise<T>;
53
+ remove? (id: Id, params?: P): Promise<T>;
45
54
 
46
- remove? (id: null, params?: Params): Promise<T[]>;
55
+ remove? (id: null, params?: P): Promise<T[]>;
47
56
  }
48
57
 
49
- export type Service<T, D = Partial<T>> =
50
- ServiceMethods<T, D> &
51
- ServiceOverloads<T, D>;
58
+ export type Service<T = any, D = Partial<T>, P = Params> =
59
+ ServiceMethods<T, D, P> &
60
+ ServiceOverloads<T, D, P>;
52
61
 
53
- export type ServiceInterface<T, D = Partial<T>> =
54
- Partial<ServiceMethods<T, D>>;
62
+ export type ServiceInterface<T = any, D = Partial<T>, P = Params> =
63
+ Partial<ServiceMethods<T, D, P>>;
55
64
 
56
- export interface ServiceAddons<A, S> extends EventEmitter {
65
+ export interface ServiceAddons<A = Application, S = Service> extends EventEmitter {
57
66
  id?: string;
58
67
  hooks (options: HookOptions<A, S>): this;
59
68
  }
60
69
 
61
- export interface ServiceHookOverloads<S> {
70
+ export interface ServiceHookOverloads<S, P = Params> {
62
71
  find (
63
- params: Params,
72
+ params: P,
64
73
  context: HookContext
65
74
  ): Promise<HookContext>;
66
75
 
67
76
  get (
68
77
  id: Id,
69
- params: Params,
78
+ params: P,
70
79
  context: HookContext
71
80
  ): Promise<HookContext>;
72
81
 
73
82
  create (
74
83
  data: ServiceGenericData<S> | ServiceGenericData<S>[],
75
- params: Params,
84
+ params: P,
76
85
  context: HookContext
77
86
  ): Promise<HookContext>;
78
87
 
79
88
  update (
80
89
  id: NullableId,
81
90
  data: ServiceGenericData<S>,
82
- params: Params,
91
+ params: P,
83
92
  context: HookContext
84
93
  ): Promise<HookContext>;
85
94
 
86
95
  patch (
87
96
  id: NullableId,
88
97
  data: ServiceGenericData<S>,
89
- params: Params,
98
+ params: P,
90
99
  context: HookContext
91
100
  ): Promise<HookContext>;
92
101
 
93
102
  remove (
94
103
  id: NullableId,
95
- params: Params,
104
+ params: P,
96
105
  context: HookContext
97
106
  ): Promise<HookContext>;
98
107
  }
99
108
 
100
- export type FeathersService<A = FeathersApplication, S = Service<any>> =
109
+ export type FeathersService<A = FeathersApplication, S = Service> =
101
110
  S & ServiceAddons<A, S> & OptionalPick<ServiceHookOverloads<S>, keyof S>;
102
111
 
103
- export type CustomMethod<Methods extends string> = {
104
- [k in Methods]: <X = any> (data: any, params?: Params) => Promise<X>;
112
+ export type CustomMethods<T extends {[key: string]: [any, any]}> = {
113
+ [K in keyof T]: (data: T[K][0], params?: Params) => Promise<T[K][1]>;
105
114
  }
106
115
 
107
- export type ServiceMixin<A> = (service: FeathersService<A>, path: string, options?: ServiceOptions) => void;
116
+ export type ServiceMixin<A> = (service: FeathersService<A>, path: string, options: ServiceOptions) => void;
108
117
 
109
118
  export type ServiceGenericType<S> = S extends ServiceInterface<infer T> ? T : any;
110
119
  export type ServiceGenericData<S> = S extends ServiceInterface<infer _T, infer D> ? D : any;
120
+ export type ServiceGenericParams<S> = S extends ServiceInterface<infer _T, infer _D, infer P> ? P : any;
111
121
 
112
- export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
122
+ export interface FeathersApplication<Services = any, Settings = any> {
113
123
  /**
114
124
  * The Feathers application version
115
125
  */
@@ -118,7 +128,7 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
118
128
  /**
119
129
  * A list of callbacks that run when a new service is registered
120
130
  */
121
- mixins: ServiceMixin<Application<ServiceTypes, AppSettings>>[];
131
+ mixins: ServiceMixin<Application<Services, Settings>>[];
122
132
 
123
133
  /**
124
134
  * The index of all services keyed by their path.
@@ -126,13 +136,13 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
126
136
  * __Important:__ Services should always be retrieved via `app.service('name')`
127
137
  * not via `app.services`.
128
138
  */
129
- services: ServiceTypes;
139
+ services: Services;
130
140
 
131
141
  /**
132
142
  * The application settings that can be used via
133
143
  * `app.get` and `app.set`
134
144
  */
135
- settings: AppSettings;
145
+ settings: Settings;
136
146
 
137
147
  /**
138
148
  * A private-ish indicator if `app.setup()` has been called already
@@ -142,14 +152,14 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
142
152
  /**
143
153
  * Contains all registered application level hooks.
144
154
  */
145
- appHooks: HookMap<Application<ServiceTypes, AppSettings>, any>;
155
+ appHooks: HookMap<Application<Services, Settings>, any>;
146
156
 
147
157
  /**
148
158
  * Retrieve an application setting by name
149
159
  *
150
160
  * @param name The setting name
151
161
  */
152
- get<L extends keyof AppSettings & string> (name: L): AppSettings[L];
162
+ get<L extends keyof Settings & string> (name: L): Settings[L];
153
163
 
154
164
  /**
155
165
  * Set an application setting
@@ -157,7 +167,7 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
157
167
  * @param name The setting name
158
168
  * @param value The setting value
159
169
  */
160
- set<L extends keyof AppSettings & string> (name: L, value: AppSettings[L]): this;
170
+ set<L extends keyof Settings & string> (name: L, value: Settings[L]): this;
161
171
 
162
172
  /**
163
173
  * Runs a callback configure function with the current application instance.
@@ -173,7 +183,7 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
173
183
  *
174
184
  * @param location The path of the service
175
185
  */
176
- defaultService (location: string): ServiceInterface<any>;
186
+ defaultService (location: string): ServiceInterface;
177
187
 
178
188
  /**
179
189
  * Register a new service or a sub-app. When passed another
@@ -185,9 +195,9 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
185
195
  * Feathers application to use a sub-app under the `path` prefix.
186
196
  * @param options The options for this service
187
197
  */
188
- use<L extends keyof ServiceTypes & string> (
198
+ use<L extends keyof Services & string> (
189
199
  path: L,
190
- service: keyof any extends keyof ServiceTypes ? ServiceInterface<any> | Application : ServiceTypes[L],
200
+ service: keyof any extends keyof Services ? ServiceInterface | Application : Services[L],
191
201
  options?: ServiceOptions
192
202
  ): this;
193
203
 
@@ -198,23 +208,35 @@ export interface FeathersApplication<ServiceTypes = any, AppSettings = any> {
198
208
  *
199
209
  * @param path The name of the service.
200
210
  */
201
- service<L extends keyof ServiceTypes & string> (
211
+ service<L extends keyof Services & string> (
202
212
  path: L
203
- ): FeathersService<this, keyof any extends keyof ServiceTypes ? Service<any> : ServiceTypes[L]>;
213
+ ): FeathersService<this, keyof any extends keyof Services ? Service : Services[L]>;
204
214
 
215
+ /**
216
+ * Set up the application and call all services `.setup` method if available.
217
+ *
218
+ * @param server A server instance (optional)
219
+ */
205
220
  setup (server?: any): Promise<this>;
206
221
 
222
+ /**
223
+ * Tear down the application and call all services `.teardown` method if available.
224
+ *
225
+ * @param server A server instance (optional)
226
+ */
227
+ teardown (server?: any): Promise<this>;
228
+
207
229
  /**
208
230
  * Register application level hooks.
209
231
  *
210
232
  * @param map The application hook settings.
211
233
  */
212
- hooks (map: HookOptions<this, any>): this;
234
+ hooks (map: ApplicationHookOptions<this>): this;
213
235
  }
214
236
 
215
237
  // This needs to be an interface instead of a type
216
238
  // so that the declaration can be extended by other modules
217
- export interface Application<ServiceTypes = any, AppSettings = any> extends FeathersApplication<ServiceTypes, AppSettings>, EventEmitter {
239
+ export interface Application<Services = any, Settings = any> extends FeathersApplication<Services, Settings>, EventEmitter {
218
240
 
219
241
  }
220
242
 
@@ -225,12 +247,26 @@ export interface Query {
225
247
  [key: string]: any;
226
248
  }
227
249
 
228
- export interface Params {
229
- query?: Query;
250
+ export interface Params<Q = Query> {
251
+ query?: Q;
230
252
  provider?: string;
231
- route?: { [key: string]: string };
253
+ route?: { [key: string]: any };
232
254
  headers?: { [key: string]: any };
233
- [key: string]: any; // (JL) not sure if we want this
255
+ }
256
+
257
+ export interface Http {
258
+ /**
259
+ * A writeable, optional property with status code override.
260
+ */
261
+ status?: number;
262
+ /**
263
+ * A writeable, optional property with headers.
264
+ */
265
+ headers?: { [key: string]: string | string[] };
266
+ /**
267
+ * A writeable, optional property with `Location` header's value.
268
+ */
269
+ location?: string;
234
270
  }
235
271
 
236
272
  export interface HookContext<A = Application, S = any> extends BaseHookContext<ServiceGenericType<S>> {
@@ -283,7 +319,7 @@ export interface HookContext<A = Application, S = any> extends BaseHookContext<S
283
319
  * A writeable property that contains the service method parameters (including
284
320
  * params.query).
285
321
  */
286
- params: Params;
322
+ params: ServiceGenericParams<S>;
287
323
  /**
288
324
  * A writeable property containing the result of the successful service method call.
289
325
  * It is only available in after hooks.
@@ -303,33 +339,41 @@ export interface HookContext<A = Application, S = any> extends BaseHookContext<S
303
339
  /**
304
340
  * A writeable, optional property that allows to override the standard HTTP status
305
341
  * code that should be returned.
342
+ *
343
+ * @deprecated Use `http.status` instead.
306
344
  */
307
345
  statusCode?: number;
346
+ /**
347
+ * A writeable, optional property with options specific to HTTP transports.
348
+ */
349
+ http?: Http;
308
350
  /**
309
351
  * The event emitted by this method. Can be set to `null` to skip event emitting.
310
352
  */
311
353
  event: string|null;
312
354
  }
313
355
 
314
- // Legacy hook typings
315
- export type LegacyHookFunction<A = Application, S = Service<any, any>> =
356
+ // Regular hook typings
357
+ export type RegularHookFunction<A = Application, S = Service> =
316
358
  (this: S, context: HookContext<A, S>) => (Promise<HookContext<Application, S> | void> | HookContext<Application, S> | void);
317
359
 
318
- type LegacyHookMethodMap<A, S> =
319
- { [L in keyof S]?: SelfOrArray<LegacyHookFunction<A, S>>; } &
320
- { all?: SelfOrArray<LegacyHookFunction<A, S>> };
360
+ export type Hook<A = Application, S = Service> = RegularHookFunction<A, S>;
321
361
 
322
- type LegacyHookTypeMap<A, S> =
323
- SelfOrArray<LegacyHookFunction<A, S>> | LegacyHookMethodMap<A, S>;
362
+ type RegularHookMethodMap<A, S> =
363
+ { [L in keyof S]?: SelfOrArray<RegularHookFunction<A, S>>; } &
364
+ { all?: SelfOrArray<RegularHookFunction<A, S>> };
324
365
 
325
- export type LegacyHookMap<A, S> = {
326
- before?: LegacyHookTypeMap<A, S>,
327
- after?: LegacyHookTypeMap<A, S>,
328
- error?: LegacyHookTypeMap<A, S>
366
+ type RegularHookTypeMap<A, S> =
367
+ SelfOrArray<RegularHookFunction<A, S>> | RegularHookMethodMap<A, S>;
368
+
369
+ export type RegularHookMap<A, S> = {
370
+ before?: RegularHookTypeMap<A, S>,
371
+ after?: RegularHookTypeMap<A, S>,
372
+ error?: RegularHookTypeMap<A, S>
329
373
  }
330
374
 
331
375
  // New @feathersjs/hook typings
332
- export type HookFunction<A = Application, S = Service<any, any>> =
376
+ export type HookFunction<A = Application, S = Service> =
333
377
  (context: HookContext<A, S>, next: NextFunction) => Promise<void>;
334
378
 
335
379
  export type HookMap<A, S> = {
@@ -337,4 +381,19 @@ export type HookMap<A, S> = {
337
381
  };
338
382
 
339
383
  export type HookOptions<A, S> =
340
- HookMap<A, S> | HookFunction<A, S>[] | LegacyHookMap<A, S>;
384
+ HookMap<A, S> | HookFunction<A, S>[] | RegularHookMap<A, S>;
385
+
386
+ export interface ApplicationHookContext<A = Application> extends BaseHookContext {
387
+ app: A;
388
+ server: any;
389
+ }
390
+
391
+ export type ApplicationHookFunction<A> =
392
+ (context: ApplicationHookContext<A>, next: NextFunction) => Promise<void>;
393
+
394
+ export type ApplicationHookMap<A> = {
395
+ setup?: ApplicationHookFunction<A>[],
396
+ teardown?: ApplicationHookFunction<A>[]
397
+ }
398
+
399
+ export type ApplicationHookOptions<A> = HookOptions<A, any> | ApplicationHookMap<A>
@@ -0,0 +1,5 @@
1
+ import { EventEmitter } from 'events';
2
+ export * from '@feathersjs/commons';
3
+ export * from '@feathersjs/hooks';
4
+
5
+ export { EventEmitter };
package/src/events.ts CHANGED
@@ -1,6 +1,4 @@
1
- import { NextFunction } from '@feathersjs/hooks';
2
- import { EventEmitter } from 'events';
3
-
1
+ import { NextFunction, EventEmitter } from './dependencies';
4
2
  import { HookContext, FeathersService } from './declarations';
5
3
  import { getServiceOptions, defaultEventMap } from './service';
6
4
 
@@ -15,7 +13,7 @@ export function eventHook (context: HookContext, next: NextFunction) {
15
13
  // This is used for custom events and for client services receiving event from the server
16
14
  if (typeof context.event === 'string' && !events.includes(context.event)) {
17
15
  const results = Array.isArray(context.result) ? context.result : [ context.result ];
18
-
16
+
19
17
  results.forEach(element => (context as any).self.emit(context.event, element, context));
20
18
  }
21
19
  });
@@ -28,6 +26,6 @@ export function eventMixin<A> (service: FeathersService<A>) {
28
26
  if (!isEmitter) {
29
27
  Object.assign(service, EventEmitter.prototype);
30
28
  }
31
-
29
+
32
30
  return service;
33
31
  }
@@ -1,17 +1,25 @@
1
- import { getManager, HookContextData, HookManager, HookMap, HOOKS, hooks, Middleware } from '@feathersjs/hooks';
2
- import { Service, ServiceOptions, HookContext, FeathersService, Application } from '../declarations';
1
+ import {
2
+ getManager, HookContextData, HookManager, HookMap, HOOKS, hooks, Middleware
3
+ } from '../dependencies';
4
+ import {
5
+ Service, ServiceOptions, HookContext, FeathersService, Application
6
+ } from '../declarations';
3
7
  import { defaultServiceArguments, getHookMethods } from '../service';
4
8
  import {
5
- collectLegacyHooks,
6
- enableLegacyHooks,
7
- fromAfterHook,
9
+ collectRegularHooks,
10
+ enableRegularHooks
11
+ } from './regular';
12
+
13
+ export {
8
14
  fromBeforeHook,
15
+ fromBeforeHooks,
16
+ fromAfterHook,
17
+ fromAfterHooks,
18
+ fromErrorHook,
9
19
  fromErrorHooks
10
- } from './legacy';
11
-
12
- export { fromAfterHook, fromBeforeHook, fromErrorHooks };
20
+ } from './regular';
13
21
 
14
- export function createContext (service: Service<any>, method: string, data: HookContextData = {}) {
22
+ export function createContext (service: Service, method: string, data: HookContextData = {}) {
15
23
  const createContext = (service as any)[method].createContext;
16
24
 
17
25
  if (typeof createContext !== 'function') {
@@ -30,11 +38,11 @@ export class FeathersHookManager<A> extends HookManager {
30
38
  collectMiddleware (self: any, args: any[]): Middleware[] {
31
39
  const app = this.app as any as Application;
32
40
  const appHooks = app.appHooks[HOOKS].concat(app.appHooks[this.method] || []);
33
- const legacyAppHooks = collectLegacyHooks(this.app, this.method);
41
+ const regularAppHooks = collectRegularHooks(this.app, this.method);
34
42
  const middleware = super.collectMiddleware(self, args);
35
- const legacyHooks = collectLegacyHooks(self, this.method);
43
+ const regularHooks = collectRegularHooks(self, this.method);
36
44
 
37
- return [...appHooks, ...legacyAppHooks, ...middleware, ...legacyHooks];
45
+ return [...appHooks, ...regularAppHooks, ...middleware, ...regularHooks];
38
46
  }
39
47
 
40
48
  initializeContext (self: any, args: any[], context: HookContext) {
@@ -59,7 +67,9 @@ export function hookMixin<A> (
59
67
  }
60
68
 
61
69
  const app = this;
62
- const serviceMethodHooks = getHookMethods(service, options).reduce((res, method) => {
70
+ const hookMethods = getHookMethods(service, options);
71
+
72
+ const serviceMethodHooks = hookMethods.reduce((res, method) => {
63
73
  const params = (defaultServiceArguments as any)[method] || [ 'data', 'params' ];
64
74
 
65
75
  res[method] = new FeathersHookManager<A>(app, method)
@@ -70,18 +80,25 @@ export function hookMixin<A> (
70
80
  method,
71
81
  service,
72
82
  event: null,
73
- type: null
83
+ type: null,
84
+ get statusCode () {
85
+ return this.http?.status;
86
+ },
87
+ set statusCode (value: number) {
88
+ (this.http ||= {}).status = value;
89
+ }
74
90
  });
75
91
 
76
92
  return res;
77
93
  }, {} as HookMap);
78
- const handleLegacyHooks = enableLegacyHooks(service);
94
+
95
+ const handleRegularHooks = enableRegularHooks(service, hookMethods);
79
96
 
80
97
  hooks(service, serviceMethodHooks);
81
98
 
82
99
  service.hooks = function (this: any, hookOptions: any) {
83
100
  if (hookOptions.before || hookOptions.after || hookOptions.error) {
84
- return handleLegacyHooks.call(this, hookOptions);
101
+ return handleRegularHooks.call(this, hookOptions);
85
102
  }
86
103
 
87
104
  if (Array.isArray(hookOptions)) {