@firebase-bridge/firestore-admin

中文文档
0.0.10发布于 2026/08/12Apache-2.0TypeScriptESM + CJS零依赖近 30 天下载 2313

用于单位测试和当地dev的Firebase Firestore Admin SDK (Gapic) 的高真能模拟器.

中文使用文档
文档目录24 节
  1. 这是什么
  2. 什么时候用
  3. 为什么不是仿真器(用于此用途)
  4. 配套软件包
  5. 支助
  6. 安装
  7. 快速启动( Jest/ Vites)
  8. 快速重置(首选)
  9. B) 新鲜DB(完全隔离)
  10. 多个数据库和 Firestore 隔离
  11. 核心概念和 API
  12. class FirestoreMock
  13. class FirestoreController
  14. class DatabaseDirect
  15. class SystemTime
  16. 结构快照(种子、diff、圆行)
  17. 状态和可观察性
  18. 关于忠诚的说明(高级)
  19. 一揽子出口(公共)
  20. 解决问题
  21. 版本兼容性( C)
  22. 捐款
  23. 许可证
  24. 商标归属

@firebase-bridge/firestore-admin (英语)

高度忠诚 模拟游戏 联 合 国 Firestore 管理员 SDK用于快速、确定性后端单元测试的目的(没有模拟器启动装置,没有部署回路).

license: Apache-2.0 node typescript

这是什么

这个软件包让你运行一个真正的 firebase-admin 消防车 实例 正在处理 相对于一个高纯度生产Firestore语义(CRUD、批量、交易、查询、汇总、矢量值、听众等)的内存数据库.

  • 仅后端 (节点.js). 无客户端/浏览器 API.
  • 发展依赖性 打算用于 测试 财务报告和审定财务报表 快速原型 后端逻辑.
  • 将起火点功能 v1/v2 起火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点火点 @ firebase-bridge/firestore-函数。 。 。 .

重要数字 : @firebase-bridge/firestore-admin 模拟数据库,而不是管理员SDK本身. 当你使用它时,你正在和真正的Firestore Admin SDK实例互动 — — 和生产中使用的一样。 模拟器只是修补它自己的 Google API Client sDK在盖子下执行, 这意味着你的测试在没有仿真器和网络呼叫的情况下,进行真实的Admin SDK行为.

什么时候用

  • 使用后端代码的单元和集成测试 firebase-admin/firestore
  • CI 现场 Firestore 模拟器 缓慢或无法使用
  • 需要可控时钟和快速重排的决定性测试

为什么不是仿真器(用于此用途)

  • 没有时间了 零部署环. 0 外部进程——只是编辑、保存和测试
  • 决定性 模拟火炉 有可控制的时间
  • 适合紧凑的测试循环和CI,其中启动成本很重要

配套软件包

  • 将起火点功能(v1 & v2) Firestore 触发器绑定在一个模拟起火点数据库中 @ firebase-bridge/firestore-函数。 。 。 .
  • 对于一个高的忠诚 模拟引用层 页:1 Firebase HTTPS 云函数 (v1 & v2) — 运行真实 onCall 编号 : onRequest 本地处理者, 符合实际 认证, (中文(简体) ), 应用检查, (中文(简体) ), 实例标识,和页眉(没有仿真符)——使用相伴包 @firebase-bridge/auth-context (英语)。 。 。 .

支助

本项目在《公约》下免费提供 Apache 2.0 许可证。 。 。 .
如果您认为它有用并愿意支持正在进行的开发,你可以 给我买杯咖啡。 。 。


安装

# npm
npm i -D @firebase-bridge/firestore-admin firebase-admin

# pnpm
pnpm add -D @firebase-bridge/firestore-admin firebase-admin

# yarn
yarn add -D @firebase-bridge/firestore-admin firebase-admin

端点 : firebase-admin 二. 支助 节点 : • 建议18+ {\FN华文楷体\FS16\1CHE0E0E0}TS: 严格模式推荐.


快速启动( Jest/ Vites)

以下列出两种常见的设置样式. 更倾向于快速重置方法 用于速度; 使用 每一次测试新鲜 DB 当您需要完整的 DB 生命周期隔离时.

