GraphQL extract possible queries from a schema - graphql

I have a graphql schema that i'm parsing
type User {
id: ID!
name: String!
email: String!
age: Int
posts: [Post!]!
}
type Post {
id: ID!
title: String!
body: String!
author: User!
comments: [Comment!]!
}
type Comment {
id: ID!
body: String!
author: User!
post: Post!
}
type Query {
users: [User!]!
user(id: ID!): User
posts: [Post!]!
post(id: ID!): Post
comments: [Comment!]!
comment(id: ID!): Comment
}
i want to get extract each possible query from it as a seperate string
in the above example,
String 1
type Query {
users: [User!]!
}
String 2
type Query {
user(id: ID!): User
}
String 3
type Query {
posts: [Post!]!
}
String 4
type Query {
post(id: ID!): Post
}
String 5
type Query {
comments: [Comment!]!
}
String 6
type Query {
comment(id: ID!): Comment
}
what is the best way to achieve this ? i'm using graphql javascript package

Related

Prisma 2 delete mutation is returning null

I am using ApolloServer/Prisma2/GraphQL/Typescript/MySQL
I have created two models, User, and Post. My createUser and createPost mutations are working fine. However, I am having trouble getting my delete mutations working. Focusing on the deletePost, here is what I have in my code.
<<schema.graphql>>
type Query {
posts: [Post!]!
users: [User!]!
}
type Mutation {
createPost(title: String!, body: String!): Post!
createUser(name: String!, email: String!, password: String!): User!
deletePost(postId: ID!): Post
deleteAllPosts: [Post!]!
}
type Post {
id: ID!
title: String!
body: String!
author: User
published: Boolean!
}
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
<<schema.prisma>>
model Post {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt #default(now())
title String
body String
published Boolean #default(false)
postedBy User? #relation(fields: [authorId], references: [id])
authorId Int?
}
model User {
id Int #id #default(autoincrement())
name String
email String #unique
password String
posts Post[]
}
<<Mutation.ts>>
async function deletePost(parent, { postId }, context, info) {
return await context.prisma.post.delete(
{
where {
id: parseInt(postId)
}
},
info
)
}
Note that the createPost and createUser are also in the Mutation.ts file and are working correctly. So I'm assuming there is no issue with the Apollo server.
When I use the GraphQL playground I use the following:
mutation {
deletePost(postId: "1") {
id
}
}
with the following result:
{
"data": {
"deletePost": null
}
}
I want the mutation to return the deleted post (at least the id if nothing else). In addition, the database is not deleting anything. I'd appreciate any help.

Why is Laravel Lighthouse GraphQL running multiple MySQL queries (not eager loading)?

