counterfact
Version:
Generate a TypeScript-based mock server from an OpenAPI spec in seconds — with stateful routes, hot reload, and REPL support.
105 lines (104 loc) • 3.89 kB
JavaScript
import { printObject } from "./printers.js";
import { SchemaTypeCoder } from "./schema-type-coder.js";
import { STREAMING_CONTENT_TYPES } from "./streaming-content-types.js";
import { TypeCoder } from "./type-coder.js";
import { pathJoin } from "../util/forward-slash-path.js";
export class ResponseTypeCoder extends TypeCoder {
openApi2MediaTypes;
constructor(requirement, version = "", openApi2MediaTypes = []) {
super(requirement, version);
this.openApi2MediaTypes = openApi2MediaTypes;
}
names() {
return super.names(this.requirement.refUrl.split("/").at(-1));
}
buildContentObjectType(script, response) {
if (response.has("content")) {
return response
.get("content")
.map((content, mediaType) => {
let schemaType;
if (content.has("itemSchema") &&
STREAMING_CONTENT_TYPES.has(mediaType)) {
schemaType = `AsyncIterable<${new SchemaTypeCoder(content.get("itemSchema"), this.version).write(script)}>`;
}
else {
schemaType = content.has("schema")
? new SchemaTypeCoder(content.get("schema"), this.version).write(script)
: "unknown";
}
return [
mediaType,
`{
schema: ${schemaType}
}`,
];
});
}
return this.openApi2MediaTypes.map((mediaType) => [
mediaType,
`{
schema: ${new SchemaTypeCoder(response.get("schema"), this.version).write(script)}
}`,
]);
}
printContentObjectType(script, response) {
if (response.has("content") || response.has("schema")) {
return printObject(this.buildContentObjectType(script, response));
}
return "never";
}
buildHeaders(script, response) {
return response
.get("headers")
.map((value, name) => [
name,
`{ schema: ${new SchemaTypeCoder(value.get("schema") ?? value, this.version).write(script)}}`,
]);
}
printHeaders(script, response) {
if (!response.has("headers")) {
return "never";
}
return printObject(this.buildHeaders(script, response));
}
printRequiredHeaders(response) {
const requiredHeaders = (response.get("headers")?.map((value, name) => ({
name,
required: value.data.required,
})) ?? [])
.filter(({ required }) => required)
.map(({ name }) => `"${name}"`);
return requiredHeaders.length === 0 ? "never" : requiredHeaders.join(" | ");
}
buildExamplesObjectType(response) {
if (!response.has("content")) {
return "{}";
}
const exampleNames = [];
response.get("content").forEach((content) => {
if (content.has("examples")) {
content.get("examples").forEach((_, name) => {
if (!exampleNames.includes(name)) {
exampleNames.push(name);
}
});
}
});
if (exampleNames.length === 0) {
return "{}";
}
return printObject(exampleNames.map((name) => [name, "unknown"]));
}
modulePath() {
return pathJoin("types", this.version, this.requirement.refUrl + ".ts");
}
writeCode(script) {
return `{
headers: ${this.printHeaders(script, this.requirement)};
requiredHeaders: ${this.printRequiredHeaders(this.requirement)};
content: ${this.printContentObjectType(script, this.requirement)};
examples: ${this.buildExamplesObjectType(this.requirement)};
}`;
}
}