UNPKG

@dudousxd/nestjs-telescope

Version:

Laravel Telescope-style observability console for NestJS — core: watchers, recorder, correlation, SQLite store, headless API.

48 lines 2.4 kB
import { type TelescopeModuleOptions } from './telescope.options.js'; import { TelescopeService } from './telescope.service.js'; /** * Public front-end error ingestion. Mounted on a SEPARATE controller from the * gated dashboard API (like {@link TelescopeAuthController}) so it carries NO * `@UseGuards(TelescopeGuard)` — ordinary users' browsers hit it, they have no * dashboard session. Security is instead the per-endpoint knobs in * {@link ClientErrorsOptions}: an opt-in `enabled` flag (404 while off), a body * byte cap, a per-IP token bucket, and an optional `authorize` hook. * * Records every accepted error as a `client_exception` entry through the normal * pipeline so it composes with new-exception alerts, per-type prune/archive, and * the dashboard — with a family-hash mirroring server exceptions and the * `failed` / `client` / `user:<id>` tags. */ export declare class ClientErrorController { private readonly options; private readonly service; private readonly logger; /** Per-pod, bounded token bucket (lazily built so a disabled endpoint is free). */ private rateLimiter; /** One warn for an authorize-hook throw, so a flaky hook can't spam logs. */ private warnedAuthorize; constructor(options: TelescopeModuleOptions, service: TelescopeService); ingest(body: unknown, request: unknown): Promise<void>; /** Build (once) the per-pod token bucket from the resolved rate-limit config. */ private limiter; /** * Run the host's authorize hook defensively: a throw is a DENIAL (fail closed) * and warn-logged once, so a buggy hook never 500s the public endpoint nor * floods the logs. */ private runAuthorize; /** * Best-effort serialized byte size of the parsed body. The framework already * parsed JSON by the time we get here, so we re-serialize to measure bytes * (UTF-8) — a tight enough proxy for the wire size to reject oversized * payloads. A non-serializable body counts as 0 (it'll fail validation anyway). */ private bodyByteSize; /** * Extract the reporting client's IP: the first hop of `x-forwarded-for` when * present (the original client behind a proxy), else `request.ip` / * `socket.remoteAddress`. Returns `null` when nothing usable is found. */ private clientIp; } //# sourceMappingURL=client-error.controller.d.ts.map