FirestoreStore — Google Cloud Firestore store
Read this page in the documentation
FirestoreStore — Google Cloud Firestore store Overview Google Cloud Firestore is a document database organized as collections of documents, each addressed by an id, with rich structured querying. While Firestore is not itself a general "multi-model" engine, its document/query access pattern does not fit the SQL-shaped Dialect interface, so FirestoreStore implements the minimal NoSqlStore marker interface (src/nosql/store.ts) — connection lifecycle plus a getClient() escape hatch — and exposes Firestore's real collection().doc() CRUD plus its where() query API through a small convenience layer. Identity: Property | Value | --------- | --------------------------- | name | 'firestore' | library | '@google-cloud/firestore' | The store is built on the official @google-cloud/firestore SDK. Documents are reached via client.collection(name).doc(id); queries chain .where(field, op, value) on the collection reference. Lazy loading — not a hard dependency @google-cloud/firestore is not a hard dependency of this package. It is an optional peer dependency loaded lazily via require('@google-cloud/firestore') inside connect(), rather than a top-level import. Importing this module therefore does not require the SDK to be installed — it is only needed when a Firestore store is actually connected without an injected client. Injected client FirestoreStoreOptions accepts a pre-built client (a native Firestore handle). When provided, connect() uses it directly and never loads the driver. This is how the test suite injects a mock client (no SDK, no network), and how callers can supply a custom-configured Firestore. Connection Build a store from connection options and call connect(): FirestoreStoreOptions: Option | Type | Purpose | ------------- | ----------- | -------------------------------------------------------------------------- | projectId | string | GCP project id passed to the Firestore constructor. | keyFilename | string | Path to a service-account key file. | client | Firestore | A pre-built Firestore client to use directly. When set, the SDK is not loaded. | Injected-client form Supply your own client (or a mock) to bypass driver-based construction: Methods CRUD methods drive client.collection(collection).doc(id); the query method applies where() conditions to the collection reference. Driver failures are wrapped in a DatabaseError (preserving the original error); using any method before connect() (or after disconnect()) throws a ConnectionError. Lifecycle Method | Signature | Behavior | ------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------- | connect | connect(): Promise<void> | Uses an injected client if provided, otherwise lazy-requires @google-cloud/firestore and builds a Firestore from projectId/keyFilename. Idempotent when already connected. Wraps failures in ConnectionError. | disconnect | disconnect(): Promise<void> | Calls the client's terminate() if present (failures wrapped in DatabaseError), then clears state. | isConnected | isConnected(): boolean | true only when connected and a client is present. | getClient | getClient(): Firestore | Returns the underlying client. Throws ConnectionError if not connected. | Document CRUD & query Method | Signature | Behavior | -------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | insert | insert(collection: string, doc: Record<string, unknown>): Promise<unknown> | If doc.id is set, writes via doc(id).set(doc) and returns that id; otherwise collection.add(doc) and returns the auto id. | get | get(collection: string, id: string): Promise<unknown> | Reads via doc(id).get(). Returns snapshot.data() when the document exists, else undefined. | update | update(collection: string, id: string, patch: Record<string, unknown>): Promise<unknown> | Partial update via doc(id).update(patch). Returns the applied patch. | delete | delete(collection: string, id: string): Promise<unknown> | Deletes via doc(id).delete(). Returns the raw driver response. | query | query(collection: string, filter?: FirestoreCondition[] \| Record<string, unknown>): Promise<unknown[]> | Applies where() clauses, runs .get(), and returns matched docs each shaped as { id, ...data }. | Filters are normalized by normalizeConditions: an array of [field, op, value] tuples is applied verbatim; a plain object is treated as equality ([field, '==', value]) on each key. FirestoreCondition is [string, string, unknown]. The default (no filter) returns every document in the collection. Example Verification status Unit / mock-verified only. The tests in tests/nosql/firestore.test.ts are fully mock-driven: a mock client whose collection() returns a jest-mocked { doc, add, where, get } object (with a chainable where()) is injected via FirestoreStoreOptions.client. The real @google-cloud/firestore package is not installed, and there is no live Firestore access and no network in the test run. What this proves: insert with an explicit id uses doc(id).set and returns the id; without an id it uses collection.add and returns the auto id. get returns data() when exists, else undefined; update calls doc(id).update(patch) and returns the patch; delete calls doc(id).delete. query applies object filters as where(field, '==', value) and tuple conditions verbatim, returns { id, ...data } rows, and returns all documents when no filter is given. Lifecycle: connecting via an injected client without loading the SDK, disconnect() calling terminate(), and ConnectionError before connect(). Error handling: driver failures wrapped in DatabaseError for both CRUD and query paths. What this does not prove: live execution against real Google Cloud Firestore. The call/response shapes are verified against the SDK's documented contract, but end-to-end execution over the wire has not been exercised here. Related reading All data stores — the full catalogue, grouped by purpose Database types — where this sits among the 22 categories