🐈
FirestoreEventで取得したデータに型をつける
私は普段Flutterでアプリ開発をしているのですが、最近通知機能をFirebase Functionで実装する機会がありました。
具体的には、Firestoreへのデータ保存をトリガーとして通知を送信する機能です。
そのときにデータを型安全に扱う方法に手こずったのでかんたんに紹介します。
(FirestoreEventとかFirebase Function v2の参考にもなるかも)
結論
FirestoreDataConverter
のfromFirestore
メソッドを使います。
公式ドキュメントのExampleではFirestoreからデータを取得するときにwithConverter
を使う例が紹介されています。
しかし、FirestoreEventを使う場合にはコールバック関数の引数としてデータを受け取るので、withConverter
が使えません。
そこで、以下のようにconverterのfromFirestore
メソッドを直接使用します。
※コードは実際に使用しているものとは異なる最小限のものです。
chat.ts
import {
DocumentData,
FirestoreDataConverter,
QueryDocumentSnapshot,
} from "firebase-admin/firestore";
class Chat {
constructor(
readonly chatId: string,
readonly token: string,
readonly content: string,
readonly fromName: string
) {}
}
export const chatConverter: FirestoreDataConverter<Chat> = {
toFirestore(chat: Chat): DocumentData {
return {
chatId: chat.chatId,
tokens: chat.token,
content: chat.content,
fromName: chat.fromName,
};
},
fromFirestore(snapshot: QueryDocumentSnapshot): Chat {
const data = snapshot.data();
return new Chat(
data.chatId,
data.token,
data.content,
data.fromName
);
},
};
index.ts
import { Message } from "firebase-admin/lib/messaging/messaging-api";
import { onDocumentCreated } from "firebase-functions/v2/firestore";
import { chatConverter } from "./models/chat";
import { sendMessage } from "./utils/send-message";
export const message = onDocumentCreated(
"rooms/{roomId}/chats/{chatId}",
async (event) => {
const snap = event.data;
if (snap === undefined) {
console.error("No data for new message");
return;
}
// ↓ココ
const chat = chatConverter.fromFirestore(snap);
const message: Message = {
notification: {
title: chat.fromName,
body: chat.content,
},
token: chat.token,
};
sendMessage(message);
}
);
ちゃんとChatの型がついています。わーい。
参考記事
Discussion