Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions plugins/webhook-event-forwarder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ The `callback` parameter takes a function that will be called with the webhook r
The `options` parameter takes an object with the following properties:

- `debug` - `boolean` - (optional) - Whether to log debug messages.
- `timeout` - `number` - (optional) - Timeout in milliseconds for the webhook request. Defaults to 5000ms (5 seconds).


## Usage
Expand All @@ -47,3 +48,14 @@ listener.use(webhookEventForwarder("https://webhook.site/...", (data, event) =>
console.log(data, event);
}));
```

#### With timeout configuration

```ts listener.js
listener.use(webhookEventForwarder("https://webhook.site/...", (data, event) => {
console.log(data, event);
}, {
timeout: 10000, // 10 seconds
debug: true
}));
```
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ describe('forward-webhook() e2e', () => {
it('should error', async () => {
mockWebhookFetch.mockResolvedValue({
status: 500,
statusText: 'Internal Server Error',
ok: false,
headers: {
get: vi.fn().mockReturnValue('application/json'),
Expand All @@ -140,7 +141,7 @@ describe('forward-webhook() e2e', () => {
expect.objectContaining({
topic: 'commit:created',
data: {
data: 'Error: Error forwarding webhook',
data: 'Error: Error forwarding webhook: 500 Internal Server Error',
error: true,
message: 'Error received, please try again',
},
Expand Down
23 changes: 20 additions & 3 deletions plugins/webhook-event-forwarder/src/forward.webhook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,58 @@ export function webhookEventForward(
) => Promise<unknown> | unknown,
options?: {
debug?: boolean
timeout?: number
}
) {
return async (listener: FlatfileListener) => {
return listener.on('**', async (event) => {
const controller = new AbortController()
const timeoutMs = options?.timeout ?? 5000 // Default 5 seconds
const timeoutId = setTimeout(() => controller.abort(), timeoutMs)

try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(event),
signal: controller.signal,
})

if (!response.ok) throw new Error('Error forwarding webhook')
if (!response.ok) {
throw new Error(
`Error forwarding webhook: ${response.status} ${response.statusText}`
)
}

const contentType = response.headers.get('content-type')
const isJson = contentType?.includes('application/json')
const data = isJson ? await response.json() : await response.text()

callback ? await callback(data, event) : null
} catch (err) {
const errorMessage =
err.name === 'AbortError'
? `Webhook request timed out after ${timeoutMs}ms`
: err.toString()

if (options?.debug) {
console.error(err.toString())
console.error(`[webhook-event-forwarder] ${errorMessage}`)
}

callback
? await callback(
{
error: true,
message: 'Error received, please try again',
data: err.toString(),
data: errorMessage,
},
event
)
: null
} finally {
clearTimeout(timeoutId)
}
})
}
Expand Down
Loading