@feathersjs/express 5.0.0-pre.3 → 5.0.0-pre.31

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/src/handlers.ts CHANGED
@@ -1,130 +1,132 @@
1
- import path from 'path';
2
- import { NotFound, GeneralError } from '@feathersjs/errors';
3
- import { Request, Response, NextFunction, ErrorRequestHandler, RequestHandler } from 'express';
1
+ import path from 'path'
2
+ import { NotFound, GeneralError } from '@feathersjs/errors'
3
+ import { Request, Response, NextFunction, ErrorRequestHandler, RequestHandler } from 'express'
4
4
 
5
5
  const defaults = {
6
6
  public: path.resolve(__dirname, '..', 'public'),
7
7
  logger: console
8
- };
9
- const defaultHtmlError = path.resolve(defaults.public, 'default.html');
8
+ }
9
+ const defaultHtmlError = path.resolve(defaults.public, 'default.html')
10
10
 
11
- export function notFound ({ verbose = false } = {}): RequestHandler {
11
+ export function notFound({ verbose = false } = {}): RequestHandler {
12
12
  return function (req: Request, _res: Response, next: NextFunction) {
13
- const url = `${req.url}`;
14
- const message = `Page not found${verbose ? ': ' + url : ''}`;
13
+ const url = `${req.url}`
14
+ const message = `Page not found${verbose ? ': ' + url : ''}`
15
15
 
16
- next(new NotFound(message, { url }));
17
- };
16
+ next(new NotFound(message, { url }))
17
+ }
18
18
  }
19
19
 
20
20
  export type ErrorHandlerOptions = {
21
- public?: string,
22
- logger?: boolean|{ error?: (msg: any) => void, info?: (msg: any) => void },
23
- html?: any,
21
+ public?: string
22
+ logger?: boolean | { error?: (msg: any) => void; info?: (msg: any) => void }
23
+ html?: any
24
24
  json?: any
25
- };
25
+ }
26
26
 
27
- export function errorHandler (_options: ErrorHandlerOptions = {}): ErrorRequestHandler {
28
- const options = Object.assign({}, defaults, _options);
27
+ export function errorHandler(_options: ErrorHandlerOptions = {}): ErrorRequestHandler {
28
+ const options = Object.assign({}, defaults, _options)
29
29
 
30
30
  if (typeof options.html === 'undefined') {
31
31
  options.html = {
32
32
  401: path.resolve(options.public, '401.html'),
33
33
  404: path.resolve(options.public, '404.html'),
34
34
  default: defaultHtmlError
35
- };
35
+ }
36
36
  }
37
37
 
38
38
  if (typeof options.json === 'undefined') {
39
- options.json = {};
39
+ options.json = {}
40
40
  }
41
41
 
42
42
  return function (error: any, req: Request, res: Response, next: NextFunction) {
43
43
  // Set the error code for HTTP processing semantics
44
- error.code = !isNaN(parseInt(error.code, 10)) ? parseInt(error.code, 10) : 500;
44
+ error.code = !isNaN(parseInt(error.code, 10)) ? parseInt(error.code, 10) : 500
45
45
 
46
46
  // Log the error if it didn't come from a service method call
47
47
  if (options.logger && typeof options.logger.error === 'function' && !res.hook) {
48
48
  if (error.code >= 500) {
49
- options.logger.error(error);
49
+ options.logger.error(error)
50
50
  } else {
51
- options.logger.info(error);
51
+ options.logger.info(error)
52
52
  }
53
53
  }
54
54
 
55
55
  if (error.type !== 'FeathersError') {
56
- const oldError = error;
56
+ const oldError = error
57
57
 
58
- error = oldError.errors ? new GeneralError(oldError.message, {
59
- errors: oldError.errors
60
- }) : new GeneralError(oldError.message);
58
+ error = oldError.errors
59
+ ? new GeneralError(oldError.message, {
60
+ errors: oldError.errors
61
+ })
62
+ : new GeneralError(oldError.message)
61
63
 
62
64
  if (oldError.stack) {
63
- error.stack = oldError.stack;
65
+ error.stack = oldError.stack
64
66
  }
65
67
  }
66
68
 
67
- const formatter: { [key: string]: any } = {};
69
+ const formatter: { [key: string]: any } = {}
68
70
 
69
71
  // If the developer passed a custom function for ALL html errors
70
72
  if (typeof options.html === 'function') {
71
- formatter['text/html'] = options.html;
73
+ formatter['text/html'] = options.html
72
74
  } else {
73
- let file = options.html[error.code];
75
+ let file = options.html[error.code]
74
76
  if (!file) {
75
- file = options.html.default || defaultHtmlError;
77
+ file = options.html.default || defaultHtmlError
76
78
  }
77
79
  // If the developer passed a custom function for individual html errors
78
80
  if (typeof file === 'function') {
79
- formatter['text/html'] = file;
81
+ formatter['text/html'] = file
80
82
  } else {
81
83
  formatter['text/html'] = function () {
82
- res.set('Content-Type', 'text/html');
83
- res.sendFile(file);
84
- };
84
+ res.set('Content-Type', 'text/html')
85
+ res.sendFile(file)
86
+ }
85
87
  }
86
88
  }
87
89
 
88
90
  // If the developer passed a custom function for ALL json errors
89
91
  if (typeof options.json === 'function') {
90
- formatter['application/json'] = options.json;
92
+ formatter['application/json'] = options.json
91
93
  } else {
92
- const handler = options.json[error.code] || options.json.default;
94
+ const handler = options.json[error.code] || options.json.default
93
95
  // If the developer passed a custom function for individual json errors
94
96
  if (typeof handler === 'function') {
95
- formatter['application/json'] = handler;
97
+ formatter['application/json'] = handler
96
98
  } else {
97
99
  // Don't show stack trace if it is a 404 error
98
100
  if (error.code === 404) {
99
- error.stack = null;
101
+ error.stack = null
100
102
  }
101
103
 
102
104
  formatter['application/json'] = function () {
103
- const output = Object.assign({}, error.toJSON());
105
+ const output = Object.assign({}, error.toJSON())
104
106
 
105
107
  if (process.env.NODE_ENV === 'production') {
106
- delete output.stack;
108
+ delete output.stack
107
109
  }
108
110
 
109
- res.set('Content-Type', 'application/json');
110
- res.json(output);
111
- };
111
+ res.set('Content-Type', 'application/json')
112
+ res.json(output)
113
+ }
112
114
  }
113
115
  }
