Swagger Auto Gen with custom routing

377 Views Asked by At

So I am trying to generate a basic documentation for my routing now the routes are not your normal expressjs routes like router.get etc.

My issue is the swagger autogen is not seeing any routes and not making anything on it.

Here is a sample for them

const express = require('express')
const fs = require('fs')
const path = require('path')
const isAuthenticated = require('../../middlewares/authMiddleware')
const isAdmin = require('../../middlewares/isAdmin')
const { hasPermission } = require('../../controllers/permissions')

const router = express.Router()

/**
 * The function recursively loads routes from a directory and adds them to a router object.
 * @param directory - The directory path where the routes are located.
 * @param [currentPath] - The current path is a string representing the current directory path being
 * traversed by the function. It is used to construct the endpoint URL for each route based on the
 * directory structure. If not provided, it defaults to an empty string.
 */
function loadRoutes(directory, currentPath = '') {
    fs.readdirSync(directory, { withFileTypes: true }).forEach((dirent) => {
        const fullPath = path.join(directory, dirent.name)
        if (dirent.isDirectory()) {
            loadRoutes(fullPath, path.join(currentPath, dirent.name))
        } else if (dirent.isFile() && !(currentPath === '' && dirent.name === 'index.js')) {
            const route = require(fullPath)
            console.log(`Loading route: ${route.metadata.method} ${path.join(currentPath, path.parse(dirent.name).name)}`)
            const endpoint = route.metadata.url || path.join(currentPath, path.parse(dirent.name).name)
            const middlewares = route.metadata?.middlewares || []
            if (route.metadata.requiresAuth) {
                if (router[route.metadata.method.toLowerCase()]) {
                    router[route.metadata.method.toLowerCase()](endpoint, isAuthenticated, ...middlewares, route.handler)
                }
            } else if (route.metadata.requiresPermission && route.metadata.requiresAuth) {
                if (hasPermission(route.metadata.permissions)) {
                    if (router[route.metadata.method.toLowerCase()]) {
                        router[route.metadata.method.toLowerCase()](endpoint, isAuthenticated, isAdmin, ...middlewares, route.handler)
                    }
                }
            } else {
                if (router[route.metadata.method.toLowerCase()]) {
                    router[route.metadata.method.toLowerCase()](endpoint, ...middlewares, route.handler)
                }
            }
        }
    })
}

loadRoutes(__dirname)

module.exports = router

This is my handler which loads in the routes that are in multiple sub-sub folders for organizing the routes and here is a sample route

const { PERMISSIONS_MAP } = require('../../../controllers/permissions')
const responseHandler = require('../../../modules/responseHandler')

const database = require('../../../config/database')

const {
    Products,
} = database.models

module.exports = {
    metadata: {
        method: 'GET',
        url: '/products/get',
        version: '1.0.0',
        requiresAuth: false,
        permissions: [],
        requiresPermission: false,
        middlewares: []
    },
    handler: async (req, res, next) => {
        responseHandler(req, res, 200, { products: [] }, null, 'Products retrieved successfully')
    }
}

And here is my swagger gen script Yes it is copied from the documentation

const swaggerAutogen = require('swagger-autogen')()


const doc = {
    info: {
        version: "1.0.0",
        title: "My API",
        description: "Documentation automatically generated by the <b>swagger-autogen</b> module."
    },
    host: "localhost:3000",
    basePath: "/",
    schemes: ['http', 'https'],
    consumes: ['application/json'],
    produces: ['application/json'],
    tags: [
        {
            "name": "User",
            "description": "Endpoints"
        }
    ],
    securityDefinitions: {
        apiKeyAuth: {
            type: "apiKey",
            in: "header",       // can be "header", "query" or "cookie"
            name: "X-API-KEY",  // name of the header, query parameter or cookie
            description: "any description..."
        }
    },
    definitions: {
        Parents: {
            father: "Simon Doe",
            mother: "Marie Doe"
        },
        User: {
            name: "Jhon Doe",
            age: 29,
            parents: {
                $ref: '#/definitions/Parents'
            },
            diplomas: [
                {
                    school: "XYZ University",
                    year: 2020,
                    completed: true,
                    internship: {
                        hours: 290,
                        location: "XYZ Company"
                    }
                }
            ]
        },
        AddUser: {
            $name: "Jhon Doe",
            $age: 29,
            about: ""
        }
    }
}

const outputFile = './swagger-output.json'
const endpointsFiles = ['./src/routes/v1/index.js']

swaggerAutogen(outputFile, endpointsFiles, doc).then(() => {
    require('./app.js')           // Your project's root file
})
0

There are 0 best solutions below