장재혁

Add likeable API

...@@ -8,7 +8,6 @@ import { MypageModule } from './mypage/mypage.module' ...@@ -8,7 +8,6 @@ import { MypageModule } from './mypage/mypage.module'
8 import { PostModule } from './post/post.module' 8 import { PostModule } from './post/post.module'
9 import { CommentModule } from './comment/comment.module' 9 import { CommentModule } from './comment/comment.module'
10 import { UserModule } from './user/user.module' 10 import { UserModule } from './user/user.module'
11 -import { LikeableService } from './likeable/likeable.service'
12 import { LikeableModule } from './likeable/likeable.module' 11 import { LikeableModule } from './likeable/likeable.module'
13 12
14 @Module({ 13 @Module({
...@@ -31,6 +30,6 @@ import { LikeableModule } from './likeable/likeable.module' ...@@ -31,6 +30,6 @@ import { LikeableModule } from './likeable/likeable.module'
31 LikeableModule, 30 LikeableModule,
32 ], 31 ],
33 controllers: [AppController], 32 controllers: [AppController],
34 - providers: [AppService, LikeableService], 33 + providers: [AppService],
35 }) 34 })
36 export class AppModule {} 35 export class AppModule {}
......
1 import { Module } from '@nestjs/common' 1 import { Module } from '@nestjs/common'
2 import { CommentService } from './comment.service' 2 import { CommentService } from './comment.service'
3 import { CommentResolver } from './comment.resolver' 3 import { CommentResolver } from './comment.resolver'
4 +import { TypeOrmModule } from '@nestjs/typeorm'
5 +import { Comment } from './model/comment.entity'
4 6
5 @Module({ 7 @Module({
8 + imports: [TypeOrmModule.forFeature([Comment])],
6 providers: [CommentService, CommentResolver], 9 providers: [CommentService, CommentResolver],
7 }) 10 })
8 export class CommentModule {} 11 export class CommentModule {}
......
1 -import { Resolver } from '@nestjs/graphql' 1 +import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'
2 +import { CommentService } from './comment.service'
3 +import { Comment } from './model/comment.entity'
4 +import { CreateCommentInput, GetCommentInput } from './dto/comment.input'
2 5
3 -@Resolver() 6 +@Resolver((of) => Comment)
4 -export class CommentResolver {} 7 +export class CommentResolver {
8 + constructor(private commentService: CommentService) {}
9 +
10 + @Query((returns) => [Comment])
11 + getAllComments(): Promise<Comment[]> {
12 + return this.commentService.findAll()
13 + }
14 +
15 + @Query((returns) => [Comment])
16 + getSomeComments(@Args('input') input: GetCommentInput): Promise<Comment[]> {
17 + return this.commentService.findSome(input)
18 + }
19 +
20 + @Query((returns) => Comment)
21 + getComment(@Args('id') id: number): Promise<Comment> {
22 + return this.commentService.findOne(id)
23 + }
24 +
25 + @Mutation(() => Comment, { name: 'createComment' })
26 + createComment(@Args('input') input: CreateCommentInput): Promise<Comment> {
27 + return this.commentService.createOne(input)
28 + }
29 +}
......
1 import { Injectable } from '@nestjs/common' 1 import { Injectable } from '@nestjs/common'
2 +import { InjectRepository } from '@nestjs/typeorm'
3 +import { QueryRunner, Repository, getConnection } from 'typeorm'
4 +import { Comment } from './model/comment.entity'
5 +import { getCurrentDate } from '../shared/utils'
6 +import { CreateCommentInput, GetCommentInput } from './dto/comment.input'
7 +import { MASTER_TEST } from 'src/shared/const'
2 8
3 @Injectable() 9 @Injectable()
4 -export class CommentService {} 10 +export class CommentService {
11 + constructor(
12 + @InjectRepository(Comment) private commentRepository: Repository<Comment>,
13 + ) {}
14 + private connection = getConnection()
15 +
16 + async findAll(): Promise<Comment[]> {
17 + return this.commentRepository.find()
18 + }
19 +
20 + async findOne(id: number): Promise<Comment> {
21 + return this.commentRepository.findOne(id)
22 + }
23 +
24 + async findSome(input: Partial<GetCommentInput>): Promise<Comment[]> {
25 + return this.commentRepository
26 + .createQueryBuilder('comment')
27 + .where('comment.post_id = :post_id', { post_id: input.post_id })
28 + .orWhere('comment.author = :author', { author: input.author })
29 + .orWhere('comment.parent = :parent', { parent: input.parent })
30 + .getMany()
31 + }
32 +
33 + async createOne(input: CreateCommentInput): Promise<Comment> {
34 + let result
35 + const queryRunner: QueryRunner = this.connection.createQueryRunner()
36 + await queryRunner.connect()
37 + await queryRunner.startTransaction()
38 +
39 + try {
40 + const newInput = {
41 + ...input,
42 + created_date: getCurrentDate(),
43 + author: MASTER_TEST,
44 + }
45 + result = await queryRunner.manager.save(
46 + this.commentRepository.create(newInput),
47 + )
48 + await queryRunner.commitTransaction()
49 + } catch (err) {
50 + await queryRunner.rollbackTransaction()
51 + throw err
52 + } finally {
53 + await queryRunner.release()
54 + }
55 +
56 + return result
57 + }
58 +}
......
1 +import { Field, InputType, PickType } from '@nestjs/graphql'
2 +import { Comment } from '../model/comment.entity'
3 +
4 +@InputType()
5 +export class GetCommentInput {
6 + @Field({ nullable: true })
7 + post_id?: number
8 +
9 + @Field({ nullable: true })
10 + author?: string
11 +
12 + @Field({ nullable: true })
13 + parent?: string
14 +}
15 +
16 +@InputType()
17 +export class CreateCommentInput extends PickType(
18 + Comment,
19 + ['post_id', 'content'],
20 + InputType,
21 +) {
22 + @Field({ nullable: true })
23 + parent?: number
24 +}
......
1 +/* eslint-disable @typescript-eslint/no-unused-vars */
2 +import { ObjectType, Field, Int } from '@nestjs/graphql'
3 +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'
4 +
5 +@Entity({ name: 'comment' })
6 +@ObjectType()
7 +export class Comment {
8 + @PrimaryGeneratedColumn()
9 + @Field((type) => Int)
10 + id: number
11 +
12 + @Column()
13 + @Field()
14 + author: string
15 +
16 + @Column()
17 + @Field((type) => Int)
18 + post_id: number
19 +
20 + @Column()
21 + @Field((type) => Int)
22 + parent: number
23 +
24 + @Column()
25 + @Field()
26 + content: string
27 +
28 + @Column()
29 + @Field()
30 + created_date: string
31 +
32 + @Column({ nullable: true })
33 + @Field({ nullable: true })
34 + updated_date?: string
35 +}
1 +import { Field, InputType, PickType } from '@nestjs/graphql'
2 +import { Likeable } from '../model/likeable.entity'
3 +
4 +@InputType()
5 +export class GetLikeableInput {
6 + @Field({ nullable: true })
7 + likeable_id?: number
8 +
9 + @Field({ nullable: true })
10 + user_id?: string
11 +
12 + @Field()
13 + likeable_type: string
14 +}
15 +
16 +@InputType()
17 +export class CreateLikeableInput extends PickType(
18 + Likeable,
19 + ['likeable_id', 'like_dislike', 'likeable_type'],
20 + InputType,
21 +) {}
......
1 import { Module } from '@nestjs/common' 1 import { Module } from '@nestjs/common'
2 import { LikeableResolver } from './likeable.resolver' 2 import { LikeableResolver } from './likeable.resolver'
3 +import { LikeableService } from './likeable.service'
4 +import { TypeOrmModule } from '@nestjs/typeorm'
5 +import { Likeable } from './model/likeable.entity'
3 6
4 @Module({ 7 @Module({
5 - providers: [LikeableResolver], 8 + imports: [TypeOrmModule.forFeature([Likeable])],
9 + providers: [LikeableService, LikeableResolver],
6 }) 10 })
7 export class LikeableModule {} 11 export class LikeableModule {}
......
1 -import { Resolver } from '@nestjs/graphql' 1 +import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'
2 +import { CreateLikeableInput, GetLikeableInput } from './dto/likeable.input'
3 +import { LikeableService } from './likeable.service'
4 +import { Likeable } from './model/likeable.entity'
2 5
3 -@Resolver() 6 +@Resolver((of) => Likeable)
4 -export class LikeableResolver {} 7 +export class LikeableResolver {
8 + constructor(private likeableService: LikeableService) {}
9 +
10 + @Query((returns) => [Likeable])
11 + getAllLikes(): Promise<Likeable[]> {
12 + return this.likeableService.findAll()
13 + }
14 +
15 + @Query((returns) => Number)
16 + getTotalLikes(@Args('input') input: GetLikeableInput): Promise<number> {
17 + return this.likeableService.findSome(input).then((res) => res.length)
18 + }
19 +
20 + @Query((returns) => Likeable)
21 + getLikeable(@Args('id') id: number): Promise<Likeable> {
22 + return this.likeableService.findOne(id)
23 + }
24 +
25 + @Mutation(() => Likeable, { name: 'createLikeable' })
26 + createLikeable(@Args('input') input: CreateLikeableInput): Promise<Likeable> {
27 + return this.likeableService.createOne(input)
28 + }
29 +}
......
1 -import { Test, TestingModule } from '@nestjs/testing'; 1 +import { Test, TestingModule } from '@nestjs/testing'
2 -import { LikeableService } from './likeable.service'; 2 +import { LikeableService } from './likeable.service'
3 3
4 describe('LikeableService', () => { 4 describe('LikeableService', () => {
5 - let service: LikeableService; 5 + let service: LikeableService
6 6
7 beforeEach(async () => { 7 beforeEach(async () => {
8 const module: TestingModule = await Test.createTestingModule({ 8 const module: TestingModule = await Test.createTestingModule({
9 providers: [LikeableService], 9 providers: [LikeableService],
10 - }).compile(); 10 + }).compile()
11 11
12 - service = module.get<LikeableService>(LikeableService); 12 + service = module.get<LikeableService>(LikeableService)
13 - }); 13 + })
14 14
15 it('should be defined', () => { 15 it('should be defined', () => {
16 - expect(service).toBeDefined(); 16 + expect(service).toBeDefined()
17 - }); 17 + })
18 -}); 18 +})
......
1 import { Injectable } from '@nestjs/common' 1 import { Injectable } from '@nestjs/common'
2 +import { InjectRepository } from '@nestjs/typeorm'
3 +import { QueryRunner, Repository, getConnection } from 'typeorm'
4 +import { Likeable } from './model/likeable.entity'
5 +import { getCurrentDate } from '../shared/utils'
6 +import { GetLikeableInput, CreateLikeableInput } from './dto/likeable.input'
7 +import { MASTER_TEST } from 'src/shared/const'
2 8
3 @Injectable() 9 @Injectable()
4 -export class LikeableService {} 10 +export class LikeableService {
11 + constructor(
12 + @InjectRepository(Likeable)
13 + private likeableRepository: Repository<Likeable>,
14 + ) {}
15 + private connection = getConnection()
16 +
17 + async findAll(): Promise<Likeable[]> {
18 + return this.likeableRepository.find()
19 + }
20 +
21 + async findOne(id: number): Promise<Likeable> {
22 + return this.likeableRepository.findOne(id)
23 + }
24 +
25 + async findSome(input: Partial<GetLikeableInput>): Promise<Likeable[]> {
26 + return this.likeableRepository
27 + .createQueryBuilder('likeable')
28 + .where('likeable.user_id = :user_id', { user_id: input.user_id })
29 + .orWhere('likeable.likeable_id = :likeable_id', {
30 + likeable_id: input.likeable_id,
31 + })
32 + .andWhere('likeable.likeable_type = :likeable_type', {
33 + likeable_type: input.likeable_type,
34 + })
35 + .getMany()
36 + }
37 +
38 + async createOne(input: CreateLikeableInput): Promise<Likeable> {
39 + let result
40 + const queryRunner: QueryRunner = this.connection.createQueryRunner()
41 + await queryRunner.connect()
42 + await queryRunner.startTransaction()
43 +
44 + try {
45 + const newInput = {
46 + ...input,
47 + like_dislike: input.like_dislike > 0 ? 1 : -1,
48 + user_id: MASTER_TEST,
49 + created_date: getCurrentDate(),
50 + }
51 + result = await queryRunner.manager.save(
52 + this.likeableRepository.create(newInput),
53 + )
54 + await queryRunner.commitTransaction()
55 + } catch (err) {
56 + await queryRunner.rollbackTransaction()
57 + throw err
58 + } finally {
59 + await queryRunner.release()
60 + }
61 +
62 + return result
63 + }
64 +}
......
1 +/* eslint-disable @typescript-eslint/no-unused-vars */
2 +import { ObjectType, Field, Int } from '@nestjs/graphql'
3 +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'
4 +
5 +@Entity({ name: 'likeable' })
6 +@ObjectType()
7 +export class Likeable {
8 + @PrimaryGeneratedColumn()
9 + @Field((type) => Int)
10 + id: number
11 +
12 + @Column()
13 + @Field()
14 + user_id: string
15 +
16 + @Column()
17 + @Field((type) => Int)
18 + likeable_id: number
19 +
20 + @Column()
21 + @Field((type) => Int)
22 + like_dislike: number
23 +
24 + @Column()
25 + @Field()
26 + created_date: string
27 +
28 + @Column()
29 + @Field()
30 + likeable_type: string
31 +}
...@@ -8,6 +8,7 @@ import { ...@@ -8,6 +8,7 @@ import {
8 } from './dto/post.input' 8 } from './dto/post.input'
9 import { Post } from './model/post.entity' 9 import { Post } from './model/post.entity'
10 import { getCurrentDate } from '../shared/utils' 10 import { getCurrentDate } from '../shared/utils'
11 +import { MASTER_TEST } from 'src/shared/const'
11 12
12 @Injectable() 13 @Injectable()
13 export class PostService { 14 export class PostService {
...@@ -43,7 +44,7 @@ export class PostService { ...@@ -43,7 +44,7 @@ export class PostService {
43 const newInput = { 44 const newInput = {
44 ...input, 45 ...input,
45 created_date: getCurrentDate(), 46 created_date: getCurrentDate(),
46 - author: 'test', 47 + author: MASTER_TEST,
47 } 48 }
48 result = await queryRunner.manager.save( 49 result = await queryRunner.manager.save(
49 this.postRepository.create(newInput), 50 this.postRepository.create(newInput),
......
...@@ -2,6 +2,28 @@ ...@@ -2,6 +2,28 @@
2 # THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) 2 # THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
3 # ------------------------------------------------------ 3 # ------------------------------------------------------
4 4
5 +type Comment {
6 + author: String!
7 + content: String!
8 + created_date: String!
9 + id: Int!
10 + parent: Int!
11 + post_id: Int!
12 + updated_date: String
13 +}
14 +
15 +input CreateCommentInput {
16 + content: String!
17 + parent: Float
18 + post_id: Int!
19 +}
20 +
21 +input CreateLikeableInput {
22 + like_dislike: Int!
23 + likeable_id: Int!
24 + likeable_type: String!
25 +}
26 +
5 input CreateMyInput { 27 input CreateMyInput {
6 name: String! 28 name: String!
7 type: String 29 type: String
...@@ -13,13 +35,36 @@ input CreatePostInput { ...@@ -13,13 +35,36 @@ input CreatePostInput {
13 title: String! 35 title: String!
14 } 36 }
15 37
38 +input GetCommentInput {
39 + author: String
40 + parent: String
41 + post_id: Float
42 +}
43 +
44 +input GetLikeableInput {
45 + likeable_id: Float
46 + likeable_type: String!
47 + user_id: String
48 +}
49 +
16 input GetPostInput { 50 input GetPostInput {
17 author: String 51 author: String
18 category: String 52 category: String
19 id: Float 53 id: Float
20 } 54 }
21 55
56 +type Likeable {
57 + created_date: String!
58 + id: Int!
59 + like_dislike: Int!
60 + likeable_id: Int!
61 + likeable_type: String!
62 + user_id: String!
63 +}
64 +
22 type Mutation { 65 type Mutation {
66 + createComment(input: CreateCommentInput!): Comment!
67 + createLikeable(input: CreateLikeableInput!): Likeable!
23 createMyPage(createMyInput: CreateMyInput!): MyPage! 68 createMyPage(createMyInput: CreateMyInput!): MyPage!
24 createPost(input: CreatePostInput!): Post! 69 createPost(input: CreatePostInput!): Post!
25 } 70 }
...@@ -41,8 +86,14 @@ type Post { ...@@ -41,8 +86,14 @@ type Post {
41 } 86 }
42 87
43 type Query { 88 type Query {
89 + getAllComments: [Comment!]!
90 + getAllLikes: [Likeable!]!
44 getAllPosts: [Post!]! 91 getAllPosts: [Post!]!
92 + getComment(id: Float!): Comment!
93 + getLikeable(id: Float!): Likeable!
45 getPost(id: Float!): Post! 94 getPost(id: Float!): Post!
95 + getSomeComments(input: GetCommentInput!): [Comment!]!
46 getSomePosts(input: GetPostInput!): [Post!]! 96 getSomePosts(input: GetPostInput!): [Post!]!
97 + getTotalLikes(input: GetLikeableInput!): Float!
47 myPage: [MyPage!]! 98 myPage: [MyPage!]!
48 } 99 }
......
...@@ -2,3 +2,5 @@ export enum CATEGORY { ...@@ -2,3 +2,5 @@ export enum CATEGORY {
2 test = 'test_category', 2 test = 'test_category',
3 test2 = 'test2_category', 3 test2 = 'test2_category',
4 } 4 }
5 +
6 +export const MASTER_TEST = 'test_admin'
......