2

I'm implementing a mutation for uploading photo with type-graphql, and I also want to get another argument like and ID:

  @Mutation(() => GraphQLJSON)
  async userUploadPostPhoto(
    @Arg("photo", () => GraphQLUpload) photo: Upload,
    @Arg("id") id: string,
    @Ctx() context: TContext
  ) {
    return userUploadPostPhoto(photo, context);
  }

This is the methods that I'm trying to test the API in postman:

Screenshot from 2021-09-15 13-10-50

The response I'm getting from the API is this json file:

{
    "errors": [
        {
            "message": "Variable \"$id\" got invalid value { resolve: [function], reject: [function], promise: {} }; String cannot represent a non string value: { resolve: [function], reject: [function], promise: {} }",
            "locations": [
                {
                    "line": 1,
                    "column": 47
                }
            ],
            "extensions": {
                "code": "BAD_USER_INPUT",
                "exception": {
                    "stacktrace": [
                        "GraphQLError: Variable \"$id\" got invalid value { resolve: [function], reject: [function], promise: {} }; String cannot represent a non string value: { resolve: [function], reject: [function], promise: {} }",
                        "    at /home/ebaqeri/Projects/univarsity/server/node_modules/graphql/execution/values.js:116:15",
                        "    at coerceInputValueImpl (/home/ebaqeri/Projects/univarsity/server/node_modules/graphql/utilities/coerceInputValue.js:131:9)",
                        "    at coerceInputValueImpl (/home/ebaqeri/Projects/univarsity/server/node_modules/graphql/utilities/coerceInputValue.js:54:14)",
                        "    at coerceInputValue (/home/ebaqeri/Projects/univarsity/server/node_modules/graphql/utilities/coerceInputValue.js:37:10)",
                        "    at _loop (/home/ebaqeri/Projects/univarsity/server/node_modules/graphql/execution/values.js:109:69)",
                        "    at coerceVariableValues (/home/ebaqeri/Projects/univarsity/server/node_modules/graphql/execution/values.js:121:16)",
                        "    at getVariableValues (/home/ebaqeri/Projects/univarsity/server/node_modules/graphql/execution/values.js:50:19)",
                        "    at buildExecutionContext (/home/ebaqeri/Projects/univarsity/server/node_modules/graphql/execution/execute.js:203:61)",
                        "    at executeImpl (/home/ebaqeri/Projects/univarsity/server/node_modules/graphql/execution/execute.js:101:20)",
                        "    at Object.execute (/home/ebaqeri/Projects/univarsity/server/node_modules/graphql/execution/execute.js:60:35)",
                        "    at execute (/home/ebaqeri/Projects/univarsity/server/node_modules/apollo-server-core/src/requestPipeline.ts:480:20)",
                        "    at Object.processGraphQLRequest (/home/ebaqeri/Projects/univarsity/server/node_modules/apollo-server-core/src/requestPipeline.ts:375:28)",
                        "    at processTicksAndRejections (node:internal/process/task_queues:96:5)",
                        "    at async processHTTPRequest (/home/ebaqeri/Projects/univarsity/server/node_modules/apollo-server-core/src/runHttpQuery.ts:331:24)"
                    ]
                }
            }
        }
    ]
}
`
Anyone has any Idea on this? Is this the problem from the API side or the problem is the method that I'm trying to fix it?

Emad Baqeri
  • 2,333
  • 2
  • 14
  • 29
  • IMHO `map` is/should be used for files only ... `id` should be passed via `variables`, 2nd object encoded into operations – xadm Sep 15 '21 at 10:23
  • can you please give me an example of that? – Emad Baqeri Sep 15 '21 at 10:50
  • https://github.com/jaydenseric/graphql-multipart-request-spec - you should have a variable object encoded already [with file arg nulled] - `operations` should be an array of `query` and `variables` ... as usual in mutations [or queries with args] – xadm Sep 15 '21 at 10:54
  • ```typescript @Mutation(() => GraphQLUpload) async userUploadPostPhoto( @Arg("photo", () => GraphQLUpload) photo: Upload, @Arg("id") id: string, @Ctx() context: TContext ) { return userUploadPostPhoto(photo, id, context); } ``` this is the mutation that I have implemented and this is the map object that I pass to the mutation in form-data method ```json {"0": ["variables.photo"], "1": ["variables.id"]} ``` I think I'm doing the same thing that was mentioned in the link that you have attched – Emad Baqeri Sep 15 '21 at 11:23
  • 1
    rethink it ... https://stackoverflow.com/a/63607130/6124657 – xadm Sep 15 '21 at 12:22

2 Answers2

3

you can try to use Altair

I think this is better than postman here you can see an example of how to Upload a file whit altair

your GraphQL query should looks like this

mutation ($Picture: Upload!)
{
  
  userUploadPostPhoto
  (
    id: 123123123,  
    photo: $Picture,
  )
}
2

I believe you will need to use the variables object to pass the other input, as @xadm mentioned. Using Postman, I tested the following code and it worked:

{
  "query": "mutation userUploadPostPhoto($photo: Upload!, $id: String!) { userUploadPostPhoto(photo: $photo, id: $id) }",
  "variables": { "photo": null, "id": "10" }
}

You can also remove the photo property, since it's not needed.

PS: Please ensure that you have installed graphql-upload and apollo-server-express. Another package(apollo-server) will not accept express as a middleware as an input to a applyMiddleware method.

Sirwan Afifi
  • 10,654
  • 14
  • 63
  • 110