快速重置(首选)

为整个套间建立一个环境和一个数据库; 测试间重置数字 :

import { Firestore } from 'firebase-admin/firestore';
import { FirestoreMock } from '@firebase-bridge/firestore-admin';

describe('Example suite (fast resets)', () => {
  const env = new FirestoreMock();
  const firestore: Firestore = env.createDatabase().firestore();

  afterEach(() => {
    env.resetAll(); // clears all databases in this env, keeps them alive
  });

  it('writes and reads', async () => {
    const ref = firestore.collection('users').doc('ada');
    await ref.set({ name: 'Ada', score: 1 });
    const snap = await ref.get();
    expect(snap.exists).toBe(true);
    expect(snap.data()).toEqual({ name: 'Ada', score: 1 });
  });
});

B) 新鲜DB(完全隔离)

每个测试提供一个新的逻辑 DB 删除 在每个之后 :

import { Firestore } from 'firebase-admin/firestore';
import { FirestoreMock } from '@firebase-bridge/firestore-admin';

describe('Example suite (fresh DB per test)', () => {
  const env = new FirestoreMock();
  let firestore!: Firestore;

  beforeEach(() => {
    firestore = env.createDatabase().firestore();
  });

  afterEach(() => {
    env.deleteAll(); // disposes all databases in this env
  });

  it('writes and reads', async () => {
    const ref = firestore.collection('users').doc('ada');
    await ref.set({ name: 'Ada', score: 1 });
    const snap = await ref.get();
    expect(snap.exists).toBe(true);
    expect(snap.data()).toEqual({ name: 'Ada', score: 1 });
  });
});

多个数据库和 Firestore 隔离

您可以主机 许多逻辑数据库 在一个环境中,你可以创建 多个 Firestore 实例 页:1 不变 当您需要Firestore 级别隔离时(例如,独立的听众),该数据库将显示共享状态.

const env = new FirestoreMock();

// Two separate logical databases
const dbA = env.createDatabase('proj-A', '(default)');
const dbB = env.createDatabase('proj-B', '(default)');

const fsA1 = dbA.firestore();
const fsA2 = dbA.firestore(); // isolated Firestore instances, same DB
const fsB = dbB.firestore(); // different DB entirely

核心概念和 API

这个包裹暴露出一小组高杠杆原始人. 以下名称为 实际出口。 。 。 .

class FirestoreMock

顶级 环境 拥有一个或多个内存数据库和一个可控制的时钟.

  • createDatabase(options?: FirestoreControllerOptions): FirestoreController 提供使用选项对象的新数据库。 所有字段都是可选的,但有默认值:

    • projectId 默认为 "default-project"
    • databaseId 默认为 "(default)"
    • location 默认为 "nam5"
    • namespace 默认为 "(default)" 如果您在测试中需要指定位置或命名空间,请使用此表单.
  • createDatabase(projectId?: string, databaseId?: string): FirestoreController 通过明确的ID提供一个新的数据库(如上所述默认).

  • getDatabase(projectId?: string, databaseId?: string): FirestoreController 访问已存在的数据库( 如果缺少/ 删除则扔出) .

  • databaseExists(projectId?: string, databaseId?: string): boolean

  • deleteAll(): void - 删除环境中的所有数据库.

  • resetAll(): void – 重置所有数据库(data & stats)而无需删除.

  • systemTime: SystemTime – 说吧 – 可控制的时间来源 用于确定性测试.

class FirestoreController

