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.42k stars 131 forks source link

No "exports" main defined #348

Closed ahmadxgani closed 1 year ago

ahmadxgani commented 1 year ago

I tried to import GraphQLUpload

import { Stream } from 'stream';
import { GraphQLUpload } from 'graphql-upload';
import {
  Field,
  InputType,
  Int,
  IntersectionType,
  OmitType,
  PickType,
} from '@nestjs/graphql';
interface FileUpload {
  filename: string;
  mimetype: string;
  encoding: string;
  createReadStream: () => Stream;
}
@InputType()
export class CreateAuthorInput {
  @Field()
  username: string;

  @Field()
  email: string;

  @Field()
  password: string;

  @Field(() => GraphQLUpload)
  image: Promise<FileUpload>;
}

but i got this error below

Error: No "exports" main defined in D:\GD Gani\From Github\blog\simple-blog-backend\node_modules\graphql-upload\package.json
    at new NodeError (node:internal/errors:372:5)
    at throwExportsNotFound (node:internal/modules/esm/resolve:472:9)
    at packageExportsResolve (node:internal/modules/esm/resolve:753:3)
    at resolveExports (node:internal/modules/cjs/loader:482:36)
    at Function.Module._findPath (node:internal/modules/cjs/loader:522:31)
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:919:27)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (D:\GD Gani\From Github\blog\simple-blog-backend\src\modules\author\author.input.ts:2:1)

package.json

{
  "name": "nest-blogv2",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "private": true,
  "license": "UNLICENSED",
  "scripts": {
    "prebuild": "rimraf dist",
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "nest start",
    "start:dev": "nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  },
  "dependencies": {
    "@nestjs/apollo": "^10.0.19",
    "@nestjs/common": "^9.0.0",
    "@nestjs/config": "^2.2.0",
    "@nestjs/core": "^9.0.0",
    "@nestjs/graphql": "^10.0.21",
    "@nestjs/jwt": "^9.0.0",
    "@nestjs/passport": "^9.0.0",
    "@nestjs/platform-express": "^9.0.0",
    "@nestjs/typeorm": "^9.0.1",
    "ajv": "^8.11.0",
    "apollo-server-core": "^3.10.1",
    "apollo-server-express": "^3.10.1",
    "bcrypt": "^5.0.1",
    "graphql": "^16.5.0",
    "graphql-tools": "^8.3.3",
    "graphql-upload": "^16.0.2",
    "passport": "^0.6.0",
    "passport-jwt": "^4.0.0",
    "pg": "^8.8.0",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^7.2.0"
  },
  "devDependencies": {
    "@nestjs/cli": "^9.0.0",
    "@nestjs/schematics": "^9.0.0",
    "@nestjs/testing": "^9.0.0",
    "@types/bcrypt": "^5.0.0",
    "@types/express": "^4.17.13",
    "@types/graphql-upload": "^8.0.12",
    "@types/jest": "28.1.4",
    "@types/node": "^16.0.0",
    "@types/passport-jwt": "^3.0.6",
    "@types/supertest": "^2.0.11",
    "@typescript-eslint/eslint-plugin": "^5.0.0",
    "@typescript-eslint/parser": "^5.0.0",
    "eslint": "^8.0.1",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-prettier": "^4.0.0",
    "jest": "28.1.2",
    "prettier": "^2.3.2",
    "source-map-support": "^0.5.20",
    "supertest": "^6.1.3",
    "ts-jest": "28.0.5",
    "ts-loader": "^9.2.3",
    "ts-node": "^10.0.0",
    "tsconfig-paths": "4.0.0",
    "typescript": "^4.3.5"
  },
  "jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "collectCoverageFrom": [
      "**/*.(t|j)s"
    ],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  }
}

how to solve this problem ?

jaydenseric commented 1 year ago

There are a lot of old issues that would have answered this question.

import GraphQLUpload from "graphql-upload/GraphQLUpload.mjs";
import type { FileUpload } from "graphql-upload/processRequest.mjs";

Be sure to configure TypeScript according to the requirements:

https://github.com/jaydenseric/graphql-upload/tree/v16.0.2#requirements

ahmadxgani commented 1 year ago

thanks for the feedback, i have configured my typescript configuration below

{
  "compilerOptions": {
    "module": "NodeNext",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "allowJs": true,
    "target": "es2017",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "strictBindCallApply": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "maxNodeModuleJsDepth": 10
  }
}

but it is still throw an error: image

jaydenseric commented 1 year ago

The error is correct; you are incorrectly attempting to import an ESM module from with a CJS module (the .ts file).

You can learn about ESM in TypeScript and Node.js here:

ahmadxgani commented 1 year ago

I tried to add dynamic import inside @Field decorator, but it doesn't seem to support async inside the decorator, how can i fix it?

@Field(async () => (await import('graphql-upload/GraphQLUpload.mjs')).default)
image: Promise<FileUpload>;
Error: Cannot determine a GraphQL input type null for the "image". Make sure your class is decorated with an appropriate decorator.
    at InputTypeFactory.create (D:\GD Gani\From Github\blog\simple-blog-backend\node_modules\@nestjs\graphql\dist\schema-builder\factories\input-type.factory.js:19:23)
    at D:\GD Gani\From Github\blog\simple-blog-backend\node_modules\@nestjs\graphql\dist\schema-builder\factories\input-type-definition.factory.js:48:52
    at Array.forEach (<anonymous>)
    at D:\GD Gani\From Github\blog\simple-blog-backend\node_modules\@nestjs\graphql\dist\schema-builder\factories\input-type-definition.factory.js:46:33
    at resolveObjMapThunk (D:\GD Gani\From Github\blog\simple-blog-backend\node_modules\graphql\type\definition.js:504:40)
    at defineInputFieldMap (D:\GD Gani\From Github\blog\simple-blog-backend\node_modules\graphql\type\definition.js:1313:20)
    at GraphQLInputObjectType.getFields (D:\GD Gani\From Github\blog\simple-blog-backend\node_modules\graphql\type\definition.js:1276:27)
    at collectReferencedTypes (D:\GD Gani\From Github\blog\simple-blog-backend\node_modules\graphql\type\schema.js:395:51)
    at collectReferencedTypes (D:\GD Gani\From Github\blog\simple-blog-backend\node_modules\graphql\type\schema.js:391:11)
    at new GraphQLSchema (D:\GD Gani\From Github\blog\simple-blog-backend\node_modules\graphql\type\schema.js:183:7)