LoginSignup
2
0

Prismaで特定カラムを上手にexcludeする (userのpassword等を返さないようにする)

Last updated at Posted at 2023-07-22

はじめに

prismaでクエリを発行する際、passwordカラム等の除外したいカラムを

 this.prisma.user.findUnique({
      where: userWhereUniqueInput,
      exclude: 'password'
    })

と書けたらいいなぁ…という妄想を全人類がしていることだと思う。
これ、2020年4月からissueがあるのに、全く対応される気配がない。

愚直に select

 this.prisma.user.findUnique({
      where: userWhereUniqueInput,
      select: { id: true, email: true, ... },
    })

と書くこともできるのだが、これだとuserテーブルにカラムが増えるたびに
手動ですべての select 文をイジることになるのでつらい。

対応策

excludeしたいカラム以外のすべてのフィールドを列挙する関数を作り、
selectに指定してあげれば良い。

①以下関数を任意の場所に作成する

export const prismaExclude = <T extends Models['fields'], ExcludeT extends (keyof T)[]>(
  fields: T,
  exclude: ExcludeT,
) => {
  const keys = Object.keys(fields) as (keyof T)[];
  const excludeSet = new Set(exclude);
  const attributes: Partial<Record<keyof T[][number], boolean>> = {};
  for (const key of keys) {
    if (excludeSet.has(key)) attributes[key] = false;
    else attributes[key] = true;
  }

  type IncludeType = {
    [K in keyof T]: true;
  };
  type Result = Omit<IncludeType, ExcludeT[number]>;
  return attributes as Result;
};

②以下のように使う。prismaのfieldsを第一引数、除外したいカラムの配列を第二引数に渡す。
(例はfindUniqueだが、findMany, create, update, delete 等でも使える)

 this.prisma.user.findUnique({
      where: userWhereUniqueInput,
      select: prismaExclude(this.prisma.user.fields, ['password'])
    })

注意

fieldsはPrisma 4.3.0 からPreviewで入り、5.0.0で正式に取り入れられた機能なので、

  • 4.3.0未満を使っている人 → 要アップデート
  • 4.3.0以上~5.0.0未満を使っている人 → prisma.schemaに以下の記載が必要
    generator client {
      provider        = "prisma-client-js"
      output          = "./client"
      previewFeatures = ["fieldReference"] // ★追記
    }
    

あとがき

おそらくいつか公式でexcludeに対応する日が来ると思うので、
この記事がそれまでのつなぎになれば幸いだ。

ちなみにこの方法は上記issueに出てきたこれを参考にした

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0