一个把柄到一个 单一逻辑数据库 (单位:千美元) projectId 财务报告和审定财务报表 databaseId) (中文(简体) ).

  • projectId: string, (中文(简体) ), databaseId: string

  • location: string – Firestore 数据库位置标识符用于 CloudEvents 和资源元数据. 接受多区域ID(例如:. nam5, (中文(简体) ), eur3)或区域身份证(例如. us-central1) (中文(简体) ). 默认为 nam5 如果省略,则删除.

  • namespace: string – 数据存储取名空间. 对于 Firestore 本地模式,应该保留 (default)。用于模拟数据存储器事件时的忠诚。 默认为 (default) 如果省略,则删除.

  • firestore(settings?: Settings): Firestore 创建一个 Firestore 管理员 SDK 实例 范围 到此数据库.

  • exists(): boolean - 数据库是否仍然存在.

  • epoch(): number - 单调地增加数据库的时代版本(逐一递减) reset()) (中文(简体) ).

  • version(): number - 数据库中单调增加的原子承诺版本.

  • delete(): void - 删除此数据库;后续调用(除此之外) exists()编号 :reset())掷出.

  • reset(): void - 清除文档和数据,但保持 DB 存活.

  • getStats(): FirestoreMockStats – 当前累积数据快照.

  • watchStats(watcher: (s: FirestoreMockStats) => void): () => void – 订阅 stat 更改( 返回未订阅) .

  • watchLifecycle(watcher: (s: DatabaseLifecycleEventArg) => void): () => void - 订阅生命周期事件(返回未订阅者).

  • database: DatabaseDirect - 直接/低级访问内存数据库(见下文).

class DatabaseDirect

薄而同步的外观 直接数据访问 (种子、检查、结构进出口)。 它绕过行政SDK对象,但保持了Firestore语义学.

  • 检查和结构

    • listCollectionIds(documentPath: string): string[]
    • listDocuments(collectionPath: string, showMissing: boolean): MetaDocument[]
    • query<T>(q: DocumentQuery<T>): MetaDocumentExists<T>[]
    • toStructuralDatabase(): StructuralDatabase
    • fromStructuralDatabase(src: StructuralDatabase, merge?: MergeGranularity): NormalizedWriteResult
    • 转换助手 : toMetaArray(), (中文(简体) ), toMetaMap(), (中文(简体) ), toMap(), (中文(简体) ), toDocumentPaths()
  • 单一文件操作

    • getDocument<T>(path: string): MetaDocument<T>
    • setDocument<T>(path: string, data: T): MetaDocument<T>
    • deleteDocument<T>(path: string): MetaDocument<T>
  • 批量操作 (原子)

    • batchSet<T>(...docs: DatabaseDocument<T>[]): MetaDocument<T>[]
    • batchDelete<T>(...paths: string[]): MetaDocument<T>[]
    • batchWrite<T>(writes: (DatabaseDocument<T> | string)[]): MetaDocument<T>[] (单位:千美元){ path, data } → set· ; string → delete(中文(简体) )

触发 : 低等触发登记在 DatabaseDirect这在白盒测试中是有用的。 对于云函数等同(v1/v2事件,主题,元数据),偏好 @ firebase-bridge/firestore-函数 同伴包裹...

低等触发实例( DatabaseDirect)

import { FirestoreMock } from '@firebase-bridge/firestore-admin';

const env = new FirestoreMock();
const ctl = env.createDatabase('proj', '(default)');
const direct = ctl.database;

const unsubscribe = direct.registerTrigger({
  route: 'users/{uid}/posts/{pid}',
  callback: ({ params, doc }) => {
    // Derive semantic kind from lineage
    const prev = doc.previous;
    const kind =
      !prev?.exists && doc.exists
        ? 'create'
        : prev?.exists && doc.exists
        ? 'update'
        : prev?.exists && !doc.exists
        ? 'delete'
        : 'write';

    console.log(`[${kind}] users/${params.uid}/posts/${params.pid}`, {
      exists: doc.exists,
      version: doc.version,
      updateTime: doc.updateTime.toDate().toISOString(),
    });

    // doc.data is deeply frozen; use cloneData() for a mutable copy
    const mutable = doc.cloneData();
    // ...assertions, enqueue side effects for tests, etc.
  },
});

// Perform writes via Firestore or DatabaseDirect
const fs = ctl.firestore();
await fs
  .collection('users')
  .doc('u1')
  .collection('posts')
  .doc('p1')
  .set({ title: 'hello' });

unsubscribe();

