Skip to content

Commit

Permalink
feat: 🎸 add quote api
Browse files Browse the repository at this point in the history
  • Loading branch information
yeukfei02 committed Apr 22, 2022
1 parent fab9fb6 commit 6cc025d
Show file tree
Hide file tree
Showing 10 changed files with 281 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ Api similar to [dummy-api](https://dummyapi.io/docs)

Api for playing around with dummy data. Feel free to use it in your demo projects, tutorials, or testing tasks.

All authorization headers are optional.
- All authorization headers are optional

- listing api default page = 1, default per page = 20

documentation: <https://documenter.getpostman.com/view/3827865/Uyr8kHHD>

Expand Down
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { PostModule } from './post/post.module';
import { TagModule } from './tag/tag.module';
import { CommentModule } from './comment/comment.module';
import { TodoModule } from './todo/todo.module';
import { QuoteModule } from './quote/quote.module';

@Module({
imports: [
Expand All @@ -18,6 +19,7 @@ import { TodoModule } from './todo/todo.module';
TagModule,
CommentModule,
TodoModule,
QuoteModule,
],
controllers: [AppController],
providers: [AppService],
Expand Down
18 changes: 18 additions & 0 deletions src/quote/quote.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { QuoteController } from './quote.controller';

describe('QuoteController', () => {
let controller: QuoteController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [QuoteController],
}).compile();

controller = module.get<QuoteController>(QuoteController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
91 changes: 91 additions & 0 deletions src/quote/quote.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { Controller, Get, Query, Param } from '@nestjs/common';
import { QuoteService } from './quote.service';

import {
ApiBearerAuth,
ApiHeader,
ApiQuery,
ApiResponse,
} from '@nestjs/swagger';
import { GetQuotesResponse } from './response/getQuotes.response';
import { GetQuoteByIdResponse } from './response/getQuoteById.response';
import { GetRandomQuoteResponse } from './response/getRandomQuote.response';

@ApiBearerAuth()
@ApiHeader({
name: 'Authorization',
description: 'Jwt Token',
})
@Controller('quote')
export class QuoteController {
constructor(private readonly quoteService: QuoteService) {}

@Get()
@ApiQuery({
name: 'page',
description: 'page',
required: false,
type: String,
})
@ApiQuery({
name: 'per_page',
description: 'per_page',
required: false,
type: String,
})
@ApiResponse({
status: 200,
description: 'Successful response',
type: GetQuotesResponse,
})
async getQuotes(
@Query('page') page: string,
@Query('per_page') perPage: string,
): Promise<any> {
const pageInt = page ? parseInt(page, 10) : 1;
const perPageInt = page ? parseInt(perPage, 10) : 20;

const quotes = await this.quoteService.getQuotes(pageInt, perPageInt);

const response = {
message: 'getQuotes',
data: quotes,
total: quotes.length,
page: pageInt,
limit: perPageInt,
};
return response;
}

@Get('/random')
@ApiResponse({
status: 200,
description: 'Successful response',
type: GetRandomQuoteResponse,
})
async getRandomQuote(): Promise<any> {
const quote = await this.quoteService.getRandomQuote();

const response = {
message: 'getRandomQuote',
quote: quote,
};
return response;
}

@Get('/:id')
@ApiResponse({
status: 200,
description: 'Successful response',
type: GetQuoteByIdResponse,
})
async getQuoteById(@Param('id') id: string): Promise<any> {
const quote = await this.quoteService.getQuoteById(id);

const response = {
message: 'getQuoteById',
quote: quote,
};
return response;
}
}
16 changes: 16 additions & 0 deletions src/quote/quote.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Module, MiddlewareConsumer } from '@nestjs/common';
import { QuoteController } from './quote.controller';
import { QuoteService } from './quote.service';
import { PrismaService } from '../prisma.service';
import { AuthMiddleware } from '../auth.middleware';

@Module({
imports: [],
controllers: [QuoteController],
providers: [QuoteService, PrismaService],
})
export class QuoteModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(AuthMiddleware).forRoutes('quote');
}
}
18 changes: 18 additions & 0 deletions src/quote/quote.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { QuoteService } from './quote.service';

describe('QuoteService', () => {
let service: QuoteService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [QuoteService],
}).compile();

service = module.get<QuoteService>(QuoteService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
35 changes: 35 additions & 0 deletions src/quote/quote.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma.service';
import { quote } from '@prisma/client';
import _ from 'lodash';

@Injectable()
export class QuoteService {
constructor(private readonly prisma: PrismaService) {}

async getQuotes(pageInt: number, perPageInt: number): Promise<quote[]> {
const quotes = await this.prisma.quote.findMany({
skip: perPageInt * (pageInt - 1),
take: perPageInt,
});
return quotes;
}

async getRandomQuote(): Promise<quote> {
const quotes = await this.prisma.quote.findMany({
take: 100,
});

const quote = _.sample(quotes);
return quote;
}

async getQuoteById(id: string): Promise<quote> {
const quote = await this.prisma.quote.findUnique({
where: {
id,
},
});
return quote;
}
}
29 changes: 29 additions & 0 deletions src/quote/response/getQuoteById.response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ApiProperty } from '@nestjs/swagger';

export class Quote {
@ApiProperty()
id: string;

@ApiProperty()
content: string;

@ApiProperty()
author: string;

@ApiProperty()
tags: string[];

@ApiProperty()
created_at: string;

@ApiProperty()
updated_at: string;
}

export class GetQuoteByIdResponse {
@ApiProperty()
message: string;

@ApiProperty()
quote: Quote;
}
40 changes: 40 additions & 0 deletions src/quote/response/getQuotes.response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ApiProperty } from '@nestjs/swagger';

export class GetQuotesResponse {
@ApiProperty()
message: string;

@ApiProperty({ default: [], isArray: true })
data: Data[];

@ApiProperty()
total: number;

@ApiProperty()
page: number;

@ApiProperty()
limit: number;
}

export class Data {
@ApiProperty()
id: string;

@ApiProperty()
content: string;

@ApiProperty()
author: string;

@ApiProperty()
tags: Tag[];

@ApiProperty()
created_at: string;

@ApiProperty()
updated_at: string;
}

export class Tag {}
29 changes: 29 additions & 0 deletions src/quote/response/getRandomQuote.response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ApiProperty } from '@nestjs/swagger';

export class Quote {
@ApiProperty()
id: string;

@ApiProperty()
content: string;

@ApiProperty()
author: string;

@ApiProperty()
tags: string[];

@ApiProperty()
created_at: string;

@ApiProperty()
updated_at: string;
}

export class GetRandomQuoteResponse {
@ApiProperty()
message: string;

@ApiProperty()
quote: Quote;
}

0 comments on commit 6cc025d

Please sign in to comment.