import { Firestore, Settings } from 'firebase-admin/firestore'; import { DatabasePool } from './_internal/database-pool.js'; import { DatabaseDirect } from './database-direct.js'; import { SystemTime } from './system-time.js'; import { FirestoreMockStats } from './types.js'; /** * Configuration for a mock Firestore controller instance. * * These options define the logical identity and environment of the mocked * Firestore database and are used when constructing resource names * (e.g. `//firestore.googleapis.com/projects/{projectId}/databases/{databaseId}`) * and CloudEvent metadata (project, database, location, namespace). * * All properties are optional and have sensible defaults to allow quick setup. * * @example * const ctrl = env.createDatabase({ * projectId: 'my-project', * databaseId: '(default)', * location: 'nam5', // or 'us-central1' * namespace: '(default)', * }); */ export interface FirestoreControllerOptions { /** * The logical database ID (Firestore database). * Used in resource names like: * //firestore.googleapis.com/projects/{projectId}/databases/{databaseId} * Defaults to '(default)' if omitted. */ databaseId?: string; /** * The logical Google Cloud project ID. * Defaults to 'default-project' if omitted. */ projectId?: string; /** * Firestore database location identifier used in CloudEvents and resource metadata. * Accepts multi-region IDs (e.g. 'nam5', 'eur3') or regional IDs (e.g. 'us-central1'). * Defaults to 'nam5' if omitted. */ location?: string; /** * Datastore namespace. For Firestore Native mode this should remain '(default)'. * Included for fidelity when simulating Datastore-mode events. * Defaults to '(default)' if omitted. */ namespace?: string; } /** * Discrete lifecycle transitions emitted by a {@link FirestoreController}. * * - `'delete'` — The database has been **permanently disposed**. All resources * held by the controller are released and no further operations against this * instance are expected to succeed. * - `'reset'` — The database has been **cleared back to an empty state** and its `epoch` incremented * while keeping the same controller instance. This is typically used between tests to * guarantee isolation without tearing down the process. * * @remarks * Use these event types to distinguish teardown vs. in-place reinitialization * when coordinating triggers, listeners, or other observers. */ export type DatabaseLifecycleEventType = 'delete' | 'reset'; /** * Payload describing a lifecycle transition of a {@link FirestoreController}. * * @public */ export interface DatabaseLifecycleEventArg { /** * The kind of lifecycle transition that occurred. * * - `'delete'` — The controller has been torn down and will not emit further * events. * - `'reset'` — The controller remains valid, but its underlying database * contents have been cleared to a pristine state and its `epoch` incremented. * * @see DatabaseLifecycleEventType */ type: DatabaseLifecycleEventType; /** * The `epoch` of the underlying database when the event was raised. */ epoch: number; /** * The controller instance whose database underwent the transition. * * @remarks * On `'reset'`, consumers can re-establish data/fixtures or rebind observers * against this controller. On `'delete'`, consumers should release references * and unsubscribe from any observers associated with this controller. */ database: FirestoreController; } /** * An in-memory Firestore mock environment supporting multiple named projects and databases. * * ## Purpose * - Injects an in-memory database into a Firestore Admin SDK `Firestore` instance for unit and integration testing, without network or emulator dependencies. * - Supports multiple logical projects and databases in a single environment. * - Enables deterministic testing, time manipulation, and low-level access to mock database state and statistics. * * ## Usage * - Typically, create a fresh `FirestoreMock` per test (or test suite) to ensure data isolation. * - Use `createDatabase()` to provision databases, and `getDatabase()` to access/manage them. * - Use `firestore()` to create Firestore SDK-compatible mock instances. * * @example * const env = new FirestoreMock(); * const db = env.createDatabase('my-project', 'my-database'); * const firestore = db.firestore(); * // ... use Firestore API as normal, all operations are in-memory */ export declare class FirestoreMock { private readonly _databasePool; readonly systemTime: SystemTime; /** * Constructs a new FirestoreMock. * * @param config Optional configuration for time mocking, etc. */ constructor(); /** * Constructs a new mock `Firestore` instance using the specified settings. * * - `settings()` may also be invoked on the returned instance for further configuration (mirroring the real SDK). * - Network settings (e.g., host, port) are accepted for compatibility but have no effect. * - The returned instance is not tied to a specific project/database unless set in `settings`. * * @param settings Optional Firestore settings. Project/database may be specified here. * @returns A `Firestore` instance that operates upon the specified mock database. */ firestore(settings?: Settings): Firestore; /** * Creates a new mock Firestore database using an options object. * * - Preferred overload: pass a single {@link FirestoreControllerOptions} for clarity. * - Throws if a database with the same `projectId`/`databaseId` already exists in this environment. * - Returns a {@link FirestoreController} for low-level control and access. * * Defaults (when omitted): * - `projectId`: `'default-project'` * - `databaseId`: `'(default)'` * - `location`: `'nam5'` (or your environment default) * - `namespace`: `'(default)'` * * @param options Optional configuration for the database identity and environment. * @returns A {@link FirestoreController} instance for the created database. * @throws {Error} If a database with the given `projectId`/`databaseId` already exists. * * @example * const ctrl = env.createDatabase({ * projectId: 'my-project', * databaseId: '(default)', * location: 'nam5', * namespace: '(default)', * }); */ createDatabase(options?: FirestoreControllerOptions): FirestoreController; /** * Creates a new mock Firestore database within the specified project. * * - Throws if the database already exists in this environment. * - Returns a {@link FirestoreController} for low-level control and access. * * @param projectId The logical project ID. Defaults to 'default-project' if omitted. * @param databaseId The logical database ID. Defaults to '(default)' if omitted. * @returns A FirestoreController instance for the created database. * @throws {Error} If a database with the given projectId/databaseId already exists. */ createDatabase(projectId?: string, databaseId?: string): FirestoreController; /** * Retrieves a controller for the specified mock Firestore database, if it exists. * * - Throws if the requested database has not been created or has been deleted. * - Returns the same controller instance for the same project/database while it exists. * * @param projectId The logical project ID. Defaults to 'default-project' if omitted. * @param databaseId The logical database ID. Defaults to '(default)' if omitted. * @returns The FirestoreController instance for the requested database. * @throws {Error} If the database does not exist. */ getDatabase(projectId?: string, databaseId?: string): FirestoreController; /** * Retrieves a value indicating whether or not the specified mock Firestore database exists. * * @param projectId The logical project ID. Defaults to 'default-project' if omitted. * @param databaseId The logical database ID. Defaults to '(default)' if omitted. * @returns `true` if the specified database exists, otherwise `false`. */ databaseExists(projectId?: string, databaseId?: string): boolean; /** * Deletes all databases in the environment. * - Synchronously invokes the `delete()` operation on all pooled database controllers. */ deleteAll(): void; /** * Resets all databases in the environment. * - Synchronously invokes the `reset()` operation on all pooled database controllers. */ resetAll(): void; } /** * Provides low-level control and observation for a single mock Firestore database instance. * * - Used for creating project/database-scoped Firestore API instances, inspecting stats, resetting, or deleting the database. * - One controller exists per database within a `FirestoreMock`; always use {@link FirestoreMock.getDatabase} or {@link FirestoreMock.createDatabase} to obtain a controller. * - Deleting a database via `delete()` invalidates the controller and removes all associated data. */ export declare class FirestoreController { readonly mock: FirestoreMock; private readonly _pool; private _accessor; private _statWatchers; private _lifecycleWatchers; /** The project ID for this mock database. */ readonly projectId: string; /** The database ID for this mock database. */ readonly databaseId: string; /** * Firestore database location identifier used in CloudEvents and resource metadata. * Accepts multi-region IDs (e.g. 'nam5', 'eur3') or regional IDs (e.g. 'us-central1'). * Defaults to 'nam5' if omitted. */ readonly location: string; /** * Datastore namespace. For Firestore Native mode this should remain '(default)'. * Included for fidelity when simulating Datastore-mode events. * Defaults to '(default)' if omitted. */ readonly namespace: string; /** * Provides direct, low-level access to the underlying mock database. * - Primarily for advanced test scenarios, data seeding, or test-only operations. */ readonly database: DatabaseDirect; /** * @internal * Constructs a new FirestoreController. * @param mock The parent mock environment. * @param _pool The backing database pool (internal). * @param projectId The logical project ID for this database. * @param databaseId The logical database ID for this database. */ constructor(mock: FirestoreMock, _pool: DatabasePool, options?: FirestoreControllerOptions); /** * Constructs a new mock Firestore instance, scoped to this controller's project/database. * * - The returned instance always uses this controller's `projectId` and `databaseId`, regardless of settings provided. * - `settings()` may also be invoked on the returned instance (mirroring the real SDK). * - Network-related settings are accepted but have no effect. * * @param settings Optional Firestore settings; projectId/databaseId will be overridden. * @returns A Firestore instance scoped to this database. */ firestore(settings?: Settings): Firestore; /** * Checks if this database still exists in the mock environment. * * @returns `true` if the database exists; `false` if it has been deleted. */ exists(): boolean; /** * The monotonically increasing database epoch identifier. * * - **Increments only when the database is reset** (never for reads/writes/commits). * - Remains constant for the entire lifetime of a given database instance between resets. * - When combined with {@link version()} (the commit sequence number), `(epoch, version)` * provides a stable total ordering key across resets. */ epoch(): number; /** * The monotonically increasing atomic commit version of the database. * * @returns The database commit version. * @throws {Error} If this database has been deleted. */ version(): number; /** * Deletes the database from the mock environment, invalidating this controller. * * - After deletion, further calls to methods on this controller (other than `exists()` and `reset()`) * will throw. * - All associated data and stats are lost. */ delete(): void; /** * Resets all documents and stats for this database, preserving its existence and this controller. * * - Does not affect listeners or other attached controllers. * - Useful for resetting state between tests. */ reset(): void; /** * Retrieves the current stats for this database. * * @returns A snapshot of current FirestoreMockStats (e.g., document/operation counts). * @throws {Error} If this database has been deleted. */ getStats(): FirestoreMockStats; /** * Registers a watcher function to receive the latest stats whenever they change. * * - The watcher is immediately called with the current stats. * - Returns a function to deregister the watcher. * - Throws if the database has been deleted. * * @param statsWatcher Callback function to receive FirestoreMockStats updates. * @returns Deregistration function. * @throws {Error} If this database has been deleted. */ watchStats(statsWatcher: (stats: FirestoreMockStats) => void): () => void; /** * Registers a watcher function to receive **database lifecycle events** emitted * by this {@link FirestoreController}. * * - Fires on `'reset'` when the underlying database is cleared but the * controller remains usable. * - Fires on `'delete'` when the controller/database is permanently disposed. * - Returns a function to deregister the watcher. * - Throws if the database has already been deleted. * * @param lifecycleWatcher Callback invoked for each lifecycle transition with a * {@link DatabaseLifecycleEventArg} describing the event and source controller. * @returns Deregistration function. * @throws {Error} If this database has been deleted. */ watchLifecycle(lifecycleWatcher: (arg: DatabaseLifecycleEventArg) => void): () => void; /** * Formats internal DataAccessorStats as a user-facing FirestoreMockStats object. * * @param stats Raw stats from the DataAccessor. * @returns Immutable FirestoreMockStats. * @internal */ private formatStats; /** * Throws if this controller's database has been deleted. * * @throws {Error} If the database has been deleted via `delete()`. * @internal */ private assertExists; } //# sourceMappingURL=controller.d.ts.map