From 17f3852fff64940664c143d10587aa125f38a6b7 Mon Sep 17 00:00:00 2001 From: daffl Date: Wed, 27 Apr 2022 15:28:01 -0700 Subject: [PATCH 1/2] fix(hooks): Allow hooks on functions that have properties --- main/hooks/src/hooks.ts | 17 ++++++++--------- main/hooks/test/class.test.ts | 22 ++++++++++++++++++++-- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/main/hooks/src/hooks.ts b/main/hooks/src/hooks.ts index 804d6fa..b766c09 100644 --- a/main/hooks/src/hooks.ts +++ b/main/hooks/src/hooks.ts @@ -68,15 +68,14 @@ export type HookMap = { [L in keyof O]?: HookOptions; }; -export function objectHooks(_obj: any, hooks: HookMap | AsyncMiddleware[]) { - const obj = typeof _obj === 'function' ? _obj.prototype : _obj; - +export function objectHooks(obj: any, hooks: HookMap | AsyncMiddleware[]) { if (Array.isArray(hooks)) { return setMiddleware(obj, hooks); } - return Object.keys(hooks).reduce((result, method) => { - const fn = obj[method]; + for (const method of Object.keys(hooks)) { + const target = typeof obj[method] === 'function' ? obj : obj.prototype + const fn = target && target[method]; if (typeof fn !== 'function') { throw new Error(`Can not apply hooks. '${method}' is not a function`); @@ -84,10 +83,10 @@ export function objectHooks(_obj: any, hooks: HookMap | AsyncMiddleware[]) { const manager = convertOptions(hooks[method]); - result[method] = functionHooks(fn, manager.props({ method })); - - return result; - }, obj); + target[method] = functionHooks(fn, manager.props({ method })); + } + + return obj; } export const hookDecorator = (managerOrMiddleware?: HookOptions) => { diff --git a/main/hooks/test/class.test.ts b/main/hooks/test/class.test.ts index 346c431..ec5d641 100644 --- a/main/hooks/test/class.test.ts +++ b/main/hooks/test/class.test.ts @@ -39,7 +39,7 @@ it('hooking object on class adds to the prototype', async () => { await next(); ctx.result += '?'; - }, + } ]).params('name'), addOne: middleware([ @@ -47,7 +47,7 @@ it('hooking object on class adds to the prototype', async () => { ctx.arguments[0] += 1; await next(); - }, + } ]), }); @@ -57,6 +57,24 @@ it('hooking object on class adds to the prototype', async () => { assertEquals(await instance.addOne(1), 3); }); +it('hooking object works on function that has property', async () => { + const app = function () {} + + app.sayHi = (name: string) => `Hello ${name}`; + + hooks(app as any, { + sayHi: middleware([ + async (ctx: HookContext, next: NextFunction) => { + await next(); + + ctx.result += '?'; + }, + ]).params('name') + }); + + assertEquals(await app.sayHi('David'), 'Hello David?'); +}); + it('works with inheritance', async () => { const DummyClass = createDummyClass(); From 62054a9b6dda71f2b37cacad72c0d60148b21459 Mon Sep 17 00:00:00 2001 From: daffl Date: Wed, 27 Apr 2022 15:38:53 -0700 Subject: [PATCH 2/2] Fix Deno configuration and linting --- deno.json | 4 ++-- main/hooks/src/hooks.ts | 6 +++--- main/hooks/src/utils.ts | 2 +- main/hooks/test/class.test.ts | 8 ++++---- main/hooks/test/compose.test.ts | 2 +- main/hooks/test/decorator.test.ts | 2 +- main/hooks/test/object.test.ts | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/deno.json b/deno.json index 814216a..3d5a002 100644 --- a/deno.json +++ b/deno.json @@ -5,9 +5,9 @@ "exclude": [] }, "rules": { - "tags": [], + "tags": ["recommended"], "include": [], - "exclude": ["no-explicit-any", "require-await"] + "exclude": ["no-explicit-any", "require-await", "no-self-assign"] } }, "fmt": { diff --git a/main/hooks/src/hooks.ts b/main/hooks/src/hooks.ts index b766c09..c2b5f08 100644 --- a/main/hooks/src/hooks.ts +++ b/main/hooks/src/hooks.ts @@ -74,7 +74,7 @@ export function objectHooks(obj: any, hooks: HookMap | AsyncMiddleware[]) { } for (const method of Object.keys(hooks)) { - const target = typeof obj[method] === 'function' ? obj : obj.prototype + const target = typeof obj[method] === 'function' ? obj : obj.prototype; const fn = target && target[method]; if (typeof fn !== 'function') { @@ -83,9 +83,9 @@ export function objectHooks(obj: any, hooks: HookMap | AsyncMiddleware[]) { const manager = convertOptions(hooks[method]); - target[method] = functionHooks(fn, manager.props({ method })); + target[method] = functionHooks(fn, manager.props({ method })); } - + return obj; } diff --git a/main/hooks/src/utils.ts b/main/hooks/src/utils.ts index 74bf6c8..bc3bf87 100644 --- a/main/hooks/src/utils.ts +++ b/main/hooks/src/utils.ts @@ -58,7 +58,7 @@ export function copyFnProperties(target: F, original: any) { Object.defineProperty(target, prop, { value }); } - } catch (e) { + } catch (_e) { // Avoid IE error } diff --git a/main/hooks/test/class.test.ts b/main/hooks/test/class.test.ts index ec5d641..d0a6105 100644 --- a/main/hooks/test/class.test.ts +++ b/main/hooks/test/class.test.ts @@ -39,7 +39,7 @@ it('hooking object on class adds to the prototype', async () => { await next(); ctx.result += '?'; - } + }, ]).params('name'), addOne: middleware([ @@ -47,7 +47,7 @@ it('hooking object on class adds to the prototype', async () => { ctx.arguments[0] += 1; await next(); - } + }, ]), }); @@ -58,7 +58,7 @@ it('hooking object on class adds to the prototype', async () => { }); it('hooking object works on function that has property', async () => { - const app = function () {} + const app = function () {}; app.sayHi = (name: string) => `Hello ${name}`; @@ -69,7 +69,7 @@ it('hooking object works on function that has property', async () => { ctx.result += '?'; }, - ]).params('name') + ]).params('name'), }); assertEquals(await app.sayHi('David'), 'Hello David?'); diff --git a/main/hooks/test/compose.test.ts b/main/hooks/test/compose.test.ts index 19b9fcc..a5fe0f3 100644 --- a/main/hooks/test/compose.test.ts +++ b/main/hooks/test/compose.test.ts @@ -182,7 +182,7 @@ it('compose: should catch downstream errors', async () => { arr.push(6); await next(); arr.push(7); - } catch (err) { + } catch (_err) { arr.push(2); } arr.push(3); diff --git a/main/hooks/test/decorator.test.ts b/main/hooks/test/decorator.test.ts index bdc114b..235a11e 100644 --- a/main/hooks/test/decorator.test.ts +++ b/main/hooks/test/decorator.test.ts @@ -1,4 +1,4 @@ -import { assert, assertEquals, assertThrows, it } from './dependencies.ts'; +import { assertEquals, assertThrows, it } from './dependencies.ts'; import { HookContext, hooks, middleware, NextFunction } from '../src/index.ts'; it('hook decorator on method and classes with inheritance', async () => { diff --git a/main/hooks/test/object.test.ts b/main/hooks/test/object.test.ts index 20b92aa..814e487 100644 --- a/main/hooks/test/object.test.ts +++ b/main/hooks/test/object.test.ts @@ -1,4 +1,4 @@ -import { assert, assertEquals, assertStrictEquals, assertThrows, it } from './dependencies.ts'; +import { assertEquals, assertStrictEquals, assertThrows, it } from './dependencies.ts'; import { HookContext, hooks, middleware, NextFunction } from '../src/index.ts'; interface HookableObject {