How to set the Apollo GraphQL server to accept an object as a variable to a mutation? - graphql

Currently, I'm trying to pass an object as a variable to a mutation as shown below:
type ShopLocation {
lane1: String
lane2: String
city: String
postalCode: String
country: String
}
type ShopResponse {
statusCode: Int
messageCode: String
data: String
}
type Mutation {
createShop(
name: String
email: String
location: ShopLocation
): ShopResponse
}
But I get the following error:
{
"error": {
"errors": [
{
"message": "The type of Mutation.createShop(location:) must be Input Type but got: ShopLocation.",
"extensions": {
"code": "GRAPHQL_VALIDATION_FAILED",
"exception": {
"stacktrace": [
"Error: The type of Mutation.createShop(location:) must be Input Type but got: ShopLocation.",
" at assertValidSchema (.../node_modules/graphql/type/validate.js:71:11)",
" at Object.validate (.../node_modules/graphql/validation/validate.js:55:35)",
" at Promise.resolve.then (.../node_modules/apollo-server-core/src/runQuery.ts:188:30)",
" at <anonymous>",
" at process._tickDomainCallback (internal/process/next_tick.js:228:7)"
]
}
}
}
]
}
}
Any idea how to properly do this?

You need to make the ShopLocation with input keyword instead of type,
input ShopLocationInput {
lane1: String
lane2: String
city: String
postalCode: String
country: String
}
type ShopResponse {
statusCode: Int
messageCode: String
data: String
}
type Mutation {
createShop(
name: String
email: String
location: ShopLocationInput
): ShopResponse
}

Related

graphql query with args not working for user id

I am bamboozled. I initially created the user query and it was giving me errors that I assumed were syntax errors. But then I created an identical query for vehicles which works perfectly. I have a suspicion that it's related to the ID! type but I have run out of leads. Any help would be appreciated!
Here are my typedefs and resolvers.
//TYPEDEFS//
type User {
id: ID!
fname: String
lname: String
email: String
password: String
vehicles: [Vehicle]
}
type Vehicle {
id: ID!
vin: String
model: String
make: String
drivers: [User]
}
type Query {
users: [User]
user(id: ID!): User
vehicles: [Vehicle]
vehicle(vin: String): Vehicle
}
//RESOLVERS//
user: async (parent, args, context) => {
const { id } = args
return context.prisma.user.findUnique({
where: {
id,
},
})
},
vehicle: async (parent, args, context) => {
const { vin } = args
return context.prisma.vehicle.findUnique({
where: {
vin,
}
})
}
//QUERY//
**This one is the broken one and has the error: Got invalid value '1' on prisma.findOneUser. Provided String, expected Int
**I've tried doing id: "1" and user(where: {id: 1})
query {
user(id:1){
id
fname
}
}
**This one works as intended
query {
vehicle(vin:"123123123"){
vin
make
}
}
//FULL ERROR*//
{
"errors": [
{
"message": "\nInvalid `prisma.user.findUnique()` invocation:\n\n{\n where: {\n id: '1'\n ~~~\n }\n}\n\nArgument id: Got invalid value '1' on prisma.findOneUser. Provided String, expected Int.\n\n",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"user"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"clientVersion": "2.13.1",
"stacktrace": [
"Error: ",
"Invalid `prisma.user.findUnique()` invocation:",
"",
"{",
" where: {",
" id: '1'",
" ~~~",
" }",
"}",
"",
"Argument id: Got invalid value '1' on prisma.findOneUser. Provided String, expected Int.",
"",
"",
" at Document.validate (/home/atran/workspace/m4m/m4m_server/node_modules/#prisma/client/runtime/index.js:76090:19)",
" at NewPrismaClient._executeRequest (/home/atran/workspace/m4m/m4m_server/node_modules/#prisma/client/runtime/index.js:77796:17)",
" at resource.runInAsyncScope (/home/atran/workspace/m4m/m4m_server/node_modules/#prisma/client/runtime/index.js:77733:52)",
" at AsyncResource.runInAsyncScope (async_hooks.js:188:21)",
" at NewPrismaClient._request (/home/atran/workspace/m4m/m4m_server/node_modules/#prisma/client/runtime/index.js:77733:25)",
" at Object.then (/home/atran/workspace/m4m/m4m_server/node_modules/#prisma/client/runtime/index.js:77850:39)",
" at process._tickCallback (internal/process/next_tick.js:68:7)"
]
}
}
}
],
"data": {
"user": null
}
}
Prisma expects an Int:
"Argument id: Got invalid value '1' on prisma.findOneUser. Provided
String, expected Int.",
Therefore you need to cast id to a number. Maybe something like this:
user: async (parent, args, context) => {
const id = +args.id;
return context.prisma.user.findUnique({
where: { id }
});
}

How to pass nested variables to the GraphQL query in Apollo?

