3.2 KiB
plugin.ts — createWebhookPlugin factory
(no submodules)
Purpose
Top-level definePlugin consumer for the webhook plugin. Returns a typed PluginDescriptor<WebhookPluginConfig> whose onInit executes the canonical five-step lifecycle: resolve app / openAPIRegistry from the host ServiceRegistry, construct the WebhookService wired to the configured (or default) collaborators, register the service under the webhookService slot, mount the six CRUD + test routes under routePrefix (gated by requireAuth()), and register the routes with the OpenAPIRegistry when one is present so /openapi.json exposes them.
Features
- Zod-validates options at the factory boundary; invalid input raises
WebhookError(WEBHOOK_INVALID_INPUT)carrying theZodErrorascause. - Wires defaults for every optional collaborator (
MemoryEndpointStore,MemoryDeadLetterSink, system clock, globalfetch, noop logger) socreateWebhookPlugin()works zero-config. - Raises
WebhookError(WEBHOOK_SERVICE_NOT_AVAILABLE)if the requiredappslot is absent. - Raises
WebhookError(WEBHOOK_ROUTE_PREFIX_COLLISION)when theroutePrefixcollides with previously-registered routes. - Falls back to a manual Hono sub-router mount when no
OpenAPIRegistryis present so the runtime surface still works even when the OpenAPI doc is not assembled.
Usage: Basic
import { defineApp } from "@suaveplan/api";
import { createWebhookPlugin } from "@suaveplan/api-plugin-webhook";
const app = defineApp().use(createWebhookPlugin());
Usage: Advanced
import { defineApp } from "@suaveplan/api";
import { createAuthPlugin } from "@suaveplan/api-plugin-auth";
import { createWebhookPlugin } from "@suaveplan/api-plugin-webhook";
import { MemoryEndpointStore } from "@suaveplan/api-plugin-webhook/store/memory";
import { MemoryDeadLetterSink } from "@suaveplan/api-plugin-webhook/dead-letter/memory";
const app = defineApp()
.use(createAuthPlugin({ betterAuth: {} }))
.use(
createWebhookPlugin({
routePrefix: "/api/v1/webhooks",
endpointStore: new MemoryEndpointStore(),
deadLetterSink: new MemoryDeadLetterSink(),
maxAttempts: 8,
initialRetryDelayMs: 250,
maxRetryDelayMs: 60_000,
})
);
API Reference
createWebhookPlugin(options?)— factory. Returns aPluginDescriptor<WebhookPluginConfig>.WebhookPluginOptions— every field optional; defaults supplied for omitted fields.WebhookPluginConfig— post-default-merge shape carried on the descriptor'sdefaults.
Implementation Notes
The plugin name webhook is singular (not webhooks) so dependent plugins reference one stable identifier when declaring dependencies: ["webhook"]. The lifecycle is one-shot — there is no onClose hook because the service does not hold network resources (the in-flight dedup map drains naturally as deliveries resolve). The route mount path joins routePrefix + entry path so the generated OpenAPI paths read as /webhooks, /webhooks/{id}, /webhooks/{id}/test; the special-case routePrefix === "/" keeps the root namespace clean for apps that want webhook CRUD at the top level.