Browse Source

Part 2: Building a REST API with NestJS and Prisma: Input Validation & Transformation

master
Hendra Lin 3 years ago
parent
commit
2b4e80b314
  1. 2
      package.json
  2. 14
      src/articles/articles.controller.ts
  3. 12
      src/articles/dto/create-article.dto.ts
  4. 3
      src/main.ts
  5. 29
      yarn.lock

2
package.json

@ -25,6 +25,8 @@
"@nestjs/platform-express": "^9.0.0", "@nestjs/platform-express": "^9.0.0",
"@nestjs/swagger": "^6.3.0", "@nestjs/swagger": "^6.3.0",
"@prisma/client": "^4.12.0", "@prisma/client": "^4.12.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rxjs": "^7.2.0", "rxjs": "^7.2.0",
"swagger-ui-express": "^4.6.2" "swagger-ui-express": "^4.6.2"

14
src/articles/articles.controller.ts

@ -1,4 +1,4 @@
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
import { Controller, Get, Post, Body, Patch, Param, Delete, ParseIntPipe } from '@nestjs/common';
import { ArticlesService } from './articles.service'; import { ArticlesService } from './articles.service';
import { CreateArticleDto } from './dto/create-article.dto'; import { CreateArticleDto } from './dto/create-article.dto';
import { UpdateArticleDto } from './dto/update-article.dto'; import { UpdateArticleDto } from './dto/update-article.dto';
@ -30,19 +30,19 @@ export class ArticlesController {
@Get(':id') @Get(':id')
@ApiOkResponse({ type: ArticleEntity }) @ApiOkResponse({ type: ArticleEntity })
findOne(@Param('id') id: string) {
return this.articlesService.findOne(+id);
findOne(@Param('id', ParseIntPipe) id: number) {
return this.articlesService.findOne(id);
} }
@Patch(':id') @Patch(':id')
@ApiOkResponse({ type: ArticleEntity }) @ApiOkResponse({ type: ArticleEntity })
update(@Param('id') id: string, @Body() updateArticleDto: UpdateArticleDto) {
return this.articlesService.update(+id, updateArticleDto);
update(@Param('id', ParseIntPipe) id: number, @Body() updateArticleDto: UpdateArticleDto) {
return this.articlesService.update(id, updateArticleDto);
} }
@Delete(':id') @Delete(':id')
@ApiOkResponse({ type: ArticleEntity }) @ApiOkResponse({ type: ArticleEntity })
remove(@Param('id') id: string) {
return this.articlesService.remove(+id);
remove(@Param('id', ParseIntPipe) id: number) {
return this.articlesService.remove(id);
} }
} }

12
src/articles/dto/create-article.dto.ts

@ -1,15 +1,27 @@
import { ApiProperty } from '@nestjs/swagger' import { ApiProperty } from '@nestjs/swagger'
import { IsBoolean, IsNotEmpty, IsOptional, IsString, MaxLength, MinLength } from 'class-validator'
export class CreateArticleDto { export class CreateArticleDto {
@IsString()
@IsNotEmpty()
@MinLength(5)
@ApiProperty() @ApiProperty()
title: string title: string
@IsString()
@IsOptional()
@IsNotEmpty()
@MaxLength(300)
@ApiProperty({ required: false }) @ApiProperty({ required: false })
description?: string description?: string
@IsString()
@IsNotEmpty()
@ApiProperty() @ApiProperty()
body: string body: string
@IsBoolean()
@IsOptional()
@ApiProperty({ required: false, default: false }) @ApiProperty({ required: false, default: false })
published?: boolean = false published?: boolean = false
} }

3
src/main.ts

@ -1,10 +1,13 @@
import { NestFactory } from '@nestjs/core'; import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module'; import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { ValidationPipe } from '@nestjs/common'
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule); const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe({ whitelist: true }))
const config = new DocumentBuilder() const config = new DocumentBuilder()
.setTitle('Median') .setTitle('Median')
.setDescription('The Median API description') .setDescription('The Median API description')

29
yarn.lock

@ -1046,6 +1046,11 @@
dependencies: dependencies:
"@types/superagent" "*" "@types/superagent" "*"
"@types/validator@^13.7.10":
version "13.7.15"
resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.15.tgz#408c99d1b5f0eecc78109c11f896f72d1f026a10"
integrity sha512-yeinDVQunb03AEP8luErFcyf/7Lf7AzKCD0NXfgVoGCCQDNpZET8Jgq74oBgqKld3hafLbfzt/3inUdQvaFeXQ==
"@types/yargs-parser@*": "@types/yargs-parser@*":
version "21.0.0" version "21.0.0"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"
@ -1695,6 +1700,20 @@ cjs-module-lexer@^1.0.0:
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40"
integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==
class-transformer@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/class-transformer/-/class-transformer-0.5.1.tgz#24147d5dffd2a6cea930a3250a677addf96ab336"
integrity sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==
class-validator@^0.14.0:
version "0.14.0"
resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.14.0.tgz#40ed0ecf3c83b2a8a6a320f4edb607be0f0df159"
integrity sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==
dependencies:
"@types/validator" "^13.7.10"
libphonenumber-js "^1.10.14"
validator "^13.7.0"
cli-cursor@^3.1.0: cli-cursor@^3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
@ -3311,6 +3330,11 @@ levn@^0.4.1:
prelude-ls "^1.2.1" prelude-ls "^1.2.1"
type-check "~0.4.0" type-check "~0.4.0"
libphonenumber-js@^1.10.14:
version "1.10.26"
resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.26.tgz#3e6604357b3434b0005f85778b44153f4fadeecd"
integrity sha512-oB3l4J5gEhMV+ymmlIjWedsbCpsNRqbEZ/E/MpN2QVyinKNra6DcuXywxSk/72M3DZDoH/6kzurOq1erznBMwQ==
lines-and-columns@^1.1.6: lines-and-columns@^1.1.6:
version "1.2.4" version "1.2.4"
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
@ -4626,6 +4650,11 @@ v8-to-istanbul@^9.0.1:
"@types/istanbul-lib-coverage" "^2.0.1" "@types/istanbul-lib-coverage" "^2.0.1"
convert-source-map "^1.6.0" convert-source-map "^1.6.0"
validator@^13.7.0:
version "13.9.0"
resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855"
integrity sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==
vary@^1, vary@~1.1.2: vary@^1, vary@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"

Loading…
Cancel
Save