97 lines
3.0 KiB
JavaScript
97 lines
3.0 KiB
JavaScript
const swaggerAutogen = require('swagger-autogen')();
|
||
const path = require('path');
|
||
const fs = require('fs');
|
||
|
||
const outputFile = path.join(__dirname, '..', 'docs', 'openapi.json');
|
||
|
||
// Import route mappings (Single Source of Truth - keine Router-Imports!)
|
||
const routeMappings = require('./routes/routeMappings');
|
||
|
||
// Use mappings directly (already has file + prefix)
|
||
const routerMappings = routeMappings;
|
||
|
||
const routesDir = path.join(__dirname, 'routes');
|
||
const endpointsFiles = routerMappings.map(r => path.join(routesDir, r.file));
|
||
|
||
const doc = {
|
||
info: {
|
||
title: 'Project Image Uploader API',
|
||
version: '2.0.1',
|
||
description: 'Auto-generated OpenAPI spec with correct mount prefixes'
|
||
},
|
||
host: 'localhost:5001',
|
||
schemes: ['http'],
|
||
// Add base path hints per router (swagger-autogen doesn't natively support per-file prefixes,
|
||
// so we'll post-process or use @swagger annotations in route files)
|
||
};
|
||
|
||
console.log('Generating OpenAPI spec...');
|
||
|
||
// Generate specs for each router separately with correct basePath
|
||
async function generateWithPrefixes() {
|
||
const allPaths = {};
|
||
const allTags = new Set();
|
||
|
||
for (const mapping of routerMappings) {
|
||
console.log(`<EFBFBD> Processing ${mapping.file} with prefix: "${mapping.prefix || '/'}"...`);
|
||
|
||
const uniqueName = mapping.name || mapping.file.replace('.js', '');
|
||
const tempOutput = path.join(__dirname, '..', 'docs', `.temp-${uniqueName}.json`);
|
||
const routeFile = path.join(routesDir, mapping.file);
|
||
|
||
const tempDoc = {
|
||
...doc,
|
||
basePath: mapping.prefix || '/'
|
||
};
|
||
|
||
await swaggerAutogen(tempOutput, [routeFile], tempDoc);
|
||
|
||
// Read the generated spec
|
||
const tempSpec = JSON.parse(fs.readFileSync(tempOutput, 'utf8'));
|
||
|
||
// Merge paths - prepend prefix to each path
|
||
for (const [routePath, pathObj] of Object.entries(tempSpec.paths || {})) {
|
||
const fullPath = mapping.prefix + routePath;
|
||
allPaths[fullPath] = pathObj;
|
||
|
||
// Collect tags
|
||
Object.values(pathObj).forEach(methodObj => {
|
||
if (methodObj.tags) {
|
||
methodObj.tags.forEach(tag => allTags.add(tag));
|
||
}
|
||
});
|
||
}
|
||
|
||
// Clean up temp file
|
||
fs.unlinkSync(tempOutput);
|
||
}
|
||
|
||
// Write final merged spec
|
||
const finalSpec = {
|
||
openapi: '3.0.0',
|
||
info: doc.info,
|
||
servers: [
|
||
{ url: 'http://localhost:5001', description: 'Development server (dev compose backend)' }
|
||
],
|
||
tags: Array.from(allTags).map(name => ({ name })),
|
||
paths: allPaths
|
||
};
|
||
|
||
fs.writeFileSync(outputFile, JSON.stringify(finalSpec, null, 2));
|
||
|
||
console.log('\n✅ OpenAPI spec generated successfully!');
|
||
console.log(`📊 Total paths: ${Object.keys(allPaths).length}`);
|
||
console.log(`📋 Tags: ${Array.from(allTags).join(', ')}`);
|
||
}
|
||
|
||
// Export for programmatic usage (e.g., from server.js)
|
||
module.exports = generateWithPrefixes;
|
||
|
||
// Run directly when called from CLI
|
||
if (require.main === module) {
|
||
generateWithPrefixes().catch(err => {
|
||
console.error('❌ Failed to generate OpenAPI spec:', err);
|
||
process.exit(1);
|
||
});
|
||
}
|