openapi-typescript
Version:
Convert OpenAPI 3.0 & 3.1 schemas to TypeScript
124 lines (116 loc) • 4.57 kB
text/typescript
import type { GlobalContext, OperationObject, ParameterObject } from "../types.js";
import { escObjKey, getEntries, getSchemaObjectComment, indent, tsOptionalProperty, tsReadonly } from "../utils.js";
import transformParameterObject from "./parameter-object.js";
import transformRequestBodyObject from "./request-body-object.js";
import transformResponseObject from "./response-object.js";
import transformSchemaObject from "./schema-object.js";
export interface TransformOperationObjectOptions {
path: string;
ctx: GlobalContext;
wrapObject?: boolean;
}
export default function transformOperationObject(operationObject: OperationObject, { path, ctx, wrapObject = true }: TransformOperationObjectOptions): string {
let { indentLv } = ctx;
const output: string[] = wrapObject ? ["{"] : [];
indentLv++;
// parameters
{
if (operationObject.parameters) {
const parameterOutput: string[] = [];
indentLv++;
for (const paramIn of ["query", "header", "path", "cookie"] as ParameterObject["in"][]) {
const paramInternalOutput: string[] = [];
indentLv++;
let allOptional = true;
for (const param of operationObject.parameters ?? []) {
const node: ParameterObject | undefined = "$ref" in param ? ctx.parameters[param.$ref] : param;
if (node?.in !== paramIn) continue;
let key = escObjKey(node.name);
if (paramIn !== "path" && !node.required) {
key = tsOptionalProperty(key);
} else {
allOptional = false;
}
const c = getSchemaObjectComment(param, indentLv);
if (c) paramInternalOutput.push(indent(c, indentLv));
const parameterType =
"$ref" in param
? param.$ref
: transformParameterObject(param, {
path: `${path}/parameters/${param.name}`,
ctx: { ...ctx, indentLv },
});
paramInternalOutput.push(indent(`${key}: ${parameterType};`, indentLv));
}
indentLv--;
if (paramInternalOutput.length) {
const key = allOptional ? tsOptionalProperty(paramIn) : paramIn;
parameterOutput.push(indent(`${key}: {`, indentLv));
parameterOutput.push(...paramInternalOutput);
parameterOutput.push(indent(`};`, indentLv));
}
}
indentLv--;
if (parameterOutput.length) {
output.push(indent(`parameters: {`, indentLv));
output.push(parameterOutput.join("\n"));
output.push(indent("};", indentLv));
}
}
}
// requestBody
{
if (operationObject.requestBody) {
const c = getSchemaObjectComment(operationObject.requestBody, indentLv);
if (c) output.push(indent(c, indentLv));
let key = "requestBody";
if (ctx.immutableTypes) key = tsReadonly(key);
if ("$ref" in operationObject.requestBody) {
output.push(indent(`${key}: ${transformSchemaObject(operationObject.requestBody, { path, ctx })};`, indentLv));
} else {
if (!operationObject.requestBody.required) key = tsOptionalProperty(key);
const requestBody = transformRequestBodyObject(operationObject.requestBody, {
path: `${path}/requestBody`,
ctx: { ...ctx, indentLv },
});
output.push(indent(`${key}: ${requestBody};`, indentLv));
}
}
}
// responses
{
if (operationObject.responses) {
output.push(indent(`responses: {`, indentLv));
indentLv++;
for (const [responseCode, responseObject] of getEntries(operationObject.responses, ctx.alphabetize, ctx.excludeDeprecated)) {
const key = escObjKey(responseCode);
const c = getSchemaObjectComment(responseObject, indentLv);
if (c) output.push(indent(c, indentLv));
if ("$ref" in responseObject) {
output.push(
indent(
`${key}: ${transformSchemaObject(responseObject, {
path: `${path}/responses/${responseCode}`,
ctx,
})};`,
indentLv,
),
);
} else {
const responseType = transformResponseObject(responseObject, {
path: `${path}/responses/${responseCode}`,
ctx: { ...ctx, indentLv },
});
output.push(indent(`${key}: ${responseType};`, indentLv));
}
}
indentLv--;
output.push(indent(`};`, indentLv));
}
}
indentLv--;
if (wrapObject) {
output.push(indent("}", indentLv));
}
return output.join("\n");
}