注释:

  • 触发起火 之后 每一次原子实验.
  • 如果多个写到同一文档的单项承诺,则仅指 最终状态 因为那条路已经实现.
  • 对于云函数忠诚度(v1/v2有效载荷塑造、对象、事件ID),偏好 @ firebase-bridge/firestore-函数 配套软件包.

数据库指令——写作(包括 fromStructuralDatabase() 形状)

import {
  FirestoreMock,
  StructuralDatabase,
  MergeGranularity,
} from '@firebase-bridge/firestore-admin';

const env = new FirestoreMock();
const ctl = env.createDatabase('proj', '(default)');
const direct = ctl.database;

// 1) Single set / delete
direct.setDocument('users/alice', { name: 'Alice', score: 7 });
direct.deleteDocument('users/bob'); // no-op if it didn't exist

// 2) Batch set / delete (atomic)
direct.batchSet(
  { path: 'users/bob', data: { name: 'Bob', score: 3 } },
  { path: 'users/cara', data: { name: 'Cara', tags: ['pro'] } }
);
direct.batchDelete('users/bob', 'users/ghost');

// 3) Heterogeneous batch write (atomic)
//    - {path,data} → normalized to 'set' (merge: 'root')
//    - 'string'   → normalized to 'delete'
direct.batchWrite([{ path: 'users/alice', data: { score: 8 } }, 'users/ghost']);

// 4) Import from a structural snapshot
const snapshot: StructuralDatabase = {
  users: {
    alice: {
      data: { name: 'Alice', role: 'admin' },
      collections: {
        posts: {
          p1: { data: { title: 'Hello', likes: 1 } },
          p2: { data: { title: 'Second', likes: 0 } },
        },
      },
    },
    cara: { data: { name: 'Cara' } },
  },
  products: {
    p1: { data: { sku: 'ABC-123', price: 19.95 } },
  },
};

// Merge strategies:
// - 'root'   → replace entire doc with provided data
// - 'branch' → deep-merge maps; scalars/arrays replace
// - 'node'   → apply only explicit field paths (like update/mergeFields)

direct.fromStructuralDatabase(snapshot, 'root' satisfies MergeGranularity);

// 5) Export to a structural snapshot (round-trippable)
const roundTrip = direct.toStructuralDatabase();

fromStructuralDatabase 返回正则写入结果(服务器时间+ MetaDocument[]) (中文(简体) ). 所有写作助手都是 原子 在批量调用边界.

