import { type Committed, NonRetryableError, type Schemas } from "@rotorsoft/act"; /** * Function or static value resolver. Used so callers can pass either a * constant or a per-event function for headers / body / url. * * The static side `T` is constrained to non-function types so that a * passed `(event) => ...` is unambiguously typed as the function variant. */ export type WebhookResolver = T | ((event: Committed) => T); /** * Plain-data body shape the helper accepts as a static value. Functions * are deliberately excluded so the union with the resolver function is * unambiguous at the call site (TypeScript can discriminate by shape). */ export type WebhookBody = string | { readonly [k: string]: unknown; } | readonly unknown[]; /** * Configuration for {@link webhook}. * * @template TEvents - Event schemas; resolvers receive the typed committed event. */ export type WebhookConfig = { /** Target URL — static string or per-event function. */ readonly url: WebhookResolver; /** HTTP method. Defaults to `"POST"`. */ readonly method?: "POST" | "PUT" | "PATCH" | "DELETE"; /** * Headers to send. Resolver may return a record per event. The * `Content-Type: application/json` and `Idempotency-Key` headers are * applied automatically; both can be overridden by returning a header * with the same name (case-insensitive). */ readonly headers?: WebhookResolver>; /** * Request body. Static plain data (object, array, string) or a * per-event function returning the same. Strings are sent as-is; * anything else is JSON-serialized. Defaults to the committed event * itself. */ readonly body?: WebhookBody | ((event: Committed) => WebhookBody); /** * Per-request timeout in milliseconds. Defaults to 5000. * The handler throws after the timeout via `AbortController`. */ readonly timeoutMs?: number; /** * Override for the auto-generated `Idempotency-Key`. By default, the * helper sends `event.id` (the immutable, monotonic event identifier). * Return a string to override; return `null` to skip the header entirely. */ readonly idempotencyKey?: (event: Committed) => string | null; /** * Injection point for tests. Defaults to global `fetch`. */ readonly fetch?: typeof fetch; /** * HMAC-SHA256 signing key. When set, the webhook helper attaches * two headers to every request: * * - `X-Webhook-Signature: sha256=` — HMAC of * `${timestamp}.${body}` (`body` is the final serialized payload) * - `X-Webhook-Timestamp: ` * * Pair with `verifyWebhook` from `@rotorsoft/act-http/receiver` on * the receiving side. When undefined, no signature headers are * added — back-compat with consumers that don't need signing. * * Callers can override either header by returning it from the * `headers` resolver (case-insensitive), the same way the * `Idempotency-Key` and `Content-Type` defaults yield to caller * intent. */ readonly secret?: string; }; /** * Common fields carried on every HTTP delivery error in this package. */ export type HttpDeliveryErrorInit = { status: number; url: string; responseBody?: string; }; /** * Thrown when an HTTP delivery fails in a way the drain pipeline * should retry: network failure, timeout, or 5xx response. `status` is * `0` for network / timeout errors, the HTTP status code otherwise. * * The class itself is the retry signal — if a reaction throws this, * drain treats it like any other error (counts against `maxRetries`, * paces with `backoff`). For permanent failures, throw * {@link NonRetryableHttpError} instead. * * Generic enough to cover any custom HTTP-like integration (gRPC * bridges, SDK-based reactions). {@link WebhookError} is a * webhook-specific subclass kept for backward compatibility. */ export declare class RetryableHttpError extends Error { readonly status: number; readonly url: string; readonly responseBody?: string; constructor(message: string, init: HttpDeliveryErrorInit); } /** * Thrown when an HTTP delivery returns a 3xx or 4xx response — * permanent client errors that won't recover on retry. Extends * {@link NonRetryableError} so the drain finalizer blocks the stream * on the first failed attempt (when `blockOnError` is true) — no * wasted retries on a malformed payload or wrong URL. * * Generic enough to cover any custom HTTP-like integration. * {@link NonRetryableWebhookError} is a webhook-specific subclass kept * for backward compatibility. */ export declare class NonRetryableHttpError extends NonRetryableError { readonly status: number; readonly url: string; readonly responseBody?: string; constructor(message: string, init: HttpDeliveryErrorInit); } /** * Webhook-specific subclass of {@link RetryableHttpError}. Thrown by * the {@link webhook} helper on 5xx responses, network failures, and * timeouts. Existing `instanceof WebhookError` checks continue to * work; new code targeting the generic HTTP integration shape can * catch {@link RetryableHttpError} instead and handle webhook + * custom integrations uniformly. */ export declare class WebhookError extends RetryableHttpError { constructor(message: string, init: HttpDeliveryErrorInit); } /** * Webhook-specific subclass of {@link NonRetryableHttpError}. Thrown * by the {@link webhook} helper on 3xx/4xx responses. Existing * `instanceof NonRetryableWebhookError` checks continue to work; new * code can catch {@link NonRetryableHttpError} or * {@link NonRetryableError} for broader coverage. */ export declare class NonRetryableWebhookError extends NonRetryableHttpError { constructor(message: string, init: HttpDeliveryErrorInit); } //# sourceMappingURL=types.d.ts.map