From 12afb27555288c5d5fa4044195e014092b75b48e Mon Sep 17 00:00:00 2001 From: Oscar Dominguez Date: Sat, 13 Mar 2021 00:06:23 +0100 Subject: [PATCH 1/6] fix(types): transform method only accepts current event type --- src/event-handler/index.ts | 8 ++++---- src/index.ts | 4 ++-- src/types.ts | 9 ++------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/event-handler/index.ts b/src/event-handler/index.ts index 754081b3..8d152b0a 100644 --- a/src/event-handler/index.ts +++ b/src/event-handler/index.ts @@ -15,23 +15,23 @@ import { import { receiverHandle as receive } from "./receive"; import { removeListener } from "./remove-listener"; -interface EventHandler { +interface EventHandler { on( event: E | E[], - callback: HandlerFunction + callback: HandlerFunction ): void; onAny(handler: (event: EmitterWebhookEvent) => any): void; onError(handler: (event: WebhookEventHandlerError) => any): void; removeListener( event: E | E[], - callback: HandlerFunction + callback: HandlerFunction ): void; receive(event: EmitterWebhookEvent): Promise; } export function createEventHandler( options?: T -): EventHandler { +): EventHandler { const state: State = { hooks: {}, log: createLogger(options && options.log), diff --git a/src/index.ts b/src/index.ts index 08c2bf00..00d53ff8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,13 +22,13 @@ class Webhooks { public verify: (eventPayload: string | object, signature: string) => boolean; public on: ( event: E | E[], - callback: HandlerFunction + callback: HandlerFunction ) => void; public onAny: (callback: (event: EmitterWebhookEvent) => any) => void; public onError: (callback: (event: WebhookEventHandlerError) => any) => void; public removeListener: ( event: E | E[], - callback: HandlerFunction + callback: HandlerFunction ) => void; public receive: (event: EmitterWebhookEvent) => Promise; public middleware: ( diff --git a/src/types.ts b/src/types.ts index b25b3ff7..fc9970f7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -30,13 +30,8 @@ export interface Options { type TransformMethod = (event: EmitterWebhookEvent) => T | PromiseLike; -export type HandlerFunction< - TName extends EmitterWebhookEventName, - TTransform -> = ( - event: TTransform extends TransformMethod - ? T - : EmitterWebhookEvent +export type HandlerFunction = ( + event: EmitterWebhookEvent ) => any; type Hooks = { From fc8fdedf3920ba3e863f5f90814770abb84ed8db Mon Sep 17 00:00:00 2001 From: Oscar Dominguez Date: Sat, 13 Mar 2021 00:23:32 +0100 Subject: [PATCH 2/6] test(event-handler-test): expected-error because typing becomes more restrictive --- test/integration/event-handler-test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/integration/event-handler-test.ts b/test/integration/event-handler-test.ts index 278e171c..3a4e5535 100644 --- a/test/integration/event-handler-test.ts +++ b/test/integration/event-handler-test.ts @@ -135,6 +135,10 @@ test("options.transform", (done) => { }, }); + // Argument of type '(event: string) => void' is not assignable to parameter of type 'HandlerFunction<"push">'. + // Types of parameters 'event' and 'event' are incompatible. + // Type 'BaseWebhookEvent<"push">' is not assignable to type 'string'.ts(2345) + // @ts-expect-error eventHandler.on("push", (event: string) => { expect(event).toBe("funky"); @@ -155,6 +159,10 @@ test("async options.transform", (done) => { }, }); + // Argument of type '(event: string) => void' is not assignable to parameter of type 'HandlerFunction<"push">'. + // Types of parameters 'event' and 'event' are incompatible. + // Type 'BaseWebhookEvent<"push">' is not assignable to type 'string'.ts(2345) + // @ts-expect-error eventHandler.on("push", (event: string) => { expect(event).toBe("funky"); done(); From 147fb7c2e6b7cda69ea905a0d58750b2e435d2f6 Mon Sep 17 00:00:00 2001 From: Oscar Dominguez Date: Sat, 13 Mar 2021 01:16:12 +0100 Subject: [PATCH 3/6] fix(types): proper type fixing applied --- src/event-handler/index.ts | 12 ++++++------ src/index.ts | 6 +++--- src/middleware/index.ts | 2 +- src/types.ts | 16 ++++++++++++---- test/integration/event-handler-test.ts | 10 +--------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/event-handler/index.ts b/src/event-handler/index.ts index 8d152b0a..1188bfc8 100644 --- a/src/event-handler/index.ts +++ b/src/event-handler/index.ts @@ -15,23 +15,23 @@ import { import { receiverHandle as receive } from "./receive"; import { removeListener } from "./remove-listener"; -interface EventHandler { +interface EventHandler> { on( event: E | E[], - callback: HandlerFunction + callback: HandlerFunction ): void; onAny(handler: (event: EmitterWebhookEvent) => any): void; onError(handler: (event: WebhookEventHandlerError) => any): void; removeListener( event: E | E[], - callback: HandlerFunction + callback: HandlerFunction ): void; receive(event: EmitterWebhookEvent): Promise; } -export function createEventHandler( - options?: T -): EventHandler { +export function createEventHandler< + T extends Options +>(options?: T): EventHandler { const state: State = { hooks: {}, log: createLogger(options && options.log), diff --git a/src/index.ts b/src/index.ts index 00d53ff8..67e889ec 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,18 +17,18 @@ import { import { verify } from "./verify/index"; // U holds the return value of `transform` function in Options -class Webhooks { +class Webhooks> { public sign: (payload: string | object) => string; public verify: (eventPayload: string | object, signature: string) => boolean; public on: ( event: E | E[], - callback: HandlerFunction + callback: HandlerFunction ) => void; public onAny: (callback: (event: EmitterWebhookEvent) => any) => void; public onError: (callback: (event: WebhookEventHandlerError) => any) => void; public removeListener: ( event: E | E[], - callback: HandlerFunction + callback: HandlerFunction ) => void; public receive: (event: EmitterWebhookEvent) => Promise; public middleware: ( diff --git a/src/middleware/index.ts b/src/middleware/index.ts index 015602fc..86d98da1 100644 --- a/src/middleware/index.ts +++ b/src/middleware/index.ts @@ -4,7 +4,7 @@ import { createEventHandler } from "../event-handler/index"; import { middleware } from "./middleware"; import { Options, State } from "../types"; -export function createMiddleware(options: Options) { +export function createMiddleware(options: Options) { if (!options || !options.secret) { throw new Error("[@octokit/webhooks] options.secret required"); } diff --git a/src/types.ts b/src/types.ts index fc9970f7..47b47742 100644 --- a/src/types.ts +++ b/src/types.ts @@ -21,7 +21,10 @@ interface BaseWebhookEvent { payload: WebhookEventMap[TName]; } -export interface Options { +export interface Options< + E extends EmitterWebhookEventName, + TTransformed extends EmitterWebhookEvent +> { path?: string; secret?: string; transform?: TransformMethod; @@ -30,15 +33,20 @@ export interface Options { type TransformMethod = (event: EmitterWebhookEvent) => T | PromiseLike; -export type HandlerFunction = ( - event: EmitterWebhookEvent +export type HandlerFunction< + TName extends EmitterWebhookEventName, + TTransform +> = ( + event: TTransform extends TransformMethod + ? T + : EmitterWebhookEvent ) => any; type Hooks = { [key: string]: Function[]; }; -export interface State extends Options { +export interface State extends Options { eventHandler?: any; hooks: Hooks; log: Logger; diff --git a/test/integration/event-handler-test.ts b/test/integration/event-handler-test.ts index 3a4e5535..d91f127e 100644 --- a/test/integration/event-handler-test.ts +++ b/test/integration/event-handler-test.ts @@ -135,11 +135,7 @@ test("options.transform", (done) => { }, }); - // Argument of type '(event: string) => void' is not assignable to parameter of type 'HandlerFunction<"push">'. - // Types of parameters 'event' and 'event' are incompatible. - // Type 'BaseWebhookEvent<"push">' is not assignable to type 'string'.ts(2345) - // @ts-expect-error - eventHandler.on("push", (event: string) => { + eventHandler.on("push", (event) => { expect(event).toBe("funky"); done(); @@ -159,10 +155,6 @@ test("async options.transform", (done) => { }, }); - // Argument of type '(event: string) => void' is not assignable to parameter of type 'HandlerFunction<"push">'. - // Types of parameters 'event' and 'event' are incompatible. - // Type 'BaseWebhookEvent<"push">' is not assignable to type 'string'.ts(2345) - // @ts-expect-error eventHandler.on("push", (event: string) => { expect(event).toBe("funky"); done(); From 0b41d7f17a0661f91c7b35c1607181f7fc6f1812 Mon Sep 17 00:00:00 2001 From: Oscar Dominguez Date: Sat, 13 Mar 2021 01:21:52 +0100 Subject: [PATCH 4/6] test(event-handler): restore string type in L138 --- test/integration/event-handler-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/event-handler-test.ts b/test/integration/event-handler-test.ts index d91f127e..278e171c 100644 --- a/test/integration/event-handler-test.ts +++ b/test/integration/event-handler-test.ts @@ -135,7 +135,7 @@ test("options.transform", (done) => { }, }); - eventHandler.on("push", (event) => { + eventHandler.on("push", (event: string) => { expect(event).toBe("funky"); done(); From 3d7b192f4a36ecf9b83b8fcaeb2cdfc4d582d0c5 Mon Sep 17 00:00:00 2001 From: Oscar Dominguez Date: Sat, 13 Mar 2021 01:28:22 +0100 Subject: [PATCH 5/6] refactor(types): move any default values to type definition --- src/event-handler/index.ts | 8 ++++---- src/index.ts | 2 +- src/middleware/index.ts | 2 +- src/types.ts | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/event-handler/index.ts b/src/event-handler/index.ts index 1188bfc8..8a372329 100644 --- a/src/event-handler/index.ts +++ b/src/event-handler/index.ts @@ -15,7 +15,7 @@ import { import { receiverHandle as receive } from "./receive"; import { removeListener } from "./remove-listener"; -interface EventHandler> { +interface EventHandler> { on( event: E | E[], callback: HandlerFunction @@ -29,9 +29,9 @@ interface EventHandler> { receive(event: EmitterWebhookEvent): Promise; } -export function createEventHandler< - T extends Options ->(options?: T): EventHandler { +export function createEventHandler>( + options?: T +): EventHandler { const state: State = { hooks: {}, log: createLogger(options && options.log), diff --git a/src/index.ts b/src/index.ts index 67e889ec..08c2bf00 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,7 +17,7 @@ import { import { verify } from "./verify/index"; // U holds the return value of `transform` function in Options -class Webhooks> { +class Webhooks { public sign: (payload: string | object) => string; public verify: (eventPayload: string | object, signature: string) => boolean; public on: ( diff --git a/src/middleware/index.ts b/src/middleware/index.ts index 86d98da1..015602fc 100644 --- a/src/middleware/index.ts +++ b/src/middleware/index.ts @@ -4,7 +4,7 @@ import { createEventHandler } from "../event-handler/index"; import { middleware } from "./middleware"; import { Options, State } from "../types"; -export function createMiddleware(options: Options) { +export function createMiddleware(options: Options) { if (!options || !options.secret) { throw new Error("[@octokit/webhooks] options.secret required"); } diff --git a/src/types.ts b/src/types.ts index 47b47742..17dc9a5e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -22,8 +22,8 @@ interface BaseWebhookEvent { } export interface Options< - E extends EmitterWebhookEventName, - TTransformed extends EmitterWebhookEvent + E extends EmitterWebhookEventName = any, + TTransformed extends EmitterWebhookEvent = any > { path?: string; secret?: string; From 84a841eb7e0bd711a5af3abf9c23de49a7af7b63 Mon Sep 17 00:00:00 2001 From: Oscar Dominguez Date: Sat, 13 Mar 2021 01:29:21 +0100 Subject: [PATCH 6/6] refactor(types): infer any from Options as default value --- src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index 17dc9a5e..0a41f47f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -46,7 +46,7 @@ type Hooks = { [key: string]: Function[]; }; -export interface State extends Options { +export interface State extends Options { eventHandler?: any; hooks: Hooks; log: Logger;