import { Cause } from 'effect'; import { LogRecord } from '@voltro/logger'; import { Subject } from '@voltro/protocol'; import { VoltroPlugin } from '@voltro/protocol'; export declare interface Breadcrumb { /** Unix SECONDS (Sentry breadcrumb convention). */ readonly timestamp: number; readonly level: 'debug' | 'info' | 'warning' | 'error' | 'fatal'; readonly category?: string; readonly message: string; readonly data?: Record; } declare interface BreadcrumbRing { /** Record a log line under its trace. */ readonly add: (traceId: string, record: LogRecord) => void; /** Return + REMOVE a trace's breadcrumbs (chronological). */ readonly take: (traceId: string) => ReadonlyArray; readonly drop: (traceId: string) => void; readonly size: () => number; } declare interface BreadcrumbRingOptions { readonly maxPerTrace?: number; readonly maxTraces?: number; readonly ttlMs?: number; } declare interface CaptureContext { readonly tag: string; readonly kind: string; readonly subject: Subject; readonly traceId: string; readonly spanId?: string; } /** What `captureFailures` accepts: a boolean, the `'infrastructure'` preset, * or a predicate over the failure value. */ declare type CaptureFailuresOption = boolean | 'infrastructure' | ((error: unknown) => boolean); export declare const captureToSentry: (sentry: SentryLike, cause: Cause.Cause, ctx: CaptureContext, breadcrumbs: ReadonlyArray, captureFailures?: boolean | ((error: unknown) => boolean)) => void; /** Unwrap an Effect `Cause` to the underlying error value (Error | tagged * error | defect). `Cause.squash` returns the most informative throwable. */ export declare const causeToError: (cause: Cause.Cause) => unknown; export declare const makeBreadcrumbRing: (opts?: BreadcrumbRingOptions, now?: () => number) => BreadcrumbRing; export declare const parseDsn: (dsn: string | undefined) => SentryDsn | null; declare interface SentryDsn { readonly protocol: string; readonly publicKey: string; readonly host: string; readonly projectId: string; } /** Extra `Sentry.init` options passed through verbatim — the escape hatch for * everything the first-class options don't cover: `beforeSend` / * `beforeBreadcrumb` (PII/event scrubbing), `ignoreErrors`, error * `sampleRate`, `maxValueLength`, … Structural (not `NodeOptions`) so * `@sentry/node` stays an optional dependency. * * Merge contract: the bag is spread FIRST, then the plugin's own keys — so * the plugin stays authoritative for everything it manages (`dsn`, * `skipOpenTelemetrySetup`, `tracesSampleRate`, and `environment` / * `release` / `profilesSampleRate` when set). `integrations` is the one * exception: user integrations are APPENDED to the plugin's own, never * replacing them. */ export declare interface SentryInitOverrides { /** Extra Sentry integrations, appended AFTER the plugin's own. */ readonly integrations?: ReadonlyArray; readonly [key: string]: unknown; } export declare interface SentryLike { withScope(callback: (scope: SentryScopeLike) => void): unknown; captureException(exception: unknown): unknown; } export declare const sentryPlugin: (options?: SentryPluginOptions) => VoltroPlugin; export declare interface SentryPluginOptions { /** Sentry DSN. Default `SENTRY_DSN` env. Without a valid DSN the plugin is a no-op. */ readonly dsn?: string; /** `environment` tag (Sentry env). Default `SENTRY_ENVIRONMENT` env. */ readonly environment?: string; /** Release identifier (Sentry release health + source maps). Default `SENTRY_RELEASE` env. */ readonly release?: string; /** Performance-trace sample rate (0..1). Default 1.0 — the same rate the * browser half uses, and named on the boot line so a first boot shows what it * is about to send. Deliberately not lowered on your behalf: a rate the * framework picks is a number nobody can find again. */ readonly tracesSampleRate?: number; /** * Route the framework's OTel spans to Sentry as transactions. Default **true**. * * The browser half records page/navigation transactions and page-owned rpc * child spans; those children link to the Effect/server trace. `false` turns * server transactions off while leaving errors + breadcrumbs intact. */ readonly traces?: boolean; /** * Whether a DECLARED failure reaches Sentry. **Default `false`.** * * A procedure's `error:` union is a contract: somebody wrote the outcome * down, the client gets it typed and branches on it, and it describes a state * of the world. `AccessDeniedError` on a team you are not in is the system * working. A DEFECT is the opposite — nobody foresaw it — and that is what * Sentry is built for. Defects are always reported; this option is only about * the other half. * * The default was `true` by omission rather than by decision, and it filled a * deployment's issue list with `level: error` entries for every invalid form * value, every click on a resource without access and every call on a deleted * row. An issue list of expected things is one nobody reads. * * Set `true` to keep the old behaviour — worth it if Sentry is where you see * errors at all. Or pass a predicate when only some of them are signal: * * ```ts * sentryPlugin({ captureFailures: (e) => (e as { _tag?: string })._tag === 'PaymentDeclined' }) * ``` * * A cause carrying a defect is reported whatever it travelled with, so this * cannot hide one by accident. * * `'infrastructure'` is the preset between the two booleans: a failure whose * tag says the STORE, a transport, the cipher or an authority source broke * (`StoreOperationFailed`, `SqlError`, `RequestError`, …) is reported even * though a handler declared it, because a declared database outage is still * a database outage. Everything else declared stays out. */ readonly captureFailures?: CaptureFailuresOption; /** Continuous CPU profiling via @sentry/profiling-node. Default false. */ readonly profiling?: boolean; /** Profile sample rate (0..1) when `profiling`. Default 1.0. */ readonly profilesSampleRate?: number; /** Max breadcrumbs retained per trace. Default 50. */ readonly maxBreadcrumbs?: number; /** Disambiguates multiple instances. */ readonly name?: string; /** Escape hatch: extra `Sentry.init` options (`beforeSend`, `ignoreErrors`, * `sampleRate`, extra `integrations`, …). Plugin-managed keys win; user * `integrations` are appended. See {@link SentryInitOverrides}. */ readonly init?: SentryInitOverrides; } declare interface SentryScopeLike { setContext(key: string, context: Record | null): unknown; setTag(key: string, value: string): unknown; addBreadcrumb(breadcrumb: Breadcrumb): unknown; } export declare const toBreadcrumb: (r: LogRecord) => Breadcrumb; export { }