graphql-mesh: CLI generates code with invalid imports on Windows

Describe the bug

Running mesh build generates JS code with invalid require paths on Windows. I tried to generate client code for MS Graph and run a script using the generated code. This throws an error the following error: Error: Cannot find module './sourcesMicrosoft Graphmetadata.json.js'. As you can see the path to the metadata is invalid, it should actually be ./sources/Microsoft Graph/metadata.json.js. But it seems the path separates have somehow been lost.

To Reproduce Steps to reproduce the behavior:

  • Clone the repo, navigate to the examples-odata-msgraph-programmatic sample
  • Run yarn start or npm start
  • You will get an error like:
Error: Cannot find module './sourcesMicrosoft Graphmetadata.json.js'
Require stack:
- <redacted>\graphql-mesh\examples\odata-msgraph-programmatic\.mesh\index.js
- <redacted>\graphql-mesh\examples\odata-msgraph-programmatic\index.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)
    at Function.Module._load (internal/modules/cjs/loader.js:746:27)
    at Module.require (internal/modules/cjs/loader.js:974:19)
    at require (internal/modules/cjs/helpers.js:92:18)
    at Object.<anonymous> (<redacted>\graphql-mesh\examples\odata-msgraph-programmatic\.mesh\index.js:3572:74)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:14)
    at Module.require (internal/modules/cjs/loader.js:974:19) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '<redacted>\\graphql-mesh\\examples\\odata-msgraph-programmatic\\.mesh\\index.js',
    '<redacted>\\graphql-mesh\\examples\\odata-msgraph-programmatic\\index.js'
  ]
}

Further, if you open the generated JS module in .mesh/index.js and search for “Microsoft Graph”, you will see the following statement (in my case it’s on line 3572):

const sourcesMicrosoft_Graphmetadata_json_js_1 = tslib_1.__importDefault(require("./sourcesMicrosoft Graphmetadata.json.js"));

Notice the call:

require("./sourcesMicrosoft Graphmetadata.json.js")

Expected behavior

The generated code should not have import errors. The correct require call should look like:

require("./sources/Microsoft Graph/metadata.json.js")

Environment:

  • OS: Windows 10
  • @graphql-mesh/cli: 0.34.3
  • NodeJS: 14.7.3

Additional context

I investigated this issue and found that it’s related to Windows paths using backslash as the separator. The error seems to result from the generateTsArtifacts function in the packages/cli/src/commands/ts-artifacts.ts module. The path to the metadata.json.js file is among the imported modules in the generated TS code (see the importCodes variable) that will be passed to the ts compiler. When the path is a Windows-style path, it leads to the following import statement in the TS code:

"import ExternalModule_3 from './sources\\Microsoft Graph\\metadata.json.js';"

I’m not sure at which point the backslashes are removed, probably by the ts compiler.

I’ve found that if you change the importPath to a posix path, then you get the expected results, something like this:

const importedModulesCodes: string[] = [...importedModulesSet].map((importedModuleName, i) => {
  let moduleMapProp = importedModuleName;
  let importPath = importedModuleName;
  if (importPath.startsWith('.')) {
    importPath = join(baseDir, importPath);
  }
  if (isAbsolute(importPath)) {
    moduleMapProp = relative(baseDir, importedModuleName);
    importPath = `./${relative(artifactsDir, importedModuleName)}`;
  }

+ if (path.sep === path.win32.sep) {
+   importPath = importPath.replace(new RegExp(`\\${path.sep}`, 'g'), path.posix.sep);
+ }
  const importedModuleVariable = pascalCase(`ExternalModule$${i}`);
  importCodes.push(`import ${importedModuleVariable} from '${importPath}';`);
  return `  // @ts-ignore\n  [\`${moduleMapProp}\`]: ${importedModuleVariable}`;
});

Not sure if that’s the most desirable solution, or whether that’s the ideal place to make the code changes. But that seems to fix the issue.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 22 (11 by maintainers)

Most upvoted comments

Not sure how your setup looks like but we use /graphql not /graphql as endpoint and GraphiQL is disabled in production mesh start command which can be enabled with

serve:
    playground:true

Cool! Let’s close this issue then. We can always reopen it later

@ardatan it works well for me now. Even the cannot read property 'Edmx' of undefined error seems to be gone now. My script is able to make queries to MS Graph.

@ardatan Yeah, so my coworker just told me that npm might not get updated through our proxy for 24 hrs. I’ll test this right when it comes through. Thanks for all the help and responsiveness on this!

https://github.com/Urigo/graphql-mesh/runs/3377639976 You can track the publish progress here 😃

@Davenporten In my case the code gets generated correctly, I also get an undefined-related error when I try to run my script based on the generated code:

TypeError: Cannot read property 'Edmx' of undefined
    at ODataHandler.getMeshSource (...\node_modules\@graphql-mesh\odata\index.js:128:38)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at async ...\node_modules\@graphql-mesh\runtime\index.js:82:24
    at async Promise.all (index 0)
    at async Object.getMesh (...\node_modules\@graphql-mesh\runtime\index.js:78:5)
    at async start (...\index.js:6:20)

I’m not sure if this is related to your issue. But after investigating, in my case it’s based on a bug in the cache proxy used by GraphQl-Mesh. Specifically the proxy.getWithSet() method which is supposed to fetch the OData schema and cache it. However, it does not store the fetched schema and returns an unefined value instead. I will create a separate issue for this.