Files
mcp-tool/extract-complete-api-parameters.js
nasir@endelospay.com 8c74b0e23f first
2025-07-11 20:22:12 +05:00

272 lines
9.6 KiB
JavaScript

/**
* @fileoverview Extract complete API parameter specifications from api-docs.json
* Parse every API endpoint with complete parameter specifications including names, types,
* required/optional status, descriptions, and request body schemas.
*/
import fs from "fs";
import path from "path";
/**
* Extract complete parameter specifications from API documentation
*/
function extractCompleteAPIParameters() {
try {
console.log("=== EXTRACTING COMPLETE API PARAMETER SPECIFICATIONS ===");
console.log("");
// Read the API documentation
const apiDocsPath = path.join(process.cwd(), "api-docs-analysis.json");
const apiDocsContent = fs.readFileSync(apiDocsPath, "utf8");
const apiDocs = JSON.parse(apiDocsContent);
const allEndpoints = [];
const parameterStats = {
totalEndpoints: 0,
endpointsWithParameters: 0,
totalParameters: 0,
requiredParameters: 0,
optionalParameters: 0,
pathParameters: 0,
queryParameters: 0,
bodyParameters: 0,
};
// Process each tag and its endpoints in the API documentation
Object.keys(apiDocs.endpointsByTag || {}).forEach((tag) => {
const endpoints = apiDocs.endpointsByTag[tag];
endpoints.forEach((endpoint) => {
parameterStats.totalEndpoints++;
const endpointData = {
path: endpoint.path,
method: endpoint.method.toUpperCase(),
operationId: endpoint.operationId || null,
summary: endpoint.summary || "",
description: endpoint.description || "",
tags: endpoint.tags || [tag],
security: endpoint.security || [],
requiresAuth: endpoint.requiresAuth || false,
parameters: {
path: [],
query: [],
body: [],
header: [],
},
requestBody: endpoint.requestBody || null,
responses: endpoint.responses || {},
};
let hasParameters = false;
// Extract path and query parameters
if (endpoint.parameters && Array.isArray(endpoint.parameters)) {
endpoint.parameters.forEach((param) => {
hasParameters = true;
parameterStats.totalParameters++;
const paramData = {
name: param.name,
type: param.schema?.type || param.type || "string",
format: param.schema?.format || param.format || null,
required: param.required === true,
description: param.description || "",
in: param.in,
enum: param.schema?.enum || param.enum || null,
example: param.schema?.example || param.example || null,
};
if (param.required) {
parameterStats.requiredParameters++;
} else {
parameterStats.optionalParameters++;
}
switch (param.in) {
case "path":
endpointData.parameters.path.push(paramData);
parameterStats.pathParameters++;
break;
case "query":
endpointData.parameters.query.push(paramData);
parameterStats.queryParameters++;
break;
case "header":
endpointData.parameters.header.push(paramData);
break;
}
});
}
// Extract request body parameters
if (endpoint.requestBody) {
hasParameters = true;
endpointData.requestBody = {
required: endpoint.requestBody.required === true,
description: endpoint.requestBody.description || "",
content: {},
};
// Process different content types
Object.keys(endpoint.requestBody.content || {}).forEach(
(contentType) => {
const content = endpoint.requestBody.content[contentType];
endpointData.requestBody.content[contentType] = {
schema: content.schema || {},
examples: content.examples || {},
};
// Extract properties from schema
if (content.schema && content.schema.properties) {
Object.keys(content.schema.properties).forEach((propName) => {
const prop = content.schema.properties[propName];
parameterStats.totalParameters++;
parameterStats.bodyParameters++;
const isRequired = (content.schema.required || []).includes(
propName
);
if (isRequired) {
parameterStats.requiredParameters++;
} else {
parameterStats.optionalParameters++;
}
const bodyParam = {
name: propName,
type: prop.type || "string",
format: prop.format || null,
required: isRequired,
description: prop.description || "",
enum: prop.enum || null,
example: prop.example || null,
items: prop.items || null,
properties: prop.properties || null,
};
endpointData.parameters.body.push(bodyParam);
});
}
}
);
}
if (hasParameters) {
parameterStats.endpointsWithParameters++;
}
allEndpoints.push(endpointData);
});
});
// Sort endpoints by path and method
allEndpoints.sort((a, b) => {
if (a.path !== b.path) return a.path.localeCompare(b.path);
return a.method.localeCompare(b.method);
});
// Save complete endpoint data
const outputPath = path.join(process.cwd(), "complete-api-parameters.json");
fs.writeFileSync(outputPath, JSON.stringify(allEndpoints, null, 2));
// Generate parameter statistics report
console.log("📊 PARAMETER EXTRACTION STATISTICS:");
console.log(`Total endpoints: ${parameterStats.totalEndpoints}`);
console.log(
`Endpoints with parameters: ${parameterStats.endpointsWithParameters}`
);
console.log(`Total parameters: ${parameterStats.totalParameters}`);
console.log(`Required parameters: ${parameterStats.requiredParameters}`);
console.log(`Optional parameters: ${parameterStats.optionalParameters}`);
console.log(`Path parameters: ${parameterStats.pathParameters}`);
console.log(`Query parameters: ${parameterStats.queryParameters}`);
console.log(`Body parameters: ${parameterStats.bodyParameters}`);
console.log("");
// Generate authentication type breakdown
const authTypeBreakdown = {};
allEndpoints.forEach((endpoint) => {
let authType = "public";
if (endpoint.security && endpoint.security.length > 0) {
// Determine auth type based on security requirements
const securitySchemes = endpoint.security[0];
if (securitySchemes.sanctum) {
// Determine specific auth type based on path patterns
if (
endpoint.path.includes("/api/emr/") ||
endpoint.path.includes("/emr-api/") ||
endpoint.path.includes("/api/provider/") ||
endpoint.path.includes("/api/practitioners") ||
endpoint.path.includes("/api/appointment") ||
endpoint.path.includes("/api/patient") ||
endpoint.path.includes("/api/forms") ||
endpoint.path.includes("/api/medical-problems") ||
endpoint.path.includes("/api/locations") ||
endpoint.path.includes("/api/tasks") ||
endpoint.path.includes("/api/user") ||
endpoint.path.includes("/api/add-") ||
endpoint.path.includes("/api/get-") ||
endpoint.path.includes("/api/update-") ||
endpoint.path.includes("/api/store-") ||
endpoint.path.includes("/api/save-") ||
endpoint.path.includes("/api/delete-") ||
endpoint.path.includes("/api/assistant/") ||
endpoint.path.includes("/api/token/") ||
endpoint.path.includes("/inventory") ||
endpoint.path.includes("/tags/") ||
endpoint.path.includes("/phone-log")
) {
authType = "provider";
} else if (
endpoint.path.includes("/api/frontend/patient") ||
endpoint.path.includes("/patient/")
) {
authType = "patient";
} else if (endpoint.path.includes("/partner/")) {
authType = "partner";
} else if (endpoint.path.includes("/affiliate/")) {
authType = "affiliate";
} else if (endpoint.path.includes("/network/")) {
authType = "network";
} else {
authType = "provider"; // Default for authenticated endpoints
}
}
}
authTypeBreakdown[authType] = (authTypeBreakdown[authType] || 0) + 1;
});
console.log("🔐 AUTHENTICATION TYPE BREAKDOWN:");
Object.keys(authTypeBreakdown)
.sort()
.forEach((authType) => {
console.log(`${authType}: ${authTypeBreakdown[authType]} endpoints`);
});
console.log("");
console.log(
`✅ Complete API parameter specifications extracted to: ${outputPath}`
);
console.log(`📋 Total endpoints processed: ${allEndpoints.length}`);
return {
endpoints: allEndpoints,
statistics: parameterStats,
authTypeBreakdown,
};
} catch (error) {
console.error("Error extracting API parameters:", error);
throw error;
}
}
// Run the extraction
if (import.meta.url === `file://${process.argv[1]}`) {
extractCompleteAPIParameters();
}
export { extractCompleteAPIParameters };