GraphQL Input set Boolean value - graphql

I am working on a GraphQL Input Scheme which is based on a Union. The goal is to have either only a delivery address with hasInvoice: false or have a delivery address and invoice address with hasInvoice: true. I got it everything working except the boolean part.
input BaseAddress {
street: String!
number: Int!
}
input OnlyDeliveryAddress {
address: BaseAddress!
withInvoiceAddress: false!
}
input WithInvoiceAddress {
address: BaseAddress!
withInvoiceAddress: true!
invoiceAddress: BaseAddress!
}
union Address = OnlyDeliveryAddress | WithInvoiceAddress
Having booleans as Scalars is not working. Is there a way to only allow the specified boolean to be accepted?

Related

GraphQL variable combination validation

Imagine the following (simplified) GraphQL schema:
type User {
username: String
email: String
}
type Query {
user(username: String, email: String): User
}
If I would only want to allow querying user by giving a username, I would of course change it to user(username: String!), making the username required using the exclamation mark. Same thing vice versa with the email.
Is it possible though to have a GraphQL native solution where I validate for the existence of only either one (logical XOR) or at least one (logical OR) of the two input parameters?
Of course I could do it in the query resolver manually, but a #constraint directive like it is being used in Apollo GraphQL spreading across variables would be nice.
Directly ... not possible:
check fields existence [within args] on resolver;
use #constraint to check each field shape;
Indirectly:
you can try to use union of input types:
.
type UserNameInput {
username: String!
}
type UserEmailInput {
email: String!
}
type UserInput = UserNameInput | UserEmailInput
type Query {
user(input: UserInput): User
}

How to write mutation in graphql-playgraound for the output

I want to see output in graphql-playground of mutations which I don't know how to do. Code is below.
type Query {
""" Gets single referral program"""
program:Program
setting(level_id:Int!): Setting
}
type Mutation {
"""Define loyalty program for a club"""
define_program(input:DefineProgram): Program
"""Club level loyalty program configuration"""
config_program(input:ProgramConfig): Setting
get_individual_code(input:Individual): String
get_group_code(input:Group): String
}
type Program {
id: String
name: String
referral_level_id:Int
enabled:Boolean
}
input DefineProgram {
name: String!
type:ReferralType!
referral_level_id:Int!
enabled:Boolean = true
userid: Int
}
input ProgramConfig {
program_id: Int!
level_id:Int!
type:CodeType!
expirydays:String!
validity:Int!
limit:Int!
userid:Int
}
input Individual {
member_id:Int!
days_to_expire:Int!
first_name:String!
last_name:String!
email:String!
userid:Int
}
input Group {
member_id: Int!
days_to_expire:Int!
people:Int!
userid:Int
}
input Filter {
program_id: Int!
level_id: Int!
}
type Setting {
program_id: Int
program_name:String
level_id:Int
tier:String
type:CodeType
expirydays:String
validity:Int
limit:Int
}
enum CodeType {
NUMERIC
ALPHA_NUMERIC
}
enum ReferralType {
INDIVIDUAL,
GROUP,
BOTH
}
Can anyone tell me how to write for all mutations to get data in graphql-playground.
Help if anyone can.
GraphQL playground will actually give you autocomplete capabilities. It sounds like you're just starting out with consuming GraphQL, though, so I would recommend you start with the learning queries from graphql.org, and then once you're comfortable there, you should be able to put together queries / mutations for your specific examples.

GraphQL error FieldsConflict: fields have different list shapes

I'm using AWS AppSync's GraphQL server with the following (simplified) schema:
type Query {
getIssue(id: String!): Issue
}
type Issue {
id: String!
data: IssueData!
}
type Event {
id: String!
time: AWSDateTime!
status: [String]
}
type Payment {
id: String!
amount: Int!
status: String
}
union IssueData = Event | Payment
When I make a query that includes inline fragments to select the status as a child of either an Event or Payment type in the Issue/data field, I get a FieldsConflict error:
query getIssue($id: String!) {
getIssue(id: $id) {
id
data {
... on Event {
time
status
}
... on Payment {
amount
status
}
}
}
}
Validation error of type FieldsConflict: status: fields have different list shapes # 'getIssue/data'
This is presumably caused by the Event/status field returning an array of strings, while the Payment/status field returns a single string.
Why does GraphQL consider this to be a conflict? How should I construct my query to allow access to the status field on both data types?
Note that I'm using a union rather than an extended interface because the Issue and Payment types have no common data structure.
From the spec:
If multiple field selections with the same response names are encountered during execution, the field and arguments to execute and the resulting value should be unambiguous. Therefore any two field selections which might both be encountered for the same object are only valid if they are equivalent.
You can resolve the issue by providing a field alias for one or both fields:
query getIssue($id: String!) {
getIssue(id: $id) {
id
data {
... on Event {
time
eventStatus: status
}
... on Payment {
amount
status
}
}
}
}
Renaming one or both fields in your schema would obviously also resolve the issue.

