/** * @module @arcis/node/nextjs * * Next.js adapter for Arcis. Two entry points covering the modern Next.js * stack (Edge Middleware + App Router route handlers). * * **Scope:** rate-limit + bot detection + security headers. The Edge * runtime cannot easily inspect request bodies (they are streams that * can only be read once, and consuming them in middleware defeats the * route handler). For XSS/SQL/SSTI/etc. body-payload blocking, call * `sanitizeObject(await request.json())` from `@arcis/node/sanitizers` * inside your route handler, or wrap individual handlers with * `arcisProtect` (also exported from this module). * * **1. Edge Middleware (`middleware.ts` at the project root):** * * ```ts * import { arcisMiddleware } from '@arcis/node/nextjs'; * import { NextResponse } from 'next/server'; * * const arcis = arcisMiddleware({ * rateLimit: { max: 100, windowMs: 60_000 }, * bot: true, * }); * * export default async function middleware(request: Request) { * const blocked = await arcis(request); * if (blocked) return blocked; * return NextResponse.next(); * } * ``` * * The returned function inspects the request and returns either: * - a `Response` (rate-limited 429 / bot-blocked 403) to short-circuit, or * - `undefined` to let the request proceed. * * The caller decides what "proceed" means — `NextResponse.next()` for Edge * Middleware, or a re-thrown handler call for custom plumbing. Keeping the * allow-path explicit avoids importing `next/server` from the adapter. * * **2. App Router route handlers (`app/api/.../route.ts`):** * * ```ts * import { arcisProtect } from '@arcis/node/nextjs'; * * export const POST = arcisProtect( * async (request: Request) => Response.json({ ok: true }), * { rateLimit: { max: 100 }, bot: true }, * ); * ``` * * The wrapper runs the same allow / deny pipeline as `arcisMiddleware`, * then on the allow path calls the handler, mutates the resulting * Response's headers with security defaults, and returns it. * * Pages-router API routes (`pages/api/...`) use Node-style req/res rather * than the Web Fetch shape; for those, drop the standard Express adapter * (`arcis()` from the package root) into `app.use(...)` of a custom server, * or migrate to the App Router for first-party support. * * No runtime dependency on `next` — the adapter speaks Web Fetch * `Request`/`Response` directly. NextRequest extends Request and * NextResponse extends Response, so both are assignable into / out of this * surface without imports. */ import type { HeaderOptions, RateLimitOptions } from '../core/types'; import { type BotProtectionOptions } from './bot-detection'; export interface ArcisNextOptions { /** 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; } /** * Build a Next.js Edge Middleware factory. The returned function runs the * Arcis allow / deny pipeline against the request and returns a `Response` * to short-circuit OR `undefined` to indicate "let the request proceed." * * The caller is responsible for the proceed-path (typically * `NextResponse.next()` from `next/server`). This split keeps the adapter * dependency-free of `next/server` while preserving clean Edge Middleware * ergonomics. * * Security headers are NOT applied here — Edge Middleware can't easily * mutate the response body's headers without consuming the body. For * security-headers-on-response, use `arcisProtect` on the route handler. */ export declare function arcisMiddleware(options?: ArcisNextOptions): (request: Request) => Promise; /** * Wrap an App Router route handler with the Arcis pipeline. Runs rate-limit * + bot checks BEFORE the handler, then security headers on the response * AFTER. The `...args` spread preserves the second-arg shape route handlers * receive, e.g. `(request, { params })` for dynamic routes. * * ```ts * export const GET = arcisProtect( * async (request, { params }) => Response.json({ id: params.id }), * { rateLimit: { max: 50 } }, * ); * ``` */ export declare function arcisProtect(handler: (request: Request, ...args: TArgs) => Promise | Response, options?: ArcisNextOptions): (request: Request, ...args: TArgs) => Promise; export default arcisMiddleware; //# sourceMappingURL=nextjs.d.ts.map