114
116
 
115
- res.status(error.code);
117
+ res.status(error.code)
116
118
 
117
- const contentType = req.headers['content-type'] || '';
118
- const accepts = req.headers.accept || '';
119
+ const contentType = req.headers['content-type'] || ''
120
+ const accepts = req.headers.accept || ''
119
121
 
120
122
  // by default just send back json
121
123
  if (contentType.indexOf('json') !== -1 || accepts.indexOf('json') !== -1) {
122
- formatter['application/json'](error, req, res, next);
124
+ formatter['application/json'](error, req, res, next)
123
125
  } else if (options.html && (contentType.indexOf('html') !== -1 || accepts.indexOf('html') !== -1)) {
124
- formatter['text/html'](error, req, res, next);
126
+ formatter['text/html'](error, req, res, next)
125
127
  } else {
126
128
  // TODO (EK): Maybe just return plain text
127
- formatter['application/json'](error, req, res, next);
129
+ formatter['application/json'](error, req, res, next)
128
130
  }
129
- };
131
+ }
130
132
  }
package/src/index.ts CHANGED
@@ -1,107 +1,150 @@
1
- import express, {
2
- Express, static as _static, json, raw, text, urlencoded, query
3
- } from 'express';
4
- import {
5
- Application as FeathersApplication, defaultServiceMethods
6
- } from '@feathersjs/feathers';
7
- import { createDebug } from '@feathersjs/commons';
8
-
9
- import { Application } from './declarations';
10
- import { errorHandler, notFound } from './handlers';
11
- import { parseAuthentication, authenticate } from './authentication';
1
+ import express, { Express } from 'express'
2
+ import { Application as FeathersApplication, defaultServiceMethods } from '@feathersjs/feathers'
3
+ import { routing } from '@feathersjs/transport-commons'
4
+ import { createDebug } from '@feathersjs/commons'
5
+ import cors from 'cors'
6
+
7
+ import { rest, RestOptions, formatter } from './rest'
8
+ import { errorHandler, notFound, ErrorHandlerOptions } from './handlers'
9
+ import { Application, ExpressOverrides } from './declarations'
10
+ import { AuthenticationSettings, authenticate, parseAuthentication } from './authentication'
11
+ import { default as original, static as serveStatic, json, raw, text, urlencoded, query } from 'express'
12
12
 
