1
votes

I need help figuring out the GraphQL tag for use with Apollo Client. The Docs don't go far beyond the most basic use case for mutations.

My goal is to have the only required input be an email. If the other variables are present, I would like those to be accepted and create a proposal with all that information.

I have the mutation (in both only email and full variables scenarios) working successfully on the GraphQl Playground (if it helps, you can find it here and test it out, look at the schema, etc.,): https://prisma2-graphql-yoga-shield.now.sh/playground)

mutation {
  createOneProposal(
    data: {
      email: "[email protected]"
      name: "Sean"
      types: {
        create: {
          model: PURCHASE
          name: "e-commerce"
          cost: 600
          services: {
            create: [
              { service: "Responsive web design" }
              { service: "Another service!" }
              { service: "And yet another service!" }
            ]
          }
        }
      }
    }
  ) {
    created_at
    proposal_id
    types {
      cost
      model
      name
      type_id
      services {
        service
        service_id
      }
    }
  }
}

Producing as a result:

{
  "data": {
    "createOneProposal": {
      "created_at": "2020-02-27T21:28:53.256Z",
      "proposal_id": 35,
      "types": [
        {
          "cost": 600,
          "model": "PURCHASE",
          "name": "e-commerce",
          "type_id": 6,
          "services": [
            {
              "service": "Responsive web design",
              "service_id": 10
            },
            {
              "service": "Another service!",
              "service_id": 11
            },
            {
              "service": "And yet another service!",
              "service_id": 12
            }
          ]
        }
      ]
    }
  }
}

My initial design for the gql tag:

export const NEW_PROPOSAL = gql`
  mutation createOneProposal(
    $email: String!
    $name: String
    $cost: Int
    $model: Model
    $service: Service
  ) {
    createOneProposal(
      email: $email
      name: $name
      cost: $cost
      model: $model
      service: $service
    ) {
      created_at
      proposal_id
      types {
        services {
          service_id
        }
      }
    }
  }
`;

But, I get a lot of errors with this.

{"errors":[
{"Variable "$service" cannot be non-input type `"Service`".","locations":[{"line":1,"column":97}]},
{"Unknown argument "email" on field "createOneProposal`" of type "Mutation`".","locations":[{"line":2,"column":21}]},
{"Unknown argument "name" on field "createOneProposal`" of type "Mutation`".","locations":[{"line":2,"column":36}]},
{"Unknown argument"cost" on field "createOneProposal\" of type "Mutation`".","locations":[{"line":2,"column":49}]},
{"Unknown argument "model" on field "createOneProposal`" of type "Mutation`".","locations":[{"line":2,"column":62}]},
{"Unknown argument "service" on field "createOneProposal`" of type "Mutation`".","locations":[{"line":2,"column":77}]},
{"Field "createOneProposal" argument "data" of type "ProposalCreateInput!`" is required, but it was not provided.","locations":[{"line":2,"column":3}]}]}

So, how can I go about this... I figured out the query version (much easier...), but I just can't figure this out!

My schema, if it helps:

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mysql"
  url      = env("MYSQL_URL_PRISMA2")
}

model Post {
  content      String    @default("")
  created_at   DateTime  @default(now())
  post_id      Int       @default(autoincrement()) @id
  published    Boolean   @default(false)
  published_at DateTime?
  title        String    @default("")
  author       User
}

model Profile {
  bio        String?
  profile_id Int     @default(autoincrement()) @id
  user_id    User
}

model Proposal {
  email       String   @unique
  name        String?
  proposal_id Int      @default(autoincrement()) @id
  created_at  DateTime @default(now())
  types       Type[]
}

model Type {
  cost        Int?
  name        String?
  model       Model?    @default(SUBSCRIPTION)
  services    Service[]
  type_id     Int       @default(autoincrement()) @id
  proposal_id Proposal
}

model Service {
  service_id Int     @default(autoincrement()) @id
  service    String?
  type_id    Type
}

model User {
  email    String    @default("") @unique
  name     String    @default("")
  password String    @default("")
  role     Role      @default(USER)
  user_id  Int       @default(autoincrement()) @id
  posts    Post[]
  profiles Profile[]
}

enum Role {
  USER ADMIN
}

enum Model {
  SUBSCRIPTION PURCHASE CUSTOM
}
2
missing data in mutation ... service is not defined in ProposalCreateInput type ... types are required ... why you're trying to define/pass COMPLETELY different structure than working one??xadm
@xadm Hi! It's not my intention to try and pass completely different structures... where would I pass the data field within the graphql-tag? That's confusing me a lot. service is defined within Services type. I'll add my schema if that helps!realhat
schema is one, generated by yoga is other ... explore docs in playground ... copy structure from 1st snippet ... createOneProposal( data: { email: $email name: $name types: ... ... into middle section of gqlxadm
Okay, will do, thanks @xadm! I'll update with an answer once I've got it working. Thanks again!realhat

2 Answers

0
votes

GraphQL types are categorized as either input types or output types. Input types are used for inputs like variable definitions or argument definitions. Output types are used for typing fields, which are what compose the actual response. Certain types, like scalars and enums, can be used as either an input or an output. However, with objects, there are output object types (sometimes referred to just object types or objects) and input object types.

Service is an output type, so it can't be used where an input type is expected (in this case, a variable definition). Examine the schema generated by Prisma to determine the appropriate type to use.

0
votes

Thanks to some very needed direction from @xadm, I figured out the structure of the tag! For anyone who comes across this in the future:

mutation createOneProposal($input: ProposalCreateInput!){
    createOneProposal(data:$input){
        created_at
    name
    email
    proposal_id
    type{
      cost
      description
      model
      name
      type_id
      services{
        service
        cost
        service_id
      }
    }
      }
    }