import { z } from "zod";
import type { BlockMdxConfig } from "../types.js";
/**
* Pure (React-free) part of the PLAN-SPECIFIC `openapi-spec` block: its data
* schema and MDX round-trip config. Shared by the server MDX adapter
* (`plan-mdx.ts` via `plan-block-registry.ts`) and the client spec
* (`planBlocks.tsx`). Keeping this React-free means importing it into a server
* module never pulls React into the Nitro/SSR bundle.
*
* This is the WHOLE-DOCUMENT counterpart to the single-endpoint `api-endpoint`
* block: instead of one operation, it carries a complete OpenAPI 3 / Swagger 2
* document (the `spec` string) and the reader renders a Redoc / Swagger-UI-style
* reference — operations grouped by tag, each a collapsible row (colored method
* pill + path + summary) expanding to params / request body / per-status
* responses, with `$ref` models resolved. The raw `spec` TEXT is the source of
* truth, so authoring round-trips losslessly even when the spec is malformed —
* the reader parses defensively and falls back to a graceful error rather than
* throwing.
*
* v1 supports JSON specs only. A YAML parser (`yaml`) is NOT a declared
* dependency of this package, so to avoid pulling in an undeclared/transitive
* module the reader parses JSON (a superset of nothing — pure `JSON.parse`).
* The Edit form documents the JSON-only constraint inline. When `yaml` is later
* added as a real dependency, the reader's `parseSpec` is the single seam to
* extend.
*
* The schema MUST stay data-compatible with the inline `openapi-spec` member of
* `planBlockSchema` (`plan-content.ts`), and the MDX `tag` (`OpenApi`) +
* attribute shape MUST match the `` encoding so stored
* `.mdx` round-trips. `spec` lives in the `spec` ATTRIBUTE (not MDX children) —
* the shared `prop()` encoder round-trips multiline strings cleanly, and keeping
* it an attribute avoids the payload being reflowed as prose.
*/
export interface OpenApiSpecData {
/** Raw OpenAPI 3 / Swagger 2 document text (JSON in v1). Source of truth. */
spec: string;
/** Optional heading shown above the reference. */
title?: string;
}
export const openApiSpecSchema = z.object({
spec: z.string().max(400_000),
title: z.string().trim().max(200).optional(),
}) as unknown as z.ZodType;
/**
* MDX config: `title` and `spec` are flat attributes — the `` self-closing form. Insertion order of `toAttrs` is the on-disk
* attribute order (`title` → `spec`). `fromAttrs` mirrors a forgiving parse
* (`spec ?? ""`, `title` undefined when absent) so a plan missing an attribute
* still parses.
*/
export const openApiSpecMdx: BlockMdxConfig = {
tag: "OpenApi",
toAttrs: (data) => ({
title: data.title,
spec: data.spec,
}),
fromAttrs: (attrs) => ({
spec: attrs.string("spec") ?? "",
title: attrs.string("title"),
}),
};