/** * @module @arcis/node/fastify * * Fastify plugin for Arcis. Registers `onRequest` (rate-limit + bot) and * `onSend` (security headers) hooks so the protections compose with any * other Fastify plugins your app uses. * * ```ts * import Fastify from 'fastify'; * import { arcisFastify } from '@arcis/node/fastify'; * * const app = Fastify(); * await app.register(arcisFastify, { * rateLimit: { max: 100, windowMs: 60_000 }, * bot: true, * }); * * app.get('/', async () => ({ ok: true })); * await app.listen({ port: 3000 }); * ``` * * No runtime dependency on `fastify` — its types are duck-typed enough to * satisfy Fastify's actual `FastifyInstance` / `FastifyRequest` / * `FastifyReply` shapes without pulling Fastify into peer-deps. * * For body-content inspection (the `block: true` flow other adapters * expose), drop the standard Express adapter (`arcis()` from the package * root) into a custom server, or pair this plugin with the standalone * sanitizer middleware on a hook. v1 keeps the surface narrow: * rate-limit, bot, headers. */ import type { HeaderOptions, RateLimitOptions } from '../core/types'; import { type BotProtectionOptions } from './bot-detection'; /** * Subset of Fastify's request shape used by the hooks. Real * `FastifyRequest` is assignable to this. */ export interface FastifyRequestLike { headers: Record; url?: string; method?: string; ip?: string; socket?: { remoteAddress?: string; }; raw?: { headers: Record; url?: string; }; } /** * Subset of Fastify's reply shape. Real `FastifyReply` is assignable to * this — the methods we use (`status`, `header`, `send`) all exist on * the actual Fastify reply. */ export interface FastifyReplyLike { status(code: number): FastifyReplyLike; header(name: string, value: string): FastifyReplyLike; send(payload: unknown): FastifyReplyLike; } export type FastifyHookHandler = (request: FastifyRequestLike, reply: FastifyReplyLike) => Promise | void; export type FastifyOnSendHandler = (request: FastifyRequestLike, reply: FastifyReplyLike, payload: unknown) => Promise | unknown; export interface FastifyInstanceLike { addHook(name: 'onRequest', handler: FastifyHookHandler): unknown; addHook(name: 'onSend', handler: FastifyOnSendHandler): unknown; } export interface ArcisFastifyOptions { /** Security headers configuration. Default: enabled. Pass `false` to disable. */ headers?: boolean | HeaderOptions; /** Rate limiter configuration. Default: 100 req/60s in-memory. Pass `false` to disable. */ rateLimit?: boolean | RateLimitOptions; /** * Bot protection. Default: disabled (opt-in to avoid surprising behavior on * legitimate crawlers). Pass `true` for sensible defaults or an options * object for full control. */ bot?: boolean | BotProtectionOptions; } /** * Fastify plugin. Registers `onRequest` (rate-limit + bot) + `onSend` * (security headers) hooks. Use via `app.register(arcisFastify, options)`. * * Plugin signature follows the canonical async Fastify plugin shape. * Returns a Promise so Fastify's encapsulation contract is met * even if no async work is currently performed inside. */ export declare function arcisFastify(fastify: FastifyInstanceLike, options?: ArcisFastifyOptions): Promise; export default arcisFastify; //# sourceMappingURL=fastify.d.ts.map