Amplify GraphQL adding nested Inputs to Connections - graphql

I have created the following schema which up until yesterday would generate Input using the #connection reference ID. I created a new API which is now creating an Input with the actual nested type as part of the Input for some of the types. E.g:
type Metadata
#model(subscriptions: null)
#versioned
#auth(
rules: [
]
) {
id: ID!
merchant: Merchant! #connection
}
type Merchant
#model(subscriptions: null)
#versioned
#auth(
rules: []
) {
id: ID!
metadata: Metadata! #connection
}
would create the Input types:
export type CreateMerchantInput = {
id?: string | null,
merchantMetadataId: string,
};
export type CreateMetadataInput = {
id?: string | null,
merchant: MerchantInput, <-- Contains this!!
metadataMerchantId: string,
};
The Appsync schema shows this too, so it's something on my machine that has compiled the main GraphQL schema and pushed it. Really scary that different machines can compile it differently!!
Does anyone have any ideas what I have changed or am missing or have specified in my schema or Amplify CLI config please?

Related

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.

Graphql mutation error in aws amplify appsync

I am trying to insert/mutate a data using graphql to a dynamodb, see image below having error while inserting data. I am confused if the error exist while creating the schema or while mutating the data. The table was created using amplify
this is the schema script
type PersonalAttributes {
FirstName: String
LastName: String
MiddleName: String
Email: String
Highlights: String
}
type Configurations {
StudyTopic: String
SpokenLanguage: String
Gender: String
ReadbackSpeed: Float
}
type Chapter {
CTitle: String
Content: String
TermHighlights: [String]
}
type Book {
Title: String
Author: String
HighlightsChapter: [Chapter]
}
type Athena #model {
UserKey: ID
UserName: String!
PersonalInformation: [PersonalAttributes]
SysConfig: [Configurations]
Books: [Book]
}
I recommend including an id: ID! for your Athena model. Provide a valid ID whenever you create Athena objects.
The error indicates that no id was provided (Dynamo wanted a valid, non-null String, but it got null.)
The error results from the create mutation call, not from setup of the Dynamo table.

Apollo client's codegen adds unwanted "or null" in my types

Apollo client's codegen adds | null in the generated types, and I don't understand why they are there and how to get rid of them.
I see no reason why the API would return an array of null, so I don't want to check in my code weather the oject is null or not everytime.
Offending generated types from apollo codegen:
export interface MusicGenres_musicGenres {
name: string;
}
export interface MusicGenres {
musicGenres: (MusicGenres_musicGenres | null)[];
^^^^^^
WHY ?
}
My Graphql Schema:
type Query {
musicGenres: [MusicGenre]!
}
type MusicGenre {
id: ID!
name: String!
}
Query in my TypeScript code from which are generated the types:
gql`
query MusicGenres {
musicGenres { name }
}
`
In your schema, you have the following field definition:
musicGenres: [MusicGenre]!
This means that while musicGenres will be a list and will itself never be null, any item in the list could be null. If you want to indicate that all items in the list are also non-nullable, your field definition should instead be:
musicGenres: [MusicGenre!]!
See this post for an extended explanation.

Prisma Not Returning Created Related Records

i want to create a new graphql api and i have an issue that i am struggling to fix.
the code is open source and can be found at: https://github.com/glitr-io/glitr-api
i want to create a mutation to create a record with relations... it seems the record is created correctly with all the expected relations, (when checking directly into the database), but the value returned by the create<YourTableName> method, is missing all the relations.
... so so i get an error on the api because "Cannot return null for non-nullable field Meme.author.". i am unable to figure out what could be wrong in my code.
the resolver looks like the following:
...
const newMeme = await ctx.prisma.createMeme({
author: {
connect: { id: userId },
},
memeItems: {
create: memeItems.map(({
type,
meta,
value,
style,
tags = []
}) => ({
type,
meta,
value,
style,
tags: {
create: tags.map(({ name = '' }) => (
{
name
}
))
}
}))
},
tags: {
create: tags.map(({ name = '' }) => (
{
name
}
))
}
});
console.log('newMeme', newMeme);
...
that value of newMeme in the console.log here (which what is returned in this resolver) is:
newMeme {
id: 'ck351j0f9pqa90919f52fx67w',
createdAt: '2019-11-18T23:08:46.437Z',
updatedAt: '2019-11-18T23:08:46.437Z',
}
where those fields returned are the auto-generated fields. so i get an error for a following mutation because i tried to get the author:
mutation{
meme(
memeItems: [{
type: TEXT
meta: "test1-meta"
value: "test1-value"
style: "test1-style"
}, {
type: TEXT
meta: "test2-meta"
value: "test2-value"
style: "test2-style"
}]
) {
id,
author {
displayName
}
}
}
can anyone see what issue could be causing this?
(as previously mentioned... the record is created successfully with all relationships as expected when checking directly into the database).
As described in the prisma docs the promise of the Prisma client functions to write data, e.g for the createMeme function, only returns the scalar fields of the object:
When creating new records in the database, the create-method takes one input object which wraps all the scalar fields of the record to be
created. It also provides a way to create relational data for the
model, this can be supplied using nested object writes.
Each method call returns a Promise for an object that contains all the
scalar fields of the model that was just created.
See: https://www.prisma.io/docs/prisma-client/basic-data-access/writing-data-JAVASCRIPT-rsc6/#creating-records
To also return the relations of the object you need to read the object again using an info fragment or the fluent api, see: https://www.prisma.io/docs/prisma-client/basic-data-access/reading-data-JAVASCRIPT-rsc2/#relations

GraphQL no object type?

I've read everything, understood no solution and concrete explanation (even here: Apollo / GraphQl - Type must be Input type)
I want to create an object System that contains Suns. So I do:
type System {
_id: ID
name: String! #unique
diameter: Int
suns: [Sun]
}
type Sun {
_id: ID
name: String
diameter: Int
}
type Mutation {
createSystem(name: String!, diameter: Int, suns: [Sun]): System!
}
And I write in playground:
mutation {
createSystem(name:"new system", suns: [{ name: "John" }]) {
name
suns
}
}
But I got a terminal error: "Error: The type of Mutation.createSystem(suns:) must be Input Type but got: [Sun]."
I understand that Sun isn't received as an object. How to declare it as an object?
Thank you very much for your answers
The GraphQL spec. does not allow using type (i.e. output type) as the input argument.It only allows the input arguments to be enum , Scalar and Input . That means you have to create a SunInput
input SunInput {
_id: ID
name: String
diameter: Int
}
You need to make a custom "Type" for sun with its own resolver.
suns: { type: new GraphQLList(SunType) } // just an example
mutation {
createSystem(name:"new system", suns-names: "John") {
name
}
}
It will have resolver that writes a new system to the database called new system that adds a sun of "SunType" to the a database collection with the name of "Sun" for example.

Resources