Skip to main content
Glama
PSPDFKit

Nutrient Document Engine MCP Server

by PSPDFKit
generateSchema.js4.68 kB
#!/usr/bin/env node import { execSync } from 'child_process'; import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; // Get the directory of the current module const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Define paths const apiYamlPath = path.resolve(__dirname, '../src/api/document-engine-api.yml'); const schemaOutputPath = path.resolve(__dirname, '../src/api/DocumentEngineSchema.ts'); console.log('Generating TypeScript schema from OpenAPI YAML...'); function fixIndexSignatureConflictsSimple(content) { // Match interfaces with index signatures followed by named properties const pattern = /export interface (\w+) \{\s*\[name: string\]: ([^;]+);([\s\S]*?)\n\s*\}/g; return content.replace(pattern, (match, interfaceName, indexType, bodyContent) => { // Extract only TOP-LEVEL property names from the body content const propertyNames = []; const lines = bodyContent.split('\n'); let inNestedObject = false; let braceDepth = 0; for (const line of lines) { const trimmed = line.trim(); // Skip comments and empty lines if ( !trimmed || trimmed.startsWith('*') || trimmed.startsWith('//') || trimmed.startsWith('/**') || trimmed === '*/' || trimmed.includes('example:') || trimmed.includes('description:') ) { continue; } // Track brace depth to know if we're inside a nested object for (const char of trimmed) { if (char === '{') braceDepth++; if (char === '}') braceDepth--; } // Only look for properties at the top level (braceDepth should be 0 before we encounter the property) if (braceDepth === 0 || (braceDepth === 1 && trimmed.includes('{'))) { // Look for top-level property definitions (name: type pattern) const propertyMatch = trimmed.match(/^(\w+)\??:\s*/); if (propertyMatch) { propertyNames.push(propertyMatch[1]); } } } // If we found properties, create union type if (propertyNames.length > 0) { const propertyUnions = propertyNames.map(name => `${interfaceName}['${name}']`); const newIndexType = `${indexType.trim()} | ${propertyUnions.join(' | ')}`; return `export interface ${interfaceName} { [name: string]: ${newIndexType};${bodyContent} }`; } return match; }); } try { // Run openapicmd to generate the TypeScript schema const command = `npx openapicmd typegen ${apiYamlPath} > ${schemaOutputPath}`; execSync(command, { stdio: 'inherit' }); console.log('Schema generated successfully.'); // Read the generated file let schemaContent = fs.readFileSync(schemaOutputPath, 'utf8'); // Apply string replacements console.log('Applying fixes to the generated schema...'); // Fix 1: Convert dot notation with version numbers (e.g., Type.v1) to camelCase (TypeV1) schemaContent = schemaContent.replace( /export type ([A-Za-z]+)\.v([0-9]+) = Components\.Schemas\.([A-Za-z]+)V([0-9]+);/g, 'export type $1V$2 = Components.Schemas.$3V$4;' ); // Fix 2: Convert hyphenated types (e.g., type-name) to camelCase (typeName) schemaContent = schemaContent.replace( /export type ([a-z]+)-([A-Za-z]+) = Components\.Schemas\.([A-Za-z]+)([A-Za-z]+);/g, (match, p1, p2, p3, p4) => { // Convert first letter of second part to uppercase for camelCase const camelCaseName = p1 + p2.charAt(0).toUpperCase() + p2.slice(1); return `export type ${camelCaseName} = Components.Schemas.${p3}${p4};`; } ); // Fix 3: Convert underscore types (e.g., _type_name) to camelCase (typeName) schemaContent = schemaContent.replace( /export type _([a-z]+)_([A-Za-z]+) = Components\.Schemas\.([A-Za-z]+)([A-Za-z]+);/g, (match, p1, p2, p3, p4) => { // Convert first letter of each part to uppercase for camelCase (except the first part) const camelCaseName = p1 + p2.charAt(0).toUpperCase() + p2.slice(1); return `export type ${camelCaseName} = Components.Schemas.${p3}${p4};`; } ); // Fix 4: Add id field to DocumentProperties interface schemaContent = schemaContent.replace( /export interface DocumentProperties \{/, 'export interface DocumentProperties {\n id: string;' ); schemaContent = fixIndexSignatureConflictsSimple(schemaContent); // Write the fixed content back to the file fs.writeFileSync(schemaOutputPath, schemaContent); console.log('Schema fixes applied successfully.'); console.log('Schema generation and fixes completed.'); } catch (error) { console.error('Error generating schema:', error); process.exit(1); }

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/PSPDFKit/nutrient-document-engine-mcp-server'

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