Skip to content

Commit 164d75c

Browse files
authored
fix(core): Improve service option usage and method option typings (#2902)
1 parent 31f9a12 commit 164d75c

File tree

9 files changed

+40
-29
lines changed

9 files changed

+40
-29
lines changed

packages/authentication-oauth/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { resolveDispatch } from '@feathersjs/schema'
44

55
import { OAuthStrategy, OAuthProfile } from './strategy'
66
import { redirectHook, OAuthService } from './service'
7-
import { getGrantConfig, getServiceOptions, OauthSetupSettings } from './utils'
7+
import { getGrantConfig, authenticationServiceOptions, OauthSetupSettings } from './utils'
88

99
const debug = createDebug('@feathersjs/authentication-oauth')
1010

@@ -32,7 +32,7 @@ export const oauth =
3232
}
3333

3434
const grantConfig = getGrantConfig(authService)
35-
const serviceOptions = getServiceOptions(authService, oauthOptions)
35+
const serviceOptions = authenticationServiceOptions(authService, oauthOptions)
3636
const servicePath = `${grantConfig.defaults.prefix || 'oauth'}/:provider`
3737

3838
app.use(servicePath, new OAuthService(authService, oauthOptions), serviceOptions)

packages/authentication-oauth/src/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export const setKoaParams: Middleware = async (ctx, next) => {
8989
await next()
9090
}
9191

