import type * as Webhooks from './Webhooks.js'; export { assertBetterstackUrl, betterStack } from './webhookDestinations/betterStack.js'; export { assertSlackUrl, redactSlackUrl, slack } from './webhookDestinations/slack.js'; export { assertDeliverableUrl, url } from './webhookDestinations/url.js'; /** * Where a subscription's matched events are delivered. * * - `url` — a subscriber HTTPS endpoint; the signed envelope is POSTed verbatim * (HMAC in `tempo-signature`). * - `slack` — a subscriber-supplied Slack incoming-webhook URL (`hooks.slack.com`). * The envelope is formatted into a Slack Block Kit message and POSTed there * with no signature (the URL is itself the shared secret). No OAuth. * - `betterstack` — a Better Stack Telemetry source: an ingest host URL * (`*.betterstackdata.com`) plus a source token. The envelope is POSTed as a * structured log event authenticated with `Authorization: Bearer `. * * A `Destination` is plain, serializable data — it is what a `Subscription` * persists. The builders (`from`, `url`, `slack`, `betterStack`) return an * {@link Instance}: the same data plus a bound {@link Instance.deliver}. `deliver` * is a function property, so an instance serializes and structurally compares as * the plain destination it is. */ export type Destination = BetterStack | Slack | Url; /** A `url` delivery destination (a signed event POST to an HTTPS endpoint). */ export type Url = { /** Destination kind. */ type: 'url'; /** Subscriber callback URL (validated `https`). */ url: string; }; /** A `slack` delivery destination (a formatted message to an incoming webhook). */ export type Slack = { /** Destination kind. */ type: 'slack'; /** Slack incoming-webhook URL (`https://hooks.slack.com/services/…`). */ url: string; }; /** A `betterstack` delivery destination (a log event to a Better Stack source). */ export type BetterStack = { /** Better Stack source token, sent as `Authorization: Bearer …`. */ token: string; /** Destination kind. */ type: 'betterstack'; /** Better Stack ingest host URL (`https://.betterstackdata.com`). */ url: string; }; /** * A built destination: the plain {@link Destination} data plus a `deliver` * method that owns this transport's delivery logic (formatting, headers, * signing, redirect policy). `deliver` is a function property, so it drops out of * `JSON.stringify` — an instance serializes to just its data. * * There is no central delivery router: each provider carries its own transport. * To deliver a persisted (plain) `Subscription.destination`, rebuild an instance * with {@link from} and call `.deliver(...)`. */ export type Instance = destination & { /** Delivers an envelope to this destination using its own transport. */ deliver: (options: deliver.Options) => Promise; }; export declare namespace deliver { /** Options for {@link Instance.deliver}. */ type Options = { /** The envelope to deliver. */ envelope: Webhooks.Envelope; /** `fetch` implementation; defaults to the global. Injectable for tests. */ fetch?: typeof globalThis.fetch | undefined; /** Monotonic clock in ms; defaults to `Date.now`. Injectable for tests. */ now?: (() => number) | undefined; /** Signing secret; required by the `url` transport, ignored by others. */ secret?: string | undefined; /** Abort the request after this many ms (default 10000). */ timeoutMs?: number | undefined; /** Unix timestamp (seconds) embedded in the signature; defaults to now. */ timestamp?: number | undefined; }; } /** Outcome of a single delivery attempt, shared by every transport. */ export type Result = { /** Wall-clock duration of the attempt in ms, when the request was made. */ durationMs?: number | undefined; /** Failure reason when `ok` is false. */ error?: string | undefined; /** Whether the destination accepted the delivery (2xx). */ ok: boolean; /** HTTP response status, when a response was received. */ status?: number | undefined; }; /** Returns whether another delivery attempt could plausibly succeed. */ export declare function isRetryable(result: Result): boolean; /** * Canonical constructor: normalizes a value into a validated {@link Instance} by * delegating to the matching builder (`url`, `slack`, `betterStack`), each of * which owns its own transport. This is also how you deliver a persisted (plain) * destination: `from(subscription.destination).deliver(...)`. * * @example * ```ts * WebhookDestination.from('https://example.com/hook') * WebhookDestination.from({ type: 'slack', url: 'https://hooks.slack.com/…' }) * ``` */ export declare function from(value: from.Value): Instance; export declare namespace from { /** A destination object, or a bare HTTPS URL string (shorthand for `url`). */ type Value = Destination | string; } /** Validates a destination's URL according to its transport-specific rules. */ export declare function assertDestination(destination: Destination): void; /** * A non-secret label for a destination, used in delivery-log `requestUrl`. Slack * incoming-webhook URLs are bearer secrets, so `slack` destinations log a * token-redacted form (see {@link core_slack.redactSlackUrl}) rather than the raw * URL. Better Stack keeps its secret in a separate `token`, so its ingest URL * logs verbatim. */ export declare function destinationLabel(destination: Destination): string; /** * Low-level HTTP send shared by every transport: POSTs a prebuilt body/headers * with a timeout and classifies the response into a {@link Result}. This is the * network mechanic only — each provider owns its own body formatting, headers, * signing, and redirect policy. Never throws. */ export declare function send(options: send.Options): Promise; export declare namespace send { /** Options for {@link send}. */ type Options = { /** Serialized request body. */ body: string; /** Prefix for the non-2xx error message (e.g. `slack `). */ errorPrefix?: string | undefined; /** `fetch` implementation; defaults to the global. */ fetch?: typeof globalThis.fetch | undefined; /** Extra request headers merged over `content-type: application/json`. */ headers?: Record | undefined; /** Monotonic clock in ms; defaults to `Date.now`. */ now?: (() => number) | undefined; /** Treat any 3xx/opaque redirect as a failed delivery (SSRF guard). */ rejectRedirects?: boolean | undefined; /** Abort the request after this many ms (default 10000). */ timeoutMs?: number | undefined; /** Destination URL. */ url: string; }; } /** Header carrying the HMAC signature (`t=…,v1=…`). */ export declare const signatureHeader = "tempo-signature"; /** Header carrying the idempotent event id (`evt_…`). */ export declare const eventIdHeader = "tempo-event-id"; /** Header carrying the event type. */ export declare const eventTypeHeader = "tempo-event-type"; /** * Signs a delivery body with a per-subscription secret. Returns a Stripe-style * header value `t=,v1=` where the timestamp guards against replay. */ export declare function sign(options: sign.Options): string; export declare namespace sign { /** Options for {@link sign}. */ type Options = { /** Raw request body to sign. */ body: string; /** Per-subscription signing secret. */ secret: string; /** Unix timestamp (seconds) to embed; defaults to now. */ timestamp?: number | undefined; }; } /** * Verifies a signature produced by {@link sign}: recomputes the HMAC and * rejects signatures older than `tolerance` seconds (default 300). */ export declare function verify(options: verify.Options): boolean; export declare namespace verify { /** Options for {@link verify}. */ type Options = { /** Raw request body that was signed. */ body: string; /** Current Unix timestamp (seconds); injectable for tests. */ now?: number | undefined; /** Per-subscription signing secret. */ secret: string; /** Signature header value (`t=…,v1=…`). */ signature: string; /** Maximum age in seconds before a signature is rejected. */ tolerance?: number | undefined; }; } /** Thrown when a subscriber URL fails SSRF/format validation. */ export declare class InvalidUrlError extends Error { /** Why the URL was rejected. */ reason: InvalidUrlError.Reason; /** The rejected URL. */ url: string; constructor(reason: InvalidUrlError.Reason, url: string); } export declare namespace InvalidUrlError { /** Reason a URL was rejected. */ type Reason = 'betterstack_host' | 'blocked_host' | 'credentials' | 'malformed' | 'protocol' | 'slack_host'; } //# sourceMappingURL=WebhookDestination.d.ts.map