@dereekb/firebase 13.6.6 → 13.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/firebase",
3
- "version": "13.6.6",
3
+ "version": "13.6.8",
4
4
  "exports": {
5
5
  "./test": {
6
6
  "module": "./test/index.esm.js",
@@ -17,10 +17,10 @@
17
17
  }
18
18
  },
19
19
  "peerDependencies": {
20
- "@dereekb/util": "13.6.6",
21
- "@dereekb/date": "13.6.6",
22
- "@dereekb/model": "13.6.6",
23
- "@dereekb/rxjs": "13.6.6",
20
+ "@dereekb/util": "13.6.8",
21
+ "@dereekb/date": "13.6.8",
22
+ "@dereekb/model": "13.6.8",
23
+ "@dereekb/rxjs": "13.6.8",
24
24
  "@firebase/rules-unit-testing": "5.0.0",
25
25
  "arktype": "^2.2.0",
26
26
  "date-fns": "^4.0.0",
@@ -8,8 +8,13 @@ import { type FirestoreContextFactory } from '../../common/firestore/context';
8
8
  *
9
9
  * @example
10
10
  * ```ts
11
+ * // Without caching
11
12
  * const context = clientFirebaseFirestoreContextFactory(firestore);
12
- * const collection = context.collection(myCollectionConfig);
13
+ *
14
+ * // With caching
15
+ * const context = clientFirebaseFirestoreContextFactory(firestore, {
16
+ * firestoreContextCacheFactory: inMemoryFirestoreContextCacheFactory()
17
+ * });
13
18
  * ```
14
19
  */
15
20
  export declare const clientFirebaseFirestoreContextFactory: FirestoreContextFactory;
@@ -1,4 +1,5 @@
1
1
  import { type Observable } from 'rxjs';
2
+ import { type FirestoreCollectionCache, type FirestoreCollectionDocumentCache } from '../cache/cache';
2
3
  import { type FirestoreAccessorDriverRef } from '../driver/accessor';
3
4
  import { type FirestoreCollectionNameRef, type FirestoreModelId, type FirestoreModelIdentityCollectionName, type FirestoreModelIdentityModelType, type FirestoreModelIdentityRef, type FirestoreModelIdRef, type FirestoreModelKey, type FirestoreModelKeyRef, type FirestoreModelTypeRef, type FirestoreModelIdentity, type FirestoreModelTypeModelIdentityRef } from './../collection/collection';
4
5
  import { type DocumentReference, type CollectionReference, type Transaction, type WriteBatch, type DocumentSnapshot, type SnapshotOptions, type WriteResult, type FirestoreDataConverter } from '../types';
@@ -27,6 +28,7 @@ import { type FirestoreDataConverterFactory, type FirestoreDataConverterFactoryR
27
28
  */
28
29
  export interface FirestoreDocument<T, I extends FirestoreModelIdentity = FirestoreModelIdentity> extends FirestoreDataConverterRef<T>, DocumentReferenceRef<T>, CollectionReferenceRef<T>, FirestoreModelIdentityRef<I>, FirestoreModelTypeRef<FirestoreModelIdentityModelType<I>>, FirestoreCollectionNameRef<FirestoreModelIdentityCollectionName<I>>, FirestoreModelKeyRef, FirestoreModelIdRef {
29
30
  readonly accessor: FirestoreDocumentDataAccessor<T>;
31
+ readonly cache: FirestoreCollectionDocumentCache<T>;
30
32
  readonly id: FirestoreModelId;
31
33
  snapshotStream(mode: FirestoreAccessorStreamMode): Observable<DocumentSnapshot<T>>;
32
34
  snapshotDataStream(mode: FirestoreAccessorStreamMode, options?: SnapshotOptions): Observable<Maybe<T>>;
@@ -60,10 +62,12 @@ export type FirestoreDocumentData<D extends FirestoreDocument<any>> = D extends
60
62
  export declare abstract class AbstractFirestoreDocument<T, D extends AbstractFirestoreDocument<T, any, I>, I extends FirestoreModelIdentity = FirestoreModelIdentity> implements FirestoreDocument<T>, LimitedFirestoreDocumentAccessorRef<T, D>, CollectionReferenceRef<T> {
61
63
  private readonly _accessor;
62
64
  private readonly _documentAccessor;
65
+ private readonly _cache;
63
66
  readonly stream$: Observable<DocumentSnapshot<T>>;
64
67
  readonly data$: Observable<T>;
65
68
  constructor(accessor: FirestoreDocumentDataAccessor<T>, documentAccessor: LimitedFirestoreDocumentAccessor<T, D>);
66
69
  get accessor(): FirestoreDocumentDataAccessor<T>;
70
+ get cache(): FirestoreCollectionDocumentCache<T>;
67
71
  get documentAccessor(): LimitedFirestoreDocumentAccessor<T, D>;
68
72
  abstract get modelIdentity(): I;
69
73
  get modelType(): FirestoreModelIdentityModelType<I>;
@@ -76,6 +80,8 @@ export declare abstract class AbstractFirestoreDocument<T, D extends AbstractFir
76
80
  /**
77
81
  * Retrieves a DocumentSnapshot of the document as an Observable. Streams based on the input mode.
78
82
  *
83
+ * Passively populates the cache with each emitted snapshot.
84
+ *
79
85
  * @param mode - The stream mode controlling how the Observable emits snapshot updates
80
86
  * @returns An Observable that emits DocumentSnapshot values based on the given mode
81
87
  */
@@ -83,22 +89,29 @@ export declare abstract class AbstractFirestoreDocument<T, D extends AbstractFir
83
89
  /**
84
90
  * Retrieves the data of the DocumentSnapshot of the document as an Observable. Streams based on the input mode.
85
91
  *
92
+ * Passively populates the cache via {@link snapshotStream}.
93
+ *
86
94
  * @param mode - The stream mode controlling how the Observable emits snapshot data updates
87
95
  * @param options - Optional SnapshotOptions for reading the document data
88
96
  * @returns An Observable that emits the document data or undefined based on the given mode
89
97
  */
90
98
  snapshotDataStream(mode: FirestoreAccessorStreamMode, options?: SnapshotOptions): Observable<Maybe<T>>;
91
99
  /**
92
- * Retrieves a DocumentSnapshot of the document.
100
+ * Retrieves a DocumentSnapshot of the document from Firestore.
93
101
  *
94
- * @returns
102
+ * Passively populates the cache with the fetched snapshot.
103
+ *
104
+ * @returns A Promise resolving to the document snapshot
95
105
  */
96
106
  snapshot(): Promise<DocumentSnapshot<T>>;
97
107
  /**
98
- * Retrieves the data of the DocumentSnapshot of the document.
108
+ * Retrieves the data of the document, checking the cache first.
99
109
  *
100
- * @param options
101
- * @returns
110
+ * If a fresh cache entry exists, returns it without hitting Firestore.
111
+ * Otherwise falls through to {@link snapshot} which populates the cache.
112
+ *
113
+ * @param options - Optional SnapshotOptions for reading the document data
114
+ * @returns A Promise resolving to the document data, or undefined if the document does not exist
102
115
  */
103
116
  snapshotData(options?: SnapshotOptions): Promise<Maybe<T>>;
104
117
  /**
@@ -111,16 +124,19 @@ export declare abstract class AbstractFirestoreDocument<T, D extends AbstractFir
111
124
  /**
112
125
  * Creates the document if it does not exist, using the accessor's create functionality.
113
126
  *
114
- * @param data
115
- * @returns
127
+ * Populates the cache with the written data after a successful create.
128
+ *
129
+ * @param data - The document data to create
130
+ * @returns A Promise that resolves when the create completes
116
131
  */
117
132
  create(data: T): Promise<WriteResult | void>;
118
133
  /**
119
- * Updates the document using the accessor's update functionalty if the document exists. This differs from Firestore's default
134
+ * Updates the document using the accessor's update functionality if the document exists. This differs from Firestore's default
120
135
  * update implementation which does not use the configured converter. This update function will, allowing the use of
121
136
  * snapshotConverterFunctions().
122
137
  *
123
- * Throws an exception when it does not exist.
138
+ * Invalidates the cache entry since partial updates don't provide the full document.
139
+ * Throws an exception when the document does not exist.
124
140
  *
125
141
  * @param data - Partial document data to update
126
142
  * @param params - Optional update parameters
@@ -130,6 +146,8 @@ export declare abstract class AbstractFirestoreDocument<T, D extends AbstractFir
130
146
  /**
131
147
  * Updates the document using the accessor's increment functionality.
132
148
  *
149
+ * Invalidates the cache entry since increment updates don't provide the full document.
150
+ *
133
151
  * @param data - The increment update to apply to numeric fields
134
152
  * @returns A Promise that resolves when the increment update completes
135
153
  */
@@ -137,6 +155,8 @@ export declare abstract class AbstractFirestoreDocument<T, D extends AbstractFir
137
155
  /**
138
156
  * Updates the document using the accessor's array field update functionality.
139
157
  *
158
+ * Invalidates the cache entry since array updates don't provide the full document.
159
+ *
140
160
  * @param data - The array field update to apply (union or remove elements)
141
161
  * @returns A Promise that resolves when the array update completes
142
162
  */
@@ -162,6 +182,16 @@ export type FirestoreDocumentAccessorRef<T, D extends FirestoreDocument<T> = Fir
162
182
  */
163
183
  export interface LimitedFirestoreDocumentAccessor<T, D extends FirestoreDocument<T> = FirestoreDocument<T>> extends FirestoreDataConverterRef<T>, FirestoreModelTypeModelIdentityRef, FirestoreAccessorDriverRef {
164
184
  readonly databaseContext: FirestoreDocumentContext<T>;
185
+ /**
186
+ * Returns the collection cache for the given document reference.
187
+ *
188
+ * Returns a noop cache when operating within a transaction or write batch context,
189
+ * since cache reads/writes must be bypassed in those contexts.
190
+ *
191
+ * @param ref - The document reference to get the cache for
192
+ * @returns The collection cache (real or noop) for the document
193
+ */
194
+ cacheForDocument(ref: DocumentReference<T>): FirestoreCollectionDocumentCache<T>;
165
195
  /**
166
196
  * Loads a document from the datastore.
167
197
  *
@@ -259,6 +289,10 @@ export interface LimitedFirestoreDocumentAccessorFactoryConfig<T, D extends Fire
259
289
  * Optional InterceptFirestoreDataConverterFactory to return a modified converter.
260
290
  */
261
291
  readonly converterFactory?: InterceptFirestoreDataConverterFactory<T>;
292
+ /**
293
+ * The collection cache for documents created by this factory.
294
+ */
295
+ readonly cache: FirestoreCollectionCache<T>;
262
296
  readonly makeDocument: FirestoreDocumentFactoryFunction<T, D>;
263
297
  }
264
298
  /**
@@ -0,0 +1,365 @@
1
+ import { type Observable } from 'rxjs';
2
+ import { type Destroyable, type Maybe, type Milliseconds } from '@dereekb/util';
3
+ import { type FirestoreCollectionType } from '../collection/collection';
4
+ import { type FirestoreModelKey } from '../collection/collection';
5
+ /**
6
+ * Options for loading a document with cache support.
7
+ *
8
+ * These options control whether a document read should consult the cache
9
+ * and how stale a cached entry is allowed to be. They are passed to
10
+ * `snapshotData()` (the cache-aware read path) on document instances.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const data = await document.snapshotData({ allowCache: true, maxTtl: 60000 });
15
+ * ```
16
+ */
17
+ export interface LoadDocumentOptions {
18
+ /**
19
+ * Whether to allow reading from the cache for this read.
20
+ *
21
+ * When true, the accessor checks the collection cache before hitting Firestore.
22
+ * Defaults to false unless the document accessor was created with default cache options enabled.
23
+ */
24
+ readonly allowCache?: boolean;
25
+ /**
26
+ * Maximum TTL to accept for a cached entry on this specific read.
27
+ *
28
+ * Overrides the collection-level TTL. If the cached entry is older than this value,
29
+ * it is treated as a cache miss. Only relevant when allowCache is true.
30
+ */
31
+ readonly maxTtl?: Milliseconds;
32
+ }
33
+ /**
34
+ * Default cache behavior for a document accessor. When set, all reads through this
35
+ * accessor use the cache unless overridden per-read via {@link LoadDocumentOptions}.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const defaults: DocumentAccessorCacheDefaults = { allowCache: true, maxTtl: 300000 };
40
+ * ```
41
+ */
42
+ export interface DocumentAccessorCacheDefaults {
43
+ /**
44
+ * When true, reads through this accessor use the cache by default.
45
+ */
46
+ readonly allowCache: boolean;
47
+ /**
48
+ * Default max TTL for cached reads through this accessor.
49
+ */
50
+ readonly maxTtl?: Milliseconds;
51
+ }
52
+ /**
53
+ * Type of cache event emitted by {@link FirestoreContextCache}.
54
+ */
55
+ export type FirestoreCacheEventType = 'hit' | 'miss' | 'update' | 'invalidate' | 'enable_collection' | 'disable_collection';
56
+ /**
57
+ * Event emitted by {@link FirestoreContextCache.events$} on cache interactions.
58
+ *
59
+ * Provides visibility into cache behavior for analytics, debugging,
60
+ * and monitoring cache effectiveness across all collections.
61
+ */
62
+ export interface FirestoreCacheEvent {
63
+ readonly type: FirestoreCacheEventType;
64
+ readonly collectionType: FirestoreCollectionType;
65
+ /**
66
+ * Document key for hit/miss/update/invalidate events.
67
+ * Undefined for enable_collection/disable_collection events.
68
+ */
69
+ readonly key: Maybe<FirestoreModelKey>;
70
+ readonly timestamp: Date;
71
+ }
72
+ /**
73
+ * A cached entry for a single document, including Firestore metadata timestamps.
74
+ *
75
+ * Only existing documents are cached — `data` is always present (never `Maybe<T>`).
76
+ *
77
+ * @template T - The document data type
78
+ */
79
+ export interface FirestoreCacheEntry<T> {
80
+ readonly key: FirestoreModelKey;
81
+ readonly data: T;
82
+ readonly cachedAt: Date;
83
+ }
84
+ /**
85
+ * Input for setting a cache entry. Extracted from a DocumentSnapshot.
86
+ *
87
+ * @template T - The document data type
88
+ */
89
+ export interface FirestoreCacheEntryInput<T> {
90
+ readonly data: T;
91
+ }
92
+ /**
93
+ * Cache for a single Firestore collection. Entries are keyed by document path.
94
+ *
95
+ * Each collection gets its own cache instance managed by {@link FirestoreContextCache}.
96
+ * The cache supports TTL-based expiration, passive population from reads/writes,
97
+ * and operation-scoped instances for deduplication.
98
+ *
99
+ * @template T - The document data type
100
+ */
101
+ export interface FirestoreCollectionCache<T = unknown> extends Destroyable {
102
+ /**
103
+ * Gets a cached entry if it exists and is within the TTL.
104
+ *
105
+ * @param key - The document path
106
+ * @param maxTtl - Optional TTL override; defaults to the collection's defaultTtl
107
+ * @returns The cached entry, or undefined if not found or expired
108
+ */
109
+ get(key: FirestoreModelKey, maxTtl?: Milliseconds): Maybe<FirestoreCacheEntry<T>>;
110
+ /**
111
+ * Sets or updates a cache entry. Called passively on every read/write.
112
+ *
113
+ * @param key - The document path
114
+ * @param entry - The data to cache
115
+ */
116
+ set(key: FirestoreModelKey, entry: FirestoreCacheEntryInput<T>): void;
117
+ /**
118
+ * Invalidates a specific cache entry.
119
+ *
120
+ * @param key - The document path to invalidate
121
+ */
122
+ invalidate(key: FirestoreModelKey): void;
123
+ /**
124
+ * Clears all entries in this collection cache.
125
+ */
126
+ clear(): void;
127
+ /**
128
+ * Creates a short-lived in-memory cache instance scoped to a single operation.
129
+ *
130
+ * Deduplicates reads within a batch operation — equivalent to what
131
+ * `LimitedFirestoreDocumentAccessorSnapshotCache` does today, but backed
132
+ * by this cache's existing entries as a warm start.
133
+ */
134
+ instance(): FirestoreCollectionCacheInstance<T>;
135
+ /**
136
+ * The default TTL for this collection cache.
137
+ */
138
+ readonly defaultTtl: Milliseconds;
139
+ }
140
+ /**
141
+ * Short-lived, operation-scoped cache instance. Wraps the parent
142
+ * {@link FirestoreCollectionCache} and adds Promise-level deduplication for
143
+ * concurrent in-flight reads within the same operation.
144
+ *
145
+ * Replaces the existing `LimitedFirestoreDocumentAccessorSnapshotCache` pattern.
146
+ *
147
+ * @template T - The document data type
148
+ */
149
+ export interface FirestoreCollectionCacheInstance<T = unknown> {
150
+ /**
151
+ * Gets a cached entry, checking the instance's local cache first,
152
+ * then the parent {@link FirestoreCollectionCache}.
153
+ *
154
+ * @param key - The document path
155
+ * @param maxTtl - Optional TTL override
156
+ * @returns The cached entry, or undefined if not found or expired
157
+ */
158
+ get(key: FirestoreModelKey, maxTtl?: Milliseconds): Maybe<FirestoreCacheEntry<T>>;
159
+ /**
160
+ * Gets or fetches a document, deduplicating concurrent requests for the same key.
161
+ * If a fetch for this key is already in-flight, returns the same Promise.
162
+ *
163
+ * @param key - The document path
164
+ * @param fetchFn - Function that fetches the document from Firestore
165
+ * @returns The cached or freshly-fetched entry
166
+ */
167
+ getOrFetch(key: FirestoreModelKey, fetchFn: () => Promise<FirestoreCacheEntry<T>>): Promise<FirestoreCacheEntry<T>>;
168
+ }
169
+ /**
170
+ * Configuration for a cacheable collection.
171
+ */
172
+ export interface FirestoreCollectionCacheConfig {
173
+ /**
174
+ * Default TTL for cached entries in this collection.
175
+ */
176
+ readonly defaultTtl: Milliseconds;
177
+ }
178
+ /**
179
+ * Factory and manager for per-collection caches. Lives on {@link FirestoreContext}.
180
+ *
181
+ * Provides global and per-type controls for enabling/disabling caching and
182
+ * resetting cached data. Uses {@link FirestoreCollectionType} for keying.
183
+ */
184
+ export interface FirestoreContextCache extends Destroyable {
185
+ /**
186
+ * Gets or creates a cache for the given collection.
187
+ *
188
+ * @param collectionType - The unique collection type identifier
189
+ * @param config - TTL configuration for this collection
190
+ * @returns A cache instance for the collection
191
+ */
192
+ cacheForCollection<T>(collectionType: FirestoreCollectionType, config: FirestoreCollectionCacheConfig): FirestoreCollectionCache<T>;
193
+ /**
194
+ * Observable stream of cache events (hits, misses, updates) across all collections.
195
+ *
196
+ * Useful for analytics, debugging, and monitoring cache effectiveness.
197
+ */
198
+ readonly events$: Observable<FirestoreCacheEvent>;
199
+ /**
200
+ * Set of model types that have caching explicitly disabled.
201
+ *
202
+ * Caching is enabled by default for all types. Only types added here are excluded.
203
+ */
204
+ readonly disabledTypes: ReadonlySet<FirestoreCollectionType>;
205
+ /**
206
+ * Whether caching is globally enabled. Defaults to true. When false, all
207
+ * collection caches behave as noops regardless of their individual configuration.
208
+ */
209
+ isEnabled(): boolean;
210
+ /**
211
+ * Enables or disables caching globally.
212
+ *
213
+ * @param enabled - Whether to enable caching
214
+ */
215
+ setEnabled(enabled: boolean): void;
216
+ /**
217
+ * Clears all cached entries across all collections.
218
+ */
219
+ clearAll(): void;
220
+ /**
221
+ * Whether caching is enabled for a specific model type/identity.
222
+ *
223
+ * Returns false if the type is explicitly disabled or if caching is globally disabled.
224
+ *
225
+ * @param collectionType - The collection type to check
226
+ * @returns Whether caching is active for this type
227
+ */
228
+ isEnabledForType(collectionType: FirestoreCollectionType): boolean;
229
+ /**
230
+ * Enables or disables caching for a specific model type/identity.
231
+ *
232
+ * When disabled, the collection cache for that type behaves as a noop.
233
+ * When re-enabled, the cache resumes normal operation.
234
+ *
235
+ * @param collectionType - The collection type to toggle
236
+ * @param enabled - Whether to enable caching for this type
237
+ */
238
+ setEnabledForType(collectionType: FirestoreCollectionType, enabled: boolean): void;
239
+ /**
240
+ * Clears all cached entries for a specific model type/identity.
241
+ *
242
+ * @param collectionType - The collection type to clear
243
+ */
244
+ clearForType(collectionType: FirestoreCollectionType): void;
245
+ }
246
+ /**
247
+ * Cache bound to a specific document. Wraps a {@link FirestoreCollectionCache}
248
+ * with the document's key pre-applied, so callers don't need to pass the key.
249
+ *
250
+ * Returned by {@link LimitedFirestoreDocumentAccessor.cacheForDocument}.
251
+ *
252
+ * @template T - The document data type
253
+ */
254
+ export interface FirestoreCollectionDocumentCache<T = unknown> {
255
+ /**
256
+ * Gets the cached entry for this document if it exists and is within the TTL.
257
+ *
258
+ * @param maxTtl - Optional TTL override; defaults to the collection's defaultTtl
259
+ * @returns The cached entry, or undefined if not found or expired
260
+ */
261
+ get(maxTtl?: Milliseconds): Maybe<FirestoreCacheEntry<T>>;
262
+ /**
263
+ * Sets or updates the cache entry for this document.
264
+ *
265
+ * @param entry - The data to cache
266
+ */
267
+ set(entry: FirestoreCacheEntryInput<T>): void;
268
+ /**
269
+ * Invalidates the cache entry for this document.
270
+ */
271
+ invalidate(): void;
272
+ }
273
+ /**
274
+ * Creates a {@link FirestoreCollectionDocumentCache} that delegates to the given
275
+ * collection cache with the key pre-bound.
276
+ *
277
+ * @param collectionCache - The parent collection cache
278
+ * @param key - The document path to bind
279
+ * @returns A document-scoped cache
280
+ *
281
+ * @example
282
+ * ```ts
283
+ * const docCache = firestoreCollectionDocumentCache(collectionCache, 'users/abc');
284
+ * docCache.set({ data: userData });
285
+ * const entry = docCache.get();
286
+ * ```
287
+ */
288
+ export declare function firestoreCollectionDocumentCache<T>(collectionCache: FirestoreCollectionCache<T>, key: FirestoreModelKey): FirestoreCollectionDocumentCache<T>;
289
+ /**
290
+ * Returns the singleton noop {@link FirestoreCollectionDocumentCache}.
291
+ */
292
+ export declare function noopFirestoreCollectionDocumentCache<T>(): FirestoreCollectionDocumentCache<T>;
293
+ /**
294
+ * Reference to a {@link FirestoreCollectionCache} instance.
295
+ *
296
+ * @template T - The document data type
297
+ */
298
+ export interface FirestoreCollectionCacheRef<T = unknown> {
299
+ readonly cache: FirestoreCollectionCache<T>;
300
+ }
301
+ /**
302
+ * Reference to a {@link FirestoreContextCache} instance.
303
+ *
304
+ * The cache is always defined — when no cache factory is configured,
305
+ * a noop implementation is used.
306
+ */
307
+ export interface FirestoreContextCacheRef {
308
+ readonly cache: FirestoreContextCache;
309
+ }
310
+ /**
311
+ * Factory function that creates a {@link FirestoreContextCache}.
312
+ *
313
+ * Provided at the app level (Angular providers / NestJS modules) via
314
+ * {@link FirestoreContextFactoryParams}. Each platform can use its own
315
+ * implementation — e.g. {@link inMemoryFirestoreContextCacheFactory} for
316
+ * in-memory TTL-based caching.
317
+ *
318
+ * @example
319
+ * ```ts
320
+ * const factory: FirestoreContextCacheFactory = (config) => inMemoryFirestoreContextCache(config);
321
+ * ```
322
+ */
323
+ export type FirestoreContextCacheFactory = (config?: FirestoreContextCacheFactoryConfig) => FirestoreContextCache;
324
+ /**
325
+ * Configuration passed to a {@link FirestoreContextCacheFactory} when creating the cache.
326
+ */
327
+ export interface FirestoreContextCacheFactoryConfig {
328
+ /**
329
+ * Default TTL for all collections unless overridden per-collection.
330
+ */
331
+ readonly defaultTtl?: Milliseconds;
332
+ }
333
+ /**
334
+ * Reference to an optional {@link FirestoreContextCacheFactory}.
335
+ */
336
+ export interface FirestoreContextCacheFactoryRef {
337
+ readonly firestoreContextCacheFactory?: Maybe<FirestoreContextCacheFactory>;
338
+ }
339
+ /**
340
+ * Returns the singleton noop {@link FirestoreCollectionCache} that discards all operations.
341
+ *
342
+ * Used when no cache driver is configured so that `.cache` is always defined.
343
+ *
344
+ * @example
345
+ * ```ts
346
+ * const cache = noopFirestoreCollectionCache();
347
+ * cache.get('path/to/doc'); // always returns undefined
348
+ * cache.set('path/to/doc', { data }); // no-op
349
+ * ```
350
+ */
351
+ export declare function noopFirestoreCollectionCache<T>(): FirestoreCollectionCache<T>;
352
+ /**
353
+ * Returns the singleton noop {@link FirestoreContextCache}.
354
+ *
355
+ * Used when no cache factory is configured so that `FirestoreContext.cache` is always defined,
356
+ * avoiding null checks throughout the codebase.
357
+ *
358
+ * @example
359
+ * ```ts
360
+ * const cache = noopFirestoreContextCache();
361
+ * cache.cacheForCollection('user', { defaultTtl: 0 }); // returns noop collection cache
362
+ * cache.isEnabled(); // false
363
+ * ```
364
+ */
365
+ export declare function noopFirestoreContextCache(): FirestoreContextCache;