92-
export const getServiceOptions = (
92+
export const authenticationServiceOptions = (
9393
service: AuthenticationService,
9494
settings: OauthSetupSettings
9595
): ServiceOptions => {

packages/feathers/src/application.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ export class Feathers<Services, Settings>
145145
use<L extends keyof Services & string>(
146146
path: L,
147147
service: keyof any extends keyof Services ? ServiceInterface | Application : Services[L],
148-
options?: ServiceOptions
148+
options?: ServiceOptions<keyof any extends keyof Services ? string : keyof Services[L]>
149149
): this {
150150
if (typeof path !== 'string') {
151151
throw new Error(`'${path}' is not a valid service path.`)
@@ -163,7 +163,7 @@ export class Feathers<Services, Settings>
163163
return this
164164
}
165165

166-
const protoService = wrapService(location, service, options)
166+
const protoService = wrapService(location, service, options as ServiceOptions)
167167
const serviceOptions = getServiceOptions(protoService)
168168

169169
for (const name of protectedMethods) {

packages/feathers/src/declarations.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,23 @@ export interface Paginated<T> {
1919
/**
2020
* Options that can be passed when registering a service via `app.use(name, service, options)`
2121
*/
22-
export interface ServiceOptions {
22+
export interface ServiceOptions<MethodTypes = string> {
23+
/**
24+
* A list of custom events that this service emits to clients
25+
*/
2326
events?: string[] | readonly string[]
24-
methods?: string[] | readonly string[]
27+
/**
28+
* A list of service methods that should be available __externally__ to clients
29+
*/
30+
methods?: MethodTypes[] | readonly MethodTypes[]
31+
/**
32+
* Provide a full list of events that this service should emit to clients.
33+
* Unlike the `events` option, this will not be merged with the default events.
34+
*/
2535
serviceEvents?: string[] | readonly string[]
36+
/**
37+
* Initial data to always add as route params to this service.
38+
*/
2639
routeParams?: { [key: string]: any }
2740
}
2841

@@ -226,7 +239,7 @@ export interface FeathersApplication<Services = any, Settings = any> {
226239
use<L extends keyof Services & string>(
227240
path: L,
228241
service: keyof any extends keyof Services ? ServiceInterface | Application : Services[L],
229-
options?: ServiceOptions
242+
options?: ServiceOptions<keyof any extends keyof Services ? string : keyof Services[L]>
230243
): this
231244

232245
/**

packages/feathers/src/service.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export const defaultEventMap = {
2121
remove: 'removed'
2222
}
2323

24+
export const defaultServiceEvents = Object.values(defaultEventMap)
25+
2426
export const protectedMethods = Object.keys(Object.prototype)
2527
.concat(Object.keys(EventEmitter.prototype))
2628
.concat(['all', 'around', 'before', 'after', 'error', 'hooks', 'setup', 'teardown', 'publish'])
@@ -33,18 +35,16 @@ export function getHookMethods(service: any, options: ServiceOptions) {
3335
.concat(methods)
3436
}
3537

36-
export function getServiceOptions(service: any, options: ServiceOptions = {}): ServiceOptions {
37-
const existingOptions = service[SERVICE]
38-
39-
if (existingOptions) {
40-
return existingOptions
41-
}
38+
export function getServiceOptions(service: any): ServiceOptions {
39+
return service[SERVICE]
40+
}
4241

42+
export const normalizeServiceOptions = (service: any, options: ServiceOptions = {}): ServiceOptions => {
4343
const {
4444
methods = defaultServiceMethods.filter((method) => typeof service[method] === 'function'),
4545
events = service.events || []
4646
} = options
47-
const { serviceEvents = Object.values(defaultEventMap).concat(events) } = options
47+
const serviceEvents = options.serviceEvents || defaultServiceEvents.concat(events)
4848

4949
return {
5050
...options,
@@ -61,7 +61,7 @@ export function wrapService(location: string, service: any, options: ServiceOpti
6161
}
6262

6363
const protoService = Object.create(service)
64-
const serviceOptions = getServiceOptions(service, options)
64+
const serviceOptions = normalizeServiceOptions(service, options)
6565

6666
if (Object.keys(serviceOptions.methods).length === 0 && typeof service.setup !== 'function') {
6767
throw new Error(`Invalid service object passed for path \`${location}\``)

packages/feathers/test/application.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ describe('Feathers application', () => {
441441
app.mixins.push(function (service: any, location: any, options: any) {
442442
assert.ok(service.dummy)
443443
assert.strictEqual(location, 'dummy')
444-
assert.deepStrictEqual(options, getServiceOptions(new Dummy()))
444+
assert.deepStrictEqual(options, getServiceOptions(service))
445445
mixinRan = true
446446
})
447447

@@ -461,7 +461,7 @@ describe('Feathers application', () => {
461461
app.mixins.push(function (service: any, location: any, options: any) {
462462
assert.ok(service.dummy)
463463
assert.strictEqual(location, 'dummy')
464-
assert.deepStrictEqual(options, getServiceOptions(new Dummy(), opts))
464+
assert.deepStrictEqual(options, getServiceOptions(service))
465465
mixinRan = true
466466
})
467467

packages/feathers/test/declarations.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ describe('Feathers typings', () => {
7070
const app2 = feathers<Record<string, unknown>, Configuration>()
7171

7272
app.set('port', 80)
73-
app.use('todos', new TodoService())
73+
app.use('todos', new TodoService(), {
74+
methods: ['find', 'create']
75+
})
7476
app.use('v2', app2)
7577

7678
const service = app.service('todos')
@@ -84,8 +86,9 @@ describe('Feathers typings', () => {
8486
all: [],
8587
create: [
8688
async (context) => {
87-
const { result, data } = context
89+
const { result, data, service } = context
8890

91+
assert.ok(service instanceof TodoService)
8992
assert.ok(result)
9093
assert.ok(data)
9194
assert.ok(context.app.service('todos'))

packages/schema/test/fixture.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
import {
2-
feathers,
3-
HookContext,
4-
Application as FeathersApplication,
5-
defaultServiceMethods
6-
} from '@feathersjs/feathers'
1+
import { feathers, HookContext, Application as FeathersApplication } from '@feathersjs/feathers'
72
import { memory, MemoryService } from '@feathersjs/memory'
83
import { GeneralError } from '@feathersjs/errors'
94

@@ -193,7 +188,7 @@ app.use(
193188
})
194189
)
195190
app.use('messages', new MessageService(), {
196-
methods: [...defaultServiceMethods, 'customMethod']
191+
methods: ['find', 'get', 'create', 'update', 'patch', 'remove', 'customMethod']
197192
})
198193
app.use('paginatedMessages', memory({ paginate: { default: 10 } }))
199194

packages/transport-commons/src/channels/mixins.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
2-
import { Application, HookContext, getServiceOptions } from '@feathersjs/feathers'
2+
import { Application, HookContext, getServiceOptions, defaultServiceEvents } from '@feathersjs/feathers'
33
import { createDebug } from '@feathersjs/commons'
44
import { Channel } from './channel/base'
55
import { CombinedChannel } from './channel/combined'
@@ -90,7 +90,7 @@ export function publishMixin() {
9090
event = ALL_EVENTS
9191
}
9292

93-
const { serviceEvents } = getServiceOptions(this)
93+
const { serviceEvents = defaultServiceEvents } = getServiceOptions(this) || {}
9494

9595
if (event !== ALL_EVENTS && !serviceEvents.includes(event)) {
9696
throw new Error(`'${event.toString()}' is not a valid service event`)

0 commit comments

Comments
 (0)