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 as operation handlers #660

Open
mahnunchik opened this issue Sep 13, 2021 · 4 comments
Open

Support ESM as operation handlers #660

mahnunchik opened this issue Sep 13, 2021 · 4 comments
Labels
enhancement New feature or request

Comments

@mahnunchik
Copy link

Is your feature request related to a problem? Please describe.

It would be helpfull to support ECMAScript modules as operation handlers.

export default {
  // the express handler implementation for ping
  ping: (req, res) => res.status(200).send('pong'),
};

Describe the solution you'd like

operationHandlers: import.meta.url

Describe alternatives you've considered

#575

@cdimascio cdimascio added the enhancement New feature or request label Sep 23, 2021
@mahnunchik
Copy link
Author

Hi @cdimascio

There is one of pretty simple implementation: https://github.com/CoinSpace/CoinSpace/blob/fd5c229ce60b67bcf88a342209931efb1cf87b93/server/lib/esmresolver.js

@cdimascio
Copy link
Owner

@mahnunchik thanks for the example. it looks reasonable. to help move this along, would you be up for preparing this as a PR.

@ViniGodoy
Copy link

ViniGodoy commented Jun 13, 2022

I've tested @mahnunchik but it does not work for a function array. In order for this to work, the resolver usage should preview the possibility of a Promise. I've tried by modifying openapivalidator.js from:

router[method.toLowerCase()](path, resolver(basePath, route, context.apiDoc));

to:

Promise.resolve(resolver(basePath, route, context.apiDoc)).then(r => {
     router[method.toLowerCase()](path, r);
});

Then changing @mahnunchik code to:

handlersCache[cacheKey] = import(modulePath).then(module => {
    if (!module[oId]) {
          // eslint-disable-next-line max-len
          throw Error(`Could not find 'x-eov-operation-handler' with id ${oId} in module '${baseName}'. Make sure operation '${oId}' defined in your API spec exists as a handler function in '${baseName}'.`);
        }
        return module[oId];
      }
).catch(next);

And finally just returning handlersCache[cacheKey] in the resolver function. Although it take a little extra time for the routes to work in the server, it allowed me to use an array with middlewares, just like I was already used to.

@ViniGodoy
Copy link

Just came back to say that I discovered that @mahnunchik implementation fails on Windows. In order to fix it, just add a "file://" in the import at line 24:

const modulePath = "file://" + path.join(handlersPath, `${baseName}.mjs`);
cache[cacheKey] = import(modulePath);

But the library should really support this properly, considering async imports properly.

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

No branches or pull requests

3 participants