const { ApolloServer, gql } = require('apollo-server'); const { v4: uuidv4 } = require('uuid');
const db = { users: [ { id: '1', name: 'John Doe', email: 'john@example.com', age: 30, role: 'ADMIN', createdAt: '2023-01-01T00:00:00Z', posts: ['1', '2'], }, { id: '2', name: 'Jane Smith', email: 'jane@example.com', age: 25, role: 'USER', createdAt: '2023-02-01T00:00:00Z', posts: ['3'], }, ], posts: [ { id: '1', title: 'Hello World', content: 'This is my first post', author: '1', publishedAt: '2023-01-15T00:00:00Z', comments: ['1'], }, { id: '2', title: 'GraphQL Basics', content: 'Learn GraphQL fundamentals', author: '1', publishedAt: '2023-01-20T00:00:00Z', comments: [], }, { id: '3', title: 'React & GraphQL', content: 'Integrating React with GraphQL', author: '2', publishedAt: '2023-02-10T00:00:00Z', comments: ['2'], }, ], comments: [ { id: '1', text: 'Great post!', author: '2', post: '1', createdAt: '2023-01-16T00:00:00Z', }, { id: '2', text: 'Very helpful, thanks!', author: '1', post: '3', createdAt: '2023-02-11T00:00:00Z', }, ], };
const typeDefs = gql` type UserRole { ADMIN USER GUEST }
scalar DateTime
type User { id: ID! name: String! email: String! age: Int role: UserRole! createdAt: DateTime! posts: [Post!]! friends: [User!]! }
type Post { id: ID! title: String! content: String! author: User! publishedAt: DateTime! comments: [Comment!]! }
type Comment { id: ID! text: String! author: User! post: Post! createdAt: DateTime! }
type Query { user(id: ID!): User users: [User!]! post(id: ID!): Post posts: [Post!]! comment(id: ID!): Comment comments: [Comment!]! }
type Mutation { createUser(name: String!, email: String!, age: Int): User updateUser(id: ID!, name: String, email: String, age: Int): User deleteUser(id: ID!): User createPost(title: String!, content: String!, authorId: ID!): Post updatePost(id: ID!, title: String, content: String): Post deletePost(id: ID!): Post createComment(text: String!, authorId: ID!, postId: ID!): Comment }
type Subscription { newUser: User! newPost: Post! newComment: Comment! } `;
const resolvers = { Query: { user: (parent, { id }, context) => { return db.users.find(user => user.id === id); }, users: () => db.users, post: (parent, { id }) => { return db.posts.find(post => post.id === id); }, posts: () => db.posts, comment: (parent, { id }) => { return db.comments.find(comment => comment.id === id); }, comments: () => db.comments, },
Mutation: { createUser: (parent, { name, email, age }) => { const newUser = { id: uuidv4(), name, email, age, role: 'USER', createdAt: new Date().toISOString(), posts: [], }; db.users.push(newUser); return newUser; }, updateUser: (parent, { id, name, email, age }) => { const userIndex = db.users.findIndex(user => user.id === id); if (userIndex !== -1) { db.users[userIndex] = { ...db.users[userIndex], name: name || db.users[userIndex].name, email: email || db.users[userIndex].email, age: age !== undefined ? age : db.users[userIndex].age, }; return db.users[userIndex]; } return null; }, deleteUser: (parent, { id }) => { const userIndex = db.users.findIndex(user => user.id === id); if (userIndex !== -1) { const deletedUser = db.users.splice(userIndex, 1)[0]; return deletedUser; } return null; }, createPost: (parent, { title, content, authorId }) => { const newPost = { id: uuidv4(), title, content, author: authorId, publishedAt: new Date().toISOString(), comments: [], }; db.posts.push(newPost); const user = db.users.find(u => u.id === authorId); if (user) { user.posts.push(newPost.id); } return newPost; }, updatePost: (parent, { id, title, content }) => { const postIndex = db.posts.findIndex(post => post.id === id); if (postIndex !== -1) { db.posts[postIndex] = { ...db.posts[postIndex], title: title || db.posts[postIndex].title, content: content || db.posts[postIndex].content, }; return db.posts[postIndex]; } return null; }, deletePost: (parent, { id }) => { const postIndex = db.posts.findIndex(post => post.id === id); if (postIndex !== -1) { const deletedPost = db.posts.splice(postIndex, 1)[0]; db.users.forEach(user => { user.posts = user.posts.filter(postId => postId !== id); }); return deletedPost; } return null; }, createComment: (parent, { text, authorId, postId }) => { const newComment = { id: uuidv4(), text, author: authorId, post: postId, createdAt: new Date().toISOString(), }; db.comments.push(newComment); const post = db.posts.find(p => p.id === postId); if (post) { post.comments.push(newComment.id); } return newComment; }, },
Subscription: { newUser: { subscribe: (parent, args, { pubsub }) => { return pubsub.asyncIterator('NEW_USER'); }, }, newPost: { subscribe: (parent, args, { pubsub }) => { return pubsub.asyncIterator('NEW_POST'); }, }, newComment: { subscribe: (parent, args, { pubsub }) => { return pubsub.asyncIterator('NEW_COMMENT'); }, }, },
User: { posts: (parent) => { return parent.posts.map(postId => db.posts.find(p => p.id === postId) ); }, friends: (parent) => { return db.users.filter(user => user.id !== parent.id); }, },
Post: { author: (parent) => { return db.users.find(user => user.id === parent.author); }, comments: (parent) => { return parent.comments.map(commentId => db.comments.find(c => c.id === commentId) ); }, },
Comment: { author: (parent) => { return db.users.find(user => user.id === parent.author); }, post: (parent) => { return db.posts.find(post => post.id === parent.post); }, }, };
const server = new ApolloServer({ typeDefs, resolvers, context: ({ req }) => { return { user: req.headers.user, }; }, });
server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });
|