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 #922

Closed
wants to merge 2 commits into from

Conversation

mdmower-csnw
Copy link
Contributor

@mdmower-csnw mdmower-csnw commented May 29, 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...

Usage example

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": {

Copy link
Owner

@cdimascio cdimascio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks

@cdimascio
Copy link
Owner

#921 is now merged. please resolve conflicts and will get this in as well

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

Because this project uses moduleResolution:node in tsconfig, it's not
possible to write async import(...) directly in code. It has to be
obscured so that the compiler does not replace it, hence the HACK!
function that is essentially eval('import(...)').

ESM users should be aware that a file extension must be specified when
defining x-eov-operation-handler in schemas. For example:

```
{
  "get": {
    "summary": "Get list",
    "x-eov-operation-id": "getList",
    "x-eov-operation-handler": "list.js",
    "responses": {
       ...
```
- Restore original "baseName" variable name
- Make sure string path handling is exactly the same as prior to URL
  handling was added
@mdmower-csnw mdmower-csnw marked this pull request as ready for review June 2, 2024 18:51
@mdmower-csnw
Copy link
Contributor Author

Usage instructions could be incorporated into https://github.com/cdimascio/express-openapi-validator/tree/master/examples/5-custom-operation-resolver, but maybe the name should change to 5-operation-resolvers with two sections: esm tips and custom resolvers? Then the link in the documentation on operation handlers would need to be updated as well. Let me know how I can help.

zeiglerd added a commit to zeiglerd/pidwin-fs-take-home-project that referenced this pull request Jul 20, 2024
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