Nested GraphQL mutations with AWS Amplify - graphql

I'm struggling to write a nested GraphQL mutation for a React Native app I'm building with GraphQL client being AWS Amplify API. Here's my type definition file
type Game #model {
id: ID!
gameId: String!
players: [Player!]!
}
type Player #model {
id: ID!
username: String!
}
Here's my attempt to create a mutation to create a new Game
import API, { graphqlOperation } from '#aws-amplify/api';
const CreateGame = `
mutation ($gameId: String! $username: String!) {
createGame(input: {
gameId: $gameId,
players: [{ username: $username }]
}) {
id
gameId
players
}
}
`;
const gameObj = {
gameId: 'example_game_id',
username: 'example_username'
};
const queryResp = await API.graphql(graphqlOperation(CreateGame, gameObj));
console.log(queryResp.data);
Here's the error I get
"Validation error of type WrongType: argument 'input' with value 'ObjectValue{objectFields=[ObjectField{name='gameId', value=VariableReference{name='gameId'}}, ObjectField{name='players', value=ArrayValue{values=[ObjectValue{objectFields=[ObjectField{name='username', value=VariableReference{name='username'}}]}]}}]}' contains a field not in 'CreateGameInput': 'players' # 'createGame'"

Related

Prisma - Where selector on type with two unique fields

I'm trying to implement resolver which will check if the user with given login exists in the database. But I have a hard time with where selector in Prisma.
So I have the type User:
type User {
UserID: ID! #id
Login: String! #unique
Password: String!
Phone: String!
Mail: String!
Comments: [Comment!]
#relation(
name: "AllCommentsOfUser"
fields: [UserID]
references: [CommentID]
)
Likes: [Like!]
#relation(name: "AllLikesOfUser", fields: [UserID], references: [LikeID])
createdAt: DateTime! #createdAt
}
This is the query generated by Prisma
user(where: UserWhereUniqueInput!): User
input UserWhereUniqueInput {
UserID: ID
Login: String
}
In the login function am trying to check if the user with given login exist in my database:
async login(parent, { email, password, username }, ctx, info) {
const user = await ctx.prisma.user({ username }); // Option 1
const user = await ctx.prisma.user({ Login: username }); // Option 2
if (!user) {
throw new Error(`No such user found for email: ${username}`);
}
const valid = await bcrypt.compare(password, user.password);
if (!valid) {
throw new Error("Invalid password");
}
return {
token: jwt.sign({ userId: user.id }, process.env.JWT_SECRET),
user,
};
},
},
Each time I'm ending up with following error message:
You provided an invalid argument for the where selector on User. Please provide exactly one unique field and value.

GraphQL Query returning null. Not sure why though [duplicate]

