Skip to main content
Glama
kadykov

OpenAPI Schema Explorer

reference-transform.ts3.31 kB
import { OpenAPIV3 } from 'openapi-types'; import { buildComponentDetailUri } from '../utils/uri-builder.js'; // Added .js extension export interface TransformContext { resourceType: 'endpoint' | 'schema'; format: 'openapi' | 'asyncapi' | 'graphql'; path?: string; method?: string; } export interface ReferenceObject { $ref: string; } export interface TransformedReference { $ref: string; } export interface ReferenceTransform<T> { transformRefs(document: T, context: TransformContext): T; } export class ReferenceTransformService { private transformers = new Map<string, ReferenceTransform<unknown>>(); registerTransformer<T>(format: string, transformer: ReferenceTransform<T>): void { this.transformers.set(format, transformer as ReferenceTransform<unknown>); } transformDocument<T>(document: T, context: TransformContext): T { const transformer = this.transformers.get(context.format) as ReferenceTransform<T>; if (!transformer) { throw new Error(`No transformer registered for format: ${context.format}`); } return transformer.transformRefs(document, context); } } export class OpenAPITransformer implements ReferenceTransform<OpenAPIV3.Document> { // Handle nested objects recursively private transformObject(obj: unknown, _context: TransformContext): unknown { if (!obj || typeof obj !== 'object') { return obj; } // Handle arrays if (Array.isArray(obj)) { return obj.map(item => this.transformObject(item, _context)); } // Handle references if (this.isReferenceObject(obj)) { return this.transformReference(obj.$ref); } // Recursively transform object properties const result: Record<string, unknown> = {}; if (typeof obj === 'object') { for (const [key, value] of Object.entries(obj)) { if (Object.prototype.hasOwnProperty.call(obj, key)) { Object.defineProperty(result, key, { value: this.transformObject(value, _context), enumerable: true, writable: true, configurable: true, }); } } } return result; } private isReferenceObject(obj: unknown): obj is ReferenceObject { return typeof obj === 'object' && obj !== null && '$ref' in obj; } private transformReference(ref: string): TransformedReference { // Handle only internal references for now if (!ref.startsWith('#/')) { return { $ref: ref }; // Keep external refs as-is } // Example ref: #/components/schemas/MySchema const parts = ref.split('/'); // Check if it's an internal component reference if (parts[0] === '#' && parts[1] === 'components' && parts.length === 4) { const componentType = parts[2]; const componentName = parts[3]; // Use the centralized builder to create the correct URI const newUri = buildComponentDetailUri(componentType, componentName); return { $ref: newUri, }; } // Keep other internal references (#/paths/...) and external references as-is return { $ref: ref }; } transformRefs(document: OpenAPIV3.Document, context: TransformContext): OpenAPIV3.Document { const transformed = this.transformObject(document, context); return transformed as OpenAPIV3.Document; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kadykov/mcp-openapi-schema-explorer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server