Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error in Custom Operation Resolver #575

Open
linqFR opened this issue Apr 12, 2021 · 1 comment
Open

Error in Custom Operation Resolver #575

linqFR opened this issue Apr 12, 2021 · 1 comment

Comments

@linqFR
Copy link

linqFR commented Apr 12, 2021

Describe the bug
In the example given for custom operation resolver, we can read:

new OpenApiValidator({
  apiSpec,
  operationHandlers: {
    basePath: path.join(__dirname, 'routes'),
    resolver: (basePath, route) => {
      // Pluck controller and function names from operationId
      const [controllerName, functionName] = route.schema['operationId'].split('.')
      // Get path to module and attempt to require it
      const modulePath = path.join(basePath, controllerName);
      const handler = require(modulePath)
      // Simplistic error checking to make sure the function actually exists
      // on the handler module
      if (handler[functionName] === undefined) {
        throw new Error(
          `Could not find a [${functionName}] function in ${modulePath} when trying to route [${route.method} ${route.expressRoute}].`
        )
      }
      // Finally return our function
      return handler[functionName]
    }
});

So route is supposed to have a schema property.
We can only access:

{
  basePath: "..."
  expressRoute: "..."
  method: "GET"
  openApiRoute: "..."
  pathParams: []
}

Instead resolver has 3 arguments : basePath (which is the baseDirectory, not route.basePath), route AND apiDoc !

The example should mention apiDoc instead of route.schema.

@andyvanee
Copy link

andyvanee commented Jun 9, 2021

Yeah, I came across this issue as well and it should be noted that apiDoc is the full schema, not just the schema for this route. It wasn't exactly trivial to get the schema for the current route but I was able to get it. Below is the resolver I put together for async ESM modules. Hopefully this can help someone encountering the same issue!

import path from "path"

const esmresolver = basePath => {
    return {
        basePath,
        resolver: (basePath, route, apiDoc) => {
            const pathKey = route.openApiRoute.substring(route.basePath.length)
            const schema = apiDoc.paths[pathKey][route.method.toLowerCase()]

            // x-eov-operation-id takes priority over operationId
            const fn = schema["x-eov-operation-id"] || schema["operationId"]

            // x-eov-operation-handler with fallback to routes.js
            const handler = schema["x-eov-operation-handler"] || "routes"

            const handlerFile = `${handler}.js`
            const modP = import(path.join(basePath, handlerFile))

            return async (req, res, next) => {
                try {
                    const mod = await modP
                    mod[fn](req, res)
                } catch (err) {
                    console.error(err)
                    next(new Error(`Routing error ${handlerFile}:${fn}`))
                }
            }
        }
    }
}

export default esmresolver

This can be used like this:

app.use(
    OpenApiValidator.middleware({
        apiSpec,
        validateResponses: true,
        operationHandlers: esmresolver(modulePath)
    })
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants