/** * @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 };