⚙️ Backend
GraphQL API Development
Last updated: 2025-09-25 02:29:54
GraphQL Query Language
GraphQL provides a more efficient, powerful and flexible alternative to REST APIs.
GraphQL Schema Definition
const { gql } = require('apollo-server-express');
// Schema definition
const typeDefs = gql`
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
createdAt: String!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
comments: [Comment!]!
publishedAt: String
}
type Comment {
id: ID!
content: String!
author: User!
post: Post!
}
type Query {
users: [User!]!
user(id: ID!): User
posts: [Post!]!
post(id: ID!): Post
}
type Mutation {
createUser(input: CreateUserInput!): User!
createPost(input: CreatePostInput!): Post!
updatePost(id: ID!, input: UpdatePostInput!): Post!
deletePost(id: ID!): Boolean!
}
input CreateUserInput {
name: String!
email: String!
}
input CreatePostInput {
title: String!
content: String!
authorId: ID!
}
input UpdatePostInput {
title: String
content: String
}
`;
Resolvers Implementation
// Resolvers
const resolvers = {
Query: {
users: async () => {
return await User.findAll();
},
user: async (parent, { id }) => {
return await User.findByPk(id);
},
posts: async (parent, args, context) => {
// Apply filtering, pagination, etc.
const { limit = 10, offset = 0, authorId } = args;
const where = authorId ? { authorId } : {};
return await Post.findAll({
where,
limit,
offset,
order: [['createdAt', 'DESC']]
});
},
post: async (parent, { id }) => {
return await Post.findByPk(id);
}
},
Mutation: {
createUser: async (parent, { input }) => {
const { name, email } = input;
// Validation
if (!email.includes('@')) {
throw new Error('Invalid email format');
}
return await User.create({ name, email });
},
createPost: async (parent, { input }, context) => {
// Check authentication
if (!context.user) {
throw new Error('Authentication required');
}
const { title, content, authorId } = input;
return await Post.create({ title, content, authorId });
},
updatePost: async (parent, { id, input }, context) => {
const post = await Post.findByPk(id);
if (!post) {
throw new Error('Post not found');
}
// Authorization check
if (post.authorId !== context.user.id && !context.user.isAdmin) {
throw new Error('Not authorized to update this post');
}
await post.update(input);
return post;
},
deletePost: async (parent, { id }, context) => {
const post = await Post.findByPk(id);
if (!post) {
throw new Error('Post not found');
}
await post.destroy();
return true;
}
},
// Nested resolvers
User: {
posts: async (parent) => {
return await Post.findAll({ where: { authorId: parent.id } });
}
},
Post: {
author: async (parent) => {
return await User.findByPk(parent.authorId);
},
comments: async (parent) => {
return await Comment.findAll({ where: { postId: parent.id } });
}
},
Comment: {
author: async (parent) => {
return await User.findByPk(parent.authorId);
},
post: async (parent) => {
return await Post.findByPk(parent.postId);
}
}
};
Client-Side GraphQL Queries
// Apollo Client setup
import { ApolloClient, InMemoryCache, gql } from '@apollo/client';
const client = new ApolloClient({
uri: 'http://localhost:4000/graphql',
cache: new InMemoryCache()
});
// Queries
const GET_USERS = gql`
query GetUsers {
users {
id
name
email
posts {
id
title
}
}
}
`;
const GET_POST = gql`
query GetPost($id: ID!) {
post(id: $id) {
id
title
content
author {
name
email
}
comments {
id
content
author {
name
}
}
}
}
`;
// Mutations
const CREATE_POST = gql`
mutation CreatePost($input: CreatePostInput!) {
createPost(input: $input) {
id
title
content
author {
name
}
}
}
`;
// Using in React components
import { useQuery, useMutation } from '@apollo/client';
function PostList() {
const { loading, error, data } = useQuery(GET_USERS);
const [createPost] = useMutation(CREATE_POST);
if (loading) return Loading...
;
if (error) return Error: {error.message}
;
const handleCreatePost = async (postData) => {
try {
await createPost({
variables: { input: postData },
refetchQueries: [{ query: GET_USERS }]
});
} catch (error) {
console.error('Error creating post:', error);
}
};
return (
{data.users.map(user => (
{user.name}
{user.posts.map(post => (
{post.title}
))}
))}
);
}