I am new to GraphQL and Lighthouse.
My understanding from https://lighthouse-php.com/4.0/performance/n-plus-one.html#eager-loading-relationships is that for a nested GraphQL query, "Under the hood, Lighthouse will batch the relationship queries together in a single database query."
However, I see in the logs all of these queries where there should be only 1:
select count(*) as aggregate from `posts`
select * from `posts` order by `created_at` asc limit 20 offset 0
select * from `post_files` where `post_files`.`post_id` in (249, 5...
select * from `post_tags` where `post_tags`.`post_id` in (249, 5...
select * from `comments` where `comments`.`post_id` in (249, 5...
select * from `files` where `files`.`id` in (269, 615, ...
select * from `tags` where `tags`.`id` in (2, 3, 4, ...
Here is my GraphQL query:
gql`
query Posts($page: Int) {
posts(
first: 20
page: $page,
orderBy: { field: CREATED_AT, order: ASC }
) {
paginatorInfo {
currentPage
hasMorePages
total
}
data {
id
content
created_at
postFiles {
file {
id
original_name
extension
}
}
postTags {
id
tag {
id
label
}
}
comments {
id
user_id
message
created_at
seen_at
}
}
}
}
`;
My schema.graphql has the right #belongsTo and #hasMany directives:
"A date string with format `Y-m-d`, e.g. `2011-05-23`."
scalar Date #scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\Date")
"A datetime string with format `Y-m-d H:i:s`, e.g. `2018-05-23 13:43:32`."
scalar DateTime
#scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\DateTime")
"A datetime and timezone string in ISO 8601 format `Y-m-dTH:i:sO`, e.g. `2020-04-20T13:53:12+02:00`."
scalar DateTimeTz
#scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\DateTimeTz")
type Comment {
id: Int!
user: User! #belongsTo
user_id: Int!
post: Post! #belongsTo
post_id: Int!
message: String!
emailed_at: DateTime
seen_at: DateTime
created_at: DateTime!
modified_at: DateTime!
}
type File {
id: Int!
original_name: String!
extension: String!
postFiles: [PostFile!]! #hasMany
}
type Post {
id: Int!
user: User! #belongsTo
user_id: Int!
content: String
origin: String
created_at: DateTime!
modified_at: DateTime!
postFiles: [PostFile!]! #hasMany
comments: [Comment!]! #hasMany
postTags: [PostTag!]! #hasMany
}
type PostFile {
post: Post! #belongsTo
post_id: Int!
file: File! #belongsTo
file_id: Int!
}
type PostTag {
id: Int!
post: Post! #belongsTo
post_id: Int!
tag: Tag! #belongsTo
tag_id: Int!
created_at: DateTime!
modified_at: DateTime!
}
type Tag {
id: Int!
label: String!
hash: String!
created_at: DateTime!
modified_at: DateTime!
postTags: [PostTag!]! #hasMany
}
type User {
id: Int!
email: String!
password: String!
salt: String
db_key: String
created_at: DateTime!
modified_at: DateTime!
posts: [Post!]! #hasMany
comments: [Comment!]! #hasMany
}
type Query {
comments: [Comment!]! #all
files: [File!]! #all
posts(
orderBy: _ #orderBy(columns: ["id", "created_at"], order: ASC)
): [Post!]! #paginate(defaultCount: 20)
post(id: ID! #eq): Post #find
postFiles: [PostFile!]! #all
postTags: [PostTag!]! #all
tags: [Tag!]! #all
users: [User!]! #all
}
My Laravel models have all the right relationships. E.g. class Post has:
public function comments() {
return $this->hasMany(Comment::class, Comment::POST_ID);
}
And class Comment has:
public function post() {
return $this->belongsTo(Post::class);
}
and so on.
You must use Type hinting
import these types
use Illuminate\Database\Eloquent\Relations\HasMany;
And
use Illuminate\Database\Eloquent\Relations\BelongsTo;
public function post() : BelongsTo {
return $this->belongsTo(Post::class);
}

How to resolve subselections / relations in prisma (nested lists)

Let's take an example from the github repo of prisma:
We have a user, the user could have multiple posts, and one post could have multiple links.
My goal is, to retrieve all posts and all links.
This means, my response is a list (links) in a list (posts).
I want to map the values I get back as two nested lists.
datamodel.prisma
type User {
id: ID! #id
email: String! #unique
name: String
posts: [Post]!
}
type Post {
id: ID! #id
createdAt: DateTime! #createdAt
updatedAt: DateTime! #updatedAt
published: Boolean! #default(value: false)
title: String!
content: String
author: User!
links: [Link]!
}
type Link {
id: ID! #id
url: String
title: String
post: Post!
}
schema.graphql
type Query {
...
}
type Mutation {
...
}
type Link {
id: ID!
url: String
title: String
post: Post!
}
type Post {
id: ID!
createdAt: DateTime!
updatedAt: DateTime!
published: Boolean!
title: String!
content: String
author: User!
}
type User {
id: ID!
email: String!
name: String
posts: [Post]!
}
I want to query all posts of a user, and all of the links for every post in the response.
How would I query this request?
user {
id
posts {
id
links {
id
}
}
}
The above code snipper would not work.
EDIT
I want to use the following:
User: {
listPosts: (parent, args, context, info) {
return context.prisma.posts().links()
}
}
So in my response (data in front-end via react-apollo Query Component), I want to map over posts AND the links in each post.
BUT the links attribute in posts is null.
Is there another way to achieve this?!
According to the docs:
Prisma client has a fluent API to query relations in your database. Meaning you can simply chain your method calls to navigate the relation properties of the returned records. This is only possible when retrieving single records, not for lists. Meaning you can not query relation fields of records that are returned in a list.
In order to get around that limitation, you can use the $fragment method:
const fragment = `
fragment UserWithPostsAndLinks on User {
id
email
name
posts {
id
title
content
links {
id
url
title
}
}
}
`
const userWithPostsAndLinks = await prisma.user({ id: args.id }).$fragment(fragment)

authenticate user and serve only their related data

I have a schema in graphcool with these nodes (not sure what the correct term is here... leaf? node? model? type??)
type User #model {
auth0UserId: String #isUnique
createdAt: DateTime!
id: ID! #isUnique
userIdentifier: String
bundleIdentifier: String
updatedAt: DateTime!
devices: [Device!]! #relation(name: "UserOnDevice")
tokens: [Token!]! #relation(name: "TokenOnUser")
}
type Device #model {
id: ID! #isUnique
deviceIdentifier: String!
users: [User!]! #relation(name: "UserOnDevice")
token: Token #relation(name: "DeviceOnToken")
}
I'd like to make it so that a user must be authenticated and be related to the device data to be able to query on it. So, for a query like:
query($deviceIdentifier: String!) {
device(deviceIdentifier: $deviceIdentifier) {
id
}
}
This should return null unless they are autthenticated and are a user in the specified relation. I was thinking I needed a permission query like this one:
query ($node_id: ID!, $user_id: ID!) {
SomeDeviceExists(filter: {
id: $node_id,
users: {
id: $user_id
}
})
}
But it turns out that is invalid. How do I do it?
query ($node_id: ID!, $user_id: ID!) {
SomeDeviceExists(filter: {
id: $node_id,
users_some: {
id: $user_id
}
})
}
but this does require submitting the user_id in the request.

Query elements where relationship is null

If I have a simple schema like:
type Author #model {
id: ID! #isUnique
posts: [Post!]! #relation(name: "AuthorOfPost")
}
type Post #model {
id: ID! #isUnique
author: Author #relation(name: "AuthorOfPost")
}
How can I query all Posts that do not have an author?
Unfortunately, I cannot find something in the authorFilter like id_is_null.
try this!
query PostsWithAuthor {
allPosts(filter: { author: null }) {
id
author {
id
}
}
}

Resources