This commit is contained in:
nasir@endelospay.com
2025-07-11 20:22:12 +05:00
commit 8c74b0e23f
120 changed files with 206874 additions and 0 deletions

View File

@@ -0,0 +1,293 @@
/**
* @fileoverview Extract complete provider endpoint details from api-docs.json
* Extracts all 147 provider endpoints with exact parameter names, types, and descriptions
*/
import fs from 'fs';
import path from 'path';
/**
* Extract complete provider endpoint details
*/
function extractCompleteProviderDetails() {
try {
console.log('=== EXTRACTING COMPLETE PROVIDER ENDPOINT DETAILS ===');
console.log('');
// Read the categorized endpoints
const categorizedPath = path.join(process.cwd(), 'categorized-endpoints.json');
const categorizedContent = fs.readFileSync(categorizedPath, 'utf8');
const categorized = JSON.parse(categorizedContent);
// Read the original api-docs.json for complete parameter details
const apiDocsPath = path.join(process.cwd(), '..', 'api-docs.json');
const apiDocsContent = fs.readFileSync(apiDocsPath, 'utf8');
const apiDocs = JSON.parse(apiDocsContent);
console.log(`Found ${categorized.provider.length} provider endpoints to process`);
console.log('');
const completeProviderEndpoints = [];
// Process each provider endpoint
categorized.provider.forEach((endpoint, index) => {
console.log(`Processing ${index + 1}/${categorized.provider.length}: ${endpoint.method} ${endpoint.path}`);
// Find the complete endpoint details in api-docs.json
const completeDetails = findCompleteEndpointDetails(apiDocs, endpoint.path, endpoint.method);
if (completeDetails) {
const enhancedEndpoint = {
...endpoint,
completeParameters: extractCompleteParameters(completeDetails),
requestBodySchema: extractRequestBodySchema(completeDetails),
responseSchema: extractResponseSchema(completeDetails),
exactToolName: generateExactToolName(endpoint, completeDetails),
detailedDescription: completeDetails.summary || completeDetails.description || endpoint.summary,
operationId: completeDetails.operationId,
tags: completeDetails.tags || []
};
completeProviderEndpoints.push(enhancedEndpoint);
} else {
console.warn(`⚠️ Could not find complete details for: ${endpoint.method} ${endpoint.path}`);
// Still add the endpoint with available information
completeProviderEndpoints.push({
...endpoint,
completeParameters: {},
requestBodySchema: null,
responseSchema: null,
exactToolName: generateExactToolName(endpoint, null),
detailedDescription: endpoint.summary || endpoint.description,
operationId: null,
tags: []
});
}
});
console.log('');
console.log(`=== EXTRACTION COMPLETE ===`);
console.log(`Processed ${completeProviderEndpoints.length} provider endpoints`);
console.log('');
// Save the complete provider details
const outputPath = path.join(process.cwd(), 'complete-provider-endpoints.json');
fs.writeFileSync(outputPath, JSON.stringify(completeProviderEndpoints, null, 2));
console.log(`Complete provider endpoint details saved to: ${outputPath}`);
// Display summary by category
const categoryCount = {};
completeProviderEndpoints.forEach(endpoint => {
const category = endpoint.category || 'unknown';
categoryCount[category] = (categoryCount[category] || 0) + 1;
});
console.log('');
console.log('=== PROVIDER ENDPOINTS BY CATEGORY ===');
Object.keys(categoryCount).sort().forEach(category => {
console.log(`${category}: ${categoryCount[category]} endpoints`);
});
return completeProviderEndpoints;
} catch (error) {
console.error('Error extracting complete provider details:', error);
throw error;
}
}
/**
* Find complete endpoint details in api-docs.json
*/
function findCompleteEndpointDetails(apiDocs, path, method) {
const paths = apiDocs.paths || {};
const pathData = paths[path];
if (!pathData) {
return null;
}
const methodData = pathData[method.toLowerCase()];
return methodData || null;
}
/**
* Extract complete parameters from endpoint definition
*/
function extractCompleteParameters(endpointDetails) {
const parameters = {};
// Extract path parameters, query parameters, header parameters
if (endpointDetails.parameters) {
endpointDetails.parameters.forEach(param => {
parameters[param.name] = {
name: param.name,
in: param.in, // path, query, header, etc.
type: param.schema?.type || param.type || 'string',
format: param.schema?.format || param.format,
required: param.required || false,
description: param.description || `${param.name} parameter`,
example: param.schema?.example || param.example,
enum: param.schema?.enum || param.enum,
minimum: param.schema?.minimum || param.minimum,
maximum: param.schema?.maximum || param.maximum
};
});
}
return parameters;
}
/**
* Extract request body schema
*/
function extractRequestBodySchema(endpointDetails) {
if (!endpointDetails.requestBody) {
return null;
}
const requestBody = {
required: endpointDetails.requestBody.required || false,
description: endpointDetails.requestBody.description || '',
content: {}
};
// Extract content types and their schemas
if (endpointDetails.requestBody.content) {
Object.keys(endpointDetails.requestBody.content).forEach(contentType => {
const contentData = endpointDetails.requestBody.content[contentType];
if (contentData.schema) {
requestBody.content[contentType] = {
schema: contentData.schema,
properties: extractSchemaProperties(contentData.schema),
required: contentData.schema.required || []
};
}
});
}
return requestBody;
}
/**
* Extract schema properties recursively
*/
function extractSchemaProperties(schema) {
if (!schema || !schema.properties) {
return {};
}
const properties = {};
Object.keys(schema.properties).forEach(propName => {
const prop = schema.properties[propName];
properties[propName] = {
type: prop.type || 'string',
format: prop.format,
description: prop.description || `${propName} property`,
example: prop.example,
enum: prop.enum,
items: prop.items,
properties: prop.properties ? extractSchemaProperties(prop) : undefined,
required: schema.required ? schema.required.includes(propName) : false
};
});
return properties;
}
/**
* Extract response schema
*/
function extractResponseSchema(endpointDetails) {
if (!endpointDetails.responses) {
return null;
}
const responses = {};
Object.keys(endpointDetails.responses).forEach(statusCode => {
const response = endpointDetails.responses[statusCode];
responses[statusCode] = {
description: response.description || '',
content: response.content || {}
};
});
return responses;
}
/**
* Generate exact tool name following the established convention
*/
function generateExactToolName(endpoint, completeDetails) {
const method = endpoint.method.toLowerCase();
const path = endpoint.path.toLowerCase();
// Extract meaningful parts from the path
let pathParts = path.split('/').filter(part => part && !part.startsWith('{') && !part.endsWith('}'));
// Remove common prefixes
pathParts = pathParts.filter(part => !['api', 'emr', 'emr-api'].includes(part));
// Determine action based on method and path context
let action = method;
if (method === 'get') {
action = 'get';
} else if (method === 'post') {
if (path.includes('/login') || path.includes('/register') || path.includes('/create')) {
action = 'create';
} else if (path.includes('/search') || path.includes('/find')) {
action = 'search';
} else {
action = 'create';
}
} else if (method === 'put' || method === 'patch') {
action = 'update';
} else if (method === 'delete') {
action = 'delete';
}
// Create resource name from path parts
let resource = pathParts.join('_').replace(/-/g, '_');
// Clean up resource name
resource = resource.replace(/[^a-z0-9_]/g, '');
// Handle special cases for better naming
if (path.includes('/appointment')) {
resource = resource.replace(/appointment/, 'appointment');
}
if (path.includes('/patient')) {
resource = resource.replace(/patient/, 'patient');
}
if (path.includes('/meeting')) {
resource = resource.replace(/meeting/, 'meeting');
}
if (path.includes('/form')) {
resource = resource.replace(/form/, 'form');
}
if (path.includes('/document')) {
resource = resource.replace(/document/, 'document');
}
// Ensure we have a resource name
if (!resource) {
if (completeDetails && completeDetails.operationId) {
resource = completeDetails.operationId.toLowerCase().replace(/[^a-z0-9_]/g, '_');
} else {
resource = 'unknown';
}
}
return `provider_${action}_${resource}`;
}
// Run the extraction
if (import.meta.url === `file://${process.argv[1]}`) {
extractCompleteProviderDetails();
}
export { extractCompleteProviderDetails };