数据库指令 - stats() (例为外形

import { DatabaseStats } from '@firebase-bridge/firestore-admin';

const s: DatabaseStats = direct.stats();
console.log(s);
/*
{
  // Operation counters (cumulative until reset)
  writes: 4,
  reads: 3,
  deletes: 1,
  noopReads: 1,
  noopWrites: 0,
  noopDeletes: 1,

  // Structural counters (current view of the tree)
  documentCount: 3,
  collectionCount: 2,
  stubDocumentCount: 0,
  stubCollectionCount: 0
}
*/
  • 使用 ctl.getStats() 用于控制范围统计(添加 DB 身份).
  • 重置计数器 财务报告和审定财务报表 在保存数据库时擦除所有数据, 调用 ctl.reset() (单 DB) 或 env.resetAll() (所有DB). 这个 删除所有文档和收藏, (中文(简体) ), 在不引用监视器回调的情况下冲出待定的更改, (中文(简体) ), 0 全部数据库数据,以及 将内部更改版本非ce重置为 0。 。 。 .

数据库指令 - query() 实例

DocumentQuery<T> 提供范围界定(根/文档、收藏ID、收藏组切换),可选时间点 readTime,则a predicate 超过现有文件.

import { Timestamp } from 'firebase-admin/firestore';
import {
  DocumentQuery,
  MetaDocumentExists,
} from '@firebase-bridge/firestore-admin';

// 1) All docs in top-level 'users'
const q1: DocumentQuery = {
  parent: '',
  allDescendants: false,
  collectionId: 'users',
  predicate: () => true,
};
const users: MetaDocumentExists[] = direct.query(q1);

// 2) Collection group query: any 'posts' anywhere under 'users/alice'
const q2: DocumentQuery<{ title: string; likes: number }> = {
  parent: 'users/alice',
  allDescendants: true,
  collectionId: 'posts',
  predicate: (m) => (m.data.likes ?? 0) >= 1,
};
const hotPosts = direct.query(q2);

// 3) As-of read (point-in-time)
const at: Timestamp = Timestamp.fromMillis(Date.now() - 1000);
const q3: DocumentQuery = {
  parent: '',
  allDescendants: true,
  predicate: () => true,
  readTime: at, // include docs with updateTime <= at
};
const asOfDocs = direct.query(q3);

结果为: MetaDocumentExists<T>[] 只有(不包括没有的文件)。 在测试代码中按需要排列.

MetaDocumentExists 打开 MetaDocumentNotExists (你得到的东西)

从直接操作、查询和写结果中返回的不可移动快照.

共同领域MetaDocument<T>(中文(简体) )

  • epoch: number - 内部数据库 时代 每次重置内部数据库时递增
  • parent: string - 医生父母的收集路径
  • path: string - 完全合格的文档路径
  • id: string - 最后一个部分 path
  • serverTime: Timestamp - 制作行动的权威承诺/适用时间
  • updateTime: Timestamp — doc 的上个更新时间( 如果从未存在过 0)
  • version: number - 单调增加的原子 承诺 数据库版本
  • hasChanges: boolean - 生产操作是否改变了文件
  • createTime?: Timestamp — 当 doc 首次创建时( 如果从未存在, 未定义)
  • data?: T – 说吧 – 深冻了 数据; 使用 cloneData() 可变副本
  • previous?: MetaDocument<T> – 说吧 – 即时 同一路径的上一个状态(在 hasChanges === true; 不是一个中转链)
  • cloneData(): T | undefined - 防御性深克隆 data

改进

  • MetaDocumentExists<T>数字 :

    • exists: true
    • createTime: Timestamp
    • data: T
  • MetaDocumentNotExists<T>数字 :

    • exists: false
    • createTime?: undefined
    • data?: undefined
const m = direct.getDocument<{ name: string }>('users/alice');
if (m.exists) {
  // MetaDocumentExists<{name:string}>
  console.log(m.path, m.updateTime.toDate(), m.data.name);
  const mutable = m.cloneData();
} else {
  // MetaDocumentNotExists
  console.log('missing:', m.path);
}

作为阵列和地图的快照( M)toMetaArray, (中文(简体) ), toMetaMap, (中文(简体) ), toMap(中文(简体) )

// Seed
direct.batchSet(
  { path: 'users/alice', data: { name: 'Alice', score: 7 } },
  { path: 'users/cara', data: { name: 'Cara', score: 3 } }
);

// 1) Array of existing meta documents (ordered)
const arr = direct.toMetaArray();

// 2) Map of path → MetaDocumentExists
const metaMap = direct.toMetaMap();

// 3) Map of path → plain document data (no meta)
const dataMap = direct.toMap();

class SystemTime

写作、变形和快照时间戳所观察到的“现在”决定控制.

  • now(): Date - 目前每个战略的时间.
  • system(): void - 真正的时钟.
  • constant(date: Date): void - 固定瞬间.
  • offset(...): 从 a 开始 根号 时间和实时前进(超载支持) Date 或者说 UTC parts) (中文(简体) ).
  • advance(msOrParts): void - 跳出时钟向前.
  • custom(fn: () => Date): void - 完全定制时间生成器.

系统时间( M) Timestamp.now() 来了

在内部,这个模拟器来自所有承诺/写作/更新时间 SystemTime然而, firebase-admin’: Timestamp.now() 调用 真实时钟 (例如, Date.now())),我们这样做 没有 猴-patch默认。 因此,如果您的应用程序/测试代码 直接 电话 Timestamp.now(),它不会反映 SystemTime 除非您采取额外步骤.

选项 :

  1. 不要打电话 Timestamp.now() 直接在测试. 相反,来自 SystemTime数字 :
import { Timestamp } from 'firebase-admin/firestore';
const ts = Timestamp.fromDate(env.systemTime.now());
  1. 猴头 Timestamp.now 测试期间 (范围可逆):
