import type { SwaggerTransform } from '@fastify/swagger'; import { type DocumentationRouteMatcher, type OpenApiRouteSchema } from './documentationRouteMatchers.js'; /** Which of the two generated documents a transform is producing. */ export type ApiDocumentationAudience = 'public' | 'internal'; /** What {@link apiDocumentationTransform} builds: a `@fastify/swagger` transform. */ export type ApiDocumentationTransform = SwaggerTransform; /** * The transform input, with `schema` optional because a route may not have * one. `SwaggerTransform` declares it as always present, which is not what * `@fastify/swagger` passes for a route registered without a schema. */ export type ApiDocumentationTransformInput = { schema?: OpenApiRouteSchema; url: string; route: any; openapiObject?: unknown; swaggerObject?: unknown; }; export type ApiDocumentationTransformResult = { schema: OpenApiRouteSchema; url: string; }; /** * A transform to run underneath the audience decision, typically * `jsonSchemaTransform` from `fastify-type-provider-zod`. * * Looser than `SwaggerTransform` on purpose: a schema-less route is handed * down as `schema: undefined`, which every `SwaggerTransform` in practice * handles (`jsonSchemaTransform` returns it straight back) but none of them * declares. */ export type ChainedApiDocumentationTransform = (input: any) => { schema: any; url: string; }; /** * Key marking an internal endpoint in the internal document. * * Deliberately not `x-internal`: Scalar treats both `x-internal` and * `x-scalar-ignore` as "do not render this operation", so marking with either * would hide every internal endpoint from the very document that exists to * show them. */ export declare const DEFAULT_INTERNAL_MARKER_KEY = "x-internal-endpoint"; /** * Reject a marker key that would not survive to the document, or that would * make the internal reference hide the endpoints it is meant to document. * * `@fastify/swagger` copies only `x-`-prefixed schema keys into the generated * operation object and silently drops the rest, so a marker without the prefix * never reaches the document at all. `x-internal` and `x-scalar-ignore` do * reach it, and Scalar then leaves the operation out of the rendered * reference. Both failures are silent at runtime, so they are rejected when * the plugin is configured. */ export declare function assertInternalMarkerKey(key: string, optionPath: string): void; export type ApiDocumentationTransformOptions = { /** * `'public'` produces the customer-facing document: hidden routes stay * hidden. `'internal'` produces the internal one: hidden routes are shown * again, alongside the public ones. */ audience: ApiDocumentationAudience; /** * Routes kept out of *both* documents, whatever their `hide` flag says. * * `hide: true` is also how infrastructure endpoints and the documentation * UIs themselves keep out of the spec, and nothing in the flag says which * kind of hiding it was, so the internal document would otherwise end up * documenting the documentation. */ hiddenRoutes?: readonly DocumentationRouteMatcher[]; /** * Key stamped on internal operations in the internal document, so readers * and downstream tooling can tell them apart from the public ones. `false` * turns the marking off. * * @default 'x-internal-endpoint' */ internalMarkerKey?: string | false; /** * Transform to run underneath this one, on the audience-adjusted schema. * * Order matters: `jsonSchemaTransform` short-circuits on `hide: true` and * throws away the Zod schemas, so the audience decision has to happen first. * Chaining here guarantees that. */ transform?: ChainedApiDocumentationTransform; }; /** * Build a `@fastify/swagger` `transform` that re-derives the `hide` flag for * one audience. * * Route builders fail closed: an endpoint that is not customer-facing is * registered with `schema.hide: true`, which keeps it out of the OpenAPI * document. That is the right default for a customer-facing spec and the * wrong one for the teams consuming the service internally. This transform * reads the same flag as a statement about the audience, so both documents can * be generated from one route table. * * `hiddenRoutes` is the only override, and it only ever subtracts: a route on * that list is in neither document, whatever its `hide` flag says. There is * deliberately no way to move a route between the two documents from here. * `schema.hide` is the builder's own answer to whether an endpoint is * customer-facing, and a route that needs to contradict it wants its contract * changed rather than the documentation configured around it. * * The route's schema is never mutated: every registered document sees the same * route objects, and Fastify's own validation pipeline reads them too. */ export declare function apiDocumentationTransform(options: ApiDocumentationTransformOptions): ApiDocumentationTransform;