Trying to pass nested variables to the GraphQL query but my server gets only top-level variables (shopId), everything else is null.
I tried:
#1
const CALCULATE_PACKAGE_PRICE = gql`
query CalculatePackagePrice(
$shopId: String!
$address1: String
$zip: String
$city: String
$countryCode: String
) {
calculatePackagePrice(
where: {
shopId: $shopId
destination: {
address1: $address1
zip: $zip
city: $city
countryCode: $countryCode
}
}
) {
name
price
userErrors {
field
message
}
}
}
`
const [calculatePackagePrice, { loading, data }] = useLazyQuery(
CALCULATE_PACKAGE_PRICE,
{
variables: {
shopId: shopId,
destination: {
address1: "Example 123",
zip: "123",
city: "Test",
countryCode: "US",
},
},
}
)
And #2:
export function CALCULATE_PACKAGE_PRICE({ shopId, destination }) {
return gql`
query CalculatePackagePrice {
calculatePackagePrice(
where: {
shopId: "${shopId}"
destination: {
address1: "${destination.address1}"
zip: "${destination.zip}
city: "${destination.city}"
countryCode: "${destination.countryCode}"
}
}
) {
name
price
userErrors {
field
message
}
}
}
`
}
const [calculatePackagePrice, { loading, data }] = useLazyQuery(
CALCULATE_PACKAGE_PRICE({
shopId: shopId,
destination: {
address1: "Example 123",
zip: "123",
city: "Test",
countryCode: "US",
},
})
)
It works just fine when I hardcoded variables content to the queries. What I'm doing wrong?
Here is a helpful snippet from graphql docs,
All declared variables must be either scalars, enums, or input object types. So if you want to pass a complex object into a field, you need to know what input type that matches on the server.
You're correctly passing in the variables as strings, but then trying (perhaps successfully, but I've never seen the syntax before) to create the object in the gql template string. Instead, create an input type for destination and where.
input WhereInput {
shopId: String!
destination: DestinationInput!
}
input DestinationInput {
address1: String!
zip: String!
city: String!
countryCode: String!
}
then change the query on the client (and update the server definition),
const CALCULATE_PACKAGE_PRICE = gql`
query CalculatePackagePrice($where: WhereInput!) {
calculatePackagePrice(where: $where) {
name
price
userErrors {
field
message
}
}
}
`
then pass the variables like,
const [calculatePackagePrice, { loading, data }] = useLazyQuery(
CALCULATE_PACKAGE_PRICE,
{
variables: {
where: {
shopId,
destination: {
address1: "Example 123",
zip: "123",
city: "Test",
countryCode: "US",
},
},
}
}
)

Apollo GraphQL tutorial: "GraphQLError: Cannot query field \"id\" on type \"LaunchConnection\"."

