@pulzar/core
Version:
Next-generation Node.js framework for ultra-fast web applications with zero-reflection DI, GraphQL, WebSockets, events, and edge runtime support
217 lines • 6.87 kB
JavaScript
export class OpenAPIServer {
generator;
options;
constructor(generator, options = {}) {
this.generator = generator;
this.options = {
path: "/api-docs",
title: "API Documentation",
description: "Interactive API documentation",
version: "1.0.0",
theme: "light",
...options,
};
}
/**
* Serve OpenAPI JSON specification
*/
serveSpec(req, res) {
try {
const spec = this.generator.generate();
res.setHeader("Content-Type", "application/json");
res.json(spec);
}
catch (error) {
res
.status(500)
.json({ error: "Failed to generate OpenAPI specification" });
}
}
/**
* Serve OpenAPI YAML specification
*/
serveSpecYaml(req, res) {
try {
const spec = this.generator.generate();
const yaml = this.jsonToYaml(spec);
res.setHeader("Content-Type", "text/yaml");
res.send(yaml);
}
catch (error) {
res
.status(500)
.json({ error: "Failed to generate OpenAPI specification" });
}
}
/**
* Serve Swagger UI
*/
serveUI(req, res) {
const html = this.generateSwaggerUI();
res.setHeader("Content-Type", "text/html");
res.send(html);
}
/**
* Generate Swagger UI HTML
*/
generateSwaggerUI() {
const { path, title, description, version, contact, license, servers, security, theme, customCss, customJs, } = this.options;
const specUrl = `${path}/spec.json`;
const themeUrl = theme === "dark"
? "https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui.css"
: "https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui.css";
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${title}</title>
<link rel="stylesheet" type="text/css" href="${themeUrl}" />
<style>
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
margin:0;
background: #fafafa;
}
${customCss || ""}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui-bundle.js"></script>
<script src="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui-standalone-preset.js"></script>
<script>
window.onload = function() {
const ui = SwaggerUIBundle({
url: '${specUrl}',
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout",
validatorUrl: null,
oauth2RedirectUrl: window.location.origin + '/swagger-ui/oauth2-redirect.html',
initOAuth: {
clientId: "your-client-id",
clientSecret: "your-client-secret",
realm: "your-realms",
appName: "your-app-name",
scopeSeparator: " ",
scopes: "read write",
additionalQueryStringParams: {},
usePkceWithAuthorizationCodeGrant: false
},
onComplete: function() {
console.log('Swagger UI loaded successfully');
},
onFailure: function(data) {
console.log('Swagger UI failed to load', data);
}
});
};
${customJs || ""}
</script>
</body>
</html>`;
}
/**
* Convert JSON to YAML (simplified implementation)
*/
jsonToYaml(obj, indent = 0) {
const spaces = " ".repeat(indent);
let yaml = "";
if (Array.isArray(obj)) {
for (const item of obj) {
if (typeof item === "object" && item !== null) {
yaml += spaces + "-\n" + this.jsonToYaml(item, indent + 1);
}
else {
yaml += spaces + "- " + this.stringifyValue(item) + "\n";
}
}
}
else if (typeof obj === "object" && obj !== null) {
for (const [key, value] of Object.entries(obj)) {
if (typeof value === "object" &&
value !== null &&
!Array.isArray(value)) {
yaml += spaces + key + ":\n" + this.jsonToYaml(value, indent + 1);
}
else {
yaml += spaces + key + ": " + this.stringifyValue(value) + "\n";
}
}
}
return yaml;
}
/**
* Stringify a value for YAML
*/
stringifyValue(value) {
if (value === null)
return "null";
if (typeof value === "string")
return `"${value}"`;
if (typeof value === "number")
return value.toString();
if (typeof value === "boolean")
return value.toString();
if (Array.isArray(value))
return "[]";
if (typeof value === "object")
return "{}";
return String(value);
}
/**
* Get middleware for Express
*/
getMiddleware() {
return (req, res, next) => {
const { path } = this.options;
if (req.path === path) {
return this.serveUI(req, res);
}
if (req.path === `${path}/spec.json`) {
return this.serveSpec(req, res);
}
if (req.path === `${path}/spec.yaml`) {
return this.serveSpecYaml(req, res);
}
next();
};
}
/**
* Get routes for Express Router
*/
getRoutes() {
const { path } = this.options;
return {
[path]: {
get: (req, res) => this.serveUI(req, res),
},
[`${path}/spec.json`]: {
get: (req, res) => this.serveSpec(req, res),
},
[`${path}/spec.yaml`]: {
get: (req, res) => this.serveSpecYaml(req, res),
},
};
}
}
export function createOpenAPIServer(generator, options) {
return new OpenAPIServer(generator, options);
}
//# sourceMappingURL=serve.js.map