easy-webhooks-engine
v1.0.0
Published
Easy Webhooks Engine
Maintainers
Readme
easy-webhooks-engine
Small Node.js library that queues outbound HTTP webhook jobs, persists them through a pluggable storage adapter, and delivers them with configurable retries, timeouts, and concurrency.
Requires Node.js 18+. The published build exposes ESM (import) and CommonJS (require) via the exports field.
Install
npm install easy-webhooks-engine axiosaxios is a peer dependency; install a compatible version in your app (see peerDependencies in package.json).
Quick start (in-memory)
ESM:
import { createInMemoryWebhookEngine } from "easy-webhooks-engine";
const engine = createInMemoryWebhookEngine({
retries: 3,
timeout: 10_000,
concurrency: 4,
log: false,
});
await engine.enqueue({
url: "https://api.example.com/hooks/receiver",
method: "POST",
payload: { event: "user.created", id: "123" },
headers: { "Content-Type": "application/json" },
});CommonJS:
const { createInMemoryWebhookEngine } = require("easy-webhooks-engine");
(async () => {
const engine = createInMemoryWebhookEngine({ retries: 3, timeout: 10_000 });
await engine.enqueue({
url: "https://api.example.com/hooks/receiver",
method: "POST",
payload: { event: "user.created", id: "123" },
});
})();enqueue validates the payload, stores a pending job, assigns an id and timestamps, then runs process() to drain the queue.
Custom storage
Implement StorageInterface and pass it to createWebhookEngine (or new WebhookEngine(storage, options)):
| Method | Role |
|-----------|------|
| create | Persist a new job. |
| update | Replace a job by id (engine updates status, attempts, timestamps). |
| next | Return the next pending job to work on, or null if none. |
| remove | Delete a job (used by adapters that need explicit removal). |
The engine serializes calls to next() per instance so simple in-memory arrays are safe under concurrent workers. update runs in parallel across workers for different jobs—if your backend needs stronger isolation (e.g. PostgreSQL), use row locking / SKIP LOCKED in next() and design update accordingly.
Options (WebhookEngineOptions)
| Option | Default | Description |
|--------|---------|-------------|
| retries | 0 | Max delivery attempts (including the first try). 0 means the job is marked failed without calling the URL. |
| timeout | 5000 | Axios request timeout (ms). |
| concurrency | 1 | Number of parallel workers; each runs dequeue → HTTP → update in parallel with siblings. |
| log | false | When true, forwards messages to logger. |
| logger | console-style default | Must implement info, error, warn, debug, trace. |
Read the configured limit via engine.concurrency.
Delivery rules
- Successful HTTP status: 2xx (including 204).
- Other statuses and network errors increment attempts and either return the job to pending or mark failed when attempts reach
retries. enqueuerunsassertValidEnqueuePayload: absolute URL, allowedmethod, optionalqueryParams/headers(string values only), optional non-negative integerretries.
API surface
import {
WebhookEngine,
createInMemoryWebhookEngine,
createWebhookEngine,
MemoryStorage,
assertValidEnqueuePayload,
WebhookJobStatus,
type WebhookJob,
type WebhookEngineOptions,
type StorageInterface,
type Logger,
} from "easy-webhooks-engine";process()— Drain pending jobs until the queue is empty for this run. Overlappingprocess()/enqueue()calls on the same engine share one drain (singleflight).dequeue()— Same serializednext()path workers use; useful for tests or tooling.
Development
npm install
npm test
npm run buildTests live under test/ (validation, storage, engine behavior, concurrency, factory).
License
MIT — see LICENSE.