I'm trying to follow the Apollo GraphQL tutorial at this step, https://www.apollographql.com/docs/tutorial/resolvers/#run-queries-in-the-playground. Following https://github.com/apollographql/fullstack-tutorial, I ran
cd final/server && npm i && npm start
as well as
cd final/client && npm i && npm start
(For the final/server, I first deleted the package-lock.json before running npm install because I was running into issues with the sqlite3 dependency).
However, in the GraphQL playground on localhost:4000, if I try to run the query
query GetLaunches {
launches {
id
mission {
name
}
}
}
I get the error response
{
"error": {
"errors": [
{
"message": "Cannot query field \"id\" on type \"LaunchConnection\".",
"locations": [
{
"line": 3,
"column": 5
}
],
"extensions": {
"code": "GRAPHQL_VALIDATION_FAILED",
"exception": {
"stacktrace": [
"GraphQLError: Cannot query field \"id\" on type \"LaunchConnection\".",
" at Object.Field (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/graphql/validation/rules/FieldsOnCorrectType.js:64:31)",
" at Object.enter (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/graphql/language/visitor.js:334:29)",
" at Object.enter (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/graphql/language/visitor.js:385:25)",
" at visit (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/graphql/language/visitor.js:252:26)",
" at Object.validate (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/graphql/validation/validate.js:63:22)",
" at validate (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/apollo-server-core/dist/requestPipeline.js:211:32)",
" at Object.<anonymous> (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/apollo-server-core/dist/requestPipeline.js:124:42)",
" at Generator.next (<anonymous>)",
" at fulfilled (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/apollo-server-core/dist/requestPipeline.js:4:58)",
" at processTicksAndRejections (internal/process/task_queues.js:93:5)"
]
}
}
},
{
"message": "Cannot query field \"mission\" on type \"LaunchConnection\".",
"locations": [
{
"line": 4,
"column": 5
}
],
"extensions": {
"code": "GRAPHQL_VALIDATION_FAILED",
"exception": {
"stacktrace": [
"GraphQLError: Cannot query field \"mission\" on type \"LaunchConnection\".",
" at Object.Field (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/graphql/validation/rules/FieldsOnCorrectType.js:64:31)",
" at Object.enter (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/graphql/language/visitor.js:334:29)",
" at Object.enter (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/graphql/language/visitor.js:385:25)",
" at visit (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/graphql/language/visitor.js:252:26)",
" at Object.validate (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/graphql/validation/validate.js:63:22)",
" at validate (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/apollo-server-core/dist/requestPipeline.js:211:32)",
" at Object.<anonymous> (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/apollo-server-core/dist/requestPipeline.js:124:42)",
" at Generator.next (<anonymous>)",
" at fulfilled (/Users/kurt/Documents/Scratch/fullstack-tutorial/final/server/node_modules/apollo-server-core/dist/requestPipeline.js:4:58)",
" at processTicksAndRejections (internal/process/task_queues.js:93:5)"
]
}
}
}
]
}
}
(See screenshot below).
Any idea what is causing this? I do see a GraphQL schema in the right pop-up window which appears to contain these fields:
directive #cacheControl(
maxAge: Int
scope: CacheControlScope
) on FIELD_DEFINITION | OBJECT | INTERFACE
enum CacheControlScope {
PUBLIC
PRIVATE
}
type Launch {
id: ID!
site: String
mission: Mission
rocket: Rocket
isBooked: Boolean!
}
type LaunchConnection {
cursor: String!
hasMore: Boolean!
launches: [Launch]!
}
type Mission {
name: String
missionPatch(size: PatchSize): String
}
type Mutation {
bookTrips(launchIds: [ID]!): TripUpdateResponse!
cancelTrip(launchId: ID!): TripUpdateResponse!
login(email: String): String
}
enum PatchSize {
SMALL
LARGE
}
type Query {
launches(
pageSize: Int
after: String
): LaunchConnection!
launch(id: ID!): Launch
me: User
}
type Rocket {
id: ID!
name: String
type: String
}
type TripUpdateResponse {
success: Boolean!
message: String
launches: [Launch]
}
scalar Upload
type User {
id: ID!
email: String!
trips: [Launch]!
}
Looking at the schema you provided, Query launches returns type LaunchConnection
type LaunchConnection {
cursor: String!
hasMore: Boolean!
launches: [Launch]!
}
type Query {
launches: LaunchConnection!
}
Your query, below, is expected to return type LaunchConnection
query GetLaunches {
launches {
id
mission {
name
}
}
}
But LaunchConnection has fields cursor, hasMore & launches. You are asking for fields id & mission on the incorrect type. You should first dive into the launches field on LaunchConnection then you can ask for fields on the Launch type. Your query should look like the following:
query GetLaunches {
launches {
launches {
id
mission {
name
}
}
}
}

Logical OR in SDL - field name 'OR' that is not defined for input object type

I am trying to return students of who are either mature or highscool
graphqlOperation(listStudents, {
filter: {
type: { eq: 'student' },
OR: [{ category: { eq: 'mature' }, { eq: 'highschool' }]
},
})
);
It looks like I need to add the logical OR in my schema
input TableStudentFilterInput {
ID: TableStringFilterInput
type: TableStringFilterInput
category: TableStringFilterInput
name: TableStringFilterInput
}
and my filter
input TableStringFilterInput {
ne: String
eq: String
le: String
lt: String
ge: String
gt: String
contains: String
notContains: String
between: [String]
}
How do I allow my schema to accept a logical operator?

How to write graphql query wiith custom objects

The server side of graphql is with nodejs and express. This is the schema for graphql. It has one query which accepts DateT object having from and to dates.
var schema = buildSchema(`
type Query {
courseWithDate(
timeFilter: DateT
): Course
},
type Course {
...
from: String
to: String
},
type DateT{
from : String
to : String
}
`);
and this is how I am getting courses
I am able to run the application with this url
localhost:4000/graphql
This is the query I am using
query courseWithDate($from: dateFrom, $to: dateTo) {
courseWithDate(timeFilter: {
from: "${dateFrom}"
to: "${dateTo}"
}) {
title
...
}
}
with these parameters
{
"from": "2019-10-10","to":"2019-10-10"
}
Exception message I get is related to the input type I am trying to pass.
{
"errors": [
{
"message": "The type of Query.courseWithDate(timeFilter:) must be Input Type but got: DateT.",
"locations": [
{
"line": 6,
"column": 25
}
]
}
]
}
I'm not sure, but probably this style looks more like best practice
type Course {
id: Int
title: String
author: String
from: String
to: String
description: String
topic: String
url: String
}
input DateInput {
dateFrom: String!
dateTo: String!
}
type Query {
courseWithDate(input: DateInput!, name: String!): Course
}
And Query on client side should be:
{
courseWithDate(input: {
dateFrom: "${dateFrom}"
dateTo: "${dateTo}"
}
name: "${name}")
{
id
name
}
}

Resources