jaydenseric / graphql-upload

Middleware and an Upload scalar to add support for GraphQL multipart requests (file uploads via queries and mutations) to various Node.js GraphQL servers.
https://npm.im/graphql-upload
MIT License
1.43k stars 131 forks source link

Cannot load v16.0.1 #332

Closed vincentwinkel closed 2 years ago

vincentwinkel commented 2 years ago

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",
jaydenseric commented 2 years ago

This duplicates a lot of other issues. Please see the changelog or GitHub release descriptions for the breaking changes in the past few major versions. Pay particular attention to the migration instructions for imports.

jaydenseric commented 2 years ago

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

vincentwinkel commented 2 years ago

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.

jaydenseric commented 2 years ago

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.

Javadebi commented 2 years ago

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.

is-jaduda commented 2 years ago

@vincentwinkel I have same issue.

jaydenseric commented 2 years ago

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

is-jaduda commented 2 years ago

Well, I am not using nestjs.

jaydenseric commented 2 years ago

@is-jaduda then you don't have the exact same issue as the comment you were referring too. Lots of different project setups can result in the same error message.

simplenotezy commented 1 year ago

@jaydenseric Are you aware of any workarounds to this? Is there a way that you could publish it, so that us nest.js developers can benefit from your great package?

We depend on a lot of open-source projects, and usually just import like this:

image

It's also interesting how there are many articles referencing your library, and they seem to work just fine with Nest.js:

They just don't anymore 🙁 (basically how you did it in version 13) - it seems to break from version 14 upwards.

jaydenseric commented 1 year ago

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.

simplenotezy commented 1 year ago

No worries, I'll find another approach. Thanks for your time.

quimgv commented 1 year ago

Did you find another approach @simplenotezy ? It would be helpful to have it here if you did :)

simplenotezy commented 1 year ago

Hey! Ended up using a standard REST API endpoint for the upload

quimgv commented 1 year ago

Nice! Thanks for replying :)

Can you have the upload field within the Input Type with the other fields of a form, or that way you are always forced to upload a file alone?

zuffik commented 1 year ago

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')>);
jaydenseric commented 1 year ago

@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.

ahmedshahd commented 1 year ago

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

leandroluk commented 1 month ago

Holly jesus... Why don't use typescript like any other library?

jaydenseric commented 4 weeks ago

@leandroluk

Why don't use typescript

This project does use TypeScript, see how tsc is used to check the types:

https://github.com/jaydenseric/graphql-upload/blob/f24d71bfe5be343e65d084d23073c3686a7f4d18/package.json#L89

At work I use graphql-upload in a TypeScript codebase perfectly fine; full type safety.

As to why all my open source packages are published with baked in TypeScript types via JSDoc comments, instead of seperate type definition files, see:

https://github.com/jaydenseric/apollo-upload-client/issues/338#issuecomment-2041348730