diff --git a/src/schema.js b/src/schema.js index 8a99faf..c65e7e8 100644 --- a/src/schema.js +++ b/src/schema.js @@ -20,7 +20,7 @@ const { UserConnection, UserFieldFilter, UserFieldOrder, UserMutations, User, } = require('./schema/user'); const { - Post, PostMutations, + PostFieldFilter, PostFieldOrder, Post, PostConnection, PostMutations, } = require('./schema/post'); const { CommentFieldFilter, CommentFieldOrder, Comment, CommentConnection, @@ -60,8 +60,16 @@ const queryType = new GraphQLObjectType({ }, resolve: (_, args) => resolveQuery({ table: 'users', args }), }, - // TODO: TASK 2. posts query - // posts: {} + posts: { + type: PostConnection, + args: { + filters: { type: new GraphQLList(PostFieldFilter) }, + order: { type: PostFieldOrder }, + limit: { type: GraphQLInt }, + offset: { type: GraphQLInt }, + }, + resolve: (_, args) => resolveQuery({ table: 'posts', args }), + }, comments: { type: CommentConnection, args: { diff --git a/src/schema/comment.js b/src/schema/comment.js index 54fdaa3..dac3f3b 100644 --- a/src/schema/comment.js +++ b/src/schema/comment.js @@ -10,7 +10,7 @@ const { get } = require('lodash'); const { resolveQuery } = require('../fetcher'); const { - Node, PageInfo, FilterOperation, OrderDirection, + Node, PageInfo, FilterOperation, OrderDirection, Datetime, } = require('./common'); const CommentArgField = new GraphQLEnumType({ @@ -41,14 +41,13 @@ const CommentFieldOrder = new GraphQLInputObjectType({ }, }); -// TODO: TASK 2. uncomment post when TASK 2. is finished const Comment = new GraphQLObjectType({ name: 'Comment', interfaces: [Node], isTypeOf: (value) => value instanceof Object, fields: () => { const { User } = require('./user'); - // const { Post } = require('./post'); + const { Post } = require('./post'); return { id: { type: GraphQLID }, content: { type: GraphQLString }, @@ -62,17 +61,17 @@ const Comment = new GraphQLObjectType({ return get(resp, 'edges[0].node', {}); }, }, - // post: { - // type: Post, - // resolve: async (parent) => { - // const resp = await resolveQuery({ - // table: 'posts', - // args: { filters: [{ field: 'id', operation: '=', value: parent.post }] }, - // }); - // return get(resp, 'edges[0].node', {}); - // }, - // }, - // timestamp: { type: Datetime }, + post: { + type: Post, + resolve: async (parent) => { + const resp = await resolveQuery({ + table: 'posts', + args: { filters: [{ field: 'id', operation: '=', value: parent.post }] }, + }); + return get(resp, 'edges[0].node', {}); + }, + }, + timestamp: { type: Datetime }, }; }, }); diff --git a/src/schema/post.js b/src/schema/post.js index b2a69c3..6a33f10 100644 --- a/src/schema/post.js +++ b/src/schema/post.js @@ -2,24 +2,108 @@ const { GraphQLObjectType, GraphQLString, GraphQLID, + GraphQLInt, + GraphQLEnumType, + GraphQLList, GraphQLInputObjectType, GraphQLNonNull, } = require('graphql'); +const { get } = require('lodash'); -const { createPost } = require('../fetcher'); +const { resolveQuery, createPost } = require('../fetcher'); +const { + Node, PageInfo, FilterOperation, OrderDirection, Datetime, +} = require('./common'); +const { CommentConnection, CommentFieldFilter, CommentFieldOrder } = require('./comment'); + +const PostArgField = new GraphQLEnumType({ + name: 'PostArgField', + values: { + id: { value: 'id' }, + content: { value: 'content' }, + title: { value: 'title' }, + description: { value: 'description' }, + author: { value: 'author' }, + timestamp: { value: 'timestamp' }, + }, +}); + +const PostFieldFilter = new GraphQLInputObjectType({ + name: 'PostFieldFilter', + fields: { + value: { type: GraphQLString }, + field: { type: PostArgField }, + operation: { type: FilterOperation }, + }, +}); + +const PostFieldOrder = new GraphQLInputObjectType({ + name: 'PostFieldOrder', + fields: { + field: { type: PostArgField }, + direction: { type: OrderDirection }, + }, +}); -// TODO: TASK 2. Post schemas -const PostArgField = {}; -const PostFieldFilter = {}; -const PostFieldOrder = {}; const Post = new GraphQLObjectType({ name: 'Post', + interfaces: [Node], + isTypeOf: (value) => value instanceof Object, + fields: () => { + const { User } = require('./user'); + return { + id: { type: GraphQLID }, + title: { type: GraphQLString }, + description: { type: GraphQLString }, + content: { type: GraphQLString }, + author: { + type: User, + resolve: async (parent) => { + const resp = await resolveQuery({ + table: 'users', + args: { filters: [{ field: 'email', operation: '=', value: parent.author }] }, + }); + return get(resp, 'edges[0].node', {}); + }, + }, + timestamp: { type: Datetime }, + comments: { + type: CommentConnection, + args: { + filters: { type: new GraphQLList(CommentFieldFilter) }, + order: { type: CommentFieldOrder }, + limit: { type: GraphQLInt }, + offset: { type: GraphQLInt }, + }, + resolve: (parent, args) => resolveQuery({ + table: 'comments', + args: { + ...args, + filters: [ + ...get(args, 'filters', []).filter((filter) => filter.field !== 'post'), + { field: 'post', operation: '=', value: parent.id }, + ], + }, + }), + }, + }; + }, +}); + +const PostEdge = new GraphQLObjectType({ + name: 'PostEdge', + fields: { + node: { type: Post }, + }, +}); + +const PostConnection = new GraphQLObjectType({ + name: 'PostConnection', fields: { - id: { type: GraphQLID }, + pageInfo: { type: PageInfo }, + edges: { type: new GraphQLList(PostEdge) }, }, }); -const PostEdge = {}; -const PostConnection = {}; const CreatePostInput = new GraphQLInputObjectType({ name: 'CreatePostInput', diff --git a/src/schema/user.js b/src/schema/user.js index a3c07d7..3ba4bcb 100644 --- a/src/schema/user.js +++ b/src/schema/user.js @@ -14,7 +14,7 @@ const { resolveQuery, createUser } = require('../fetcher'); const { Node, PageInfo, FilterOperation, OrderDirection, } = require('./common'); -// const { PostConnection, PostFieldFilter, PostFieldOrder } = require('./post'); +const { PostConnection, PostFieldFilter, PostFieldOrder } = require('./post'); const { CommentConnection, CommentFieldFilter, CommentFieldOrder } = require('./comment'); const UserArgField = new GraphQLEnumType({ @@ -44,7 +44,6 @@ const UserFieldOrder = new GraphQLInputObjectType({ }, }); -// TODO: TASK 2. uncomment posts when TASK 2. is finished const User = new GraphQLObjectType({ name: 'User', interfaces: [Node], @@ -54,25 +53,25 @@ const User = new GraphQLObjectType({ name: { type: GraphQLString }, username: { type: GraphQLString }, email: { type: GraphQLString }, - // posts: { - // type: PostConnection, - // args: { - // filters: { type: new GraphQLList(PostFieldFilter) }, - // order: { type: PostFieldOrder }, - // limit: { type: GraphQLInt }, - // offset: { type: GraphQLInt }, - // }, - // resolve: (parent, args) => resolveQuery({ - // table: 'posts', - // args: { - // ...args, - // filters: [ - // ...get(args, 'filters', []).filter((filter) => filter.field !== 'author'), - // { field: 'author', operation: '=', value: parent.email }, - // ], - // }, - // }), - // }, + posts: { + type: PostConnection, + args: { + filters: { type: new GraphQLList(PostFieldFilter) }, + order: { type: PostFieldOrder }, + limit: { type: GraphQLInt }, + offset: { type: GraphQLInt }, + }, + resolve: (parent, args) => resolveQuery({ + table: 'posts', + args: { + ...args, + filters: [ + ...get(args, 'filters', []).filter((filter) => filter.field !== 'author'), + { field: 'author', operation: '=', value: parent.email }, + ], + }, + }), + }, comments: { type: CommentConnection, args: { diff --git a/src/server.js b/src/server.js index 0ee897f..a2d2ebd 100644 --- a/src/server.js +++ b/src/server.js @@ -6,11 +6,11 @@ const cors = require('cors'); const db = require('./db'); // Graphql Types - cut rootValue from graphqlHTTP when used -// const schema = require('./schema'); +const schema = require('./schema'); const config = require('./config'); // Raw Graphql schema language - add rootValue from graphqlHTTP when used -const { schema, rootValue } = require('./gqlSchema'); +// const { schema, rootValue } = require('./gqlSchema'); const app = express(); @@ -26,7 +26,7 @@ app.use(cors({ app.use('/graphql', graphqlHTTP(async () => ({ schema, - rootValue, + // rootValue, graphiql: true, customFormatErrorFn: (error) => { // eslint-disable-next-line no-console