diff --git a/packages/feathers/src/declarations.ts b/packages/feathers/src/declarations.ts index 8c9cfff5ba..fcd7d8f408 100644 --- a/packages/feathers/src/declarations.ts +++ b/packages/feathers/src/declarations.ts @@ -18,6 +18,7 @@ export interface ServiceOptions { events?: string[]; methods?: string[]; serviceEvents?: string[]; + routeParams?: { [key: string]: any }; } export interface ServiceMethods> { @@ -110,7 +111,7 @@ export type CustomMethods = { [K in keyof T]: (data: T[K][0], params?: Params) => Promise; } -export type ServiceMixin = (service: FeathersService, path: string, options?: ServiceOptions) => void; +export type ServiceMixin = (service: FeathersService, path: string, options: ServiceOptions) => void; export type ServiceGenericType = S extends ServiceInterface ? T : any; export type ServiceGenericData = S extends ServiceInterface ? D : any; @@ -234,7 +235,7 @@ export interface Query { export interface Params { query?: Query; provider?: string; - route?: { [key: string]: string }; + route?: { [key: string]: any }; headers?: { [key: string]: any }; [key: string]: any; // (JL) not sure if we want this } diff --git a/packages/transport-commons/src/routing/index.ts b/packages/transport-commons/src/routing/index.ts index 01a3b5e2b4..9939fbe2f2 100644 --- a/packages/transport-commons/src/routing/index.ts +++ b/packages/transport-commons/src/routing/index.ts @@ -1,45 +1,50 @@ -import { Application, Service } from '@feathersjs/feathers'; +import { Application, Service, ServiceOptions } from '@feathersjs/feathers'; import { Router } from './router'; declare module '@feathersjs/feathers/lib/declarations' { interface RouteLookup { service: Service, - params: { [key: string]: string } + params: { [key: string]: any } } interface Application { // eslint-disable-line - routes: Router; + routes: Router<{ + service: Service, + params?: { [key: string]: any } + }>; lookup (path: string): RouteLookup; } } export * from './router'; -export const routing = () => (app: Application) => { - if (typeof app.lookup === 'function') { - return; +const lookup = function(this: Application, path: string) { + const result = this.routes.lookup(path); + + if (result === null) { + return null; } - const routes = new Router(); + const { params: colonParams, data: { service, params: dataParams } } = result; - Object.assign(app, { - routes, - lookup (this: Application, path: string) { - const result = this.routes.lookup(path); + const params = dataParams ? { ...dataParams, ...colonParams } : colonParams; - if (result !== null) { - const { params, data: service } = result; + return { service, params }; +}; - return { params, service }; - } +export const routing = () => (app: Application) => { + if (typeof app.lookup === 'function') { + return; + } - return result; - } - }); + app.routes = new Router(); + app.lookup = lookup; // Add a mixin that registers a service on the router - app.mixins.push((service: Service, path: string) => { - app.routes.insert(path, service); - app.routes.insert(`${path}/:__id`, service); + app.mixins.push((service: Service, path: string, options: ServiceOptions) => { + const { routeParams: params = {} } = options; + + app.routes.insert(path, { service, params }); + app.routes.insert(`${path}/:__id`, { service, params }); }); }; diff --git a/packages/transport-commons/test/routing/index.test.ts b/packages/transport-commons/test/routing/index.test.ts index c994ecf41e..eeec0e6898 100644 --- a/packages/transport-commons/test/routing/index.test.ts +++ b/packages/transport-commons/test/routing/index.test.ts @@ -69,4 +69,37 @@ describe('app.routes', () => { second: '::special' }); }); + + it('can register routes with preset params', () => { + app.routes.insert('/my/service/:__id/preset', { + service: app.service('/my/service'), + params: { preset: true } + }); + + const result = app.lookup('/my/service/1234/preset'); + + assert.strictEqual(result.service, app.service('/my/service')); + assert.deepStrictEqual(result.params, { + preset: true, + __id: '1234' + }); + }); + + it('can pass route params during a service registration', () => { + app.use('/other/service', { + async get (id: any) { + return id; + } + }, { + routeParams: { used: true } + }); + + const result = app.lookup('/other/service/1234'); + + assert.strictEqual(result.service, app.service('/other/service')); + assert.deepStrictEqual(result.params, { + used: true, + __id: '1234' + }); + }); });