Skip to main content
Glama
kadykov

OpenAPI Schema Explorer

document.ts5.96 kB
import { OpenAPIV3 } from 'openapi-types'; import { RenderableSpecObject, RenderContext, RenderResultItem } from './types.js'; // Add .js // No longer need ResourceContents here // Placeholder for other renderable objects we'll create // import { RenderablePaths } from './paths.js'; // Add .js // import { RenderableComponents } from './components.js'; // Add .js /** * Wraps an OpenAPIV3.Document to make it renderable. * Handles rendering for top-level fields like 'info', 'servers', etc. * Delegates list rendering for 'paths' and 'components' to respective objects. */ export class RenderableDocument implements RenderableSpecObject { // TODO: Add RenderablePaths and RenderableComponents instances // private renderablePaths: RenderablePaths; // private renderableComponents: RenderableComponents; constructor(private document: OpenAPIV3.Document) { // Initialize renderable wrappers for paths and components here // this.renderablePaths = new RenderablePaths(document.paths); // this.renderableComponents = new RenderableComponents(document.components); } /** * Renders a list view. For the document level, this is intended * to be called only when the requested field is 'paths' or 'components'. * The actual routing/delegation will happen in the handler based on the field. */ renderList(_context: RenderContext): RenderResultItem[] { // Prefix context with _ // This method should ideally not be called directly on the document // without specifying 'paths' or 'components' as the field. // The handler for openapi://{field} will delegate to the appropriate // sub-object's renderList. // Returning an error result item. return [ { uriSuffix: 'error', data: null, // No specific data for this error isError: true, errorText: 'Error: List rendering is only supported for specific fields like "paths" or "components" at the top level.', renderAsList: true, // Errors often shown as plain text }, ]; } /** * Renders the detail view. For the document level, this should not be called * directly without specifying a field. The handler should call * `renderTopLevelFieldDetail` instead. */ renderDetail(_context: RenderContext): RenderResultItem[] { // Prefix context with _ // This method implementation fulfills the interface requirement, // but direct detail rendering of the whole document isn't meaningful here. return [ { uriSuffix: 'error', data: null, isError: true, errorText: 'Error: Detail rendering requires specifying a top-level field (e.g., "info", "servers").', renderAsList: true, // Errors often shown as plain text }, ]; } /** * Renders the detail view for a *specific* top-level field (e.g., 'info', 'servers'). * This is called by the handler after identifying the field. * * @param context - The rendering context. * @param fieldObject - The actual top-level field object to render (e.g., document.info). * @param fieldName - The name of the field being rendered (e.g., 'info'). * @returns An array of RenderResultItem representing the detail view. */ renderTopLevelFieldDetail( context: RenderContext, fieldObject: unknown, fieldName: string ): RenderResultItem[] { // Ensure fieldObject is provided (handler should validate fieldName exists) if (fieldObject === undefined || fieldObject === null) { return [ { uriSuffix: fieldName, data: null, isError: true, errorText: `Error: Field "${fieldName}" not found in the OpenAPI document.`, renderAsList: true, }, ]; } // Avoid rendering structural fields that have dedicated list views if (fieldName === 'paths' || fieldName === 'components') { return [ { uriSuffix: fieldName, data: null, isError: true, errorText: `Error: Field "${fieldName}" should be accessed via its list view (${context.baseUri}${fieldName}). Use the list view first.`, renderAsList: true, }, ]; } try { // For successful detail rendering, return the data object itself. // The handler will format it using the context.formatter. return [ { uriSuffix: fieldName, data: fieldObject, // Pass the raw data // isError defaults to false // renderAsList defaults to false (meaning use detail formatter) }, ]; } catch (error: unknown) { // Handle potential errors during data access or initial checks // Formatting errors will be caught by the handler later return [ { uriSuffix: fieldName, data: null, isError: true, errorText: `Error preparing field "${fieldName}" for rendering: ${ error instanceof Error ? error.message : String(error) }`, renderAsList: true, }, ]; } } // End of renderTopLevelFieldDetail // --- Helper methods to access specific parts --- getPathsObject(): OpenAPIV3.PathsObject | undefined { return this.document.paths; } getComponentsObject(): OpenAPIV3.ComponentsObject | undefined { return this.document.components; } getTopLevelField(fieldName: string): unknown { // Define allowed top-level OpenAPI document properties const allowedFields: Array<keyof OpenAPIV3.Document> = [ 'openapi', 'info', 'servers', 'paths', 'components', 'security', 'tags', 'externalDocs', ]; // Only allow access to documented OpenAPI properties if (allowedFields.includes(fieldName as keyof OpenAPIV3.Document)) { return this.document[fieldName as keyof OpenAPIV3.Document]; } return undefined; } } // End of RenderableDocument class

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