58 lines
1.5 KiB
TypeScript
58 lines
1.5 KiB
TypeScript
|
|
import Wreck from "@hapi/wreck";
|
||
|
|
import * as R from "remeda";
|
||
|
|
import { withDb, AppDatabase } from "../db";
|
||
|
|
import logger from "../logger";
|
||
|
|
|
||
|
|
export interface WebhookOptions {
|
||
|
|
webhookId: string;
|
||
|
|
payload: any;
|
||
|
|
}
|
||
|
|
|
||
|
|
const notifyWebhooksTask = async (options: WebhookOptions): Promise<void> =>
|
||
|
|
withDb(async (db: AppDatabase) => {
|
||
|
|
const { webhookId, payload } = options;
|
||
|
|
|
||
|
|
const webhook = await db.webhooks.findById({ id: webhookId });
|
||
|
|
if (!webhook) {
|
||
|
|
logger.debug(
|
||
|
|
{ webhookId },
|
||
|
|
"notify-webhook: no webhook registered with id"
|
||
|
|
);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const { endpointUrl, httpMethod, headers } = webhook;
|
||
|
|
const headersFormatted = R.reduce(
|
||
|
|
headers || [],
|
||
|
|
(acc: any, h: any) => {
|
||
|
|
acc[h.header] = h.value;
|
||
|
|
return acc;
|
||
|
|
},
|
||
|
|
{}
|
||
|
|
);
|
||
|
|
|
||
|
|
const wreck = Wreck.defaults({
|
||
|
|
json: true,
|
||
|
|
headers: headersFormatted,
|
||
|
|
});
|
||
|
|
|
||
|
|
// http errors will bubble up and cause the job to fail and be retried
|
||
|
|
try {
|
||
|
|
logger.debug(
|
||
|
|
{ webhookId, endpointUrl, httpMethod },
|
||
|
|
"notify-webhook: notifying"
|
||
|
|
);
|
||
|
|
await (httpMethod === "post"
|
||
|
|
? wreck.post(endpointUrl, { payload })
|
||
|
|
: wreck.put(endpointUrl, { payload }));
|
||
|
|
} catch (error: any) {
|
||
|
|
logger.error(
|
||
|
|
{ webhookId, error: error.output },
|
||
|
|
"notify-webhook failed with this error"
|
||
|
|
);
|
||
|
|
throw new Error(`webhook failed webhookId=${webhookId}`);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
export default notifyWebhooksTask;
|