How do I write a Prisma and Apollo resolver to add a user to a chatroom? - graphql

When using resolvers in graphql, how to I add items to the arrays with the prisma syntax? And if you understand what I mean, what terminology should I be using?
I have the following graphql mutation:
mutation CreateChatRoom {
createChatroom {
id
}
}
Response: Invalid prisma.chatroom.create()
schema.prisma
model Chatroom {
id Int #id #unique #default(autoincrement())
topic String
members User[]
// *** //
}
model User {
id String #id #default(uuid())
chatrooms Chatroom[]
// *** //
}
TypeDef
type Mutation {
createChatroom(topic: String): Chatroom
}
I have Chatroom, User, and Messages. I'm trying to add a User to Chatroom with the following
Resolver
createChatroom: async (parent, { topic = "" }, { userId, prisma }) => {
const user = await prisma.user.findUnique({
where: {
id: userId
}
}) //is this necissary?
const chatroom = await prisma.chatroom.create({
data: {
members: [user], //put the first user in the Chatroom[]
topic: topic,
messages: []
}
})
return chatroom
},
joinChatroom: async (parent, { chatroomId }, { userId, prisma }) => {
const user = await prisma.user.findUnique({
where: {
id: userId
}
}),
const chatroom = await prisma.chatroom.findUnique({
where: {
id: chatroomId
}
})
// chatroom.update({ add [user, ...users] ? })
},

Related

return the id of the updated document in graphql mongodb

I am new to GraphQL. I have a query which updates a user by his Id. I want to return the id of the document that was updated, but it is returning:
{
"data": {
"editUser": {
"_id": null
}
}
}
GraphQL Query:
mutation {editUser(_id: "5eb801eef0171040044de79f", name: "dd", title:"teacher" , email:"dd#here.com") {
_id
}
}
shema:
const { buildSchema } = require("graphql");
const schema = buildSchema(`type Query {
getUser(_id: ID): User
getUsers: [User]
}
type User {
_id: ID
name: String
title: String
email: String
}
type Mutation {
addUser(name: String, title: String, email: String): User,
editUser(_id: ID, name: String, title: String, email: String): User,
deleteUser(_id: ID): String
}`);
module.exports = { schema };
in resolver.js:
try {
const client = await MongoClient.connect(url);
var dbo = client.db("UserApp");
const myquery = { _id: ObjectId(args._id) };
const updateduser = await dbo
.collection("users")
.updateOne(myquery, { $set: { name: args.name } });
const founduser = await dbo.collection("users").findOne(myquery);
console.log(founduser);
return founduser._id.toString();
} catch (err) {
console.log(err);
}

Understanding Prisma upsert

I am trying to use a one to many relationship in Prisma and am confused. My goal is that when creating an athlete it is assigned a team and likewise the team is updated to show all athletes assigned to it. My resolver is shown below.
async function signUpUser(parent, args, { prisma }, info) {
let password = await bcrypt.hash(args.password, 10)
const team = await prisma.team({ id: args.team })
const user = await prisma.createUser({
...args,
password,
team: { connect: { id: team.id } }
})
//create special user based on user type from args
switch(args.userType) {
case "ATHLETE":
createAthlete(user, prisma)
break
case "COACH":
createCoach(user, prisma)
break
case "HEAD_COACH":
createHeadCoach(user, prisma)
break
case "PARENT":
createParent(user, prisma)
break
default:
createAthlete(user, prisma)
}
return {
user
}
}
async function createAthlete(user, prisma) {
const athlete = await prisma.createAthlete({
user: { connect: { id: user.id } }
})
return athlete
}
This code almost works how I would like it. The user is set a team and an athlete. However in my datamodel I want the team they are stored to to show all the athletes that are assigned under that team. I believe I need to use the upsert method but do not know how.
async function createAthlete(user, team, prisma) {
const athlete = await prisma.createAthlete({
user: { connect: { id: user.id } }
})
const updatedTeam = await prisma.updateTeam({
where: { id: team.id },
data: {
athletes: {
connect: {
id: athlete.id,
}
}
},
})
return {athlete, updatedTeam}
}

GraphQL - Prisma - resolvers using external API

I'am having this schema:
type Invoice {
id: ID! #unique
description: String
charge: Charge
}
type Charge {
id: ID! #unique
amount: Float
dataFromAPI: DataFromAPI
}
type DataFromAPI {
id: ID! #unique
status: String
}
in the Query Resolver, I have:
async function charge(parent, args, ctx, info) {
chargeData = await ctx.db.query.charge(args, info)
chargeData.dataFromAPI = await DO_THE_API_CALL_TO_RETRIEVE_DATA()
return chargeData
}
and
async function invoice(parent, args, ctx, info) {
invoiceData = await ctx.db.query.invoice(args, info)
return invoiceData
}
the query:
query ChargeQuery {
charge {
id
amount
dataFromAPI
}
}
will return
{
charge {
id: '232323'
amount: 323
dataFromAPI: 'GREAT! DATA IS FROM API'
}
}
but this query:
query InvoiceQuery {
invoice {
id
description
charge {
id
amount
dataFromAPI
}
}
}
will return
{
Invoice {
id: '7723423',
description:'yeah',
charge {
id: '232323'
amount: 323
dataFromAPI: null
}
}
}
dataFromAPI is null because I have not called the API in this resolver.
Where should I call the function DO_THE_API_CALL_TO_RETRIEVE_DATA().
In every resolvers? I guess it is not scalable to do that.
The solution is:
We should use a resolver on the field level.
schema.graphql
type Charge {
id: ID!
invoice: Invoice!
messageErrorPayment: String
stripeChargeId: String!
dateErrorPayment: DateTime
createdAt: DateTime!
chargeData: ChargeData
}
/resolvers/index.js
const { Query } = require('./Query')
const { Mutation } = require('./mutation/Mutation')
const { Charge } = require('./Charge')
module.exports = {
Query,
Mutation,
Charge,
}
charge.js
async function chargeData(parent, args, ctx, info) {
return {
dataFromAPI: await DO_THE_API_CALL_TO_RETRIEVE_DATA()
}
}
const Charge = {
chargeData,
}
module.exports = {
Charge,
}
source: https://www.prisma.io/forum/t/how-to-use-field-resolvers-to-get-aggregates-of-inner-relation-types/2930/2?u=alan345

