闘技場

  • Nest.js
  • TypeORM
  • mongodb (AWS DocumentDB)
  • Docker

チャレンジャー紹介

絶対に秘匿したい俺

  • 秘匿したいレベル100
  • フロントに フィールド名が_id かつ mongodb固有のHexStringが露出することで一族が滅びた過去を持つ孤高の戦士
  • そもそも_idを別の名前で利用したかった(ライブラリラッパーでもいい)

絶対に秘匿させたくないmongodbおよびTypeORM

  • 秘匿したくないレベル100
  • 素晴らしいObjectIDな仕組みをもって高橋一族を滅びした魔女の末裔
  • どうあがいても _id で保持してしまう

結果

絶対に秘匿したい俺の勝利

  • 保存時とかは id -> _idをするのは我慢した
  • class-transformerの仕組みを活用

ダイジェスト

ここからはダイジェストでお送りいたします。

classToPlain()を駆使して加工した俺

SomeEntity.ts

import { Entity, ObjectIdColumn } from 'typeorm';
import { ObjectId } from 'mongodb';

@Entity()
export class SomeEntity() {
  @ObjectIdColumn()
  @Exclude()
  _id?: ObjectId;

  @Expose()
  public get id() {
    return this._id ? this._id.toHexString() : undefined;
  }
}

これをclass-transformerのclassToPlain()したあとでレスポンスを返すことで無事勝利

解説の山田さん「classToPlain()されたときの挙動を @Expose() @Exclude()の両呪文をうまくつかって隠蔽していますね」

@Exclude(): classToPlain() したときにフィールドごと吹っ飛ばす呪文
@Expose (): classToPlain() したときにフィールドと値を付け足す呪文

classToPlain()をインターセプトした俺

class-to-plain.interceptor.ts

import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { classToPlain } from 'class-transformer';

@Injectable()
export class ClassToPlainInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(map(data => classToPlain(data)));
  }
}

解説の山田さん「Controllerでいちいち return classToPlain() したくなかったことが伺えますね。インターセプターがうまく機能しているように見えます」

元記事はこちら

絶対に_idを秘匿したい俺 v.s. 絶対に_idを秘匿させたくないTypeORM – mongodb編