virtual98
virtual98

Reputation: 79

Prisma: Field ... is not defined in ... input type OR type ... expected but non object was submitted

I'm using Prisma 1.34. fro API development. Testing it through the localhost playground. Sorry for long text in advance, can't understand where I went wrong.

I have the following scheme representing hierarchy Script template consist of the Cards templates, and Cards include Tasks templates:

type ScriptTemplate {
  id: ID! 
  name: String!
  cards: [CardTemplate!]
  input: String!
  output: String!
}

type CardTemplate {
  id: ID!
  title: String!
  description: String
  tasks: [TaskTemplate!]
}

input ExistingCardTemplateInput {
  id: ID!
}

input NewCardTemplateInput {
  title: String!
  description: String!
  tasks: [NewTaskTemplateInput!]
}

type TaskTemplate {
  id: ID!
  label: String!
  description: String!
  cards: [CardTemplate!]
}

input ExistingTaskTemplateInput {
  id: ID!
}

input NewTaskTemplateInput {
  label: String!
  description: String!
}

Corresponding mutations are:

type Mutation {
  createScriptTemplate(name: String!, input: String!, output: String!, cards: [ExistingCardTemplateInput!], new_cards: [NewCardTemplateInput!]): ScriptTemplate
  createCardTemplate(title: String!, description: String! tasks:[ExistingTaskTemplateInput!], new_tasks:[NewTaskTemplateInput!]): CardTemplate
  createTaskTemplate(label: String!, description: String! cards:[ExistingCardTemplateInput!]): TaskTemplate

}

So basically, if I trying to use createTaskTemplate mutation or createCardTemplate mutation - everything is working fine. I can create these entities, including nested mutation creating new Card with the new Tasks in it or binding already existing Tasks. Or existing Card to newly created Task. That's why explicitly defined input types: ExistingTaskTemplateInput, NewTaskTemplateInput and NewCardTemplateInput. Everything is working as expected when I'm trying to create a new script with the inclusion of a new Card or connecting it to an existing one, as well. However, if I'm trying to create Script, Card and include new Tasks in it I've got error messages above.

  1. When trying the following mutation:
mutation{
  createScriptTemplate(
    name: "Script via API_H2"
    input: "Something describing initial state"
    output: "Something describing required state at the end"
    cards: [
      {
        id: "cjycl2nup00ta0703sd0kd8oa"
      },
      {
        id: "cjye3ryee01ey070383sxaoxz"
      }
    ]
    new_cards:[
      {
        title:"New card via scriptis2"
        description:"desc"
        tasks: [ 
          {
            description: "test dewscription"
            label: "test label"
          }
        ]
      },
      {
        title:"New card through scriptos2"
        description: "desc"
      }
    ]
  ){
    id
    name
    input
    output
    createdAt
    updatedAt
    cards{
      id
      title
      tasks{
        id
        label
      }
    }
  }
}

I'm having error:

