UNPKG

swagger-auto-generate

Version:

Automatically generate Swagger JSDoc documentation for Express applications

199 lines 6.91 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JSDocGenerator = void 0; class JSDocGenerator { /** * Generate JSDoc comment for a route */ static generateJSDoc(route) { const tags = []; // Add @swagger tag tags.push({ name: 'swagger', description: this.generateSwaggerTag(route), }); // Add @param tags for each parameter for (const param of route.parameters) { tags.push({ name: 'param', description: `${param.in} ${param.name} - ${param.description || param.type}`, type: param.type, optional: !param.required, }); } // Add @returns tag tags.push({ name: 'returns', description: 'Response object', type: 'object', }); const jsdoc = { description: route.description || `Handle ${route.method.toUpperCase()} request to ${route.path}`, tags, }; return this.formatJSDoc(jsdoc); } /** * Generate Swagger tag content */ static generateSwaggerTag(route) { const swaggerObj = { [`/${route.path}`]: { [route.method]: { tags: route.tags || ['api'], summary: route.summary, description: route.description, parameters: route.parameters.map(param => ({ name: param.name, in: param.in, required: param.required, type: param.type, description: param.description, schema: param.schema, })), responses: route.responses.reduce((acc, response) => { acc[response.code] = { description: response.description, schema: response.schema, }; return acc; }, {}), }, }, }; return JSON.stringify(swaggerObj, null, 2); } /** * Format JSDoc comment */ static formatJSDoc(jsdoc) { let result = '/**\n'; // Add description if (jsdoc.description) { result += ` * ${jsdoc.description}\n`; result += ' *\n'; } // Add tags for (const tag of jsdoc.tags) { if (tag.type) { result += ` * @${tag.name} {${tag.type}} ${tag.description}\n`; } else { result += ` * @${tag.name} ${tag.description}\n`; } } result += ' */'; return result; } /** * Generate complete Swagger specification */ static generateSwaggerSpec(routes, config) { const paths = {}; for (const route of routes) { const pathKey = `/${route.path}`; if (!paths[pathKey]) { paths[pathKey] = {}; } paths[pathKey][route.method] = { tags: route.tags || ['api'], summary: route.summary, description: route.description, parameters: route.parameters.map(param => ({ name: param.name, in: param.in, required: param.required, type: param.type, description: param.description, schema: param.schema, })), responses: route.responses.reduce((acc, response) => { acc[response.code] = { description: response.description, schema: response.schema, }; return acc; }, {}), }; } return { swagger: '2.0', info: { title: config.swaggerInfo.title, version: config.swaggerInfo.version, description: config.swaggerInfo.description, host: config.swaggerInfo.host, basePath: config.swaggerInfo.basePath, schemes: config.swaggerInfo.schemes || ['http'], }, paths, definitions: this.generateDefinitions(routes), }; } /** * Generate model definitions */ static generateDefinitions(routes) { const definitions = {}; // Add common response models definitions['SuccessResponse'] = { type: 'object', properties: { success: { type: 'boolean' }, data: { type: 'object' }, message: { type: 'string' }, }, }; definitions['ErrorResponse'] = { type: 'object', properties: { success: { type: 'boolean' }, error: { type: 'string' }, message: { type: 'string' }, }, }; // Extract models from route parameters and responses for (const route of routes) { for (const param of route.parameters) { if (param.schema && param.schema.$ref) { const modelName = param.schema.$ref.replace('#/definitions/', ''); if (!definitions[modelName]) { definitions[modelName] = { type: 'object', properties: {}, }; } } } for (const response of route.responses) { if (response.schema && response.schema.$ref) { const modelName = response.schema.$ref.replace('#/definitions/', ''); if (!definitions[modelName]) { definitions[modelName] = { type: 'object', properties: {}, }; } } } } return definitions; } /** * Inject JSDoc into source code */ static injectJSDoc(sourceCode, route, jsdoc) { const lines = sourceCode.split('\n'); const targetLine = route.lineNumber - 1; // Convert to 0-based index if (targetLine >= 0 && targetLine < lines.length) { // Find the function declaration line const functionLine = lines[targetLine]; // Insert JSDoc before the function lines.splice(targetLine, 0, jsdoc); return lines.join('\n'); } return sourceCode; } } exports.JSDocGenerator = JSDocGenerator; //# sourceMappingURL=jsdocGenerator.js.map