Redwood JS: Cannot query field XX on type "Query" - graphql

I'm having a GraphQL issue that popped up recently and I'm not sure where to go since I believe i'm following the GraphQL documentation correctly on querying.
I have the following model.
model Contract {
id Int #id #default(autoincrement())
userId Int?
vin String
make String
model String
year Int
ownersName String #default("")
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
ownersEmail String #default("")
User User? #relation(fields: [userId], references: [id])
Dealership Dealership #relation(fields: [dealershipId], references: [id])
notes Note[]
dealershipId Int
}
Here are the related types
type Contract {
id: Int!
vin: String!
make: String!
model: String!
year: Int!
ownersName: String!
User: User
userId: Int
createdAt: DateTime
updatedAt: DateTime
ownersEmail: String
}
type Query {
contractsByUser: [Contract]
}
and here is my query which i'm exporting from a cell
export const QUERY = gql`
query ContractByUser {
contractsByUser {
id
vin
make
model
year
ownersName
createdAt
}
}
I get the following error.
api | ERROR [2021-08-04 13:28:03.477 +0000] (apollo-graphql-server): GraphQL didEncounterErrors
api | errors: [
api | {
api | "message": "Cannot query field \"contractsByUser\" on type \"Query\".",
api | "locations": [
api | {
api | "line": 2,
api | "column": 3
api | }
api | ]
api | }
api | ]
api | INFO [2021-08-04 13:28:03.479 +0000] (apollo-graphql-server): GraphQL willSendResponse
api |
api | Error: Cannot query field "contractsByUser" on type "Query".
api |
api |
api | POST /graphql 400 21.533 ms - 1329
api |
api | GraphQLError: Cannot query field "contractsByUser" on type "Query".
This is definitely a validation error, but I'm not sure what i've missed or done incorrectly. I'm on the latest Version of Redwood and updated the breaking changes. Any help would be good. Maybe its not generating types correctly or.... any help would be appreciated.

I had redwood graphql function misconfigured and it wasn't importing the generated types.
Where I was:
import schemas from 'src/graphql/**/*.js'
import { db } from 'src/lib/db'
import { logger } from 'src/lib/logger'
import services from 'src/services/**/*.js'
Where I needed to be:
import schemas from 'src/graphql/**/*.{js,ts}'
import { db } from 'src/lib/db'
import { logger } from 'src/lib/logger'
import services from 'src/services/**/*.{js,ts}'

Related

How to use null safety of data model classes with graphql?

Let's assume we have the following graphql schema:
type Query {
getPost(id: ID!): Post!
getUserProfile(id: ID!): User!
}
type User {
id: ID!
name: String!
gender: String!
dob: Date!
}
type Post {
id: ID!
creator: User!
caption: String!
}
Here are the graphql queries that we are making on frontend:
getPost(id:"pid1") {
id
creator {
id
name
}
}
getUserProfile(id: "uid1") {
id
name
gender
dob
}
This is the data model class on the frontend side with which we are deserialising the server response:
class UserModel {
String id;
String name;
String? gender; // ? means nullable
String? dob; // ? means nullable
}
My issue is that we have to mark the gender & dob fields as nullable because we aren't fetching them in the getPost query hence absence of them in the server response will make them null. However, gender and dob are always non-nullable in the backend as well as in the GQL API contract defined above. So we cannot use the null-safety feature of the client-side language for these fields and are forced to check if there are null or not. Is there a workaround or better way to treat such fields as null safe?

GraphQL: Nesting Reusable Interface Fragment within a Type Fragment

I'm new to GraphQL and Apollo Client.
I'm trying to write DRY queries as much possible and found that Fragments can be of great help.
Here is how my GraphQL schema would look like:
interface header { # Implemented by multiple types
uuid: ID!
created_at: DateTime
created_by: String
updated_at: DateTime
updated_by: String
}
type account implements header #withSubscription {
id: String! #id #search(by:[term])
name: String #search(by:[fulltext])
description: String #search(by:[fulltext])
...
}
on the client side, I'm trying to setup my operations.graphql as follows:
fragment headerData on header {
uuid
created_at
created_by
updated_at
updated_by
}
fragment accountNode on account {
...headerData
id
name
description
#.. rest of the fields
}
query getPaginatedAccounts(first: Int, offset: Int) {
queryaccount {
...accountNode
# .. rest of the fields
}
}
However, when I execute the query, the results set doesn't fetch any data from the accountNode fragment.
Is this correct way to nest the fragments?
I realize that if I change the accountNode fragment as follows, it works and gets me the data:
fragment accountNode on account {
... on header {
uuid
created_at
#..rest of header fields
}
id
name
description
#.. rest of the fields
}
But since header interface is implemented by multiple types, its not DRY to repeat those fields on every Type Fragment.
Thanks in advance.

How to document errors in graphql?

type Query {
"""
ErrorCode: EMAIL_DUPLICATED
type EmailDuplicatedError {
email: String!
source: UserSource!
}
enum UserSource {
Google
Facebook
Github
}
"""
register(email: String!, password: String!): AccessToken!
}
"""
The AccessToken scalar type is a string of 16 characters.
"""
scalar AccessToken
Hope you can get what I mean through the above schema. I'd like to know if there is any code generator can support errors documented this way, so I can reduce the code I write on both client and server side.
I don't want to define errors like the following
type Query {
register(email: String!, password: String!): RegisterResponse
}
type RegisterResponse {
accessToken: AccessToken
error: EmailDuplicatedError
}
type EmailDuplicatedError {
email: String!
source: UserSource!
}
enum UserSource {
Google
Facebook
Github
}
"""
The AccessToken scalar type is a string of 16 characters.
"""
scalar AccessToken
Because I'd like errors to be responded in errors field, and api only shows what you can get when you succeeded.
Thank you for your time reading this post.
There's some ways to do error handling with GraphQL, I'll recommend you two:
Using response extensions:
GraphQL JSON response.error has a field called extensions, you can use this to set a code field like:
{
"error": {
"errors": [
{
"message": "example",
"extensions": {
"code": "YOUR CODE"
}
}
]
}
}
Using unions:
There is an medium post by Sasha Solomon that talks about that:
https://sachee.medium.com/200-ok-error-handling-in-graphql-7ec869aec9bc
Using the examples in this post, the way to handle graphql errors with unions is like this:
type User {
id: ID!
name: String
}
type Suspended {
reason: String
}
type IsBlocked {
message: String
blockedByUser: User
}
type UnavailableInCountry {
countryCode: Int
message: String
}
"User, or reason we can't get one normally"
union UserResult = User | IsBlocked | Suspended
type Query {
user: UserResult!
}

Create Prisma 2 Mutation on many to many field using Nexus

Hello guys i'm using prisma 2 in my node js serve and below is how i defined the schema of my models
model Interest {
id Int #default(autoincrement()) #id
name String
profile Profile[] #relation(references: [id])
createdAt DateTime #default(now())
updatedAt DateTime #default(now())
}
model Profile {
id Int #default(autoincrement()) #id
username String #unique
user User #relation(fields: [userId], references: [id])
interests Interest[] #relation(references: [id])
userId Int
dob String
location String
skills String
profession String
createdAt DateTime #default(now())
updatedAt DateTime #default(now())
}
So i want to connect profile to interest in my mutation resolver, but i'm not sure how to connect many to many field using prisma 2
this how i approached it, but i'm stuck
return ctx.prisma.profile.create({
data: {
dob: dob,
location: location,
profession: profession,
skills: skills,
username: username,
user: {
connect: {
id: Number(userId),
},
},
interests: {
create: []
}
},
})

GraphQL mutation - confusion designing gql tag for Apollo Client

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: "fake#gmail.com"
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
}
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.
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
}
}
}
}

Resources