😂

【msw】mswjs/dataで全てのデータを削除する方法

2023/10/11に公開

動機

mswのmswjs/dataを使用して仮想DBを構築し、個人開発を進めています。開発の過程で、特定のモデルに関連するデータを全件削除する必要があり、その方法についての情報が少なかったため、調査して解決策を見つけました。
この記事は、その過程と解決策を備忘録として残すものになります。

全てのデータを削除する方法

結論から言うと、deleteMany 関数のwhere句の引数に空のオブジェクト{}を渡すだけでした!

const deletedUsers = db.user.deleteMany({
  where: {},
});

簡単だった...
せっかくなので、以下に調査メモを記載したいと思います!

調査メモ

最初に、github のリポジトリのReadmeを確認したのですが、deleteMany 関数を使用することで、複数のデータを削除できることはわかりました。
ですが、以下のように関数の引数に where 句を使って条件に当てはまるデータを削除する方法しか載っておらず、条件に関わらず全てのデータを削除する方法は記載されていませんでした。

const deletedUsers = db.user.deleteMany({
  where: {
    followersCount: {
      lt: 10,
    },
  },
});

色々記事などを探した結果、直接リポジトリのソースコードを読むことにしました!
すると、mswjs/data/src/factory.tsファイルに deleteMany 関数が定義されていました。

deleteMany({ strict, ...query }) {
  const records = executeQuery(modelName, primaryKey, query, db)

  if (records.length === 0) {
    if (strict) {
      throw new OperationError(
        OperationErrorType.EntityNotFound,
        format(
          'Failed to execute "deleteMany" on the "%s" model: no entities found matching the query "%o".',
          modelName,
          query.where,
        ),
      )
    }

    return null as any
  }

  records.forEach((record) => {
    db.delete(modelName, record[record[PRIMARY_KEY]] as string)
  })

  return records
},

上記のコードを見る限り、おそらく、executeQuery(modelName, primaryKey, query, db)where句で条件を指定してデータを取得している関数だろうと予想しました。
そして、最後のrecords.forEachで取得したデータを削除していると推測しました。
そこで、executeQueryの動作を理解するためにその関数の定義を追ってみたのですが、その先のコードを追うのが大変で、他にわかる方法はないか調査したところ、以下のようにmswjs/data/test/model/deleteMany.test-d.tsというテストコードファイルにその方法が記載されているのを見つけました。

db.user.deleteMany({
  // Providing no query criteria matches all entities.
  // クエリの条件を提供しない場合、すべてのエンティティがマッチします。(日本語訳)
  where: {},
});

コメントに、「where 句を指定しなかった場合は、全てのエンティティが対象となる」と記載されており、実際に以下のように書くと対象のモデルのデータを全て削除できました。

const deletedUsers = db.user.deleteMany({
  where: {},
});

他にも、mswjs/data/src/db/drop.tsファイルの、drop 関数からも推測ができました。

export function drop(factoryApi: FactoryAPI<any>): void {
  Object.values(factoryApi).forEach((model) => {
    model.deleteMany({ where: {} });
  });
}
const db = factory(...models);

drop(db);

drop 関数は、引数に渡された db インスタンスのモデルを全て削除する機能です。
drop関数では、渡されたdbインスタンスをObject.valuesでループさせ、model.deleteMany({ where: {} });で各モデルのデータを全て削除しています。
このコードからも、deleteMany({ where: {} })でモデルの全てのデータを削除できることがわかります!!

気づき

今回の大きな気づきは、リポジトリのソースコードを直接読むことの重要性です!!
以前、業務でも、他のライブラリのソースコードを読み、その仕様を理解できた経験もあるので、今後も積極的にソースコードを読みにいくように心がけたいと思います!

GitHubで編集を提案

Discussion