{
  "data": {
    "createScriptTemplate": null
  },
  "errors": [
    {
      "message": "Variable '$data' expected value of type 'ScriptTemplateCreateInput!' but got: 
{\"name\":\"First Script through API_H2\",\"input\":\"Something describing initial state\",\"output\":\"Something describing requred state at the end\",\"cards\":{\"connect\":[{\"id\":\"cjycl2nup00ta0703sd0kd8oa\"},{\"id\":\"cjye3ryee01ey070383sxaoxz\"}],\"create\":[{\"title\":\"New card via scriptis2\",\"description\":\"desc\",\"tasks\":[{\"label\":\"test label\",\"description\":\"test dewscription\"}]},{\"title\":\"New card through scriptos2\",\"description\":\"desc\"}]}}. 
Reason: 'cards.create[0].tasks' 
Expected 'TaskTemplateCreateManyWithoutCardsInput', found not an object. (line 1, column 11):\nmutation ($data: ScriptTemplateCreateInput!) {\n          ^",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "createScriptTemplate"
      ]
    }
  ]
}

The actual request looks like this (via console.log) :

{ name: 'First Script through API_H2',
  input: 'Something describing initial state',
  output: 'Something describing requred state at the end',
  cards:
   { connect:
      [ [Object: null prototype] { id: 'cjycl2nup00ta0703sd0kd8oa' },
        [Object: null prototype] { id: 'cjye3ryee01ey070383sxaoxz' } ],
     create:
      [ [Object: null prototype] {
          title: 'New card via scriptis2',
          description: 'desc',
          tasks:
           [ [Object: null prototype] { label: 'test label', description: 'test dewscription' } ] },
        [Object: null prototype] { title: 'New card through scriptos2', description: 'desc' } ] } }

Looks like I missing {connect or create} bit for the tasks field. However when I'm altering it to look like:

tasks: {create: [ 
          {
            description: "test dewscription"
            label: "test label"
          }
        ]
       }

I'm getting error that Field \"create\" is not defined by type NewTaskTemplateInput and Field NewTaskTemplateInput.label and description of required type String! was not provided

  1. However, this works perfectly fine (same request without tasks) :
mutation{
  createScriptTemplate(
    name: "Script via API_H2"
    input: "Something describing initial state"
    output: "Something describing required state at the end"
    cards: [
      {
        id: "cjycl2nup00ta0703sd0kd8oa"
      },
      {
        id: "cjye3ryee01ey070383sxaoxz"
      }
    ]
    new_cards:[
      {
        title:"New card via scriptis2"
        description:"desc"
      },
      {
        title:"New card through scriptos2"
        description: "desc"
      }
    ]
  ){
    id
    name
    input
    output
    createdAt
    updatedAt
    cards{
      id
      title
      tasks{
        id
        label
      }
    }
  }
}

Checked generated scheme, can't spot any problems there.

input TaskTemplateCreateManyWithoutCardsInput {
  create: [TaskTemplateCreateWithoutCardsInput!]
  connect: [TaskTemplateWhereUniqueInput!]
}

input TaskTemplateCreateWithoutCardsInput {
  id: ID
  label: String!
  description: String!
}

Looks like I'm confusing scheme that I defined in gql files and the one I'm doing requests again, but don't know which direction to go.

Upvotes: 1

Views: 5091

Answers (1)

XYShaoKang
XYShaoKang

Reputation: 981

Description

First outline the entire process of a request.

enter image description here

The above image is taken from Prisma Basics in the official Prisma documentation.

As shown in this picture, localhost playground is the client in the figure. The Server accessed by localhost playground is the API Server in the figure, which is Prisma Client.Here is the first connection, the green arrow in the picture. Prisma Client gets the data from the database by accessing Prisma Server. This is the second connection, the yellow arrow in the figure.

The process of data flow, sent from localhost playground to API Server to complete the first connection transmission, and then processed by resolve, use Prisma Client to send to Prisma Server to complete the second connection transmission. Prisma Server retrieves data from Database according to the requested data and returns it to API Server, completes the second connection acceptance. API Server returns the data to localhost playground, completing the acceptance of the first connection. A complete process is completed.

In the process of using Prisma, we define two schema, one for defining Prisma Server, the name is usually datamodel.prisma. The other one is used to define Prisma Client, if it is defined in the file , usually named schema.graphql, can also be defined in the JS file through the template string, there are other ways, here is not discussed in depth. What you are showing belongs to Client Schema.

Successful completion of this process requires that the data sent by each part is correct. Your first error occurred when the second connection was sent. The data sent from API Server did not match the schema definition in Prisma Server. The second error is that the data sent from localhost playground does not match the schema definition in API Server when the first connection is sent.

Example

Assume the following architecture

# datamodel.prisma
type User {
  id: @id!
  name: String!
  post: [Post!]!
}
type Post {
  id: @id!
  title: String!
}
# schema.graphql
input CreatePost {
  title: String!
}
type Mutation {
  createUser(name: String!,posts:[CreatePost])
}

Use the following mutation Create user

mutation {
  createUser(name: "prisma", posts: [{ title: "test" }]) {
    id
    name
  }
}

When sent from localhost playground to API Server, the data is as follows

{
  "name": "prisma",
  "posts": [{ "title": "test" }]
}

If you send this data directly to Prisma Server, it does not conform to the definition of Prisma Server. You need to convert the data to a definition that conforms to the Prisma Server schema.

{
  "name": "prisma",
  "posts": { "create": [{ "title": "test" }] }
}

Then send it to Prisma Server via Prisma Client.

const resolve = {
  Mutation: {
    createUser: async (_, args) => {
      const userCreateInput = {
        name: args.name,
        posts: {
          create: args.posts,
        },
      }
      return await prisma.createUser(userCreateInput)
    },
  },
}

This way the final data arrives at the database via Prisma Server.

Solve the problem

Check out the definition of createScriptTemplate in API Server.It should be that it did not convert the received data into an error caused by the format required by API Server.


Understand Prisma

Upvotes: 2

Related Questions