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

Support ESM import of handler module in default resolver #982

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

cvchauhan
Copy link
Contributor

@cvchauhan cvchauhan commented Sep 14, 2024

Make the default request handler resolver work in ESM projects by allowing a URL value for options.operationHandlers. If a URL is passed, then a dynamic import will be used to load handler modules. If a string is passed, then require() will be used.

Existing projects should not be adversely affected by this change. The assignment of a URL value to options.operationHandlers would be the indicator that a user wants to opt-in to this new import handling.

Fixes #660
Fixes #838

Notice
Because this project uses moduleResolution:node in tsconfig.json, it's not possible to write async import(...) directly in code. It has to be obscured so that the compiler does not replace it with require(). Hence, there is a very obvious HACK! in this PR that obscures import() via Function('x', 'return import(x)') (it's very similar to eval('import(...)')).

This hack will probably sink this PR, but I figured I'd post it at least as a proof of concept. Ideally, the module resolution for tsconfig would be updated to Node16, but that brings its own issues since resolveJsonModule:true would no longer work. Fix one issue, introduce another...

import {fileURLToPath, pathToFileURL} from 'node:url';
import path from 'node:path';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const handlersPath = path.join(__dirname, '../path/to/my-routes');

const eov = OpenApiValidator.middleware({
  operationHandlers: pathToFileURL(handlersPath),
  // <rest of configuration>
});
app.use(eov);

When defining x-eov-operation-handler in schemas, include the file extension on the module name. For example:

{
  "get": {
    "summary": "Get thing",
    "x-eov-operation-id": "getThing",
    "x-eov-operation-handler": "things.js", // <-- include file extension
    "responses": {

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