Validation of properties in GraphQL

input MessageInput {
content: String
author: String
}
type Message {
id: ID!
content: String
author: String
}
type Query {
getMessage(id: ID!): Message
}
type Mutation {
createMessage(input: MessageInput): Message
}
Message content can be max length 255. How to document that max length is 255 characters? How/Where to do this validation?
On the server-side, you would validate in the resolver for the createMessage mutation.
I would also recommend having some sort of client-side validation as well!

Pagination in apollo-graphql server

I want to implement cursor based pagination in Apollo graphql server. I have prepared schema with pagination requirement. But i am stuck at resolver side.
Here is my schema
const typeDefinitions = `
input CreateDeveloperInput {
# An arbitrary string value with no semantic meaning. Will be included in the
# payload verbatim. May be used to track mutations by the client.
clientMutationId: String
developer: DeveloperInput!
}
type CreateDeveloperPayload {
clientMutationId: String
developerEdge(orderBy: DevelopersOrderBy = PRIMARY_KEY_ASC): DevelopersEdge
query: Query
}
input DeleteDeveloperByIdInput {
# An arbitrary string value with no semantic meaning. Will be included in the
# payload verbatim. May be used to track mutations by the client.
clientMutationId: String
id: Int!
}
input DeleteDeveloperInput {
clientMutationId: String
nodeId: ID!
}
type DeleteDeveloperPayload {
clientMutationId: String
developer: Developer
deletedDeveloperId: ID
# Our root query field type. Allows us to run any query from our mutation payload.
query: Query
}
type Developer implements Node {
nodeId: ID!
id: Int!
name: String!
place: String
salary: Int
joiningDate: String
}
input DeveloperCondition {
id: Int
name: String
place: String
salary: Int
joiningDate: String
}
input DeveloperInput {
id: Int
name: String!
place: String
salary: Int
joiningDate: String
}
input DeveloperPatch {
id: Int
name: String
place: String
salary: Int
joiningDate: String
}
type DevelopersConnection {
# Information to aid in pagination.
pageInfo: PageInfo!
totalCount: Int
edges: [DevelopersEdge]
nodes: [Developer!]
}
type DevelopersEdge {
# A cursor for use in pagination.
cursor: String
node: Developer!
}
enum DevelopersOrderBy {
PRIMARY_KEY_ASC
PRIMARY_KEY_DESC
NATURAL
ID_ASC
ID_DESC
NAME_ASC
NAME_DESC
PLACE_ASC
PLACE_DESC
SALARY_ASC
SALARY_DESC
JOINING_DATE_ASC
JOINING_DATE_DESC
}
# The root mutation type which contains root level fields which mutate data.
interface Node {
# A globally unique identifier. Can be used in various places throughout the system to identify this single value.
nodeId: ID!
}
# Information about pagination in a connection.
type PageInfo {
# When paginating forwards, are there more items?
hasNextPage: Boolean!
# When paginating backwards, are there more items?
hasPreviousPage: Boolean!
# When paginating backwards, the cursor to continue.
startCursor: String
# When paginating forwards, the cursor to continue.
endCursor: String
}
# The root query type which gives access points into the data universe.
type Query implements Node {
allDevelopers(
# Read all values in the set before (above) this cursor.
before: String,
# Read all values in the set after (below) this cursor.
after: String, first: Int, last: Int, offset: Int,
# A condition to be used in determining which values should be returned by the collection.
condition: DeveloperCondition): DevelopersConnection
# Exposes the root query type nested one level down. This is helpful for Relay 1
# which can only query top level fields if they are in a particular form.
nodeId: ID!
}
schema {
query: Query
}
`;
export default [typeDefinitions];
Is it possible to resolve in resolvers? If yes, can any one please tell me how to implement it
If you're using Mongo and Mongoose with Apollo Express GraphQL I have found three ways to do pagination:
You can create a cursor field on your schema and implement your resolver with the pagination logic, but I don't recommend this method if you have a complex schema that contain unions, interfaces and different nested objects on the type, but if you want to implement it by yourself here's the reference
You can use a module which will nest your Mongoose model and provide you an pagination interface, but this requires a few changes on your schema and resolvers, more work then the third method
You can use sort, skip and limit from Mongo / Mongoose, but if you do this by yourself you can find some issues, e.g if the document was sorted by a date key which can have different documents with the same date it can duplicate documents and mess up with your pagination, so I recommend that you install a pagination plugin on your Mongoose schema and use it like any other method from Mongoose

Resources