1 | import { EventEmitter } from 'events'
|
2 | import { createSymbol } from '@feathersjs/commons'
|
3 | import { ServiceOptions } from './declarations'
|
4 |
|
5 | export const SERVICE = createSymbol('@feathersjs/service')
|
6 |
|
7 | export const defaultServiceArguments = {
|
8 | find: ['params'],
|
9 | get: ['id', 'params'],
|
10 | create: ['data', 'params'],
|
11 | update: ['id', 'data', 'params'],
|
12 | patch: ['id', 'data', 'params'],
|
13 | remove: ['id', 'params']
|
14 | }
|
15 | export const defaultServiceMethods = ['find', 'get', 'create', 'update', 'patch', 'remove']
|
16 |
|
17 | export const defaultEventMap = {
|
18 | create: 'created',
|
19 | update: 'updated',
|
20 | patch: 'patched',
|
21 | remove: 'removed'
|
22 | }
|
23 |
|
24 | export const defaultServiceEvents = Object.values(defaultEventMap)
|
25 |
|
26 | export const protectedMethods = Object.keys(Object.prototype)
|
27 | .concat(Object.keys(EventEmitter.prototype))
|
28 | .concat(['all', 'around', 'before', 'after', 'error', 'hooks', 'setup', 'teardown', 'publish'])
|
29 |
|
30 | export function getHookMethods(service: any, options: ServiceOptions) {
|
31 | const { methods } = options
|
32 |
|
33 | return (defaultServiceMethods as any as string[])
|
34 | .filter((m) => typeof service[m] === 'function' && !methods.includes(m))
|
35 | .concat(methods)
|
36 | }
|
37 |
|
38 | export function getServiceOptions(service: any): ServiceOptions {
|
39 | return service[SERVICE]
|
40 | }
|
41 |
|
42 | export const normalizeServiceOptions = (service: any, options: ServiceOptions = {}): ServiceOptions => {
|
43 | const {
|
44 | methods = defaultServiceMethods.filter((method) => typeof service[method] === 'function'),
|
45 | events = service.events || []
|
46 | } = options
|
47 | const serviceEvents = options.serviceEvents || defaultServiceEvents.concat(events)
|
48 |
|
49 | return {
|
50 | ...options,
|
51 | events,
|
52 | methods,
|
53 | serviceEvents
|
54 | }
|
55 | }
|
56 |
|
57 | export function wrapService(location: string, service: any, options: ServiceOptions) {
|
58 |
|
59 | if (service[SERVICE]) {
|
60 | return service
|
61 | }
|
62 |
|
63 | const protoService = Object.create(service)
|
64 | const serviceOptions = normalizeServiceOptions(service, options)
|
65 |
|
66 | if (
|
67 | Object.keys(serviceOptions.methods).length === 0 &&
|
68 | ![...defaultServiceMethods, 'setup', 'teardown'].some((method) => typeof service[method] === 'function')
|
69 | ) {
|
70 | throw new Error(`Invalid service object passed for path \`${location}\``)
|
71 | }
|
72 |
|
73 | Object.defineProperty(protoService, SERVICE, {
|
74 | value: serviceOptions
|
75 | })
|
76 |
|
77 | return protoService
|
78 | }
|