first
This commit is contained in:
293
extract-complete-provider-details.js
Normal file
293
extract-complete-provider-details.js
Normal 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 };
|
Reference in New Issue
Block a user