How resolve a custom nested extendType resolver with prisma nexus? - graphql

I need resolve a custom resolver from a prisma type. But I can't access to children in this case course or subjects, my person type only resolve data over one level.
Deps:
"nexus": "0.11.7",
"nexus-prisma": "0.3.7",
"prisma-client-lib": "1.30.0",
...
Datamodel:
type Person {
id: ID! #unique
firstName: String!
secondName: String
firstSurname: String!
secondSurname: String
sex: SexTypes
address: String
commune: Commune
region: Region
course: Course
phone: String
state: StudentStateTypes #default(value: ACTIVE)
user: User! #relation(name: "UserPerson", onDelete: CASCADE)
birthday: DateTime
registrationNumber: String
listNumber: Int
previousSchool: OtherSchool
scholarship: Scholarship
createdAt: DateTime!
updatedAt: DateTime!
}
type Course {
id: ID! #unique
client: Client
name: String!
person: [Person!]!
teacher: User
subjects: [Subject!]!
evaluations: [Evaluation!]!
createdAt: DateTime!
updatedAt: DateTime!
}
type Subject {
id: ID! #unique
client: Client
name: String!
date: DateTime
isEvaluable: Boolean
order: Int
course: [Course!]!
evaluations: [Evaluation!]!
createdAt: DateTime!
updatedAt: DateTime!
}
type Evaluation {
id: ID! #unique
client: Client
name: String!
date: DateTime!
period: Int!
description: String
coefficientTwo: Boolean
course: Course!
subject: Subject
qualifications: [Qualification!]! #relation(name: "EvaluationQualification", onDelete: CASCADE)
createdAt: DateTime!
updatedAt: DateTime!
}
type Qualification {
id: ID! #unique
client: Client
value: Float!
evaluation: Evaluation! #relation(name: "EvaluationQualification", onDelete: SET_NULL)
person: Person
createdAt: DateTime!
updatedAt: DateTime!
}
My resolver:
export const query = extendType({
type: 'Query',
definition (t: any) {
t.field('qualificationsCustom', {
type: 'Person',
args: {
id: idArg()
},
resolve: async (parent: any, args: any, ctx: any) => {
const person = await ctx.prisma.person({ id: args.id })
const qualifications = person && person.course.subjects.reduce((acc: any, subject: any) => {
acc.push({
subject: subject.name
})
return acc
})
console.log(qualifications)
}
})
}
})
person variable only resolve the next:
{
birthday: '2008-10-27T00:00:00.000Z',
secondName: 'Gisel',
...
And person.course is undefined :/
What I'm doing wrong?

Calling prisma.person({ id: args.id }) will only fetch the requested Person. It does not eager load any associated models. You can query the relations for a particular model instance by utilizing the fluent API as shown in the docs:
prisma.person({ id: args.id }).course()
or even:
prisma.person({ id: args.id }).course().evaluations()
You can also get everything at once by providing a fragment that specifies what fields, including relations, you want to fetch as shown here:
const fragment = `
fragment PersonWithCourse on Person {
# other person fields here
course {
# some course fields here
}
}
`
prisma.person({ id: args.id }).$fragment(fragment)

Related

Why does my deleteComment mutation fail to find the entity to be deleted?

I have inherited a GraphQL/Apollo server and have been tasked with making several changes, one of which is adding Comments and Attachments to an existing Card object type (something similar to Trello). For the purposes of keeping this question simple I will only refer to Comments, assuming that the solution can also be applied to Attachments, which are suffering the same issue.
I have Mutations to Create, Update and Delete Comments, as well as the Repository, Resolver and have defined them in files below. The schema is also below for reference.
The problem being encountered is that the deleteComment mutation is failing to find the Comment to be deleted, returning a GraphQL error Could not find any entity of type "Comment" matching:. I have been able to positively confirm that the correct ID is traced through the entire path to the SQL query. However, the updateComment mutation, which uses the same access method to find the Comment, does successfully find and update the body of the correct Comment. I have been able to produce these results in both my developed frontend, and the Apollo Sandbox.
The only solution I have tried has been to define queries for Comments (both front and back end). This didn't appear to make any difference to the end result.
deleteComment.graphql
mutation DeleteComment($id: String!) {
deleteComment(id: $id) {
id
}
}
Comment.repository.ts
import { EntityRepository } from 'typeorm';
import { FindOneOptions } from 'typeorm/find-options/FindOneOptions';
import { BaseRepository } from './Base.repository';
import { Comment } from '../entities';
#EntityRepository(Comment)
export class CommentRepository extends BaseRepository<Comment> {
/**
* Fetch a comment using its UUID
* #param {string} id - UUID for comment being fetched
* #param {FindOneOptions<Comment>} options - Optional TypeORM find options
* #throws {EntityNotFoundError} if no entities match given UUID
* #returns {Promise<Comment>} Comment entity
*/
findById(id: string, options?: FindOneOptions<Comment>) {
return this.findOneByIdOrThrow(id, { ...options });
}
}
CommentResolver.ts
import { Arg, Mutation, Resolver } from 'type-graphql';
import { getConnection } from 'typeorm';
import { Comment } from '../models/entities';
import { CommentCreatePayload, CommentUpdatePayload } from '../graphql/types/CommentPayload';
import { CommentRepository } from '../models/repositories';
#Resolver()
export class CommentResolver {
private commentRepository: CommentRepository =
getConnection().getCustomRepository(CommentRepository);
#Mutation(() => Comment)
async createComment(
#Arg('commentCreatePayload', () => CommentCreatePayload) data: CommentCreatePayload,
) {
return this.commentRepository.insertWithValidate(data);
}
#Mutation(() => Comment)
async updateComment(
#Arg('id', () => String) id: string,
#Arg('commentUpdatePayload', () => CommentUpdatePayload) patch: CommentUpdatePayload,
): Promise<Comment> {
return this.commentRepository.updateWithValidate(id, patch);
}
#Mutation(() => Comment)
async deleteComment(
#Arg('id', () => String) id: string): Promise<Comment> {
return this.commentRepository.deleteOrThrow(id);
}
}
Comment.entity.ts
import { Entity, Column, ManyToOne } from 'typeorm';
import { ObjectType, Field } from 'type-graphql';
import { Base, Card, User } from './index';
#ObjectType()
#Entity()
export class Comment extends Base {
#Field(() => String)
#Column('text')
body: string;
#Field(() => User)
#ManyToOne(() => User, (user) => user.comments, { onDelete: 'CASCADE' })
user: User | undefined;
#Field(() => String)
#Column('text')
userId: string;
#Field(() => Card)
#ManyToOne(() => Card, (card) => card.comments, { onDelete: 'CASCADE' })
card: Card | undefined;
#Field(() => String)
#Column('text')
cardId: string;
}
schema.graphql (some parts omitted)
type Query {
list(id: String!): List!
card(id: String!): Card!
cardByShortId(shortId: String!): Card!
boards(archived: Boolean = false): [Board!]!
board(id: String!): Board!
boardByShortId(shortId: String!): Board!
archivedSwimlanes(boardId: String!): [Swimlane!]!
archivedLists(boardId: String!): [List!]!
currentUser: User!
swimlane(id: String!): Swimlane!
label(id: String!): Label!
}
type Card {
id: String!
createdAt: DateTime!
updatedAt: DateTime!
deletedAt: DateTime
version: Float!
shortId: String!
name: String!
slug: String!
rank: String!
description: String
startTime: DateTime
endTime: DateTime
ownerId: String!
listSection: ListSection!
listSectionId: String!
comments: [Comment!]!
attachments: [Attachment!]!
labels: [Label!]!
labelIds: [String!]!
users: [User!]!
userIds: [String!]!
}
type Comment {
id: String!
createdAt: DateTime!
updatedAt: DateTime!
deletedAt: DateTime
version: Float!
body: String!
user: User!
userId: String!
card: Card!
cardId: String!
}
type Mutation {
createCard(cardCreatePayload: CardCreatePayload!): Card!
updateCard(cardUpdatePayload: CardUpdatePayload!, id: String!): Card!
addLabelToCard(labelId: String!, id: String!): Card!
removeLabelFromCard(labelId: String!, id: String!): Card!
archiveCard(id: String!): Card!
recoverCard(id: String!): Card!
deleteCard(id: String!): Card!
createComment(commentCreatePayload: CommentCreatePayload!): Comment!
updateComment(commentUpdatePayload: CommentUpdatePayload!, id: String!): Comment!
deleteComment(id: String!): Comment!
}
input CommentCreatePayload {
id: String
body: String
userId: String!
cardId: String!
}
input CommentUpdatePayload {
body: String
}

How do I use schema.graphql file as typeDefs?

I am learning GraphQL with Node.js and I am currently using graphql-yoga as a GraphQLServer. Now, I want to seperate Type Definitions and Resolvers so I have used schema.graphql and in there I have all my types defined but now I have no Idea how to use that file as typeDefs in GraphQL Server. I have provided my files below.
index.js
const { createServer } = require('graphql-yoga');
const { resolvers } = require('./template1');
const server = createServer({
schema: {
resolvers,
typeDefs: 'src/schema.graphql'
}
});
server.start(() => {
console.log('GraphQL Server started.');
});
schema.graphql
type Query {
hello: String!
posts: [Post!]!
users: [User!]!
comments: [Comment!]!
}
type Mutation {
signUp(data: SignUpInput): User!
createPost(data: CreatePostInput): Post!
createComment(data: CreateCommentInput): Comment!
deleteUser(id: ID!): User!
deletePost(id: ID!): Post!
deleteComment(id: ID!): Comment!
}
input SignUpInput {
email:String!
username: String!
password: String!
}
input CreatePostInput {
title: String!
author: ID!
}
input CreateCommentInput {
text: String!
author: ID!
post: ID!
}
type Post {
id: ID!
title: String!
author: User!
comments: [Comment!]
}
type User {
id: ID!
email: String!
password: String!
username: String!
posts: [Post!]
comments: [Comment!]
}
type Comment {
id: ID!
text: String!
author: User!
post: Post!
}
and I am getting this Error.
Instead of directly passing the schema use:
typeDefs: fs.readFileSync(
path.join(__dirname, 'schema.graphql'),
'utf8'
)
Thanks this worked for me!
Just added this at the top of the file.
import { readFileSync } from 'node:fs';
import { join } from 'node:path';

Strapi - error GraphQLError: Syntax Error: Expected Name, found "}"

I am getting this error in Strapi app while building
error GraphQLError: Syntax Error: Expected Name, found "}".
Full Log
[2021-11-27T04:22:19.124Z] debug ⛔️ Server wasn't able to start properly.
[2021-11-27T04:22:19.127Z] error GraphQLError: Syntax Error: Expected Name, found "}".
at syntaxError (D:\Projects\Personal\Aravin.net\website\backend\node_modules\graphql\error\syntaxError.js:15:10)
at Parser.expectToken (D:\Projects\Personal\Aravin.net\website\backend\node_modules\graphql\language\parser.js:1413:40)
at Parser.parseName (D:\Projects\Personal\Aravin.net\website\backend\node_modules\graphql\language\parser.js:98:22)
at Parser.parseFieldDefinition (D:\Projects\Personal\Aravin.net\website\backend\node_modules\graphql\language\parser.js:879:21)
at Parser.optionalMany (D:\Projects\Personal\Aravin.net\website\backend\node_modules\graphql\language\parser.js:1503:28)
at Parser.parseFieldsDefinition (D:\Projects\Personal\Aravin.net\website\backend\node_modules\graphql\language\parser.js:868:17)
at Parser.parseObjectTypeDefinition (D:\Projects\Personal\Aravin.net\website\backend\node_modules\graphql\language\parser.js:812:23)
at Parser.parseTypeSystemDefinition (D:\Projects\Personal\Aravin.net\website\backend\node_modules\graphql\language\parser.js:708:23)
at Parser.parseDefinition (D:\Projects\Personal\Aravin.net\website\backend\node_modules\graphql\language\parser.js:150:23)
at Parser.many (D:\Projects\Personal\Aravin.net\website\backend\node_modules\graphql\language\parser.js:1523:26)
at Parser.parseDocument (D:\Projects\Personal\Aravin.net\website\backend\node_modules\graphql\language\parser.js:115:25)
at Object.parse (D:\Projects\Personal\Aravin.net\website\backend\node_modules\graphql\language\parser.js:31:17)
at Object.addPolymorphicUnionType (D:\Projects\Personal\Aravin.net\website\backend\node_modules\strapi-plugin-graphql\services\type-builder.js:188:8)
at Object.generateSchema (D:\Projects\Personal\Aravin.net\website\backend\node_modules\strapi-plugin-graphql\services\schema-generator.js:43:35)
at Object.initialize (D:\Projects\Personal\Aravin.net\website\backend\node_modules\strapi-plugin-graphql\hooks\graphql\index.js:76:74)
at D:\Projects\Personal\Aravin.net\website\backend\node_modules\strapi\lib\hooks\index.js:37:28
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
The terminal process "C:\WINDOWS\System32\cmd.exe /d /c yarn run develop:backend" terminated with exit code: 1.
But there is no issue in the graphQL syntax.
Source: https://github.com/Aravin/aravin.net/tree/main/backend
I am trying to fix this issue for a long time, I could see a similar problems all over the internet but there is no proper solution.
Kindly help me.
Logged the graphql error body and position
scalar Relation
enum CommentReportReason {
BAD_LANGAUGE
DISCRIMINATION
OTHER
}
enum CommentApprovalStatus {
PENDING
APPROVED
REJECTED
}
type CommentReport {
id: ID!
content: String
reason: CommentReportReason!
resolved: Boolean!
related: Comment
}
type Comment {
id: ID!
content: String!
blocked: Boolean
blockedThread: Boolean
blockReason: String
points: Int
authorUser: UsersPermissionsUser
authorType: String
authorId: String
authorName: String
authorAvatar: String
removed: Boolean
relatedSlug: String
reports: [CommentReport]
approvalStatus: CommentApprovalStatus
}
type CommentsInHierarchy {
id: ID!
content: String!
blocked: Boolean
blockedThread: Boolean
blockReason: String
points: Int
authorUser: UsersPermissionsUser
authorType: String
authorId: String
authorName: String
authorAvatar: String
removed: Boolean
relatedSlug: String
reports: [CommentReport]
approvalStatus: CommentApprovalStatus
children: [Comment]
}
type CommentsPagination {
items: [Comment]!
total: Int!
page: Float
}
type CommentsWithThread {
id: ID!
content: String!
blocked: Boolean
blockedThread: Boolean
blockReason: String
points: Int
authorUser: UsersPermissionsUser
authorType: String
authorId: String
authorName: String
authorAvatar: String
removed: Boolean
relatedSlug: String
reports: [CommentReport]
approvalStatus: CommentApprovalStatus
threadOf: Comment
}
type CommentsFindOne {
selected: CommentsWithThread
level: [Comment]!
}
type CommentsContentTypes {
key: String!
value: String!
}
type CommentsRelatedContentType {
contentManager: Boolean
isSingle: Boolean
url: String
}
type CommentsRelatedContentTypes {
}
type CommentsConfig {
contentsTypes: [CommentsContentTypes]!
relatedContentTypes: CommentsRelatedContentTypes
}
type CommentsContentType {
key: String!
value: String
}
type CommentRemove {
id: ID!
}
input NewCommentRelated {
refId: String!
ref: String!
field: String!
}
input CommentNew {
authorId: String
authorName: String
authorEmail: String
content: String!
authorUsername: String
threadOf: String
related: [NewCommentRelated!]!
approvalStatus: CommentApprovalStatus
}
input FileInfoInput {
name: String
alternativeText: String
caption: String
}
type UsersPermissionsMe {
id: ID!
username: String!
email: String!
confirmed: Boolean
blocked: Boolean
role: UsersPermissionsMeRole
}
type UsersPermissionsMeRole {
id: ID!
name: String!
description: String
type: String
}
input UsersPermissionsRegisterInput {
username: String!
email: String!
password: String!
}
input UsersPermissionsLoginInput {
identifier: String!
password: String!
provider: String = "local"
}
type UsersPermissionsLoginPayload {
jwt: String
user: UsersPermissionsMe!
}
type UserPermissionsPasswordPayload {
ok: Boolean!
}
type Article {id: ID!
created_at: DateTime!
updated_at: DateTime!
title: String!
description: String!
content: String!
slug: String!
category: Category
image: UploadFile
author: Writer
published_at: DateTime
tags(sort: String, limit: Int, start: Int, where: JSON): [Tags]}
type ArticleConnection {values: [Article]
groupBy: ArticleGroupBy
aggregate: ArticleAggregator}
type ArticleAggregator {count: Int
totalCount: Int}
type ArticleGroupBy {id: [ArticleConnectionId]
created_at: [ArticleConnectionCreated_at]
updated_at: [ArticleConnectionUpdated_at]
title: [ArticleConnectionTitle]
description: [ArticleConnectionDescription]
content: [ArticleConnectionContent]
slug: [ArticleConnectionSlug]
category: [ArticleConnectionCategory]
image: [ArticleConnectionImage]
author: [ArticleConnectionAuthor]
published_at: [ArticleConnectionPublished_at]}
type ArticleConnectionId {key: ID
connection: ArticleConnection}
type ArticleConnectionCreated_at {key: DateTime
connection: ArticleConnection}
type ArticleConnectionUpdated_at {key: DateTime
connection: ArticleConnection}
type ArticleConnectionTitle {key: String
connection: ArticleConnection}
type ArticleConnectionDescription {key: String
connection: ArticleConnection}
type ArticleConnectionContent {key: String
connection: ArticleConnection}
type ArticleConnectionSlug {key: String
connection: ArticleConnection}
type ArticleConnectionCategory {key: ID
connection: ArticleConnection}
type ArticleConnectionImage {key: ID
connection: ArticleConnection}
type ArticleConnectionAuthor {key: ID
connection: ArticleConnection}
type ArticleConnectionPublished_at {key: DateTime
connection: ArticleConnection}
input ArticleInput {
title: String!
description: String!
content: String!
slug: String!
category: ID
image: ID
author: ID
tags: [ID]
published_at: DateTime
created_by: ID
updated_by: ID
}
input editArticleInput {
title: String
description: String
content: String
slug: String
category: ID
image: ID
author: ID
tags: [ID]
published_at: DateTime
created_by: ID
updated_by: ID
}
input createArticleInput { data: ArticleInput }
type createArticlePayload { article: Article }
input updateArticleInput { where: InputID, data: editArticleInput }
type updateArticlePayload { article: Article }
input deleteArticleInput { where: InputID }
type deleteArticlePayload { article: Article }
type Category {id: ID!
created_at: DateTime!
updated_at: DateTime!
name: String!
slug: String!
articles(sort: String, limit: Int, start: Int, where: JSON): [Article]}
type CategoryConnection {values: [Category]
groupBy: CategoryGroupBy
aggregate: CategoryAggregator}
type CategoryAggregator {count: Int
totalCount: Int}
type CategoryGroupBy {id: [CategoryConnectionId]
created_at: [CategoryConnectionCreated_at]
updated_at: [CategoryConnectionUpdated_at]
name: [CategoryConnectionName]
slug: [CategoryConnectionSlug]}
type CategoryConnectionId {key: ID
connection: CategoryConnection}
type CategoryConnectionCreated_at {key: DateTime
connection: CategoryConnection}
type CategoryConnectionUpdated_at {key: DateTime
connection: CategoryConnection}
type CategoryConnectionName {key: String
connection: CategoryConnection}
type CategoryConnectionSlug {key: String
connection: CategoryConnection}
input CategoryInput {
name: String!
slug: String!
articles: [ID]
created_by: ID
updated_by: ID
}
input editCategoryInput {
name: String
slug: String
articles: [ID]
created_by: ID
updated_by: ID
}
input createCategoryInput { data: CategoryInput }
type createCategoryPayload { category: Category }
input updateCategoryInput { where: InputID, data: editCategoryInput }
type updateCategoryPayload { category: Category }
input deleteCategoryInput { where: InputID }
type deleteCategoryPayload { category: Category }
type Global {id: ID!
created_at: DateTime!
updated_at: DateTime!
favicon: UploadFile
siteName: String!
defaultSeo: ComponentSharedSeo}
input GlobalInput {
favicon: ID
siteName: String!
defaultSeo: ComponentSharedSeoInput!
created_by: ID
updated_by: ID
}
input editGlobalInput {
favicon: ID
siteName: String
defaultSeo: editComponentSharedSeoInput
created_by: ID
updated_by: ID
}
input updateGlobalInput { data: editGlobalInput }
type updateGlobalPayload { global: Global }
type deleteGlobalPayload { global: Global }
type Homepage {id: ID!
created_at: DateTime!
updated_at: DateTime!
seo: ComponentSharedSeo
hero: ComponentSectionsHero}
input HomepageInput {
seo: ComponentSharedSeoInput
hero: ComponentSectionsHeroInput!
created_by: ID
updated_by: ID
}
input editHomepageInput {
seo: editComponentSharedSeoInput
hero: editComponentSectionsHeroInput
created_by: ID
updated_by: ID
}
input updateHomepageInput { data: editHomepageInput }
type updateHomepagePayload { homepage: Homepage }
type deleteHomepagePayload { homepage: Homepage }
type Tags {id: ID!
created_at: DateTime!
updated_at: DateTime!
slug: String
color: String
Name: String
published_at: DateTime
articles(sort: String, limit: Int, start: Int, where: JSON): [Article]}
type TagsConnection {values: [Tags]
groupBy: TagsGroupBy
aggregate: TagsAggregator}
type TagsAggregator {count: Int
totalCount: Int}
type TagsGroupBy {id: [TagsConnectionId]
created_at: [TagsConnectionCreated_at]
updated_at: [TagsConnectionUpdated_at]
slug: [TagsConnectionSlug]
color: [TagsConnectionColor]
Name: [TagsConnectionName]
published_at: [TagsConnectionPublished_at]}
type TagsConnectionId {key: ID
connection: TagsConnection}
type TagsConnectionCreated_at {key: DateTime
connection: TagsConnection}
type TagsConnectionUpdated_at {key: DateTime
connection: TagsConnection}
type TagsConnectionSlug {key: String
connection: TagsConnection}
type TagsConnectionColor {key: String
connection: TagsConnection}
type TagsConnectionName {key: String
connection: TagsConnection}
type TagsConnectionPublished_at {key: DateTime
connection: TagsConnection}
input TagInput {
slug: String
color: String
Name: String
articles: [ID]
published_at: DateTime
created_by: ID
updated_by: ID
}
input editTagInput {
slug: String
color: String
Name: String
articles: [ID]
published_at: DateTime
created_by: ID
updated_by: ID
}
input createTagInput { data: TagInput }
type createTagPayload { tag: Tags }
input updateTagInput { where: InputID, data: editTagInput }
type updateTagPayload { tag: Tags }
input deleteTagInput { where: InputID }
type deleteTagPayload { tag: Tags }
type Writer {id: ID!
created_at: DateTime!
updated_at: DateTime!
name: String
picture: UploadFile
email: String
articles(sort: String, limit: Int, start: Int, where: JSON): [Article]}
type WriterConnection {values: [Writer]
groupBy: WriterGroupBy
aggregate: WriterAggregator}
type WriterAggregator {count: Int
totalCount: Int}
type WriterGroupBy {id: [WriterConnectionId]
created_at: [WriterConnectionCreated_at]
updated_at: [WriterConnectionUpdated_at]
name: [WriterConnectionName]
picture: [WriterConnectionPicture]
email: [WriterConnectionEmail]}
type WriterConnectionId {key: ID
connection: WriterConnection}
type WriterConnectionCreated_at {key: DateTime
connection: WriterConnection}
type WriterConnectionUpdated_at {key: DateTime
connection: WriterConnection}
type WriterConnectionName {key: String
connection: WriterConnection}
type WriterConnectionPicture {key: ID
connection: WriterConnection}
type WriterConnectionEmail {key: String
connection: WriterConnection}
input WriterInput {
name: String
picture: ID
articles: [ID]
email: String
created_by: ID
updated_by: ID
}
input editWriterInput {
name: String
picture: ID
articles: [ID]
email: String
created_by: ID
updated_by: ID
}
input createWriterInput { data: WriterInput }
type createWriterPayload { writer: Writer }
input updateWriterInput { where: InputID, data: editWriterInput }
type updateWriterPayload { writer: Writer }
input deleteWriterInput { where: InputID }
type deleteWriterPayload { writer: Writer }
type CommentsComment {id: ID!
created_at: DateTime!
updated_at: DateTime!
content: String!
blocked: Boolean
blockedThread: Boolean
blockReason: String
points: Int
authorUser: UsersPermissionsUser
authorType: String
authorId: String
authorName: String
authorEmail: String
authorAvatar: String
removed: Boolean
threadOf: CommentsComment
approvalStatus: String
related(sort: String, limit: Int, start: Int, where: JSON): [Morph]
reports(sort: String, limit: Int, start: Int, where: JSON): [CommentsReport]}
input CommentInput {
content: String!
blocked: Boolean
blockedThread: Boolean
blockReason: String
points: Int
authorUser: ID
authorType: String
authorId: String
authorName: String
authorEmail: String
authorAvatar: String
removed: Boolean
relatedSlug: String
related: [ID]
reports: [ID]
threadOf: ID
approvalStatus: String
created_by: ID
updated_by: ID
}
input editCommentInput {
content: String
blocked: Boolean
blockedThread: Boolean
blockReason: String
points: Int
authorUser: ID
authorType: String
authorId: String
authorName: String
authorEmail: String
authorAvatar: String
removed: Boolean
relatedSlug: String
related: [ID]
reports: [ID]
threadOf: ID
approvalStatus: String
created_by: ID
updated_by: ID
}
enum ENUM_COMMENTSREPORT_REASON {
BAD_LANGUAGE
DISCRIMINATION
OTHER
}
type CommentsReport {id: ID!
created_at: DateTime!
updated_at: DateTime!
content: String
reason: ENUM_COMMENTSREPORT_REASON!
resolved: Boolean
related: CommentsComment}
input ReportInput {
content: String
reason: ENUM_COMMENTSREPORT_REASON
resolved: Boolean
related: ID
created_by: ID
updated_by: ID
}
input editReportInput {
content: String
reason: ENUM_COMMENTSREPORT_REASON
resolved: Boolean
related: ID
created_by: ID
updated_by: ID
}
type UploadFile {id: ID!
created_at: DateTime!
updated_at: DateTime!
name: String!
alternativeText: String
caption: String
width: Int
height: Int
formats: JSON
hash: String!
ext: String
mime: String!
size: Float!
url: String!
previewUrl: String
provider: String!
provider_metadata: JSON
related(sort: String, limit: Int, start: Int, where: JSON): [Morph]}
type UploadFileConnection {values: [UploadFile]
groupBy: UploadFileGroupBy
aggregate: UploadFileAggregator}
type UploadFileAggregator {count: Int
totalCount: Int
sum: UploadFileAggregatorSum
avg: UploadFileAggregatorAvg
min: UploadFileAggregatorMin
max: UploadFileAggregatorMax}
type UploadFileAggregatorSum {width: Float
height: Float
size: Float}
type UploadFileAggregatorAvg {width: Float
height: Float
size: Float}
type UploadFileAggregatorMin {width: Float
height: Float
size: Float}
type UploadFileAggregatorMax {width: Float
height: Float
size: Float}
type UploadFileGroupBy {id: [UploadFileConnectionId]
created_at: [UploadFileConnectionCreated_at]
updated_at: [UploadFileConnectionUpdated_at]
name: [UploadFileConnectionName]
alternativeText: [UploadFileConnectionAlternativeText]
caption: [UploadFileConnectionCaption]
width: [UploadFileConnectionWidth]
height: [UploadFileConnectionHeight]
formats: [UploadFileConnectionFormats]
hash: [UploadFileConnectionHash]
ext: [UploadFileConnectionExt]
mime: [UploadFileConnectionMime]
size: [UploadFileConnectionSize]
url: [UploadFileConnectionUrl]
previewUrl: [UploadFileConnectionPreviewUrl]
provider: [UploadFileConnectionProvider]
provider_metadata: [UploadFileConnectionProvider_metadata]}
type UploadFileConnectionId {key: ID
connection: UploadFileConnection}
type UploadFileConnectionCreated_at {key: DateTime
connection: UploadFileConnection}
type UploadFileConnectionUpdated_at {key: DateTime
connection: UploadFileConnection}
type UploadFileConnectionName {key: String
connection: UploadFileConnection}
type UploadFileConnectionAlternativeText {key: String
connection: UploadFileConnection}
type UploadFileConnectionCaption {key: String
connection: UploadFileConnection}
type UploadFileConnectionWidth {key: Int
connection: UploadFileConnection}
type UploadFileConnectionHeight {key: Int
connection: UploadFileConnection}
type UploadFileConnectionFormats {key: JSON
connection: UploadFileConnection}
type UploadFileConnectionHash {key: String
connection: UploadFileConnection}
type UploadFileConnectionExt {key: String
connection: UploadFileConnection}
type UploadFileConnectionMime {key: String
connection: UploadFileConnection}
type UploadFileConnectionSize {key: Float
connection: UploadFileConnection}
type UploadFileConnectionUrl {key: String
connection: UploadFileConnection}
type UploadFileConnectionPreviewUrl {key: String
connection: UploadFileConnection}
type UploadFileConnectionProvider {key: String
connection: UploadFileConnection}
type UploadFileConnectionProvider_metadata {key: JSON
connection: UploadFileConnection}
input FileInput {
name: String!
alternativeText: String
caption: String
width: Int
height: Int
formats: JSON
hash: String!
ext: String
mime: String!
size: Float!
url: String!
previewUrl: String
provider: String!
provider_metadata: JSON
related: [ID]
created_by: ID
updated_by: ID
}
input editFileInput {
name: String
alternativeText: String
caption: String
width: Int
height: Int
formats: JSON
hash: String
ext: String
mime: String
size: Float
url: String
previewUrl: String
provider: String
provider_metadata: JSON
related: [ID]
created_by: ID
updated_by: ID
}
input deleteFileInput { where: InputID }
type deleteFilePayload { file: UploadFile }
type UsersPermissionsPermission {id: ID!
type: String!
controller: String!
action: String!
enabled: Boolean!
policy: String
role: UsersPermissionsRole}
type UsersPermissionsRole {id: ID!
name: String!
description: String
type: String
permissions(sort: String, limit: Int, start: Int, where: JSON): [UsersPermissionsPermission]
users(sort: String, limit: Int, start: Int, where: JSON): [UsersPermissionsUser]}
type UsersPermissionsRoleConnection {values: [UsersPermissionsRole]
groupBy: UsersPermissionsRoleGroupBy
aggregate: UsersPermissionsRoleAggregator}
type UsersPermissionsRoleAggregator {count: Int
totalCount: Int}
type UsersPermissionsRoleGroupBy {id: [UsersPermissionsRoleConnectionId]
name: [UsersPermissionsRoleConnectionName]
description: [UsersPermissionsRoleConnectionDescription]
type: [UsersPermissionsRoleConnectionType]}
type UsersPermissionsRoleConnectionId {key: ID
connection: UsersPermissionsRoleConnection}
type UsersPermissionsRoleConnectionName {key: String
connection: UsersPermissionsRoleConnection}
type UsersPermissionsRoleConnectionDescription {key: String
connection: UsersPermissionsRoleConnection}
type UsersPermissionsRoleConnectionType {key: String
connection: UsersPermissionsRoleConnection}
input RoleInput {
name: String!
description: String
type: String
permissions: [ID]
users: [ID]
created_by: ID
updated_by: ID
}
input editRoleInput {
name: String
description: String
type: String
permissions: [ID]
users: [ID]
created_by: ID
updated_by: ID
}
input createRoleInput { data: RoleInput }
type createRolePayload { role: UsersPermissionsRole }
input updateRoleInput { where: InputID, data: editRoleInput }
type updateRolePayload { role: UsersPermissionsRole }
input deleteRoleInput { where: InputID }
type deleteRolePayload { role: UsersPermissionsRole }
type UsersPermissionsUser {id: ID!
created_at: DateTime!
updated_at: DateTime!
username: String!
email: String!
provider: String
confirmed: Boolean
blocked: Boolean
role: UsersPermissionsRole}
type UsersPermissionsUserConnection {values: [UsersPermissionsUser]
groupBy: UsersPermissionsUserGroupBy
aggregate: UsersPermissionsUserAggregator}
type UsersPermissionsUserAggregator {count: Int
totalCount: Int}
type UsersPermissionsUserGroupBy {id: [UsersPermissionsUserConnectionId]
created_at: [UsersPermissionsUserConnectionCreated_at]
updated_at: [UsersPermissionsUserConnectionUpdated_at]
username: [UsersPermissionsUserConnectionUsername]
email: [UsersPermissionsUserConnectionEmail]
provider: [UsersPermissionsUserConnectionProvider]
confirmed: [UsersPermissionsUserConnectionConfirmed]
blocked: [UsersPermissionsUserConnectionBlocked]
role: [UsersPermissionsUserConnectionRole]}
type UsersPermissionsUserConnectionId {key: ID
connection: UsersPermissionsUserConnection}
type UsersPermissionsUserConnectionCreated_at {key: DateTime
connection: UsersPermissionsUserConnection}
type UsersPermissionsUserConnectionUpdated_at {key: DateTime
connection: UsersPermissionsUserConnection}
type UsersPermissionsUserConnectionUsername {key: String
connection: UsersPermissionsUserConnection}
type UsersPermissionsUserConnectionEmail {key: String
connection: UsersPermissionsUserConnection}
type UsersPermissionsUserConnectionProvider {key: String
connection: UsersPermissionsUserConnection}
type UsersPermissionsUserConnectionConfirmed {key: Boolean
connection: UsersPermissionsUserConnection}
type UsersPermissionsUserConnectionBlocked {key: Boolean
connection: UsersPermissionsUserConnection}
type UsersPermissionsUserConnectionRole {key: ID
connection: UsersPermissionsUserConnection}
input UserInput {
username: String!
email: String!
provider: String
password: String
resetPasswordToken: String
confirmationToken: String
confirmed: Boolean
blocked: Boolean
role: ID
created_by: ID
updated_by: ID
}
input editUserInput {
username: String
email: String
provider: String
password: String
resetPasswordToken: String
confirmationToken: String
confirmed: Boolean
blocked: Boolean
role: ID
created_by: ID
updated_by: ID
}
input createUserInput { data: UserInput }
type createUserPayload { user: UsersPermissionsUser }
input updateUserInput { where: InputID, data: editUserInput }
type updateUserPayload { user: UsersPermissionsUser }
input deleteUserInput { where: InputID }
type deleteUserPayload { user: UsersPermissionsUser }
type ComponentSectionsHero {id: ID!
title: String!}
input ComponentSectionsHeroInput {
title: String!
}
input editComponentSectionsHeroInput {
id: ID
title: String
}
type ComponentSharedSeo {id: ID!
metaTitle: String!
metaDescription: String!
shareImage: UploadFile}
input ComponentSharedSeoInput {
metaTitle: String!
metaDescription: String!
shareImage: ID
}
input editComponentSharedSeoInput {
id: ID
metaTitle: String
metaDescription: String
shareImage: ID
}
Position: 2083

"Variable '$data' expected value of type 'VoteCreateInput"

When I am trying to do the "vote" mutation, getting the below error. My other mutations are working fine.
When I am trying to do the "vote" mutation, getting the below error. My other mutations are working fine.
When I am trying to do the "vote" mutation, getting the below error. My other mutations are working fine.
"data": null,
"errors": [
{
"message": "Variable '$data' expected value of type 'VoteCreateInput!' but
got: {\"user\":{\"connect\":
{\"id\":\"ck1j3nzi68oef090830r8wd6b\"}},\"link\":{\"connect\":
{\"id\":\"ck1j58loj8x570908njwe4eu7\"}}}. Reason: 'User' Expected non-null
value, found null. (line 1, column 11):\nmutation ($data:
VoteCreateInput!) {\n ^",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"vote"
]
}
]
Mutation
async function vote(parent, args, context, info) {
// 1
const userId = getUserId(context)
// 2
const linkExists = await context.prisma.$exists.vote({
user: { id: userId },
link: { id: args.linkId },
})
if (linkExists) {
throw new Error(`Already voted for link: ${args.linkId}`)
}
// 3
return context.prisma.createVote({
user: { connect: { id: userId } },
link: { connect: { id: args.linkId } },
})
}
datamodel.schema
type Link {
id: ID! #id
createdAt: DateTime! #createdAt
description: String!
url: String!
postedBy: User
votes: [Vote!]!
}
type User {
id: ID! #id
name: String!
email: String #unique
password: String!
links: [Link!]!
votes: [Vote!]!
}
type Vote {
id: ID! #id
link: Link!
user: User!
}
schema.graphql
type Mutation {
vote(linkId: ID!): Vote!
}
type Link {
id: ID!
description: String!
url: String!
postedBy: User
votes: [Vote!]!
}
There was a glitch in prisma database which was not updating with the change in data model.
I have created a new instance of the db and now its working fine.

graphql required fields approach

This is my graphql schema, query and mutations.
I marked required fields in my schema with "!"
How I can create mutation to add new client?
Do I really need to write the same required fields again?
Like createClient(contactMethod: String!, hearAbout: String! ......... ): Client
const typeShard = `
type ClientProfile {
name: String!
surname: String!
address: String
language: String!
}
type Client {
_id: String
isEdit: Boolean
createdAt: String
shortId: Int
profile: ClientProfile
comments: String
contactMethod: String!
hearAbout: String!
leadAgentId: String
branchId: String!
}
`;
const queryShard = `
getAllClients: [Client]
`;
const mutationShard = `
removeClient(shortId : Int!): Client
createClient(contactMethod: String!, hearAbout: String! ......... ): Client
`;
const resolvers = {
Query: {
getAllClients: () => MongoClients.find().fetch(),
},
Mutation: {
removeClient(root, { shortId }) {
const client = MongoClients.findOne({ shortId });
if (!client) throw new Error(`Couldn't find client with id ${shortId}`);
MongoClients.remove({ shortId });
return client;
},
createClient: (_, args) => {
return MongoClients.insert(args);
},
},
};
You do not need to write the same fields for every mutation. You could define an input type. Please take a look at this cheat sheet.
So in your case it could look like:
const typeShard = `
type ClientProfile {
name: String!
surname: String!
address: String
language: String!
}
type Client {
_id: String
isEdit: Boolean
createdAt: String
shortId: Int
profile: ClientProfile
comments: String
contactMethod: String!
hearAbout: String!
leadAgentId: String
branchId: String!
}
input ClientInput {
contactMethod: String!
hearAbout: String!
.....
}
`;
const mutationShard = `
removeClient(shortId : Int!): Client
createClient(clientInput: ClientInput!): Client
`;

Resources