@scalar/api-reference
Version:
Generate beautiful API references from OpenAPI documents
119 lines (118 loc) • 3.25 kB
JavaScript
import { isDereferenced } from "@scalar/openapi-types/helpers";
import { getResolvedRef } from "@scalar/workspace-store/helpers/get-resolved-ref";
function formatProperty(key, obj) {
let output = key;
const isRequired = obj.required?.includes(key);
output += isRequired ? " REQUIRED " : " optional ";
const property = getResolvedRef(obj.properties?.[key]);
if (property) {
output += property.type;
if (property.description) {
output += " " + property.description;
}
}
return output;
}
function recursiveLogger(obj) {
const results = ["Body"];
const schema = getResolvedRef(obj?.schema);
const properties = schema?.properties;
if (properties) {
Object.keys(properties).forEach((key) => {
if (!obj.schema) {
return;
}
results.push(formatProperty(key, schema));
const property = getResolvedRef(properties[key]);
const isNestedObject = property.type === "object" && Boolean(property.properties);
if (isNestedObject && property.properties) {
Object.keys(property.properties).forEach((subKey) => {
results.push(`${subKey} ${getResolvedRef(property.properties?.[subKey])?.type}`);
});
}
});
}
return results;
}
function extractRequestBody(operation) {
try {
const media = getResolvedRef(operation?.requestBody)?.content?.["application/json"];
if (!media) {
throw new Error("Body not found");
}
return recursiveLogger(media);
} catch (_error) {
return false;
}
}
function deepMerge(source, target) {
for (const [key, val] of Object.entries(source)) {
if (val !== null && typeof val === "object") {
target[key] ??= new val.__proto__.constructor();
deepMerge(val, target[key]);
} else if (typeof val !== "undefined") {
target[key] = val;
}
}
return target;
}
function createEmptySpecification(partialSpecification) {
return deepMerge(partialSpecification ?? {}, {
info: {
title: "",
description: "",
termsOfService: "",
version: "",
license: {
name: "",
url: ""
},
contact: {
email: ""
}
},
servers: [],
tags: []
});
}
function createParameterMap(operation) {
const map = {
path: [],
query: [],
header: [],
cookie: [],
body: [],
formData: []
};
const parameters = operation.parameters ?? [];
if (parameters) {
parameters.forEach((parameter) => {
if (!isDereferenced(parameter)) {
return;
}
if (typeof parameter === "object" && parameter !== null && "$ref" in parameter) {
return;
}
if (parameter.in === "path") {
map.path.push(parameter);
} else if (parameter.in === "query") {
map.query.push(parameter);
} else if (parameter.in === "header") {
map.header.push(parameter);
} else if (parameter.in === "cookie") {
map.cookie.push(parameter);
} else if (parameter.in === "body") {
map.body.push(parameter);
} else if (parameter.in === "formData") {
map.formData.push(parameter);
}
});
}
return map;
}
export {
createEmptySpecification,
createParameterMap,
deepMerge,
extractRequestBody
};