UNPKG

@azure-utils/storybooks

Version:

Utils to upload and manage Storybooks via Azure Functions and storage.

113 lines (101 loc) 3.36 kB
import type { HttpRequest, HttpResponseInit, InvocationContext, } from "@azure/functions"; import { createDocument, type ZodOpenApiSecuritySchemeObject, } from "zod-openapi"; import { openAPIPaths, openAPISchemas, openAPISecuritySchemas, openAPITags, } from "../utils/openapi-utils"; import { CONTENT_TYPES, SUPPORTED_CONTENT_TYPES_MSG } from "../utils/constants"; import { responseError } from "../utils/response-utils"; import { getStore } from "../utils/store"; export async function openAPIHandler( request: HttpRequest, context: InvocationContext ): Promise<HttpResponseInit> { const { authLevel, openapi, serviceName } = getStore(); const { title = serviceName.toUpperCase(), version = process.env["NODE_ENV"] || "TEST", servers, } = openapi || {}; context.log("Serving OpenAPI schema...", authLevel); try { const securitySchemes: Record<string, ZodOpenApiSecuritySchemeObject> = {}; if (authLevel) { securitySchemes["functionsKey"] = openAPISecuritySchemas.functionsKey; } const openAPISpec = createDocument({ openapi: "3.1.0", info: { title, version }, security: authLevel ? [{ functionsKey: [] }] : [], servers, tags: Object.values(openAPITags), paths: openAPIPaths, components: { schemas: openAPISchemas, securitySchemes, }, }); const { searchParams } = new URL(request.url); const isDownloadJSON = searchParams.get("download") === "json"; if (isDownloadJSON) { const headers = new Headers({ "Content-Disposition": `attachment; filename="${title}_${version}_openapi.json"`, }); return { status: 200, jsonBody: openAPISpec, headers }; } const accept = request.headers.get("accept"); if (!accept || accept.includes(CONTENT_TYPES.JSON)) { return { status: 200, jsonBody: openAPISpec }; } if (accept.includes(CONTENT_TYPES.HTML)) { const html = generateSwaggerUI(title, openAPISpec); return { status: 200, headers: { "Content-Type": CONTENT_TYPES.HTML }, body: html, }; } return { status: 406, body: SUPPORTED_CONTENT_TYPES_MSG }; } catch (error) { return responseError(error, context); } } function generateSwaggerUI(title: string, openAPISpec: object) { return /* html */ ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="description" content="${title} SwaggerUI" /> <title>${title}</title> <link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist/swagger-ui.css" /> <script src="https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js" crossorigin></script> </head> <body style="position: relative;"> <div id="swagger-ui"></div> <div style="position: absolute; top: 0; right: 0; padding-right: 16px; display: flex; gap: 0.5rem;"> <form> <input type="hidden" name="download" value="json" /> <button type="submit">Download</button> </form> <button type="button" onClick="window.location.reload();">Refresh</button> </div> <script async defer> window.swaggerUI = SwaggerUIBundle(${JSON.stringify({ dom_id: "#swagger-ui", spec: openAPISpec, })}); </script> </body> </html>`; }