8000 fix(core): Ensure setup and teardown can be overriden and maintain hook functionality by daffl · Pull Request #2779 · feathersjs/feathers · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/cli/src/commons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ export const checkPreconditions =
() =>
async <T extends FeathersBaseContext>(ctx: T) => {
if (!ctx.feathers) {
console.log(ctx)
throw new Error(`Can not run generator since the current folder does not appear to be a Feathers application.
Either your package.json is missing or it does not have \`feathers\` property.
`)
Expand Down
28 changes: 15 additions & 13 deletions packages/express/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,6 @@ export default function feathersExpress<S = any, C = any>(
debug('Feathers application listening')

return server
},

async teardown(server?: any) {
return feathersTeardown.call(this, server).then(
() =>
new Promise((resolve, reject) => {
if (this.server) {
this.server.close((e) => (e ? reject(e) : resolve(this)))
} else {
resolve(this)
}
})
)
}
} as Application<S, C>)

Expand All @@ -138,6 +125,21 @@ export default function feathersExpress<S = any, C = any>(
}
})

// Assign teardown and setup which will also make sure that hooks are initialized
app.setup = feathersApp.setup as any
app.teardown = async function teardown(server?: any) {
return feathersTeardown.call(this, server).then(
() =>
new Promise((resolve, reject) => {
if (this.server) {
this.server.close((e) => (e ? reject(e) : resolve(this)))
} else {
resolve(this)
}
})
)
}

app.configure(routing() as any)

return app
Expand Down
17 changes: 16 additions & 1 deletion packages/express/test/rest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import axios, { AxiosRequestConfig } from 'axios'

import { Server } from 'http'
import { Request, Response, NextFunction } from 'express'
import { feathers, HookContext, Id, Params } from '@feathersjs/feathers'
import { ApplicationHookMap, feathers, HookContext, Id, Params } from '@feathersjs/feathers'
import { Service, restTests } from '@feathersjs/tests'
import { BadRequest } from '@feathersjs/errors'

Expand Down Expand Up @@ -102,6 +102,21 @@ describe('@feathersjs/express/rest provider', () => {
.use('/', new Service())
.use('todo', new Service())

app.hooks({
setup: [
async (context, next) => {
assert.ok(context.app)
await next()
}
],
teardown: [
async (context, next) => {
assert.ok(context.app)
await next()
}
]
} as ApplicationHookMap<express.Application>)

await app.listen(4777, () => app.use('tasks', new Service()))
})

Expand Down
120 changes: 71 additions & 49 deletions packages/feathers/src/application.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import version from './version'
import { EventEmitter } from 'events'
import { stripSlashes, createDebug } from '@feathersjs/commons'
import { hooks, middleware } from '@feathersjs/hooks'
import { HOOKS, hooks, middleware } from '@feathersjs/hooks'
import { eventHook, eventMixin } from './events'
import { hookMixin } from './hooks'
import { wrapService, getServiceOptions, protectedMethods } from './service'
Expand Down Expand Up @@ -33,14 +33,6 @@ export class Feathers<Services, Settings>

