Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9309

[Nest.js] クエリパラメータをPipeを使って変換する方法

$
0
0
この記事は 株式会社サイバー・バズ Advent calendar 2021 8日目の記事です。 概要 Nest.jsを使っている時に、frontから受け取ったRequestを使ってゴネゴネしている時です。 すると、、 「あれ、、、落ちる。。」 「想定した型と合っていない。。。」 ということがありました。 その時の話です。 例 検索処理を例にあげます。 dto/searchItem.dto.ts class SearchItemDTO { minPrice: number maxPrice: number page: number limit: number } item/item.controller.ts @Get() async getItems(@Query() searchItemDTO: SearchItemDTO){ // 検索処理Service } 以下のRequestをgetItemsに投げました。 curl 'http://localhost:3001/items?minPrice=3000&maxPrice=10000&page=1&limit=10' ここでgetItemsに実際に渡ってきたsearchItemDTOを確認してみると、 全てstringになっており、SearchItemDTOの型と乖離していることが分かります。 { minPrice: '3000', maxPrice: '10000', page: '1', limit: '10' } minPriceやmaxPriceを使ってnumber前提で計算処理などを書いてしまうと、落ちる危険があります。 Pipes Nestには、Pipesというものが存在します。 PipesはクライアントからのRequestをControllerに渡す前に処理を挟むことができます。 Documentでも取り上げられているように、変換とバリデーションの二つが主なユースケースのようです。 Built-in pipes 汎用的なPipesについては、あらかじめBuilt-inで@nestjs/commonからimportして使うことができます。 今回はParseIntPipeが使えそうです。 ParseIntPipeを使ってgetItemsを書き換えてみます。 item/item.controller.ts @Get() async getItems( @Query('minPrice', ParseIntPipe) minPrice: number, @Query('maxPrice', ParseIntPipe) maxPrice: number, @Query('page', ParseIntPipe) page: number, @Query('limit', ParseIntPipe) limit: number ){ // 検索処理Service } 再度getItemsに渡ってきたプロパティを確認してみると、 { minPrice: 3000, maxPrice: 10000, page: 1, limit: 10 } 想定通りnumberに変換されています。 これで目的は果たせましたが、パラメータが増えるたびにParseIntPipeを増やす必要があり、 item.controller.tsファイルが肥大化してしまうおそれがあります。 ユーザ定義pipe pipeは自作することもできます。 まずDTOのうち 変換前をSearchItemDTO 変換後をSearchItemTransformDTO として実際の型と乖離がないように再定義してみます。 dto/searchItem.dto.ts export class SearchItemDTO { minPrice: string maxPrice: string page: string limit: string } dto/searchItemTransform.dto.ts export interface SearchItemTransformDTO { minPrice: number maxPrice: number page: number limit: number } 次にpipe処理です。 pipe/searchItem.pipe.ts import { PipeTransform, Injectable } from '@nestjs/common' @Injectable() export class SearchItemPipe implements PipeTransform<SearchItemDTO, SearchItemTransformDTO> { transform(searchItemDTO: SearchItemDTO): SearchItemTransformDTO { return Object.entries(searchItemDTO).reduce((acc, cur) => { const key = cur[0] const value = ['minPrice', 'maxPrice', 'page', 'limit'].includes(key) ? parseInt(cur[1]) : cur[1] return { ...acc, [key]: value } }, {}) } } SearchItemPipeをitem.controller.tsに反映させます。 item/item.controller.ts @Get() async getItems(@Query(SearchItemPipe) searchItemTransformDTO: SearchItemTransformDTO){ // 検索処理Service } すっきり書けました。 パラメータが増えた場合は、SearchItemPipeを編集すれば対応できます。 これで定義したDTOと実際の値との間で乖離が無くなりました。 他にも方法はあるかと思いますが、一例として参考にしていただければと思います。

Viewing all articles
Browse latest Browse all 9309

Trending Articles