@dereekb/firebase 13.0.6 → 13.0.7

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/index.cjs.js CHANGED
@@ -1093,6 +1093,61 @@ function documentReferenceFromDocument(document) {
1093
1093
  function documentReferencesFromDocuments(documents) {
1094
1094
  return documents.map(documentReferenceFromDocument);
1095
1095
  }
1096
+ /**
1097
+ * Creates a {@link LimitedFirestoreDocumentAccessorSnapshotCache} that wraps the given accessor
1098
+ * with an in-memory {@link Map} cache so that repeated loads for the same key return the cached
1099
+ * promise instead of re-reading from Firestore.
1100
+ *
1101
+ * The cache stores the promise itself (not the resolved value), which means concurrent requests
1102
+ * for the same key that arrive before the first read completes will also be deduplicated.
1103
+ *
1104
+ * The cache lives for the lifetime of the returned object and is never invalidated, so this is
1105
+ * best suited for short-lived scopes (e.g. a single request or batch operation) where stale reads
1106
+ * are acceptable.
1107
+ *
1108
+ * @param accessor - The accessor to wrap with caching behavior
1109
+ * @returns A {@link LimitedFirestoreDocumentAccessorSnapshotCache} backed by the given accessor
1110
+ *
1111
+ * @example
1112
+ * ```typescript
1113
+ * const cache = limitedFirestoreDocumentAccessorSnapshotCache(accessor);
1114
+ *
1115
+ * // First call reads from Firestore; second call returns cached result
1116
+ * const pair = await cache.getDocumentSnapshotDataPairForKey('users/abc123');
1117
+ * const samePair = await cache.getDocumentSnapshotDataPairForKey('users/abc123');
1118
+ *
1119
+ * // Batch fetch with automatic deduplication
1120
+ * const pairs = await cache.getDocumentSnapshotDataPairsWithDataForKeys(['users/abc', 'users/def']);
1121
+ *
1122
+ * // Access the underlying accessor directly
1123
+ * const doc = cache.accessor.loadDocumentForKey('users/xyz');
1124
+ * ```
1125
+ */
1126
+ function limitedFirestoreDocumentAccessorSnapshotCache(accessor) {
1127
+ const cache = new Map();
1128
+ function getDocumentSnapshotDataPairForKey(key) {
1129
+ let cached = cache.get(key);
1130
+ if (!cached) {
1131
+ const document = accessor.loadDocumentForKey(key);
1132
+ cached = getDocumentSnapshotDataPair(document);
1133
+ cache.set(key, cached);
1134
+ }
1135
+ return cached;
1136
+ }
1137
+ async function getDocumentSnapshotDataPairsForKeys(keys) {
1138
+ return Promise.all(keys.map((key) => getDocumentSnapshotDataPairForKey(key)));
1139
+ }
1140
+ async function getDocumentSnapshotDataPairsWithDataForKeys(keys) {
1141
+ const pairs = await getDocumentSnapshotDataPairsForKeys(keys);
1142
+ return util.filterMaybeArrayValues(pairs.map((pair) => (pair.data != null ? pair : undefined)));
1143
+ }
1144
+ return {
1145
+ accessor,
1146
+ getDocumentSnapshotDataPairForKey,
1147
+ getDocumentSnapshotDataPairsForKeys,
1148
+ getDocumentSnapshotDataPairsWithDataForKeys
1149
+ };
1150
+ }
1096
1151
 
1097
1152
  /**
1098
1153
  * Creates an Observable that emits arrays of document snapshots for multiple documents.
@@ -1142,7 +1197,7 @@ function mapLatestSnapshotsFromDocuments(documents, operator) {
1142
1197
  * @param documents - Array of document instances to stream data for
1143
1198
  * @returns Observable that emits arrays of document data whenever any document changes
1144
1199
  */
1145
- function latestDataFromDocuments(documents) {
1200
+ function streamDocumentSnapshotsData(documents) {
1146
1201
  return latestSnapshotsFromDocuments(documents).pipe(dataFromDocumentSnapshots());
1147
1202
  }
1148
1203
  /**
@@ -1200,6 +1255,11 @@ function streamDocumentSnapshotDataPairs(documents) {
1200
1255
  function streamDocumentSnapshotDataPairsWithData(documents) {
1201
1256
  return streamDocumentSnapshotDataPairs(documents).pipe(rxjs$1.map((pairs) => pairs.filter((pair) => pair.data != null)));
1202
1257
  }
1258
+ // MARK: Compat
1259
+ /**
1260
+ * @deprecated Use {@link streamDocumentSnapshotsData} instead.
1261
+ */
1262
+ const latestDataFromDocuments = streamDocumentSnapshotsData;
1203
1263
 
1204
1264
  // A set of copied types from @google-cloud/firestore and firebase/firestore to allow cross-compatability.
1205
1265
  /* eslint-disable */
@@ -2355,20 +2415,14 @@ function firebaseQueryItemAccumulator(iteration, mapItem) {
2355
2415
  }
2356
2416
 
2357
2417
  /**
2358
- * Creates a Firestore query constraint.
2418
+ * Creates a {@link FirestoreQueryConstraint} with the given type identifier and data.
2359
2419
  *
2360
- * @template T - Type of data stored in the constraint
2361
- * @param type - The constraint type identifier
2362
- * @param data - The constraint data
2363
- * @returns A Firestore query constraint object
2364
- */
2365
- /**
2366
- * Creates a Firestore query constraint.
2420
+ * This is the low-level factory used by all constraint builder functions (e.g., {@link where},
2421
+ * {@link limit}, {@link orderBy}). Most callers should use those typed builders instead.
2367
2422
  *
2368
- * @template T - Type of data stored in the constraint
2369
- * @param type - The constraint type identifier
2370
- * @param data - The constraint data
2371
- * @returns A Firestore query constraint object
2423
+ * @param type - The constraint type identifier (e.g., 'where', 'limit')
2424
+ * @param data - The constraint-specific configuration data
2425
+ * @returns A typed constraint object
2372
2426
  */
2373
2427
  function firestoreQueryConstraint(type, data) {
2374
2428
  return {
@@ -2868,6 +2922,17 @@ function filterDisallowedFirestoreItemPageIteratorInputConstraints(constraints)
2868
2922
  * This value is used when no itemsPerPage is explicitly specified in the configuration.
2869
2923
  */
2870
2924
  const DEFAULT_FIRESTORE_ITEM_PAGE_ITERATOR_ITEMS_PER_PAGE = 50;
2925
+ /**
2926
+ * Creates a {@link FirestoreItemPageIteratorDelegate} that handles cursor-based Firestore pagination.
2927
+ *
2928
+ * The delegate implements `loadItemsForPage` by:
2929
+ * 1. Retrieving the cursor document from the previous page's results
2930
+ * 2. Building a query with the configured constraints, `startAfter` cursor, and `limit`
2931
+ * 3. Executing the query and wrapping the results in a {@link FirestoreItemPageQueryResult}
2932
+ * with `reload()` and `stream()` capabilities
2933
+ *
2934
+ * @returns A delegate instance for use with {@link ItemPageIterator}
2935
+ */
2871
2936
  function makeFirestoreItemPageIteratorDelegate() {
2872
2937
  return {
2873
2938
  loadItemsForPage: (request) => {
@@ -3025,7 +3090,14 @@ function _firestoreItemPageIterationWithSnapshotIteration(snapshotIteration) {
3025
3090
  return result;
3026
3091
  }
3027
3092
  /**
3028
- * Creates a FirestoreFixedItemPageIterationFactoryFunction.
3093
+ * Creates a factory function for generating fixed-set Firestore pagination instances.
3094
+ *
3095
+ * The returned factory takes an array of document references and an optional filter,
3096
+ * producing a pagination instance that iterates over those specific documents in pages.
3097
+ *
3098
+ * @param baseConfig - Base pagination configuration (query reference, driver, page size)
3099
+ * @param documentAccessor - Accessor used to load document snapshots from the references
3100
+ * @returns A factory function that creates fixed-set pagination instances
3029
3101
  */
3030
3102
  function firestoreFixedItemPageIterationFactory(baseConfig, documentAccessor) {
3031
3103
  return (items, filter) => {
@@ -3042,7 +3114,17 @@ function firestoreFixedItemPageIterationFactory(baseConfig, documentAccessor) {
3042
3114
  };
3043
3115
  }
3044
3116
  /**
3045
- * Creates a FirestoreItemPageIterationInstance that iterates over the fixed
3117
+ * Creates a pagination instance that iterates over a fixed set of document references.
3118
+ *
3119
+ * Unlike {@link firestoreItemPageIteration} which queries Firestore dynamically, this function
3120
+ * paginates through a pre-determined list of document references. Each page loads the next
3121
+ * slice of references via the document accessor and produces a synthetic {@link QuerySnapshot}.
3122
+ *
3123
+ * This is useful for paginating over known document sets (e.g., from a pre-computed list
3124
+ * of references) without executing Firestore queries.
3125
+ *
3126
+ * @param config - Configuration including the document references, accessor, and pagination settings
3127
+ * @returns A pagination instance that pages through the fixed reference set
3046
3128
  */
3047
3129
  function firestoreFixedItemPageIteration(config) {
3048
3130
  const { items, documentAccessor } = config;
@@ -3259,24 +3341,47 @@ function readFirestoreModelKeyFromDocumentSnapshot(snapshot) {
3259
3341
  /**
3260
3342
  * @module Firestore Query Iteration
3261
3343
  *
3262
- * This module provides a comprehensive system for iterating through Firestore query results
3263
- * with support for pagination, batching, and parallelism. It enables efficient processing of
3264
- * large result sets by using cursor-based pagination (via "checkpoints") and various iteration
3265
- * strategies.
3344
+ * Provides a layered system for iterating through Firestore query results using
3345
+ * cursor-based pagination ("checkpoints"). Each layer adds convenience on top of the
3346
+ * one below:
3347
+ *
3348
+ * 1. **Checkpoints** ({@link iterateFirestoreDocumentSnapshotCheckpoints}) — core pagination engine
3349
+ * 2. **Batches** ({@link iterateFirestoreDocumentSnapshotBatches}) — subdivides checkpoints into fixed-size batches
3350
+ * 3. **Snapshots** ({@link iterateFirestoreDocumentSnapshots}) — processes individual snapshots
3351
+ * 4. **Pairs** ({@link iterateFirestoreDocumentSnapshotPairs}) — loads typed document wrappers per snapshot
3352
+ *
3353
+ * Batch variants with document pairs are also available:
3354
+ * - {@link iterateFirestoreDocumentSnapshotPairBatches} — batch processing with typed document access
3355
+ *
3356
+ * All functions support configurable limits (`limitPerCheckpoint`, `totalSnapshotsLimit`),
3357
+ * concurrency (`maxParallelCheckpoints`), rate limiting (`waitBetweenCheckpoints`),
3358
+ * snapshot filtering, and repeat cursor detection.
3266
3359
  */
3267
3360
  /**
3268
- * Iterates through the results of a Firestore query by each FirestoreDocumentSnapshotDataPairWithData.
3361
+ * Iterates through Firestore query results, loading each snapshot as a
3362
+ * {@link FirestoreDocumentSnapshotDataPairWithData} before processing.
3269
3363
  *
3270
- * This function efficiently handles pagination through potentially large result sets by using
3271
- * the checkpoint system to load documents in batches. For each document snapshot, it loads the
3272
- * associated data using the provided document accessor, then passes the combined pair to the
3273
- * processing function.
3364
+ * Built on {@link iterateFirestoreDocumentSnapshots}, this adds an automatic document
3365
+ * loading step: each raw snapshot is resolved through the `documentAccessor` to produce
3366
+ * a pair containing both the typed {@link FirestoreDocument} and its snapshot data.
3367
+ * This is the highest-level iteration function — use it when your callback needs
3368
+ * document-level operations (updates, deletes) alongside the snapshot data.
3274
3369
  *
3275
- * @template T - The document data type
3276
- * @template R - The result type of processing each snapshot pair
3277
- * @template D - The FirestoreDocument implementation type (defaults to FirestoreDocument<T>)
3278
- * @param config - Configuration for the iteration, including the document accessor and processing function
3279
- * @returns A promise that resolves to the result of the iteration, including statistics about checkpoints and snapshots processed
3370
+ * @param config - Iteration config including the document accessor and per-pair callback
3371
+ * @returns Checkpoint-level statistics (total checkpoints, snapshots visited, limit status)
3372
+ *
3373
+ * @example
3374
+ * ```typescript
3375
+ * const result = await iterateFirestoreDocumentSnapshotPairs({
3376
+ * queryFactory,
3377
+ * constraintsFactory: [where('status', '==', 'pending')],
3378
+ * limitPerCheckpoint: 100,
3379
+ * documentAccessor: collection.documentAccessor(),
3380
+ * iterateSnapshotPair: async (pair) => {
3381
+ * await pair.document.accessor.set({ ...pair.data, status: 'processed' });
3382
+ * }
3383
+ * });
3384
+ * ```
3280
3385
  */
3281
3386
  async function iterateFirestoreDocumentSnapshotPairs(config) {
3282
3387
  const { iterateSnapshotPair, documentAccessor } = config;
@@ -3290,16 +3395,32 @@ async function iterateFirestoreDocumentSnapshotPairs(config) {
3290
3395
  });
3291
3396
  }
3292
3397
  /**
3293
- * Iterates through the results of a Firestore query by each document snapshot by itself.
3398
+ * Iterates through Firestore query results, processing each document snapshot individually.
3294
3399
  *
3295
- * This function efficiently handles pagination through potentially large result sets by using
3296
- * the checkpoint system to load documents in batches. Each document snapshot is then processed
3297
- * individually using the provided processing function.
3400
+ * Built on {@link iterateFirestoreDocumentSnapshotBatches} with `maxParallelCheckpoints: 1`,
3401
+ * this unwraps each checkpoint's snapshots and processes them one-by-one via
3402
+ * {@link performAsyncTasks} (sequential by default). Use `snapshotsPerformTasksConfig`
3403
+ * to enable parallel snapshot processing within each checkpoint.
3298
3404
  *
3299
- * @template T - The document data type
3300
- * @template R - The result type of processing each snapshot
3301
- * @param config - Configuration for the iteration, including the snapshot processing function
3302
- * @returns A promise that resolves to the result of the iteration, including statistics about checkpoints and snapshots processed
3405
+ * For document-level operations (needing the typed {@link FirestoreDocument} wrapper),
3406
+ * use {@link iterateFirestoreDocumentSnapshotPairs} instead.
3407
+ *
3408
+ * @param config - Iteration config including the per-snapshot callback
3409
+ * @returns Checkpoint-level statistics (total checkpoints, snapshots visited, limit status)
3410
+ *
3411
+ * @example
3412
+ * ```typescript
3413
+ * const result = await iterateFirestoreDocumentSnapshots({
3414
+ * queryFactory,
3415
+ * constraintsFactory: [where('active', '==', true)],
3416
+ * limitPerCheckpoint: 200,
3417
+ * totalSnapshotsLimit: 1000,
3418
+ * iterateSnapshot: async (snapshot) => {
3419
+ * const data = snapshot.data();
3420
+ * await externalApi.sync(data);
3421
+ * }
3422
+ * });
3423
+ * ```
3303
3424
  */
3304
3425
  async function iterateFirestoreDocumentSnapshots(config) {
3305
3426
  const { iterateSnapshot, performTasksConfig, snapshotsPerformTasksConfig } = config;
@@ -3316,10 +3437,32 @@ async function iterateFirestoreDocumentSnapshots(config) {
3316
3437
  });
3317
3438
  }
3318
3439
  /**
3319
- * Iterates through the results of a Firestore query by each FirestoreDocumentSnapshotDataPair.
3440
+ * Iterates through Firestore query results in batches, loading each batch as
3441
+ * {@link FirestoreDocumentSnapshotDataPairWithData} instances before processing.
3320
3442
  *
3321
- * @param config
3322
- * @returns
3443
+ * Built on {@link iterateFirestoreDocumentSnapshotBatches} with `maxParallelCheckpoints: 1`.
3444
+ * Each batch of raw snapshots is resolved through the `documentAccessor` to produce
3445
+ * typed document-snapshot pairs. Use this when you need batch-level operations with
3446
+ * typed document access (e.g., bulk updates, batch writes).
3447
+ *
3448
+ * @param config - Iteration config including the document accessor and per-batch callback
3449
+ * @returns Checkpoint-level statistics (total checkpoints, snapshots visited, limit status)
3450
+ *
3451
+ * @example
3452
+ * ```typescript
3453
+ * const result = await iterateFirestoreDocumentSnapshotPairBatches({
3454
+ * queryFactory,
3455
+ * constraintsFactory: [where('needsMigration', '==', true)],
3456
+ * limitPerCheckpoint: 500,
3457
+ * batchSize: 50,
3458
+ * documentAccessor: collection.documentAccessor(),
3459
+ * iterateSnapshotPairsBatch: async (pairs, batchIndex) => {
3460
+ * const writeBatch = firestore.batch();
3461
+ * pairs.forEach((pair) => writeBatch.update(pair.document.documentRef, { migrated: true }));
3462
+ * await writeBatch.commit();
3463
+ * }
3464
+ * });
3465
+ * ```
3323
3466
  */
3324
3467
  async function iterateFirestoreDocumentSnapshotPairBatches(config) {
3325
3468
  const { iterateSnapshotPairsBatch, documentAccessor } = config;
@@ -3340,10 +3483,32 @@ async function iterateFirestoreDocumentSnapshotPairBatches(config) {
3340
3483
  */
3341
3484
  const DEFAULT_ITERATE_FIRESTORE_DOCUMENT_SNAPSHOT_BATCHES_BATCH_SIZE = 25;
3342
3485
  /**
3343
- * Iterates through the results of a Firestore query by each document snapshot.
3486
+ * Iterates through Firestore query results by subdividing each checkpoint into smaller batches.
3344
3487
  *
3345
- * @param config
3346
- * @returns
3488
+ * Built on {@link iterateFirestoreDocumentSnapshotCheckpoints}, this function takes each
3489
+ * checkpoint's snapshots and splits them into batches (default size: 25). Batches are
3490
+ * processed via {@link performAsyncTasks}, sequential by default. Use this when operations
3491
+ * have size limits (e.g., Firestore batch writes) or benefit from controlled chunk sizes.
3492
+ *
3493
+ * For per-snapshot processing, use {@link iterateFirestoreDocumentSnapshots}.
3494
+ * For batch processing with typed document pairs, use {@link iterateFirestoreDocumentSnapshotPairBatches}.
3495
+ *
3496
+ * @param config - Iteration config including batch size and per-batch callback
3497
+ * @returns Checkpoint-level statistics (total checkpoints, snapshots visited, limit status)
3498
+ *
3499
+ * @example
3500
+ * ```typescript
3501
+ * const result = await iterateFirestoreDocumentSnapshotBatches({
3502
+ * queryFactory,
3503
+ * constraintsFactory: [where('type', '==', 'order')],
3504
+ * limitPerCheckpoint: 500,
3505
+ * batchSize: 100,
3506
+ * iterateSnapshotBatch: async (snapshots, batchIndex) => {
3507
+ * const data = snapshots.map((s) => s.data());
3508
+ * await analytics.trackBatch(data);
3509
+ * }
3510
+ * });
3511
+ * ```
3347
3512
  */
3348
3513
  async function iterateFirestoreDocumentSnapshotBatches(config) {
3349
3514
  const { iterateSnapshotBatch, batchSizeForSnapshots: inputBatchSizeForSnapshots, performTasksConfig, batchSize: inputBatchSize } = config;
@@ -3369,29 +3534,75 @@ async function iterateFirestoreDocumentSnapshotBatches(config) {
3369
3534
  });
3370
3535
  }
3371
3536
  /**
3372
- * Creates a IterateFirestoreDocumentSnapshotCheckpointsFilterCheckpointSnapshotsFunction that filters out any repeat documents.
3537
+ * Creates a checkpoint filter that deduplicates documents across checkpoints.
3373
3538
  *
3374
- * Repeat documents can occur in cases where the document is updated and the query matches it again for a different reason.
3375
- * This utility function creates a filter that prevents processing the same document multiple times.
3539
+ * Repeat documents can appear when a document is updated during iteration and
3540
+ * re-matches the query in a subsequent checkpoint. This factory returns a stateful
3541
+ * filter that tracks seen document keys and removes duplicates.
3376
3542
  *
3377
- * @param readKeyFunction - Function that extracts a unique key from a document snapshot, defaults to document ID
3378
- * @returns A filter function that prevents duplicate document processing
3543
+ * The filter maintains state across checkpoints use a single instance for the
3544
+ * entire iteration run. Pair with `handleRepeatCursor: false` to also terminate
3545
+ * iteration when cursor-level repeats are detected.
3546
+ *
3547
+ * @param readKeyFunction - Extracts a unique key from each snapshot; defaults to `snapshot.id`
3548
+ * @returns A stateful filter function suitable for `filterCheckpointSnapshots`
3549
+ *
3550
+ * @example
3551
+ * ```typescript
3552
+ * const result = await iterateFirestoreDocumentSnapshotCheckpoints({
3553
+ * queryFactory,
3554
+ * constraintsFactory: [orderBy('updatedAt')],
3555
+ * limitPerCheckpoint: 100,
3556
+ * filterCheckpointSnapshots: filterRepeatCheckpointSnapshots(),
3557
+ * handleRepeatCursor: false,
3558
+ * iterateCheckpoint: async (snapshots) => {
3559
+ * return snapshots.map((s) => s.data());
3560
+ * }
3561
+ * });
3562
+ * ```
3379
3563
  */
3380
3564
  function filterRepeatCheckpointSnapshots(readKeyFunction = (x) => x.id) {
3381
3565
  const allowOnceFilter = util.allowValueOnceFilter(readKeyFunction);
3382
3566
  return async (snapshots) => snapshots.filter(allowOnceFilter);
3383
3567
  }
3384
3568
  /**
3385
- * Iterates through the results of a Firestore query in several batches.
3569
+ * Core cursor-based pagination engine for iterating through Firestore query results.
3386
3570
  *
3387
- * This is the core pagination function that handles cursor-based iteration through
3388
- * potentially large Firestore query results. It manages cursor documents, checkpoint
3389
- * processing, parallel execution, and various limit controls.
3571
+ * This is the foundational function in the Firestore iteration hierarchy. It drives
3572
+ * sequential cursor-based pagination: each "checkpoint" executes a Firestore query,
3573
+ * uses the last document as a `startAfter` cursor for the next query, and passes
3574
+ * results to the `iterateCheckpoint` callback.
3390
3575
  *
3391
- * @template T - The document data type
3392
- * @template R - The result type of the iteration
3393
- * @param config - Complete configuration for the pagination and processing behavior
3394
- * @returns Promise resolving to statistics about the iteration
3576
+ * The iteration loop continues until one of these conditions is met:
3577
+ * - A query returns no results (no more matching documents)
3578
+ * - The `totalSnapshotsLimit` is reached
3579
+ * - A repeat cursor is detected and `handleRepeatCursor` returns `false`
3580
+ * - The effective `limitPerCheckpoint` calculates to 0 remaining
3581
+ *
3582
+ * Higher-level functions build on this:
3583
+ * - {@link iterateFirestoreDocumentSnapshotBatches} — subdivides checkpoints into smaller batches
3584
+ * - {@link iterateFirestoreDocumentSnapshots} — processes one snapshot at a time
3585
+ * - {@link iterateFirestoreDocumentSnapshotPairs} — loads typed document wrappers per snapshot
3586
+ *
3587
+ * @param config - Complete configuration for pagination, processing, and termination behavior
3588
+ * @returns Statistics including total checkpoints executed, snapshots visited, and whether the limit was hit
3589
+ *
3590
+ * @example
3591
+ * ```typescript
3592
+ * const result = await iterateFirestoreDocumentSnapshotCheckpoints({
3593
+ * queryFactory,
3594
+ * constraintsFactory: [where('createdAt', '<=', cutoffDate), orderBy('createdAt')],
3595
+ * limitPerCheckpoint: 200,
3596
+ * totalSnapshotsLimit: 5000,
3597
+ * handleRepeatCursor: false,
3598
+ * iterateCheckpoint: async (snapshots, querySnapshot) => {
3599
+ * return snapshots.map((s) => ({ id: s.id, data: s.data() }));
3600
+ * },
3601
+ * useCheckpointResult: (result) => {
3602
+ * console.log(`Checkpoint ${result.i}: processed ${result.docSnapshots.length} docs`);
3603
+ * }
3604
+ * });
3605
+ * ```
3395
3606
  */
3396
3607
  async function iterateFirestoreDocumentSnapshotCheckpoints(config) {
3397
3608
  const { iterateCheckpoint, filterCheckpointSnapshots: inputFilterCheckpointSnapshot, handleRepeatCursor: inputHandleRepeatCursor, waitBetweenCheckpoints, useCheckpointResult, constraintsFactory: inputConstraintsFactory, dynamicConstraints: inputDynamicConstraints, queryFactory, maxParallelCheckpoints = 1, limitPerCheckpoint: inputLimitPerCheckpoint, totalSnapshotsLimit: inputTotalSnapshotsLimit } = config;
@@ -3494,13 +3705,20 @@ async function iterateFirestoreDocumentSnapshotCheckpoints(config) {
3494
3705
  }
3495
3706
  // MARK: Utility
3496
3707
  /**
3497
- * Creates a filter that allows each document snapshot to be processed only once based on its path.
3708
+ * Creates a stateful filter that allows each document snapshot through only once,
3709
+ * keyed by its full Firestore model path.
3498
3710
  *
3499
- * This utility helps prevent duplicate processing of documents by tracking which ones have
3500
- * already been seen based on their path.
3711
+ * Unlike {@link filterRepeatCheckpointSnapshots} which uses document ID by default,
3712
+ * this filter uses the full document path ({@link readFirestoreModelKeyFromDocumentSnapshot}),
3713
+ * making it suitable for cross-collection iteration where document IDs alone may collide.
3501
3714
  *
3502
- * @template T - The document snapshot type
3503
- * @returns A filter function that only allows each unique document to pass once
3715
+ * @returns A reusable filter function that passes each unique document path exactly once
3716
+ *
3717
+ * @example
3718
+ * ```typescript
3719
+ * const onceFilter = allowDocumentSnapshotWithPathOnceFilter();
3720
+ * const uniqueSnapshots = allSnapshots.filter(onceFilter);
3721
+ * ```
3504
3722
  */
3505
3723
  function allowDocumentSnapshotWithPathOnceFilter() {
3506
3724
  return util.allowValueOnceFilter(readFirestoreModelKeyFromDocumentSnapshot);
@@ -9907,6 +10125,7 @@ exports.limit = limit;
9907
10125
  exports.limitToLast = limitToLast;
9908
10126
  exports.limitUploadFileTypeDeterminer = limitUploadFileTypeDeterminer;
9909
10127
  exports.limitedFirestoreDocumentAccessorFactory = limitedFirestoreDocumentAccessorFactory;
10128
+ exports.limitedFirestoreDocumentAccessorSnapshotCache = limitedFirestoreDocumentAccessorSnapshotCache;
9910
10129
  exports.loadAllFirestoreDocumentSnapshot = loadAllFirestoreDocumentSnapshot;
9911
10130
  exports.loadAllFirestoreDocumentSnapshotPairs = loadAllFirestoreDocumentSnapshotPairs;
9912
10131
  exports.loadDocumentsForDocumentReferences = loadDocumentsForDocumentReferences;
@@ -10064,6 +10283,7 @@ exports.storagePathFactory = storagePathFactory;
10064
10283
  exports.storedFileReaderFactory = storedFileReaderFactory;
10065
10284
  exports.streamDocumentSnapshotDataPairs = streamDocumentSnapshotDataPairs;
10066
10285
  exports.streamDocumentSnapshotDataPairsWithData = streamDocumentSnapshotDataPairsWithData;
10286
+ exports.streamDocumentSnapshotsData = streamDocumentSnapshotsData;
10067
10287
  exports.streamFromOnSnapshot = streamFromOnSnapshot;
10068
10288
  exports.systemStateCollectionReference = systemStateCollectionReference;
10069
10289
  exports.systemStateConverter = systemStateConverter;