GraphQL Schema and Resolvers organization return null [duplicate]

This question already has answers here:
Why does a GraphQL query return null?
(6 answers)
Closed 3 years ago.
i am toying with the Star Wars API using GraphQL. Using GraphQL Playground, i get null values for the response for the joint entities.
I believe the reason is because of the organization of my schema and resolver files. Below are my codes and the files they are stored in, anyone can help? The current setup only returns the name of the Star Wars character but doesn't return the array of films details under the person/character
Thanks a lot
GQL Playground
{
"data": {
"getPerson": {
"name": "Obi-Wan Kenobi",
"films": [
{
"title": null,
"director": null
}
]
}
}
}
graphql/schema.ts
import { gql } from "apollo-server-express";
export const typeDefs = gql`
type Person {
name: String
height: String
mass: String
homeworld: Planet
films: [Film]
vehicles: [Vehicle]
}
type Planet {
name: String
diameter: String
climate: String
terrain: String
population: String
films: [Film]
}
type Film {
title: String
episode_id: Int
director: String
producer: String
releaseDate: String
}
type Vehicle {
name: String
model: String
manufacturer: String
length: String
crew: String
passengers: String
pilots: [Person]
}
type Query {
getPerson(id: Int!): Person
}
schema {
query: Query
}
`;
graphql/resolvers/index.ts
import PersonResolvers from "./person-resolvers";
export const resolvers = {
Query: {
getPerson: PersonResolvers.getPerson
}
};
graphql/person-resolvers.ts
import fetch from "node-fetch";
export default {
getPerson: async (_: any, { id }: { id: string }) => {
try {
const res = await fetch(`https://swapi.co/api/people/${id}/`);
return res.json();
} catch (error) {
throw error;
}
},
Person: {
films: (person: any) => {
const promises = person.films.map(async (url: string) => {
const res = await fetch(url);
return res.json();
});
return Promise.all(promises);
},
vehicles: (person: any) => {
const promises = person.vehicles.map(async (url: string) => {
const res = await fetch(url);
return res.json();
});
return Promise.all(promises);
}
},
Vehicle: {
pilots: (vehicle: any) => {
const promises = vehicle.pilots.map(async (url: string) => {
const res = await fetch(url);
return res.json();
});
return Promise.all(promises);
}
}
};
I have managed to get it work with this folder organization
For those looking for answers, u can check out my repo below
myhendry gql github repo

How to pass the values of a connection to a subscription?

I'm trying to return a subscription which consists of the following:
const postsSubscription = gql`
subscription postAdded {
postAdded {
id
title
description
author{
name
}
}
}
`
What happens is that Author is type of User, and I just pass an authorId. That means that I don't have the author name when I create the Post:
createPost: async (root, req, { posts }) => {
const Item = {
id: uuid.v4(),
authorId: '565dbdc0-36f2-4bba-be67-c126d0c71fff',
...req
}
await posts.create({ Item })
pubsub.publish('postAdded', { postAdded: Item })
return Item
},
Here is the Author resolver:
Post: {
author: async({ authorId }, req, { users }) => {
const Key = { id: authorId }
const { Item } = await users.get({ Key })
return Item
}
}
Here is the schema:
type Post {
id: ID
title: String
description: String
author: User #relation(name: "PostAuthor")
}
type User {
id: ID
name: String
email: String
password: String
posts: [Post] #relation(name: "UserPosts")
}
type PostPayload {
post: Post
}
type CreateUserPayload {
user: User
}
type Query {
allPosts: [Post]
allUsers: [User]
post(id: ID!): Post
user(id: ID!): User
}
type Mutation {
createPost(input: CreatePostInput!): PostPayload
updatePost(input : UpdatePostInput!): PostPayload
createUser(input : CreateUserInput!): CreateUserPayload
}
type Subscription {
postAdded: Post
}
input CreatePostInput {
title: String!
description: String!
}
input UpdatePostInput {
id: ID!
title: String!,
description: String!
}
input CreateUserInput {
name: String!
email: String!
password: String!
}
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
So, my question is, how to pass all required fields (including the connections) to the subscription?
I made it work, but not as I wanted.
1) I had to remove this part of the code:
Post: {
author: async({ authorId }, req, { users }) => {
const Key = { id: authorId }
const { Item } = await users.get({ Key })
return Item
}
}
and added this function to the createPost function itself:
createPost: async (root, { input }, { posts, users }) => {
const Key = { id: '3b1884b8-9ee7-4d9d-ab2f-ff32bcd69b9a' }
const user = await users.get({ Key })
const Item = {
id: uuid.v4(),
author: user.Item,
...input
}
await posts.create({ Item })
await pubsub.publish(POST_ADDED_TOPIC, { [POST_ADDED_TOPIC]: Item })
return { post: Item }
}
So this is kinda fixed. But, if you know how to fix this, using the first approach (Post: author thingy) I'll appreciate.

Resources