Node.js环境下Firestore SDK Timestamp版本变更适配咨询
问题背景
升级firebase-admin到11.11.x及以上版本后,Timestamp的使用出现兼容性问题:
- 旧版本(
firebase-admin@11.9.0)通过import { firestore } from 'firebase-admin'调用firestore.Timestamp.fromDate()可正常工作 - 按照官方调整后的方式
import { Timestamp } from 'firebase-admin/firestore'创建的Timestamp,在Fireorm执行更新操作时触发报错:
Update() requires either a single JavaScript object or an alternating list of field/value pairs that can be followed by an optional precondition. Value for argument "dataOrField" is not a valid Firestore document. Detected an object of type "Timestamp" that doesn't match the expected instance.
- 改用
@google-cloud/firestore@7.1.0的Timestamp则可正常完成更新操作
核心原因
firebase-admin从11.11.x版本开始,内部依赖的Firestore SDK进行了版本升级,导致其导出的Timestamp类实例与@google-cloud/firestore包的Timestamp实例不再兼容。而Fireorm底层依赖@google-cloud/firestore的SDK做数据校验,因此firebase-admin的Timestamp实例无法通过校验。
推荐方案
方案1:统一使用@google-cloud/firestore的Timestamp(推荐)
这是目前验证可行的方案,能确保与Fireorm的兼容性,具体操作如下:
- 依赖配置:确保项目安装对应版本的依赖
"dependencies": { "@google-cloud/firestore": "^7.1.0", "firebase-admin": "^11.11.x", "fireorm": "^x.x.x" }
- 实体类定义:直接导入
@google-cloud/firestore的Timestamp
import { Timestamp } from '@google-cloud/firestore'; import { Collection } from 'fireorm'; @Collection('trucs') export class Trucs { id!: string; active: boolean; deleted: boolean; changedAt: Timestamp; }
- 更新逻辑:使用该Timestamp类创建实例
import { Timestamp } from '@google-cloud/firestore'; async updateApi(trucId: string): Promise<Truc | undefined> { const truc: Truc = await this.findTruc(trucId); const updateTruc = { ...truc }; updateTruc.changedAt = Timestamp.fromDate(new Date()); // 过滤undefined字段 Object.keys(updateTruc).forEach(key => { if (updateTruc[key] === undefined) { delete updateTruc[key]; } }); await this.update(updateTruc); return updateTruc; }
方案2:锁定firebase-admin到兼容版本(临时过渡)
如果暂时不想切换依赖,可以将firebase-admin锁定到11.10.x版本,保留原有firestore.Timestamp的使用方式,但这只是临时方案,无法享受后续版本的功能更新:
"dependencies": { "firebase-admin": "~11.10.1" }
方案3:使用Firebase Admin的Firestore实例适配(不推荐)
若坚持使用firebase-admin的Timestamp,需要确保Fireorm使用的是firebase-admin初始化后的Firestore实例而非独立的@google-cloud/firestore实例。具体需要在NestJS配置Fireorm时,传入firebase-admin初始化后的firestore对象,但该方式可能存在潜在兼容性风险,需自行验证。
内容的提问来源于stack exchange,提问作者iKK

