UNPKG

@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
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