@beignet/core
Version:
Core framework primitives for Beignet
75 lines (69 loc) • 2.27 kB
text/typescript
/**
* OpenAPI generation handler
* OpenAPI helpers for the Beignet server runtime.
*/
import type { HttpContractConfig } from "../contracts/index.js";
import type { AppEnvironment } from "./health.js";
import type { HttpRequestLike, HttpResponseLike } from "./types.js";
/**
* OpenAPI route handler configuration.
*/
export interface OpenAPIConfig {
/** Enable OpenAPI endpoint (default: false) */
enabled?: boolean;
/**
* Suggested path for the OpenAPI endpoint (e.g., "/api/openapi.json").
* NOTE: This field is for documentation/metadata only and does not control routing.
* You must manually wire the openapiHandler to your desired route.
*/
suggestedPath?: string;
/** API title */
title?: string;
/** API version */
version?: string;
/** API description */
description?: string;
}
/**
* Create a framework-neutral OpenAPI JSON handler.
*
* The OpenAPI document is generated lazily on the first request and then cached
* for the lifetime of the handler.
*/
export function createOpenAPIHandler(
contracts: readonly HttpContractConfig[],
openapiConfig: OpenAPIConfig | undefined,
_env: AppEnvironment,
): (req: HttpRequestLike) => Promise<HttpResponseLike> {
// Lazily generate OpenAPI spec on first request
let cachedSpec: object | null = null;
return async (_req: HttpRequestLike): Promise<HttpResponseLike> => {
// Generate spec if not cached
if (!cachedSpec) {
try {
// Dynamic import to avoid hard dependency
const { contractsToOpenAPI } = await import("../openapi/index.js");
cachedSpec = contractsToOpenAPI(contracts, {
title: openapiConfig?.title ?? "Beignet API",
version: openapiConfig?.version ?? "1.0.0",
description: openapiConfig?.description,
});
} catch (error) {
// OpenAPI generation failed
return {
status: 500,
body: {
error: "OpenAPI generation failed",
message: error instanceof Error ? error.message : "Unknown error",
},
headers: { "Content-Type": "application/json" },
};
}
}
return {
status: 200,
body: cachedSpec,
headers: { "Content-Type": "application/json" },
};
};
}