From f77195596a89cf3e43fe97a9626385569aee120b Mon Sep 17 00:00:00 2001 From: Karolis Narkevicius Date: Mon, 23 Jan 2023 22:55:27 +0000 Subject: [PATCH] fix(feathers): Run after all hooks first, and then after method hooks --- packages/feathers/src/hooks.ts | 46 ++++++++++++++++------ packages/feathers/test/hooks/after.test.ts | 35 ++++++++++++++++ 2 files changed, 68 insertions(+), 13 deletions(-) diff --git a/packages/feathers/src/hooks.ts b/packages/feathers/src/hooks.ts index 6d3dd4b0ec..acb857301d 100644 --- a/packages/feathers/src/hooks.ts +++ b/packages/feathers/src/hooks.ts @@ -26,7 +26,8 @@ type HookStore = { before: { [method: string]: HookFunction[] } after: { [method: string]: HookFunction[] } error: { [method: string]: HookFunction[] } - collected: { [method: string]: AroundHookFunction[] } + collected: { [method: string]: AroundHookFunction[] }, + collectedAll: { before?: AroundHookFunction[], after?: AroundHookFunction[] } } type HookEnabled = { __hooks: HookStore } @@ -55,13 +56,14 @@ export function convertHookData(input: any) { } export function collectHooks(target: HookEnabled, method: string) { - const { collected, around } = target.__hooks + const { collected, collectedAll, around } = target.__hooks return [ ...(around.all || []), ...(around[method] || []), - ...(collected.all || []), - ...(collected[method] || []) + ...(collectedAll.before || []), + ...(collected[method] || []), + ...(collectedAll.after || []), ] as AroundHookFunction[] } @@ -72,7 +74,8 @@ export function enableHooks(object: any) { before: {}, after: {}, error: {}, - collected: {} + collected: {}, + collectedAll: {}, } Object.defineProperty(object, '__hooks', { @@ -101,14 +104,31 @@ export function enableHooks(object: any) { storeHooks.push(...mapHooks) - if (store.before[method] || store.after[method] || store.error[method]) { - const collected = collect({ - before: store.before[method] || [], - after: store.after[method] || [], - error: store.error[method] || [] - }) - - store.collected[method] = [collected] + if (method === 'all') { + if (store.before[method] || store.error[method]) { + const beforeAll = collect({ + before: store.before[method] || [], + error: store.error[method] || [] + }) + store.collectedAll.before = [beforeAll] + } + + if (store.after[method]) { + const afterAll = collect({ + after: store.after[method] || [], + }) + store.collectedAll.after = [afterAll] + } + } else { + if (store.before[method] || store.after[method] || store.error[method]) { + const collected = collect({ + before: store.before[method] || [], + after: store.after[method] || [], + error: store.error[method] || [] + }) + + store.collected[method] = [collected] + } } }) ) diff --git a/packages/feathers/test/hooks/after.test.ts b/packages/feathers/test/hooks/after.test.ts index 29a1810420..d4440472fe 100644 --- a/packages/feathers/test/hooks/after.test.ts +++ b/packages/feathers/test/hooks/after.test.ts @@ -381,4 +381,39 @@ describe('`after` hooks', () => { test: 43 }) }) + + it('.after all and method specific hooks run in the correct order (#3002)', async () => { + const app = feathers().use('/dummy', { + async get(id: any) { + return { id, items: [] as any } + } + }) + const service = app.service('dummy') + + service.hooks({ + after: { + all(context) { + context.result.items.push('first') + + return context + }, + get: [ + function (context) { + context.result.items.push('second') + + return context + }, + function (context) { + context.result.items.push('third') + + return context + } + ] + } + }) + + const data = await service.get(10) + + assert.deepStrictEqual(data.items, ['first', 'second', 'third']) + }) })