Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add onAny and onError functions #324

Merged
merged 9 commits into from
Oct 17, 2020
8 changes: 7 additions & 1 deletion src/event-handler/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { receiverOn as on } from "./on";
import {
receiverOn as on,
receiverOnAny as onAny,
receiverOnError as onError,
} from "./on";
import { receiverHandle as receive } from "./receive";
import { removeListener } from "./remove-listener";
import { Options, State } from "../types";
Expand All @@ -14,6 +18,8 @@ export function createEventHandler(options: Options<any>) {

return {
on: on.bind(null, state),
onAny: onAny.bind(null, state),
onError: onError.bind(null, state),
removeListener: removeListener.bind(null, state),
receive: receive.bind(null, state),
};
Expand Down
38 changes: 34 additions & 4 deletions src/event-handler/on.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { WebhookEvents } from "../generated/get-webhook-payload-type-from-event";
import { webhookNames } from "../generated/webhook-names";
import { State } from "../types";
import { State, WebhookEvent, WebhookEventHandlerError } from "../types";

function handleEventHandlers(
state: State,
webhookName: WebhookEvents,
handler: Function
) {
if (!state.hooks[webhookName]) {
state.hooks[webhookName] = [];
}

state.hooks[webhookName].push(handler);
}
export function receiverOn(
state: State,
webhookNameOrNames: WebhookEvents | WebhookEvents[],
Expand All @@ -20,9 +31,28 @@ export function receiverOn(
);
}

if (!state.hooks[webhookNameOrNames]) {
state.hooks[webhookNameOrNames] = [];
if (webhookNameOrNames === "*" || webhookNameOrNames === "error") {
const webhookName = webhookNameOrNames === "*" ? "any" : webhookNameOrNames;
console.warn(
`Using the "${webhookNameOrNames}" event with the regular Webhooks.on() function is deprecated. Please use the Webhooks.on${
webhookName.charAt(0).toUpperCase() + webhookName.slice(1)
}() method instead`
);
}

state.hooks[webhookNameOrNames].push(handler);
handleEventHandlers(state, webhookNameOrNames, handler);
}

export function receiverOnAny(
state: State,
handler: (event: WebhookEvent<any>) => any
) {
handleEventHandlers(state, "*", handler);
}

export function receiverOnError(
state: State,
handler: (event: WebhookEventHandlerError) => any
) {
handleEventHandlers(state, "error", handler);
}
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
State,
WebhookEvent,
WebhookError,
WebhookEventHandlerError,
HandlerFunction,
} from "./types";
import { IncomingMessage, ServerResponse } from "http";
Expand All @@ -22,6 +23,8 @@ class Webhooks<T extends WebhookEvent = WebhookEvent, U = {}> {
event: E | E[],
callback: HandlerFunction<E, U>
) => void;
public onAny: (callback: (event: WebhookEvent<any>) => any) => void;
public onError: (callback: (event: WebhookEventHandlerError) => any) => void;
public removeListener: <E extends WebhookEvents>(
event: E | E[],
callback: HandlerFunction<E, U>
Expand Down Expand Up @@ -55,6 +58,8 @@ class Webhooks<T extends WebhookEvent = WebhookEvent, U = {}> {
this.sign = sign.bind(null, options.secret);
this.verify = verify.bind(null, options.secret);
this.on = state.eventHandler.on;
this.onAny = state.eventHandler.onAny;
this.onError = state.eventHandler.onError;
this.removeListener = state.eventHandler.removeListener;
this.receive = state.eventHandler.receive;
this.middleware = middleware.bind(null, state);
Expand Down
6 changes: 3 additions & 3 deletions test/integration/event-handler-test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createEventHandler } from "../../src/event-handler";
import pushEventPayload from "../fixtures/push-payload.json";
import installationCreatedPayload from "../fixtures/installation-created-payload.json";
import { WebhookError, WebhookEvent } from "../../src/types";
import { WebhookEvent, WebhookEventHandlerError } from "../../src/types";

test("events", (done) => {
const eventHandler = createEventHandler({});
Expand Down Expand Up @@ -37,7 +37,7 @@ test("events", (done) => {
eventHandler.on(["push"], hook4);
eventHandler.on("installation", hook5);
eventHandler.on("installation.created", hook6);
eventHandler.on("*", hook7);
eventHandler.onAny(hook7);

eventHandler.removeListener("push", hook3);
eventHandler.removeListener(["push"], hook4);
Expand Down Expand Up @@ -68,7 +68,7 @@ test("events", (done) => {
"* (installation)",
]);

eventHandler.on("error", (error: WebhookError) => {
eventHandler.onError((error: WebhookEventHandlerError) => {
expect(error.event.payload).toBeTruthy();
// t.pass("error event triggered");
expect(error.message).toMatch(/oops/);
Expand Down
4 changes: 2 additions & 2 deletions test/integration/server-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ describe("server-test", () => {
});
const server = http.createServer(api.middleware);
const errorHandler = jest.fn();
api.on("error", errorHandler);
api.onError(errorHandler);

promisify(server.listen.bind(server))(availablePort)

Expand Down Expand Up @@ -177,7 +177,7 @@ describe("server-test", () => {
});
const server = http.createServer(api.middleware);
const errorHandler = jest.fn();
api.on("error", errorHandler);
api.onError(errorHandler);

promisify(server.listen.bind(server))(availablePort)

Expand Down
16 changes: 16 additions & 0 deletions test/typescript-validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,19 @@ export default async function () {

verify("randomSecret", {}, "randomSignature");

// This is deprecated usage
oscard0m marked this conversation as resolved.
Show resolved Hide resolved
webhooks.on("*", ({ id, name, payload }) => {
console.log(name, "event received");
const sig = webhooks.sign(payload);
webhooks.verify(payload, sig);
});

webhooks.onAny(({ id, name, payload }) => {
console.log(name, "event received");
const sig = webhooks.sign(payload);
webhooks.verify(payload, sig);
});

webhooks.on("check_run.completed", () => {});

webhooks.on(
Expand Down Expand Up @@ -124,6 +131,7 @@ export default async function () {
console.log(event.foo);
});

// This is deprecated usage
oscard0m marked this conversation as resolved.
Show resolved Hide resolved
webhooks.on("error", (error) => {
console.log(error.event.name);
const [firstError] = Array.from(error);
Expand All @@ -132,6 +140,14 @@ export default async function () {
console.log(firstError.request);
});

webhooks.onError((error) => {
console.log(error.event.name);
const [firstError] = Array.from(error);
console.log(firstError.status);
console.log(firstError.headers);
console.log(firstError.request);
});

createServer(webhooks.middleware).listen(3000);
}

Expand Down
18 changes: 18 additions & 0 deletions test/unit/event-handler-on-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,21 @@ test("receiver.on with invalid event name", () => {

simple.restore();
});

test("receiver.on with event name of '*' logs deprecation notice", () => {
simple.mock(console, "warn").callFn(function () {});
receiverOn(state, "*", noop);
expect((console.warn as simple.Stub<void>).callCount).toBe(1);
expect((console.warn as simple.Stub<void>).lastCall.arg).toBe(
'Using the "*" event with the regular Webhooks.on() function is deprecated. Please use the Webhooks.onAny() method instead'
);
});

test("receiver.on with event name of 'error' logs deprecation notice", () => {
simple.mock(console, "warn").callFn(function () {});
receiverOn(state, "error", noop);
expect((console.warn as simple.Stub<void>).callCount).toBe(1);
expect((console.warn as simple.Stub<void>).lastCall.arg).toBe(
'Using the "error" event with the regular Webhooks.on() function is deprecated. Please use the Webhooks.onError() method instead'
);
});