openapi-typescript
Version:
Convert OpenAPI 3.0 & 3.1 schemas to TypeScript
177 lines (166 loc) • 6.93 kB
text/typescript
import type { ComponentsObject, GlobalContext } from "../types.js";
import { escObjKey, getEntries, getSchemaObjectComment, indent, tsOptionalProperty, tsReadonly } from "../utils.js";
import transformHeaderObject from "./header-object.js";
import transformParameterObject from "./parameter-object.js";
import transformPathItemObject from "./path-item-object.js";
import transformRequestBodyObject from "./request-body-object.js";
import transformResponseObject from "./response-object.js";
import transformSchemaObjectMap from "./schema-object-map.js";
import transformSchemaObject from "./schema-object.js";
export default function transformComponentsObject(components: ComponentsObject, ctx: GlobalContext): string {
let { indentLv } = ctx;
const output: string[] = ["{"];
indentLv++;
// schemas
if (components.schemas) {
const schemas = transformSchemaObjectMap(components.schemas, { path: "#/components/schemas/", ctx: { ...ctx, indentLv } });
output.push(indent(`schemas: ${schemas};`, indentLv));
} else {
output.push(indent("schemas: never;", indentLv));
}
// responses
if (components.responses) {
output.push(indent("responses: {", indentLv));
indentLv++;
for (const [name, responseObject] of getEntries(components.responses, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(responseObject, indentLv);
if (c) output.push(indent(c, indentLv));
let key = escObjKey(name);
if (ctx.immutableTypes) key = tsReadonly(key);
if ("$ref" in responseObject) {
output.push(indent(`${key}: ${transformSchemaObject(responseObject, { path: `#/components/responses/${name}`, ctx })};`, indentLv));
} else {
const responseType = transformResponseObject(responseObject, {
path: `#/components/responses/${name}`,
ctx: { ...ctx, indentLv },
});
output.push(indent(`${key}: ${responseType};`, indentLv));
}
}
indentLv--;
output.push(indent("};", indentLv));
} else {
output.push(indent("responses: never;", indentLv));
}
// parameters
if (components.parameters) {
const parameters: string[] = [];
indentLv++;
let isEveryParameterOptional = true;
for (const [name, parameterObject] of getEntries(components.parameters, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(parameterObject, indentLv);
if (c) parameters.push(indent(c, indentLv));
let key = escObjKey(name);
if (ctx.immutableTypes) key = tsReadonly(key);
if ("$ref" in parameterObject) {
parameters.push(indent(`${key}: ${transformSchemaObject(parameterObject, { path: `#/components/parameters/${name}`, ctx })};`, indentLv));
isEveryParameterOptional = false;
} else {
if (parameterObject.in !== "path" && !parameterObject.required) {
key = tsOptionalProperty(key);
} else {
isEveryParameterOptional = false;
}
const parameterType = transformParameterObject(parameterObject, {
path: `#/components/parameters/${name}`,
ctx: { ...ctx, indentLv },
});
parameters.push(indent(`${key}: ${parameterType};`, indentLv));
}
}
indentLv--;
const parametersKey = isEveryParameterOptional ? tsOptionalProperty("parameters") : "parameters";
output.push(indent(`${parametersKey}: {`, indentLv), ...parameters, indent("};", indentLv));
} else {
output.push(indent("parameters: never;", indentLv));
}
// requestBodies
if (components.requestBodies) {
output.push(indent("requestBodies: {", indentLv));
indentLv++;
for (const [name, requestBodyObject] of getEntries(components.requestBodies, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(requestBodyObject, indentLv);
if (c) output.push(indent(c, indentLv));
let key = escObjKey(name);
if ("$ref" in requestBodyObject) {
if (ctx.immutableTypes) key = tsReadonly(key);
output.push(
indent(
`${key}: ${transformSchemaObject(requestBodyObject, {
path: `#/components/requestBodies/${name}`,
ctx: { ...ctx, indentLv },
})};`,
indentLv,
),
);
} else {
if (!requestBodyObject.required) key = tsOptionalProperty(key);
if (ctx.immutableTypes) key = tsReadonly(key);
const requestBodyType = transformRequestBodyObject(requestBodyObject, {
path: `#/components/requestBodies/${name}`,
ctx: { ...ctx, indentLv },
});
output.push(indent(`${key}: ${requestBodyType};`, indentLv));
}
}
indentLv--;
output.push(indent("};", indentLv));
} else {
output.push(indent("requestBodies: never;", indentLv));
}
// headers
if (components.headers) {
output.push(indent("headers: {", indentLv));
indentLv++;
for (const [name, headerObject] of getEntries(components.headers, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(headerObject, indentLv);
if (c) output.push(indent(c, indentLv));
let key = escObjKey(name);
if (ctx.immutableTypes) key = tsReadonly(key);
if ("$ref" in headerObject) {
output.push(indent(`${key}: ${transformSchemaObject(headerObject, { path: `#/components/headers/${name}`, ctx })};`, indentLv));
} else {
const headerType = transformHeaderObject(headerObject, {
path: `#/components/headers/${name}`,
ctx: { ...ctx, indentLv },
});
output.push(indent(`${key}: ${headerType};`, indentLv));
}
}
indentLv--;
output.push(indent("};", indentLv));
} else {
output.push(indent("headers: never;", indentLv));
}
// pathItems
if (components.pathItems) {
output.push(indent("pathItems: {", indentLv));
indentLv++;
for (const [name, pathItemObject] of getEntries(components.pathItems, ctx.alphabetize, ctx.excludeDeprecated)) {
let key = escObjKey(name);
if (ctx.immutableTypes) key = tsReadonly(key);
if ("$ref" in pathItemObject) {
const c = getSchemaObjectComment(pathItemObject, indentLv);
if (c) output.push(indent(c, indentLv));
output.push(indent(`${key}: ${transformSchemaObject(pathItemObject, { path: `#/components/pathItems/${name}`, ctx })};`, indentLv));
} else {
output.push(
indent(
`${key}: ${transformPathItemObject(pathItemObject, {
path: `#/components/pathItems/${name}`,
ctx: { ...ctx, indentLv },
})};`,
indentLv,
),
);
}
}
indentLv--;
output.push(indent("};", indentLv));
} else {
output.push(indent("pathItems: never;", indentLv));
}
indentLv--;
output.push(indent("}", indentLv));
return output.join("\n");
}