This question already has answers here:
Why does a GraphQL query return null?
(6 answers)
Closed 2 years ago.
I'm having some trouble with a graphQL query returning null and i'm not quite sure why its returning null. I've read several posts similar to this post but none of those posts have helped identify my exact problem.
I think it has something to do with how i'm passing/getting parameters, since my query with no parameters works fine, but i'm not sure since I can't find any other examples online.
Any help would be greatly appreciated.
I'm using apollo-server, graphql, and a community SQL datasource implementation which uses Knex to create a database connection.
There are two queries I can make.
allParts() - this query works as expected and returns all parts in my database with requested graphQL fields
getPart(itemnum) - this is the query that is not currently working.
graphQL Query:
query{
getPart(itemnum: "T|0000000000001"){
desc
}
}
graphQL response:
"message": "Cannot return null for non-nullable field Part.desc.",
SQL query that is being executed based on Knex debug message:
method: 'select',
options: {},
timeout: false,
cancelOnTimeout: false,
bindings: [ 'T|0000000000001' ],
__knexQueryUid: '3a8234eb-0a5c-46db-ad8e-5508288c9a86',
sql: 'select * from `part` where `itemnum` = ?'
index.js:
const { ApolloServer } = require('apollo-server');
const typeDefs = require('./schema');
const resolvers = require ('./resolvers')
const PartAPI = require ('./datasources/partAPI');
const knexConfig = {
client: "sqlite3",
connection: {
/* CONNECTION INFO */
filename: "./TEAM_material.db3"
},
debug: true
};
const server = new ApolloServer({
typeDefs,
resolvers,
dataSources: () => ({
partAPI: new PartAPI(knexConfig),
}),
introspection: true,
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
partAPI.js:
const { SQLDataSource } = require("datasource-sql");
const MINUTE = 60;
class PartAPI extends SQLDataSource {
getPart(itemnum){
return this.knex.select('*').from('part').where({itemnum});
}
getAllParts(){
const query = this.knex.select('*').from('part').cache(MINUTE);
console.log (query);
return query;
}
}
module.exports = PartAPI;
schema.js
// src/schema.js
const { gql } = require('apollo-server')
const typeDefs = gql`
#Types
type Part {
itemnum: String!
desc: String!
vendor: String!
manuf: String!
venlist: Float!
price: Float!
teamlist: Float!
teamsell: Float!
unitypart: String!
pkgqty: Int!
ioType: String!
preferred: Boolean!
filterlvl1: String!
filterlvl2: String!
filterlvl3: String!
filterlvl4: String!
ipwiretype: String!
opwiretype: String!
obsolete: Boolean!
}
#Queries
type Query {
getPart(itemnum: String!): Part
allParts: [Part!]!
}
`;
module.exports = typeDefs
resolvers.js
// src/resolvers.js
const resolvers = {
Query: {
getPart: (_,args,{dataSources}) => dataSources.partAPI.getPart(args.itemnum),
allParts: (_,__,{dataSources}) => dataSources.partAPI.getAllParts(),
},
};
module.exports = resolvers
turns out my schema was incorrect. The getPart query was expecting a Part but instead my query was returning an array of Part.
old Schema
#Queries
type Query {
getPart(itemnum: String!): Part
allParts: [Part!]!
}
`;
new Schema
#Queries
type Query {
getPart(itemnum: String!): [Part]!
allParts: [Part!]!
}
`;

How to configure endpoint and custom graphql query in React-Admin

I'm setting up a react-admin app, that needs to connect with a Hasura Service using a graphql provider. To do so, I need to pass for the provider the endpoint "/v1/graphql" and the query with the selects subfields. Like this:
query MyQuery {
account_customers {
customer_id
email
given_name
}
}
I tried to use the Hasura Provider (https://github.com/hasura/ra-data-hasura/) but the requisitions are going to "/v1/query", and I couldn't found how to change it. Also couldn't figure out how to send my custom query with the subfields.
I also tried to use ra-data-graphql-simple provider, to override a query
to get the resource with the subfields.
/providers/myProvider.js
import buildGraphQLProvider, { buildQuery } from 'ra-data-graphql-simple';
import gql from 'graphql-tag';
const myBuildQuery = introspection => (fetchType, resource, params) => {
const builtQuery = buildQuery(introspection)(fetchType, resource, params);
if (resource === 'account_customers' && fetchType === 'GET_LIST') {
return {
// Use the default query variables and parseResponse
...builtQuery,
// Override the query
query: gql`
query ($id: ID!) {
account_customers {
customer_id
email
name
}
}`,
};
}
return builtQuery;
}
export default buildGraphQLProvider({ buildQuery: myBuildQuery })
App.js
import buildGraphQLProvider from './providers/myProvider.js';
class App extends Component {
constructor() {
super();
this.state = { dataProvider: null };
}
componentDidMount() {
buildGraphQLProvider({ clientOptions: { uri: 'http://localhost:8080/v1/graphql' }})
.then(dataProvider => this.setState({ dataProvider }));
}
render() {
const { dataProvider } = this.state;
return (
<div className="App">
<Admin dataProvider={dataProvider} >
<Resource name="account_customers" list={ListGuesser} />
</Admin>
</div>
);
}
}
export default App;
But I'm getting the error:
"Unknown resource account_customers. Make sure it has been declared on your server side schema. Known resources are "
I have had a similar issue.
The react-admin data provider you're using expects a certain shape of the GraphQL API, so it can get all items, create an item, update an item etc.
I have solved it by making sure that my schema complies with this:
type Query {
Post(id: ID!): Post
allPosts(page: Int, perPage: Int, sortField: String, sortOrder: String, filter: PostFilter): [Post]
_allPostsMeta(page: Int, perPage: Int, sortField: String, sortOrder: String, filter: PostFilter): ListMetadata
}
type Mutation {
createPost(
title: String!
views: Int!
user_id: ID!
): Post
updatePost(
id: ID!
title: String!
views: Int!
user_id: ID!
): Post
deletePost(id: ID!): Post
}
type Post {
id: ID!
title: String!
views: Int!
user_id: ID!
User: User
Comments: [Comment]
}
input PostFilter {
q: String
id: ID
title: String
views: Int
views_lt: Int
views_lte: Int
views_gt: Int
views_gte: Int
user_id: ID
}
type ListMetadata {
count: Int!
}
So in your case, you would need these endpoints (and change the naming in your backend):
AccountCustomer
allAccountCustomers
_allAccountCustomersMeta
updateAccountCustomer
createAccountCustomer
deleteAccountCustomer
etc...

GraphQL resolver for certain field not being invoked

I wrote simple GraphQL schemas and resolvers in studying purpose, and I could not get reason why my codes work as expected. I used Prisma for ORM, and express-graphql and graphql-import to compose the API.
type User {
id: ID!
name: String!
}
type Link {
id: ID!
url: String!
user: User!
}
type Query {
links(id: ID!): [Link!]!
}
// resolvers
const links = async (root, args, ctx) => {
const links = await ctx.prisma.links({
where: {
user {
id: args.id
}
}
}
}
// resolver for `Link` type
const user = async (root, args, ctx) => {
const user = await ctx.prisma.link({ id: parent.id }).user()
return user
}
// omitted field resolver for `url` and `id`
module.exports = {
user
}
With these codes, I expected to get id, url, user fields when I query links, but when I send the query, it returns null with user field. Which means, if I check in the server-side, the resolver for user field does not invoked at all. What is wrong with this?

Custom InputTypes with react-apollo

I'm trying to execute a mutation query that requires a custom input type on the client. Currently it looks something like this:
import { graphql } from 'react-apollo';
...
const graphQuery = graphql(gql`
input UserSignUpInput {
firstName: String!,
lastName: String!,
email: String!,
password: String!
}
mutation userSignUp($input: UserSignUpInput!) {
createUserByEmail(input: $input) {
authToken
}
}`, {
props: ({ mutate }) => ({
signup: (firstName, lastName, email, password) =>
mutate({ variables: { input: { firstName, lastName, email, password } } }),
}),
});
...
However I'm getting the error that I'm not allowed to define input types in the query. My question is: How do I define these complex input types? It doesn't seem like I'm able to provide a Schema to ApolloClient..
The correct syntax on the client side is just:
gql`
mutation userSignUp($input: UserSignUpInput!) {
createUserByEmail(input: $input) {
authToken
}
}
`
As your input UserSignUpInput is defined on the server, everything is going fine.
server
input UserSignUpInput {
firstName: String!,
lastName: String!,
email: String!,
password: String!
}

Resources