UNPKG

@duongtrungnguyen/nestro

Version:
103 lines 3.75 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __decorateClass = (decorators, target, key, kind) => { var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target; for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result; if (kind && result) __defProp(target, key, result); return result; }; var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index); import { Inject, Injectable } from "@nestjs/common"; import { setup } from "swagger-ui-express"; import { buildInstanceHttpUrl } from "../../common"; import { DiscoveryService } from "../../discovery"; import { GATEWAY_OPTIONS } from "../constants"; let GatewaySwaggerMiddleware = class { constructor(discoveryService, gatewayOptions) { this.discoveryService = discoveryService; this.gatewayOptions = gatewayOptions; } async use(req, res, next) { const requestPath = this._normalizePath(req.originalUrl); const swaggerPath = this._normalizePath(this.gatewayOptions.swagger.path); const swaggerJsonPath = this._normalizePath(this.gatewayOptions.swagger.jsonPath); if (swaggerPath === swaggerJsonPath) { throw new Error("Swagger json document path must conflict with Swagger ui document path"); } if (requestPath !== swaggerPath && requestPath !== swaggerJsonPath) return next(); const services = this.discoveryService.getServices(); const docs = []; await Promise.all( Array.from(services.entries()).sort(([a], [b]) => a.localeCompare(b, void 0, { sensitivity: "base" })).map(async ([, instances]) => { const doc = await this.fetchFirstValidDoc( instances.map((s) => `${buildInstanceHttpUrl(s)}/${s.swaggerJsonPath || "api-docs-json"}`) ); if (doc) docs.push(doc); }) ); const mergedDoc = this.mergeDocs(docs); if (requestPath === swaggerJsonPath) { return res.json(mergedDoc); } return setup(mergedDoc)(req, res, next); } _normalizePath(path) { if (!path) return void 0; if (!path.startsWith("/")) path = "/" + path; if (path.length > 1 && path.endsWith("/")) path = path.slice(0, -1); return path; } async fetchFirstValidDoc(urls) { for (const url of urls) { try { const res = await fetch(url); if (res.ok) { const doc = await res.json(); if (doc.openapi && doc.paths) return doc; } } catch (_) { continue; } } return null; } mergeDocs(docs) { return docs.reduce((acc, doc, idx) => { if (idx === 0) { acc.openapi = "3.0.0"; acc.info = { title: this.gatewayOptions.swagger.title, description: this.gatewayOptions.swagger.description, version: this.gatewayOptions.swagger.version }; acc.paths = {}; acc.components = { schemas: {} }; acc.servers = []; acc.tags = []; } acc.paths = { ...acc.paths, ...doc.paths }; acc.components.schemas = { ...acc.components.schemas, ...doc.components?.schemas ?? {} }; if (Array.isArray(doc.servers)) { acc.servers.push(...doc.servers); } if (Array.isArray(doc.tags)) { acc.tags.push(...doc.tags); } return acc; }, {}); } }; GatewaySwaggerMiddleware = __decorateClass([ Injectable(), __decorateParam(0, Inject(DiscoveryService)), __decorateParam(1, Inject(GATEWAY_OPTIONS)) ], GatewaySwaggerMiddleware); export { GatewaySwaggerMiddleware }; //# sourceMappingURL=gateway-swagger.middleware.js.map