import { Timestamp } from 'firebase-admin/firestore';
let restore: undefined | (() => void);

beforeAll(() => {
  const original = Timestamp.now;
  (Timestamp as any).now = () => Timestamp.fromDate(env.systemTime.now());
  restore = () => {
    (Timestamp as any).now = original;
  };
});

afterAll(() => restore?.());
  1. 使用您的测试选手的假工具 使全球时钟与 SystemTime。 。 。 .
  • 欢乐 (现代假计时器):
import { jest } from '@jest/globals';

beforeAll(() => {
  jest.useFakeTimers();
});

beforeEach(() => {
  jest.setSystemTime(env.systemTime.now());
});

afterAll(() => {
  jest.useRealTimers();
});
  • 维特 (单位:千美元)vi.useFakeTimers() 编号 : vi.setSystemTime(),类似地.

我们故意避免补丁 Timestamp.now() 自动保存此库的侧效果 。 全体 内部 时间戳(承诺时间, serverTimestamp, (中文(简体) ), updateTime, (中文(简体) ), writeTime做荣誉 SystemTime。 。 。 .


结构快照(种子、diff、圆行)

这个 结构 类型允许您在不使用 Firestore 对象的情况下进行快取/导入数据库状态 :

  • StructuralDatabase – 收藏的对象树 – 文件 – 嵌入式收藏.
  • StructuralCollection, (中文(简体) ), StructuralCollectionGroup, (中文(简体) ), StructuralDocument
import {
  StructuralDatabase,
  DatabaseDirect,
} from '@firebase-bridge/firestore-admin';

const ctl = new FirestoreMock().createDatabase('proj', '(default)');
const direct: DatabaseDirect = ctl.database;

// Export
const snapshot: StructuralDatabase = direct.toStructuralDatabase();

// Import/merge
const writes = direct.fromStructuralDatabase(
  snapshot /*, 'root' | 'collection' | 'document' */
);
expect(writes.count).toBeGreaterThan(0);

状态和可观察性

使用 FirestoreController.getStats() 坚持忠诚和跟踪业务:

const ctl = new FirestoreMock().createDatabase();
const fs = ctl.firestore();
await fs.collection('c').doc('d').set({ a: 1 });

const stats = ctl.getStats();
expect(stats.documents.total).toBe(1);

在测试期间订阅实时更新 watchStats() (记得未订阅):

const stop = ctl.watchStats((s) => {
  // e.g., console.log('writes', s.operations.writes.total)
});
// ...
stop();

关于忠诚的说明(高级)

  • 原子:批发/交易为原子;变换结果遵循Firestore的订购规则.
  • 时间数字 : updateTime, (中文(简体) ), writeTime,并存储 serverTimestamp 遵循 Firestore 关系; 使用 SystemTime 做决定性测试.
  • 查询: 过滤器(包括 or编号 :not-in编号 :in、命令、光标、限制、集合(例如, count()) (中文(简体) ).
  • 矢量值: 支持 FieldValue.vector() 字段和最近的“邻居”特征,通过行政API表面显示.
  • 听众: 文档和查询听众的行为像流出 API 有单调 readTime 和适当的改变套.
  • 已分割的查询( Collection Group. get partities () / Query. get Partities () ~ GAPIC 分区查询): 目前被打出- 模拟返回一个空流( 无分区) , 用于调取结果的测试。 使用仿真器/火炬来进行真正的分隔语义(平行导出/批发).

如果你发现行为与真正的行政SDK或模拟器不同, 请用最小的重写打开一个问题.. 忠诚是项目第一优先。 。 。 .


一揽子出口(公共)

您可以从此软件包导入 :

  • FirestoreMock, (中文(简体) ), FirestoreController
  • DatabaseDirect 结构类型: StructuralDatabase, (中文(简体) ), StructuralCollection, (中文(简体) ), StructuralCollectionGroup, (中文(简体) ), StructuralDocument
  • 时间控制 : SystemTime
  • 有用的断言类型: MetaDocument, (中文(简体) ), MetaDocumentExists, (中文(简体) ), MetaDocumentNotExists, (中文(简体) ), MergeGranularity, (中文(简体) ), Trigger, (中文(简体) ), TriggerEventArg, (中文(简体) ), FirestoreMockStats

云函数: 在测试中登记/使用触发器,取决于 @ firebase-bridge/firestore-函数 配套软件包.


解决问题

  • 我的Firestore电话不会被嘲笑 确保您使用 firestore = env.createDatabase(...).firestore() 从a FirestoreController 创建于 这种环境.

  • 我需要新鲜的状态 在测试之间 偏爱 env.resetAll() (快)结束 env.deleteAll() (完全处理DB). 也可以通过 controller.reset()。 。 。 .

  • 时间敏感的说法是片面的 固定或提前时间通过 env.systemTime。 。 。 .

  • 运行后测试是否完整退出
    确保所有内部数据库在测试结束后得到明确处理.
    添加一个 afterEach() 或者说 afterAll() 钩指以下之一,视范围而定:

    • env.deleteAll() - 删除 所有数据库 输入 FirestoreMock 环境
    • controller.delete() - 删除a 单一数据库 通过其 FirestoreController

    这保证了背景资源(计时器,间隔器,收听器等)的放出,并允许你的测试跑取器干净地关闭.


版本兼容性( C)

  • 同伴依赖 : firebase-admin (参见您的包裹) peerDependencies 用于支持范围.
  • 18. TypeScript项目(ESM或CJS)是通过Admin SDK支持的.

捐款

谢谢你的关心! 这个项目在 最小维护模式。 。 。 .

  • 问题第一. 请打开一个问题 一个明确的复验或失败测试。 非邀约特性公关可能关闭.
  • 限于:bug通过测试修正,小的docs改进,或者建立/释放卫生. 新的特点要求首先在某一问题上提出可接受的建议.
  • 需要进行测试. 变化必须包括高可靠性测试,显示与Firebase模拟器的对齐(或有文件记载的相差).
  • 审取自性. 我分批审查,可能很慢 没有支持解放军.
  • 范围护栏. 目标是忠于Firestore/Admin SDK语义;范围外的特性会被拒绝.

如果这对你有用的话,特别欢迎棒极了的bugfixs和docs tweaks.


许可证

Apache-2.0 2026 布莱斯·马歇尔


商标归属

这个项目是 没有 隶属于Google LLC,与其相关联,或得到其认可. “Firebase”和“Firestore”是Google有限责任公司的商标。 名称仅用于识别相容性,并不意味着认可.

版本与发布记录

@firebase-bridge/firestore-admin 共发布 10 个版本,首次发布于 2025/09/29;过去 12 个月发布了 2 个版本。

版本发布日期距今
0.0.10latest2026/08/123 个月前
0.0.92025/11/2811 个月前
0.0.82025/10/201.1 年前
0.0.72025/10/181.1 年前
0.0.62025/10/181.1 年前
0.0.52025/10/151.1 年前

关于 @firebase-bridge/firestore-admin 的常见问题

@firebase-bridge/firestore-admin 是什么?

用于单位测试和当地dev的Firebase Firestore Admin SDK (Gapic) 的高真能模拟器.

如何安装 @firebase-bridge/firestore-admin?

在项目目录运行 npm install @firebase-bridge/firestore-admin,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:firebase-admin(^13.4.0)、google-gax(>=5 <6)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@firebase-bridge/firestore-admin 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@firebase-bridge/firestore-admin 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@firebase-bridge/firestore-admin 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@firebase-bridge/firestore-admin 可以商用吗?

@firebase-bridge/firestore-admin 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@firebase-bridge/firestore-admin 的下载量有多少?

根据 npm 官方下载统计,@firebase-bridge/firestore-admin 在 2026/10/15 – 2026/11/13 这 30 天内被下载 2,313 次,日均约 77 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@firebase-bridge/firestore-admin 还在维护吗?

最新版本 0.0.10 发布于 2026/08/12(3 个月前);至今共发布 10 个版本,其中过去 12 个月发布了 2 个;首次发布于 2025/09/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。