graphql-upload: Cannot load v16.0.1

In a TS project using graphql-upload v16.0.1, when I npm run dev:

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in node_modules/graphql-upload/package.json

Setup:

    "@types/graphql-upload": "^8.0.11",
    "graphql-upload": "^16.0.1",

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 6
  • Comments: 19 (7 by maintainers)

Most upvoted comments

Me changing the graphql-upload API to named imports from a main index module or keeping it the current way with default deep imports for optimal JavaScript module design won’t make a difference for Nest.js users; their issue (apparently, I don’t use Nest.js) is that they don’t support importing from standard ESM modules at all, which graphql-upload is now. I’m not going to regress back to CJS format, graphql-upload will always be standard ESM moving forwards.

Is there a way that you could publish it, so that us nest.js developers can benefit from your great package?

No, Nest.js should fix Nest.js bugs or else users will have to abandon it as it will no longer be fit for purpose as many important npm packages are being published in standard ESM format.

Regarding all those articles/tutorials, they are years old and it’s not reasonable to expect their code examples to still work the same. I’ve published new versions of graphql-upload since they were written. The source of truth is the graphql-upload readme and what is actually published to npm.

I don’t know why you closed this issue but I got the same error. I removed the type and node module. installed again. now I get this error: Cannot find module 'graphql-upload' or its corresponding type declarations.

Your issues likely relate to Nest.js knowingly not supporting importing ESM modules, please raise more issues in their repo since they immediately closed and locked this one last year:

https://github.com/nestjs/nest/issues/7021#issuecomment-831799620

It’s up to them to support their users, not me. The format of my package is perfectly valid.

It’s a bad idea to get locked into frameworks, instead use libraries to compose your own systems that you understand and have control over. Learn how the runtime environment actually works instead of hiding behind multiple layers of build tools and “magic”. Why anyone would choose to use a framework that is incapable of working with the standard JavaScript module format (ESM) is beyond me!

If you don’t fix this in your projects, you will run into problems trying to use any of the growing number of packages that are published as ESM. I’m not being unreasonable here; graphql itself will be pure ESM in v17:

https://github.com/graphql/graphql-js/releases/tag/v17.0.0-alpha.1

If anyone is struggling with this, I found a solution for this: within some async function just call

const { default: graphqlUploadExpress } = await (eval(
    `import('graphql-upload/graphqlUploadExpress.mjs')`,
  ) as Promise<typeof import('graphql-upload/graphqlUploadExpress.mjs')>);

Well, sorry for the duplicates but I saw some issues here talking about files .js, I guess for v14/15, here it’s .mjs. Liked you said, I removed @types/graphql. I followed your example:

import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';

console.log(graphqlUploadExpress); // undefined

then in my nestjs resolver

import GraphQLUpload from 'graphql-upload/GraphQLUpload.mjs';

// Did you remove the ts type FileUpload? Lets try GraphQLUpload then
  async uploadFile(
    // ...
    @GqlArgs('file', { type: () => GraphQLUpload }) { createReadStream, filename, mimetype }: GraphQLUpload,
  ) {

Error: Must use import to load ES Module: node_modules/graphql-upload/GraphQLUpload.mjs

I’m quite lost.

This problem I faced within my NestJS project has been effectively resolved. To tackle this issue, I implemented the subsequent modifications:

Initially, I imported the required modules by employing the following syntax: import * as graphqlUploadExpress from ‘graphql-upload/graphqlUploadExpress’; import * as GraphQLUpload from ‘graphql-upload/GraphQLUpload’;

It is noteworthy that in version 16 of graphql-upload, the presence of index.js has been deprecated. This change in module structure appears to be the root cause of the encountered error. If the previously mentioned resolution method does not yield successful results, an alternative approach would be to revert to graphql-upload version 13.

When examining the available package versions in the npm repository, I observed that version 16 possesses the least number of downloads. In contrast, versions 13 and 11 appear to be more commonly adopted by the community. Therefore, considering these alternative versions could prove beneficial if further difficulties persist.

Screenshot from 2023-08-11 10-34-25

@bnussman I am using the latest version of graphql-upload at work in a Node.js + TypeScript project just fine. Your frustration most likely is not with optimal module design, the principals of which can be applied to CJS modules as well as ESM modules. It’s probably with the fact that this package is published in standard ESM format. You need to update your tooling to use standard ESM dependencies correctly, or you will start shaking your fists in impotent rage at more and more packages. The new version of Babel is to be pure ESM. Most of Sindre Sorhus’s are pure ESM. All the Remark ecosystem is pure ESM.

@jaydenseric Can you stop acting like you didn’t royally mess up this package for most consumers?

We are all people who use Node + Typescript and you ruined this packaged by using what you call “optimal JavaScript module design”. Nothing about what you’ve done is “optimal” if you keep getting Github issues about the same error.

I don’t know what build tooling you have setup (I don’t use Nest.js), but it sounds like it is transpiling the ESM module into a CJS module, then running that which is problematic because it’s a limitation of Node.js that a CJS module can’t require an ESM module. This stuff is beyond the scope of graphql-upload; it’s just how ESM and Node.js works in general.

Regarding the TypeScript type FileUpload, you can import it like this:

// Within a TypeScript module.
import type { FileUpload } from "graphql-upload/processRequest.mjs";
// Within a JavaScript module.
/** @type {import("graphql-upload/processRequest.mjs").FileUpload} */

Note that it might not be the same as whatever the type of the same name from @types/graphql-upload was.

I’ve been working on a few updates to the readme to make some things clearer like how to import the type FileUpload.

Also, uninstall @types/graphql-upload as graphql-upload ships it’s own types now.