constructor() {
super()
hooks(this, {
setup: middleware().params('server').props({
app: this
}),
teardown: middleware().params('server').props({
app: this
})
})
this.registerHooks = enableHooks(this)
this.registerHooks({
around: [eventHook]
Expand Down Expand Up @@ -80,6 +72,76 @@ export class Feathers<Services, Settings>
return current as any
}

protected _setup() {
this._isSetup = true

return Object.keys(this.services)
.reduce(
(current, path) =>
current.then(() => {
const service: any = this.service(path as any)

if (typeof service.setup === 'function') {
debug(`Setting up service for \`${path}\``)

return service.setup(this, path)
}
}),
Promise.resolve()
)
.then(() => this)
}

get setup() {
return this._setup
}

set setup(value) {
this._setup = (value as any)[HOOKS]
? value
: hooks(
value,
middleware().params('server').props({
app: this
})
)
}

protected _teardown() {
this._isSetup = false

return Object.keys(this.services)
.reduce(
(current, path) =>
current.then(() => {
const service: any = this.service(path as any)

if (typeof service.teardown === 'function') {
debug(`Tearing down service for \`${path}\``)

return service.teardown(this, path)
}
}),
Promise.resolve()
)
.then(() => this)
}

get teardown() {
return this._teardown
}

set teardown(value) {
this._teardown = (value as any)[HOOKS]
? value
: hooks(
value,
middleware().params('server').props({
app: this
})
)
}

use<L extends keyof Services & string>(
path: L,
service: keyof any extends keyof Services ? ServiceInterface | Application : Services[L],
Expand Down Expand Up @@ -159,44 +221,4 @@ export class Feathers<Services, Settings>

return this
}

setup() {
this._isSetup = true

return Object.keys(this.services)
.reduce(
(current, path) =>
current.then(() => {
const service: any = this.service(path as any)

if (typeof service.setup === 'function') {
debug(`Setting up service for \`${path}\``)

return service.setup(this, path)
}
}),
Promise.resolve()
)
.then(() => this)
}

teardown() {
this._isSetup = false

return Object.keys(this.services)
.reduce(
(current, path) =>
current.then(() => {
const service: any = this.service(path as any)

if (typeof service.teardown === 'function') {
debug(`Tearing down service for \`${path}\``)

return service.teardown(this, path)
}
}),
Promise.resolve()
)
.then(() => this)
}
}
11 changes: 11 additions & 0 deletions packages/feathers/test/hooks/app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ describe('app.hooks', () => {

it('.setup and .teardown special hooks', async () => {
const app = feathers()

// Test that setup and teardown can be overwritten
const oldSetup = app.setup
app.setup = function (arg: any) {
return oldSetup.call(this, arg)
}
const oldTeardown = app.teardown
app.teardown = function (arg: any) {
return oldTeardown.call(this, arg)
}

const order: string[] = []
const hooks: ApplicationHookMap<typeof app> = {
setup: [
Expand Down
4 changes: 4 additions & 0 deletions packages/koa/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ export function koa<S = any, C = any>(

koaQs(app as any)

// This reinitializes hooks
app.setup = feathersApp.setup as any
app.teardown = feathersApp.teardown as any

app.configure(routing() as any)
app.use((ctx, next) => {
ctx.feathers = { ...ctx.feathers, provider: 'rest' }
Expand Down
17 changes: 16 additions & 1 deletion packages/koa/test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { strict as assert } from 'assert'
import Koa from 'koa'
import axios from 'axios'
import { feathers, Id } from '@feathersjs/feathers'
import { ApplicationHookMap, feathers, Id } from '@feathersjs/feathers'
import { Service, restTests } from '@feathersjs/tests'
import { koa, rest, Application, bodyParser, errorHandler } from '../src'

Expand Down Expand Up @@ -41,6 +41,21 @@ describe('@feathersjs/koa', () => {
methods: ['get', 'find', 'create', 'update', 'patch', 'remove', 'customMethod']
})

app.hooks({
setup: [
async (context, next) => {
assert.ok(context.app)
await next()
}
],
teardown: [
async (context, next) => {
assert.ok(context.app)
await next()
}
]
} as ApplicationHookMap<Application>)

await app.listen(8465)
})

Expand Down
1 change: 0 additions & 1 deletion packages/socketio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
"dependencies": {
"@feathersjs/commons": "^5.0.0-pre.29",
"@feathersjs/feathers": "^5.0.0-pre.29",
"@feathersjs/hooks": "^0.7.5",
"@feathersjs/transport-commons": "^5.0.0-pre.29",
"socket.io": "^4.5.2"
},
Expand Down
5 changes: 0 additions & 5 deletions packages/socketio/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Server, ServerOptions } from 'socket.io'
import { createDebug } from '@feathersjs/commons'
import { Application } from '@feathersjs/feathers'
import { socket } from '@feathersjs/transport-commons'
import { hooks, middleware } from '@feathersjs/hooks'

import { disconnect, params, authentication, FeathersSocket } from './middleware'

Expand Down Expand Up @@ -89,10 +88,6 @@ function configureSocketio(port?: any, options?: any, config?: any) {
return setup.call(this, server, ...rest)
}
})

hooks(app, {
setup: middleware().params('server').props({ app })
})
})

app.configure(
Expand Down
0