13
13
  export {
14
- _static as static, json, raw, text, urlencoded, query,
15
- errorHandler, notFound, express as original,
16
- authenticate, parseAuthentication
17
- };
18
-
19
- export * from './rest';
20
- export * from './declarations';
14
+ original,
15
+ serveStatic,
16
+ serveStatic as static,
17
+ json,
18
+ raw,
19
+ text,
20
+ urlencoded,
21
+ query,
22
+ rest,
23
+ RestOptions,
24
+ formatter,
25
+ errorHandler,
26
+ notFound,
27
+ Application,
28
+ ErrorHandlerOptions,
29
+ ExpressOverrides,
30
+ AuthenticationSettings,
31
+ parseAuthentication,
32
+ authenticate,
33
+ cors
34
+ }
21
35
 
22
- const debug = createDebug('@feathersjs/express');
36
+ const debug = createDebug('@feathersjs/express')
23
37
 
24
- export default function feathersExpress<S = any, C = any> (feathersApp?: FeathersApplication<S, C>, expressApp: Express = express()): Application<S, C> {
38
+ export default function feathersExpress<S = any, C = any>(
39
+ feathersApp?: FeathersApplication<S, C>,
40
+ expressApp: Express = express()
41
+ ): Application<S, C> {
25
42
  if (!feathersApp) {
26
- return expressApp as any;
43
+ return expressApp as any
27
44
  }
28
45
 
29
46
  if (typeof feathersApp.setup !== 'function') {
30
- throw new Error('@feathersjs/express requires a valid Feathers application instance');
47
+ throw new Error('@feathersjs/express requires a valid Feathers application instance')
31
48
  }
32
49
 
33
- const { use, listen } = expressApp as any;
34
- // A mixin that provides the extended functionality
35
- const mixin: any = {
36
- use (location: string, ...rest: any[]) {
37
- let service: any;
38
- let options = {};
50
+ const app = expressApp as any as Application<S, C>
51
+ const { use: expressUse, listen: expressListen } = expressApp as any
52
+ const { use: feathersUse, teardown: feathersTeardown } = feathersApp
53
+
54
+ Object.assign(app, {
55
+ use(location: string & keyof S, ...rest: any[]) {
56
+ let service: any
57
+ let options = {}
39
58
 
40
- const middleware = rest.reduce(function (middleware, arg) {
59
+ const middleware = rest.reduce(
60
+ function (middleware, arg) {
41
61
  if (typeof arg === 'function' || Array.isArray(arg)) {
42
- middleware[service ? 'after' : 'before'].push(arg);
62
+ middleware[service ? 'after' : 'before'].push(arg)
43
63
  } else if (!service) {
44
- service = arg;
45
- } else if (arg.methods || arg.events) {
46
- options = arg;
64
+ service = arg
65
+ } else if (arg.methods || arg.events || arg.express || arg.koa) {
66
+ options = arg
47
67
  } else {
48
- throw new Error('Invalid options passed to app.use');
68
+ throw new Error('Invalid options passed to app.use')
49
69
  }
50
- return middleware;
51
- }, {
70
+ return middleware
71
+ },
72
+ {
52
73
  before: [],
53
74
  after: []
54
- });
75
+ }
76
+ )
55
77
 
56
- const hasMethod = (methods: string[]) => methods.some(name =>
57
- (service && typeof service[name] === 'function')
58
- );
78
+ const hasMethod = (methods: string[]) =>
79
+ methods.some((name) => service && typeof service[name] === 'function')
59
80
 
60
81
  // Check for service (any object with at least one service method)
61
82
  if (hasMethod(['handle', 'set']) || !hasMethod(defaultServiceMethods)) {
62
- debug('Passing app.use call to Express app');
63
- return use.call(this, location, ...rest);
83
+ debug('Passing app.use call to Express app')
84
+ return expressUse.call(this, location, ...rest)
64
85
  }
65
86
 
66
- debug('Registering service with middleware', middleware);
87
+ debug('Registering service with middleware', middleware)
67
88
  // Since this is a service, call Feathers `.use`
68
- (feathersApp as FeathersApplication).use.call(this, location, service, {
69
- ...options,
70
- middleware
71
- });
89
+ feathersUse.call(this, location, service, {
90
+ express: middleware,
91
+ ...options
92
+ })
72
93
 
73
- return this;
94
+ return this
74
95
  },
75
96
 
76
- async listen (...args: any[]) {
77
- const server = listen.call(this, ...args);
97
+ async listen(...args: any[]) {
98
+ const server = expressListen.call(this, ...args)
78
99
 
79
- await this.setup(server);
80
- debug('Feathers application listening');
100
+ this.server = server
101
+ await this.setup(server)
102
+ debug('Feathers application listening')
81
103
 
82
- return server;
104
+ return server
83
105
  }
84
- };
106
+ } as Application<S, C>)
85
107
 
86
- const feathersDescriptors = {
108
+ const appDescriptors = {
109
+ ...Object.getOwnPropertyDescriptors(Object.getPrototypeOf(app)),
110
+ ...Object.getOwnPropertyDescriptors(app)
111
+ }
112
+ const newDescriptors = {
87
113
  ...Object.getOwnPropertyDescriptors(Object.getPrototypeOf(feathersApp)),
88
114
  ...Object.getOwnPropertyDescriptors(feathersApp)
89
- };
115
+ }
90
116
 
91
117
  // Copy all non-existing properties (including non-enumerables)
92
118
  // that don't already exist on the Express app
93
- Object.keys(feathersDescriptors).forEach(prop => {
94
- const feathersProp = feathersDescriptors[prop];
95
- const expressProp = Object.getOwnPropertyDescriptor(expressApp, prop);
119
+ Object.keys(newDescriptors).forEach((prop) => {
120
+ const appProp = appDescriptors[prop]
121
+ const newProp = newDescriptors[prop]
96
122
 
97
- if (expressProp === undefined && feathersProp !== undefined) {
98
- Object.defineProperty(expressApp, prop, feathersProp);
123
+ if (appProp === undefined && newProp !== undefined) {
124
+ Object.defineProperty(expressApp, prop, newProp)
99
125
  }
100
- });
126
+ })
127
+
128
+ // Assign teardown and setup which will also make sure that hooks are initialized
129
+ app.setup = feathersApp.setup as any
130
+ app.teardown = async function teardown(server?: any) {
131
+ return feathersTeardown.call(this, server).then(
132
+ () =>
133
+ new Promise((resolve, reject) => {
134
+ if (this.server) {
135
+ this.server.close((e) => (e ? reject(e) : resolve(this)))
136
+ } else {
137
+ resolve(this)
138
+ }
139
+ })
140
+ )
141
+ }
142
+
143
+ app.configure(routing() as any)
101
144
 
102
- return Object.assign(expressApp, mixin);
145
+ return app
103
146
  }
104
147
 
105
148
  if (typeof module !== 'undefined') {
106
- module.exports = Object.assign(feathersExpress, module.exports);
149
+ module.exports = Object.assign(feathersExpress, module.exports)
107
150
  }
package/src/rest.ts CHANGED
@@ -1,160 +1,117 @@
1
- import { MethodNotAllowed } from '@feathersjs/errors';
2
- import { BaseHookContext, HookContext } from '@feathersjs/hooks';
3
- import { createDebug } from '@feathersjs/commons';
4
- import { createContext, defaultServiceMethods, getServiceOptions, NullableId, Params } from '@feathersjs/feathers';
5
- import { Request, Response, NextFunction, RequestHandler, Router } from 'express';
1
+ import { Request, Response, RequestHandler, Router } from 'express'
2
+ import { MethodNotAllowed } from '@feathersjs/errors'
3
+ import { createDebug } from '@feathersjs/commons'
4
+ import { http } from '@feathersjs/transport-commons'
5
+ import { createContext, defaultServiceMethods, getServiceOptions } from '@feathersjs/feathers'
6
6
 
7
- import { parseAuthentication } from './authentication';
7
+ import { AuthenticationSettings, parseAuthentication } from './authentication'
8
+ import { Application } from './declarations'
8
9
 
9
- const debug = createDebug('@feathersjs/express/rest');
10
+ const debug = createDebug('@feathersjs/express/rest')
10
11
 
11
- export const METHOD_HEADER = 'x-service-method';
12
-
13
- export interface ServiceParams {
14
- id: NullableId,
15
- data: any,
16
- params: Params
12
+ const toHandler = (
13
+ func: (req: Request, res: Response, next: () => void) => Promise<void>
14
+ ): RequestHandler => {
15
+ return (req, res, next) => func(req, res, next).catch((error) => next(error))
17
16
  }
18
17
 
19
- export type ServiceCallback = (req: Request, res: Response, options: ServiceParams) => Promise<HookContext|any>;
20
-
21
- export const statusCodes = {
22
- created: 201,
23
- noContent: 204,
24
- methodNotAllowed: 405,
25
- success: 200
26
- };
27
-
28
- export const feathersParams = (req: Request, _res: Response, next: NextFunction) => {
29
- req.feathers = {
30
- ...req.feathers,
31
- provider: 'rest',
32
- headers: req.headers
33
- };
34
- next();
35
- }
18
+ const serviceMiddleware = (): RequestHandler => {
19
+ return toHandler(async (req, res, next) => {
20
+ const { query, headers, path, body: data, method: httpMethod } = req
21
+ const methodOverride = req.headers[http.METHOD_HEADER] as string | undefined
36
22
 
37
- export const formatter = (_req: Request, res: Response, next: NextFunction) => {
38
- if (res.data === undefined) {
39
- return next();
40
- }
23
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
24
+ const { service, params: { __id: id = null, ...route } = {} } = req.lookup!
25
+ const method = http.getServiceMethod(httpMethod, id, methodOverride)
26
+ const { methods } = getServiceOptions(service)
41
27
 
42
- res.format({
43
- 'application/json' () {
44
- res.json(res.data);
28
+ debug(`Found service for path ${path}, attempting to run '${method}' service method`)
29
+
30
+ if (!methods.includes(method) || defaultServiceMethods.includes(methodOverride)) {
31
+ const error = new MethodNotAllowed(`Method \`${method}\` is not supported by this endpoint.`)
32
+ res.statusCode = error.code
33
+ throw error
45
34
  }
46
- });
47
- }
48
35
 
49
- const getData = (context: HookContext) => {
50
- if (!(context instanceof BaseHookContext)) {
51
- return context;
52
- }
36
+ const createArguments = http.argumentsFor[method as 'get'] || http.argumentsFor.default
37
+ const params = { query, headers, route, ...req.feathers }
38
+ const args = createArguments({ id, data, params })
39
+ const contextBase = createContext(service, method, { http: {} })
40
+ res.hook = contextBase
41
+
42
+ const context = await (service as any)[method](...args, contextBase)
43
+ res.hook = context
53
44
 
54
- return context.dispatch !== undefined
55
- ? context.dispatch
56
- : context.result;
45
+ const response = http.getResponse(context)
46
+ res.statusCode = response.status
47
+ res.set(response.headers)
48
+ res.data = response.body
49
+
50
+ return next()
51
+ })
57
52
  }
58
53
 
59
- const getStatusCode = (context: HookContext, res: Response) => {
60
- if (context instanceof BaseHookContext) {
61
- if (context.statusCode) {
62
- return context.statusCode;
63
- }
54
+ const servicesMiddleware = (): RequestHandler => {
55
+ return toHandler(async (req, res, next) => {
56
+ const app = req.app as any as Application
57
+ const lookup = app.lookup(req.path)
64
58
 
65
- if (context.method === 'create') {
66
- return statusCodes.created;
59
+ if (!lookup) {
60
+ return next()
67
61
  }
68
- }
69
-
70
- if (!res.data) {
71
- return statusCodes.noContent;
72
- }
73
62
 
74
- return statusCodes.success;
75
- }
63
+ req.lookup = lookup
76
64
 
77
- export const serviceMiddleware = (callback: ServiceCallback) =>
78
- async (req: Request, res: Response, next: NextFunction) => {
79
- debug(`Running service middleware for '${req.url}'`);
65
+ const options = getServiceOptions(lookup.service)
66
+ const middleware = options.express.composed
80
67
 
81
- try {
82
- const { query, body: data } = req;
83
- const { __feathersId: id = null, ...route } = req.params;
84
- const params = { query, route, ...req.feathers };
85
- const context = await callback(req, res, { id, data, params });
68
+ return middleware(req, res, next)
69
+ })
70
+ }
86
71
 
87
- res.data = getData(context);
88
- res.status(getStatusCode(context, res));
72
+ export const formatter: RequestHandler = (_req, res, next) => {
73
+ if (res.data === undefined) {
74
+ return next()
75
+ }
89
76
 
90
- next();
91
- } catch (error) {
92
- next(error);
77
+ res.format({
78
+ 'application/json'() {
79
+ res.json(res.data)
93
80
  }
94
- }
81
+ })
82
+ }
95
83
 
96
- export const serviceMethodHandler = (
97
- service: any, methodName: string, getArgs: (opts: ServiceParams) => any[], headerOverride?: string
98
- ) => serviceMiddleware(async (req, res, options) => {
99
- const methodOverride = typeof headerOverride === 'string' && (req.headers[headerOverride] as string);
100
- const method = methodOverride ? methodOverride : methodName
101
- const { methods } = getServiceOptions(service);
84
+ export type RestOptions = {
85
+ formatter?: RequestHandler
86
+ authentication?: AuthenticationSettings
87
+ }
102
88
 
103
- if (!methods.includes(method) || defaultServiceMethods.includes(methodOverride)) {
104
- res.status(statusCodes.methodNotAllowed);
89
+ export const rest = (options?: RestOptions | RequestHandler) => {
90
+ options = typeof options === 'function' ? { formatter: options } : options || {}
105
91
 
106
- throw new MethodNotAllowed(`Method \`${method}\` is not supported by this endpoint.`);
107
- }
92
+ const formatterMiddleware = options.formatter || formatter
93
+ const authenticationOptions = options.authentication
108
94
 
109
- const args = getArgs(options);
110
- const context = createContext(service, method);
95
+ return (app: Application) => {
96
+ if (typeof app.route !== 'function') {
97
+ throw new Error('@feathersjs/express/rest needs an Express compatible app.')
98
+ }
111
99
 
112
- res.hook = context as any;
100
+ app.use((req, _res, next) => {
101
+ req.feathers = { ...req.feathers, provider: 'rest' }
102
+ return next()
103
+ })
104
+ app.use(parseAuthentication(authenticationOptions))
105
+ app.use(servicesMiddleware())
113
106
 
114
- return service[method](...args, context);
115
- });
107
+ app.mixins.push((_service, _path, options) => {
108
+ const { express: { before = [], after = [] } = {} } = options
116
109
 
117
- export function rest (handler: RequestHandler = formatter) {
118
- return function (this: any, app: any) {
119
- if (typeof app.route !== 'function') {
120
- throw new Error('@feathersjs/express/rest needs an Express compatible app.');
121
- }
110
+ const middlewares = [].concat(before, serviceMiddleware(), after, formatterMiddleware)
111
+ const middleware = Router().use(middlewares)
122
112
 
123
- app.use(feathersParams);
124
- app.use(parseAuthentication());
125
-
126
- // Register the REST provider
127
- app.mixins.push(function (service: any, path: string, options: any) {
128
- const { middleware: { before = [] } } = options;
129
- let { middleware: { after = [] } } = options;
130
-
131
- if (typeof handler === 'function') {
132
- after = after.concat(handler);
133
- }
134
-
135
- const baseUri = `/${path}`;
136
- const find = serviceMethodHandler(service, 'find', ({ params }) => [ params ]);
137
- const get = serviceMethodHandler(service, 'get', ({ id, params }) => [ id, params ]);
138
- const create = serviceMethodHandler(service, 'create', ({ data, params }) => [ data, params ], METHOD_HEADER);
139
- const update = serviceMethodHandler(service, 'update', ({ id, data, params }) => [ id, data, params ]);
140
- const patch = serviceMethodHandler(service, 'patch', ({ id, data, params }) => [ id, data, params ]);
141
- const remove = serviceMethodHandler(service, 'remove', ({ id, params }) => [ id, params ]);
142
-
143
- debug(`Adding REST provider for service \`${path}\` at base route \`${baseUri}\``);
144
-
145
- const idRoute = '/:__feathersId';
146
- const serviceRouter = Router({ mergeParams: true })
147
- .get('/', find)
148
- .post('/', create)
149
- .get(idRoute, get)
150
- .put('/', update)
151
- .put(idRoute, update)
152
- .patch('/', patch)
153
- .patch(idRoute, patch)
154
- .delete('/', remove)
155
- .delete(idRoute, remove);
156
-
157
- app.use(baseUri, ...before, serviceRouter, ...after);
158
- });
159
- };
113
+ options.express ||= {}
114
+ options.express.composed = middleware
115
+ })
116
+ }
160
117
  }