@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 +281 -61
- package/index.cjs.js.map +1 -1
- package/index.esm.js +280 -62
- package/index.esm.js.map +1 -1
- package/package.json +5 -5
- package/src/lib/common/firestore/accessor/document.rxjs.d.ts +5 -1
- package/src/lib/common/firestore/accessor/document.utility.d.ts +89 -0
- package/src/lib/common/firestore/query/constraint.d.ts +27 -22
- package/src/lib/common/firestore/query/constraint.template.d.ts +48 -32
- package/src/lib/common/firestore/query/iterator.d.ts +58 -2
- package/src/lib/common/firestore/query/query.iterate.d.ts +300 -96
- package/test/index.cjs.js +85 -4
- package/test/index.esm.js +86 -5
- package/test/package.json +6 -6
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module Firestore Query Iteration
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Provides a layered system for iterating through Firestore query results using
|
|
5
|
+
* cursor-based pagination ("checkpoints"). Each layer adds convenience on top of the
|
|
6
|
+
* one below:
|
|
7
|
+
*
|
|
8
|
+
* 1. **Checkpoints** ({@link iterateFirestoreDocumentSnapshotCheckpoints}) — core pagination engine
|
|
9
|
+
* 2. **Batches** ({@link iterateFirestoreDocumentSnapshotBatches}) — subdivides checkpoints into fixed-size batches
|
|
10
|
+
* 3. **Snapshots** ({@link iterateFirestoreDocumentSnapshots}) — processes individual snapshots
|
|
11
|
+
* 4. **Pairs** ({@link iterateFirestoreDocumentSnapshotPairs}) — loads typed document wrappers per snapshot
|
|
12
|
+
*
|
|
13
|
+
* Batch variants with document pairs are also available:
|
|
14
|
+
* - {@link iterateFirestoreDocumentSnapshotPairBatches} — batch processing with typed document access
|
|
15
|
+
*
|
|
16
|
+
* All functions support configurable limits (`limitPerCheckpoint`, `totalSnapshotsLimit`),
|
|
17
|
+
* concurrency (`maxParallelCheckpoints`), rate limiting (`waitBetweenCheckpoints`),
|
|
18
|
+
* snapshot filtering, and repeat cursor detection.
|
|
8
19
|
*/
|
|
9
20
|
import { type GetterOrValue, type PromiseOrValue, type IndexRef, type Maybe, type PerformAsyncTasksConfig, type IndexNumber, type PerformAsyncTasksResult, type FactoryWithRequiredInput, type Milliseconds, type AllowValueOnceFilter, type ReadKeyFunction } from '@dereekb/util';
|
|
10
21
|
import { type FirestoreDocument, type LimitedFirestoreDocumentAccessor, type FirestoreDocumentSnapshotDataPairWithData } from '../accessor';
|
|
@@ -13,35 +24,53 @@ import { type FirestoreQueryConstraint } from './constraint';
|
|
|
13
24
|
import { type FirestoreQueryFactory } from './query';
|
|
14
25
|
import { type FirestoreModelKey } from '../collection/collection';
|
|
15
26
|
/**
|
|
16
|
-
* Configuration for
|
|
27
|
+
* Configuration for {@link iterateFirestoreDocumentSnapshotPairs}.
|
|
17
28
|
*
|
|
18
|
-
*
|
|
19
|
-
* @
|
|
20
|
-
*
|
|
29
|
+
* Extends per-snapshot iteration by automatically loading each snapshot's
|
|
30
|
+
* {@link FirestoreDocumentSnapshotDataPairWithData} via a document accessor,
|
|
31
|
+
* providing the callback with both the snapshot and its typed document wrapper.
|
|
21
32
|
*/
|
|
22
33
|
export interface IterateFirestoreDocumentSnapshotPairsConfig<T, R, D extends FirestoreDocument<T> = FirestoreDocument<T>> extends Omit<IterateFirestoreDocumentSnapshotsConfig<T, R>, 'iterateSnapshot'> {
|
|
23
34
|
/**
|
|
24
|
-
*
|
|
35
|
+
* Accessor used to load {@link FirestoreDocument} instances for each snapshot reference.
|
|
36
|
+
* Each snapshot is resolved through this accessor to produce a document-snapshot pair.
|
|
25
37
|
*/
|
|
26
38
|
readonly documentAccessor: LimitedFirestoreDocumentAccessor<T, D>;
|
|
27
39
|
/**
|
|
28
|
-
*
|
|
40
|
+
* Callback invoked for each document-snapshot pair.
|
|
41
|
+
*
|
|
42
|
+
* Receives a pair containing both the {@link FirestoreDocument} wrapper and its
|
|
43
|
+
* snapshot data, enabling operations that need typed document access (e.g., updates, deletes).
|
|
44
|
+
*
|
|
45
|
+
* @param snapshot - The document-snapshot pair with guaranteed data
|
|
29
46
|
*/
|
|
30
47
|
iterateSnapshotPair(snapshot: FirestoreDocumentSnapshotDataPairWithData<D>): Promise<R>;
|
|
31
48
|
}
|
|
32
49
|
/**
|
|
33
|
-
* Iterates through
|
|
50
|
+
* Iterates through Firestore query results, loading each snapshot as a
|
|
51
|
+
* {@link FirestoreDocumentSnapshotDataPairWithData} before processing.
|
|
34
52
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
53
|
+
* Built on {@link iterateFirestoreDocumentSnapshots}, this adds an automatic document
|
|
54
|
+
* loading step: each raw snapshot is resolved through the `documentAccessor` to produce
|
|
55
|
+
* a pair containing both the typed {@link FirestoreDocument} and its snapshot data.
|
|
56
|
+
* This is the highest-level iteration function — use it when your callback needs
|
|
57
|
+
* document-level operations (updates, deletes) alongside the snapshot data.
|
|
39
58
|
*
|
|
40
|
-
* @
|
|
41
|
-
* @
|
|
42
|
-
*
|
|
43
|
-
* @
|
|
44
|
-
*
|
|
59
|
+
* @param config - Iteration config including the document accessor and per-pair callback
|
|
60
|
+
* @returns Checkpoint-level statistics (total checkpoints, snapshots visited, limit status)
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const result = await iterateFirestoreDocumentSnapshotPairs({
|
|
65
|
+
* queryFactory,
|
|
66
|
+
* constraintsFactory: [where('status', '==', 'pending')],
|
|
67
|
+
* limitPerCheckpoint: 100,
|
|
68
|
+
* documentAccessor: collection.documentAccessor(),
|
|
69
|
+
* iterateSnapshotPair: async (pair) => {
|
|
70
|
+
* await pair.document.accessor.set({ ...pair.data, status: 'processed' });
|
|
71
|
+
* }
|
|
72
|
+
* });
|
|
73
|
+
* ```
|
|
45
74
|
*/
|
|
46
75
|
export declare function iterateFirestoreDocumentSnapshotPairs<T, R, D extends FirestoreDocument<T> = FirestoreDocument<T>>(config: IterateFirestoreDocumentSnapshotPairsConfig<T, R, D>): Promise<IterateFirestoreDocumentSnapshotCheckpointsResult>;
|
|
47
76
|
/**
|
|
@@ -82,44 +111,83 @@ export interface IterateFirestoreDocumentSnapshotsConfig<T, R> extends Omit<Iter
|
|
|
82
111
|
*/
|
|
83
112
|
export type IterateFirestoreDocumentSnapshotsResult<T, R> = PerformAsyncTasksResult<QueryDocumentSnapshot<T>, R>;
|
|
84
113
|
/**
|
|
85
|
-
* Iterates through
|
|
114
|
+
* Iterates through Firestore query results, processing each document snapshot individually.
|
|
86
115
|
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
116
|
+
* Built on {@link iterateFirestoreDocumentSnapshotBatches} with `maxParallelCheckpoints: 1`,
|
|
117
|
+
* this unwraps each checkpoint's snapshots and processes them one-by-one via
|
|
118
|
+
* {@link performAsyncTasks} (sequential by default). Use `snapshotsPerformTasksConfig`
|
|
119
|
+
* to enable parallel snapshot processing within each checkpoint.
|
|
90
120
|
*
|
|
91
|
-
*
|
|
92
|
-
* @
|
|
93
|
-
*
|
|
94
|
-
* @
|
|
121
|
+
* For document-level operations (needing the typed {@link FirestoreDocument} wrapper),
|
|
122
|
+
* use {@link iterateFirestoreDocumentSnapshotPairs} instead.
|
|
123
|
+
*
|
|
124
|
+
* @param config - Iteration config including the per-snapshot callback
|
|
125
|
+
* @returns Checkpoint-level statistics (total checkpoints, snapshots visited, limit status)
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* const result = await iterateFirestoreDocumentSnapshots({
|
|
130
|
+
* queryFactory,
|
|
131
|
+
* constraintsFactory: [where('active', '==', true)],
|
|
132
|
+
* limitPerCheckpoint: 200,
|
|
133
|
+
* totalSnapshotsLimit: 1000,
|
|
134
|
+
* iterateSnapshot: async (snapshot) => {
|
|
135
|
+
* const data = snapshot.data();
|
|
136
|
+
* await externalApi.sync(data);
|
|
137
|
+
* }
|
|
138
|
+
* });
|
|
139
|
+
* ```
|
|
95
140
|
*/
|
|
96
141
|
export declare function iterateFirestoreDocumentSnapshots<T, R>(config: IterateFirestoreDocumentSnapshotsConfig<T, R>): Promise<IterateFirestoreDocumentSnapshotCheckpointsResult>;
|
|
97
142
|
/**
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* This interface defines the configuration for processing batches of document snapshots
|
|
101
|
-
* with their associated data. It supports efficient batch processing operations on related
|
|
102
|
-
* documents.
|
|
143
|
+
* Configuration for {@link iterateFirestoreDocumentSnapshotPairBatches}.
|
|
103
144
|
*
|
|
104
|
-
*
|
|
105
|
-
* @
|
|
106
|
-
*
|
|
145
|
+
* Extends batch-level iteration by automatically resolving each snapshot batch into
|
|
146
|
+
* {@link FirestoreDocumentSnapshotDataPairWithData} instances via a document accessor.
|
|
147
|
+
* The callback receives fully typed document-snapshot pairs rather than raw snapshots,
|
|
148
|
+
* enabling batch operations that need document-level access.
|
|
107
149
|
*/
|
|
108
150
|
export interface IterateFirestoreDocumentSnapshotPairBatchesConfig<T, R, D extends FirestoreDocument<T> = FirestoreDocument<T>> extends Omit<IterateFirestoreDocumentSnapshotBatchesConfig<T, R>, 'iterateSnapshotBatch'> {
|
|
109
151
|
/**
|
|
110
|
-
*
|
|
152
|
+
* Accessor used to load {@link FirestoreDocument} instances for each snapshot reference.
|
|
153
|
+
* All snapshots in a batch are resolved through this accessor before being passed to the callback.
|
|
111
154
|
*/
|
|
112
155
|
readonly documentAccessor: LimitedFirestoreDocumentAccessor<T, D>;
|
|
113
156
|
/**
|
|
114
|
-
*
|
|
157
|
+
* Callback invoked for each batch of document-snapshot pairs.
|
|
158
|
+
*
|
|
159
|
+
* @param snapshotDataPairs - Array of pairs, each containing a typed document and its snapshot data
|
|
160
|
+
* @param batchIndex - Zero-based index of this batch within the current checkpoint
|
|
115
161
|
*/
|
|
116
162
|
iterateSnapshotPairsBatch(snapshotDataPairs: FirestoreDocumentSnapshotDataPairWithData<D>[], batchIndex: number): Promise<R>;
|
|
117
163
|
}
|
|
118
164
|
/**
|
|
119
|
-
* Iterates through
|
|
165
|
+
* Iterates through Firestore query results in batches, loading each batch as
|
|
166
|
+
* {@link FirestoreDocumentSnapshotDataPairWithData} instances before processing.
|
|
120
167
|
*
|
|
121
|
-
* @
|
|
122
|
-
*
|
|
168
|
+
* Built on {@link iterateFirestoreDocumentSnapshotBatches} with `maxParallelCheckpoints: 1`.
|
|
169
|
+
* Each batch of raw snapshots is resolved through the `documentAccessor` to produce
|
|
170
|
+
* typed document-snapshot pairs. Use this when you need batch-level operations with
|
|
171
|
+
* typed document access (e.g., bulk updates, batch writes).
|
|
172
|
+
*
|
|
173
|
+
* @param config - Iteration config including the document accessor and per-batch callback
|
|
174
|
+
* @returns Checkpoint-level statistics (total checkpoints, snapshots visited, limit status)
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```typescript
|
|
178
|
+
* const result = await iterateFirestoreDocumentSnapshotPairBatches({
|
|
179
|
+
* queryFactory,
|
|
180
|
+
* constraintsFactory: [where('needsMigration', '==', true)],
|
|
181
|
+
* limitPerCheckpoint: 500,
|
|
182
|
+
* batchSize: 50,
|
|
183
|
+
* documentAccessor: collection.documentAccessor(),
|
|
184
|
+
* iterateSnapshotPairsBatch: async (pairs, batchIndex) => {
|
|
185
|
+
* const writeBatch = firestore.batch();
|
|
186
|
+
* pairs.forEach((pair) => writeBatch.update(pair.document.documentRef, { migrated: true }));
|
|
187
|
+
* await writeBatch.commit();
|
|
188
|
+
* }
|
|
189
|
+
* });
|
|
190
|
+
* ```
|
|
123
191
|
*/
|
|
124
192
|
export declare function iterateFirestoreDocumentSnapshotPairBatches<T, R, D extends FirestoreDocument<T> = FirestoreDocument<T>>(config: IterateFirestoreDocumentSnapshotPairBatchesConfig<T, R>): Promise<IterateFirestoreDocumentSnapshotCheckpointsResult>;
|
|
125
193
|
/**
|
|
@@ -147,34 +215,46 @@ export interface IterateFirestoreDocumentSnapshotBatchesResult<T, R> extends Ind
|
|
|
147
215
|
readonly result: R;
|
|
148
216
|
}
|
|
149
217
|
/**
|
|
150
|
-
*
|
|
218
|
+
* Configuration for {@link iterateFirestoreDocumentSnapshotBatches}.
|
|
219
|
+
*
|
|
220
|
+
* Extends checkpoint-level iteration by subdividing each checkpoint's snapshots into
|
|
221
|
+
* smaller batches before processing. This is useful for operations that have size
|
|
222
|
+
* constraints (e.g., Firestore batch writes limited to 500 operations) or that
|
|
223
|
+
* benefit from smaller working sets for memory efficiency.
|
|
151
224
|
*/
|
|
152
225
|
export interface IterateFirestoreDocumentSnapshotBatchesConfig<T, R> extends Omit<IterateFirestoreDocumentSnapshotCheckpointsConfig<T, IterateFirestoreDocumentSnapshotBatchesResult<T, R>>, 'iterateCheckpoint'> {
|
|
153
226
|
/**
|
|
154
|
-
*
|
|
227
|
+
* Maximum number of document snapshots per batch.
|
|
155
228
|
*
|
|
156
|
-
*
|
|
229
|
+
* Defaults to {@link DEFAULT_ITERATE_FIRESTORE_DOCUMENT_SNAPSHOT_BATCHES_BATCH_SIZE} (25).
|
|
230
|
+
* Pass `null` to process all snapshots from a checkpoint in a single batch.
|
|
157
231
|
*/
|
|
158
232
|
readonly batchSize?: Maybe<number>;
|
|
159
233
|
/**
|
|
160
|
-
*
|
|
234
|
+
* Dynamic batch size factory that can vary batch size based on the checkpoint's snapshots.
|
|
161
235
|
*
|
|
162
|
-
*
|
|
236
|
+
* Called once per checkpoint with all snapshots from that checkpoint. If it returns `null`,
|
|
237
|
+
* all snapshots are processed in a single batch. Takes precedence over `batchSize` when provided.
|
|
163
238
|
*/
|
|
164
239
|
readonly batchSizeForSnapshots?: Maybe<FactoryWithRequiredInput<number | null, QueryDocumentSnapshot<T>[]>>;
|
|
165
240
|
/**
|
|
166
|
-
*
|
|
241
|
+
* Callback invoked for each batch of document snapshots within a checkpoint.
|
|
167
242
|
*
|
|
168
|
-
*
|
|
243
|
+
* Each batch is guaranteed to contain at least one item. Batches within a checkpoint
|
|
244
|
+
* are processed via {@link performAsyncTasks} (sequential by default, configurable
|
|
245
|
+
* via `performTasksConfig`).
|
|
246
|
+
*
|
|
247
|
+
* @param snapshotBatch - Non-empty array of document snapshots in this batch
|
|
248
|
+
* @param batchIndex - Zero-based index of this batch within the current checkpoint
|
|
169
249
|
*/
|
|
170
250
|
iterateSnapshotBatch(snapshotBatch: QueryDocumentSnapshot<T>[], batchIndex: number): Promise<R>;
|
|
171
251
|
/**
|
|
172
|
-
*
|
|
252
|
+
* Optional configuration for the {@link performAsyncTasks} call that processes batches
|
|
253
|
+
* within each checkpoint.
|
|
173
254
|
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* - sequential = true
|
|
255
|
+
* Defaults: `sequential: true`, `retriesAllowed: 0`, `throwError: true`.
|
|
256
|
+
* Override to enable parallel batch processing, add retries for transient failures,
|
|
257
|
+
* or customize error handling.
|
|
178
258
|
*/
|
|
179
259
|
readonly performTasksConfig?: Partial<PerformAsyncTasksConfig<QueryDocumentSnapshot<T>[]>>;
|
|
180
260
|
}
|
|
@@ -185,74 +265,145 @@ export interface IterateFirestoreDocumentSnapshotBatchesConfig<T, R> extends Omi
|
|
|
185
265
|
*/
|
|
186
266
|
export declare const DEFAULT_ITERATE_FIRESTORE_DOCUMENT_SNAPSHOT_BATCHES_BATCH_SIZE = 25;
|
|
187
267
|
/**
|
|
188
|
-
* Iterates through
|
|
268
|
+
* Iterates through Firestore query results by subdividing each checkpoint into smaller batches.
|
|
269
|
+
*
|
|
270
|
+
* Built on {@link iterateFirestoreDocumentSnapshotCheckpoints}, this function takes each
|
|
271
|
+
* checkpoint's snapshots and splits them into batches (default size: 25). Batches are
|
|
272
|
+
* processed via {@link performAsyncTasks}, sequential by default. Use this when operations
|
|
273
|
+
* have size limits (e.g., Firestore batch writes) or benefit from controlled chunk sizes.
|
|
189
274
|
*
|
|
190
|
-
* @
|
|
191
|
-
* @
|
|
275
|
+
* For per-snapshot processing, use {@link iterateFirestoreDocumentSnapshots}.
|
|
276
|
+
* For batch processing with typed document pairs, use {@link iterateFirestoreDocumentSnapshotPairBatches}.
|
|
277
|
+
*
|
|
278
|
+
* @param config - Iteration config including batch size and per-batch callback
|
|
279
|
+
* @returns Checkpoint-level statistics (total checkpoints, snapshots visited, limit status)
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```typescript
|
|
283
|
+
* const result = await iterateFirestoreDocumentSnapshotBatches({
|
|
284
|
+
* queryFactory,
|
|
285
|
+
* constraintsFactory: [where('type', '==', 'order')],
|
|
286
|
+
* limitPerCheckpoint: 500,
|
|
287
|
+
* batchSize: 100,
|
|
288
|
+
* iterateSnapshotBatch: async (snapshots, batchIndex) => {
|
|
289
|
+
* const data = snapshots.map((s) => s.data());
|
|
290
|
+
* await analytics.trackBatch(data);
|
|
291
|
+
* }
|
|
292
|
+
* });
|
|
293
|
+
* ```
|
|
192
294
|
*/
|
|
193
295
|
export declare function iterateFirestoreDocumentSnapshotBatches<T, R>(config: IterateFirestoreDocumentSnapshotBatchesConfig<T, R>): Promise<IterateFirestoreDocumentSnapshotCheckpointsResult>;
|
|
194
296
|
/**
|
|
195
|
-
*
|
|
297
|
+
* Configuration for {@link iterateFirestoreDocumentSnapshotCheckpoints}.
|
|
298
|
+
*
|
|
299
|
+
* This is the lowest-level configuration in the iteration hierarchy. It controls
|
|
300
|
+
* cursor-based pagination through Firestore query results, where each "checkpoint"
|
|
301
|
+
* represents one query execution that fetches a page of documents. Higher-level
|
|
302
|
+
* functions ({@link iterateFirestoreDocumentSnapshotBatches}, {@link iterateFirestoreDocumentSnapshots},
|
|
303
|
+
* {@link iterateFirestoreDocumentSnapshotPairs}) build on this.
|
|
196
304
|
*/
|
|
197
305
|
export interface IterateFirestoreDocumentSnapshotCheckpointsConfig<T, R> {
|
|
306
|
+
/**
|
|
307
|
+
* Factory used to create Firestore queries. The query is rebuilt for each checkpoint
|
|
308
|
+
* with the current constraints (including the cursor `startAfter` and `limit`).
|
|
309
|
+
*/
|
|
198
310
|
readonly queryFactory: FirestoreQueryFactory<T>;
|
|
311
|
+
/**
|
|
312
|
+
* Base query constraints applied to every checkpoint query.
|
|
313
|
+
*
|
|
314
|
+
* When a function (getter), it is called for each checkpoint by default, enabling
|
|
315
|
+
* dynamic constraints that change between pages. When a static array, the same
|
|
316
|
+
* constraints are reused. Override this behavior with `dynamicConstraints`.
|
|
317
|
+
*
|
|
318
|
+
* The cursor (`startAfter`) and page limit are appended automatically — do not
|
|
319
|
+
* include them here.
|
|
320
|
+
*/
|
|
199
321
|
readonly constraintsFactory: GetterOrValue<FirestoreQueryConstraint[]>;
|
|
200
322
|
/**
|
|
201
|
-
*
|
|
323
|
+
* Controls whether `constraintsFactory` is re-evaluated for each checkpoint.
|
|
202
324
|
*
|
|
203
|
-
*
|
|
325
|
+
* Defaults to `true` when `constraintsFactory` is a function, `false` when it is a static array.
|
|
326
|
+
* Set explicitly to override the default — e.g., `false` to cache a function's result,
|
|
327
|
+
* or `true` to force re-evaluation of a memoized getter.
|
|
204
328
|
*/
|
|
205
329
|
readonly dynamicConstraints?: boolean;
|
|
206
330
|
/**
|
|
207
|
-
*
|
|
331
|
+
* Maximum number of documents to fetch per checkpoint (Firestore query `limit`).
|
|
208
332
|
*
|
|
209
|
-
* The
|
|
333
|
+
* The effective limit is the minimum of this value and the remaining documents
|
|
334
|
+
* allowed by `totalSnapshotsLimit`. Defaults to `totalSnapshotsLimit` if not set.
|
|
210
335
|
*
|
|
211
|
-
* A
|
|
336
|
+
* A value of `0` causes immediate termination with no documents loaded — it is NOT
|
|
337
|
+
* treated as "unlimited".
|
|
212
338
|
*/
|
|
213
339
|
readonly limitPerCheckpoint?: Maybe<number>;
|
|
214
340
|
/**
|
|
215
|
-
*
|
|
341
|
+
* Maximum total number of document snapshots to load across all checkpoints.
|
|
216
342
|
*
|
|
217
|
-
*
|
|
343
|
+
* Iteration stops after the checkpoint that causes this limit to be reached or exceeded.
|
|
344
|
+
* When omitted, there is no snapshot count limit (pagination continues until results
|
|
345
|
+
* are exhausted or `maxPage`/`endEarly` terminates it).
|
|
218
346
|
*/
|
|
219
347
|
readonly totalSnapshotsLimit?: Maybe<number>;
|
|
220
348
|
/**
|
|
221
|
-
*
|
|
349
|
+
* Maximum number of checkpoints to process concurrently.
|
|
222
350
|
*
|
|
223
|
-
*
|
|
351
|
+
* Defaults to 1 (serial execution). When set higher, checkpoint *processing*
|
|
352
|
+
* (via `iterateCheckpoint`) can overlap, though checkpoint *fetching* remains
|
|
353
|
+
* sequential since each query depends on the previous checkpoint's cursor.
|
|
224
354
|
*/
|
|
225
355
|
readonly maxParallelCheckpoints?: number;
|
|
226
356
|
/**
|
|
227
|
-
*
|
|
357
|
+
* Minimum delay in milliseconds between initiating consecutive checkpoint queries.
|
|
228
358
|
*
|
|
229
|
-
*
|
|
359
|
+
* Useful for Firestore rate limiting or quota management. When running checkpoints
|
|
360
|
+
* in parallel, this ensures at least this much time passes between starting each
|
|
361
|
+
* new query.
|
|
230
362
|
*/
|
|
231
363
|
readonly waitBetweenCheckpoints?: Milliseconds;
|
|
232
364
|
/**
|
|
233
|
-
*
|
|
365
|
+
* Strategy for handling repeat cursor documents, which can indicate an infinite loop.
|
|
234
366
|
*
|
|
235
|
-
*
|
|
367
|
+
* A repeat cursor occurs when the last document of a checkpoint has already been
|
|
368
|
+
* seen as a cursor in a previous checkpoint — often caused by document updates
|
|
369
|
+
* during iteration that re-match the query.
|
|
236
370
|
*
|
|
237
|
-
*
|
|
371
|
+
* - `false` or `undefined`: Immediately stop iteration when a repeat is detected
|
|
372
|
+
* - `async (cursor) => boolean`: Custom handler — return `true` to continue iteration
|
|
373
|
+
* despite the repeat, or `false` to stop
|
|
238
374
|
*/
|
|
239
375
|
readonly handleRepeatCursor?: Maybe<false | ((cursor: QueryDocumentSnapshot<T>) => Promise<boolean>)>;
|
|
240
376
|
/**
|
|
241
|
-
*
|
|
377
|
+
* Optional filter applied to each checkpoint's snapshots before they reach `iterateCheckpoint`.
|
|
242
378
|
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
379
|
+
* Filtering does not affect pagination decisions — the cursor for the next checkpoint
|
|
380
|
+
* is always based on the last *unfiltered* document. If all documents in a checkpoint
|
|
381
|
+
* are filtered out, iteration continues to the next checkpoint.
|
|
245
382
|
*
|
|
246
|
-
* @
|
|
247
|
-
*
|
|
383
|
+
* Use {@link filterRepeatCheckpointSnapshots} to deduplicate documents that appear
|
|
384
|
+
* in multiple checkpoints. Combine with `handleRepeatCursor` to properly terminate
|
|
385
|
+
* iteration when filtering causes repeated cursors.
|
|
248
386
|
*/
|
|
249
387
|
readonly filterCheckpointSnapshots?: IterateFirestoreDocumentSnapshotCheckpointsFilterCheckpointSnapshotsFunction<T>;
|
|
250
388
|
/**
|
|
251
|
-
*
|
|
389
|
+
* Core callback invoked once per checkpoint with the (optionally filtered) document snapshots.
|
|
390
|
+
*
|
|
391
|
+
* Receives all snapshots for this checkpoint and the raw query snapshot for metadata access.
|
|
392
|
+
* Returns an array of results — one per logical unit processed (could be per-document,
|
|
393
|
+
* per-batch, or any grouping the implementation chooses).
|
|
394
|
+
*
|
|
395
|
+
* @param snapshots - Document snapshots for this checkpoint (post-filter)
|
|
396
|
+
* @param query - The raw Firestore query snapshot for this checkpoint
|
|
252
397
|
*/
|
|
253
398
|
iterateCheckpoint(snapshots: QueryDocumentSnapshot<T>[], query: QuerySnapshot<T>): Promise<R[]>;
|
|
254
399
|
/**
|
|
255
|
-
*
|
|
400
|
+
* Optional side-effect callback invoked after each checkpoint is fully processed.
|
|
401
|
+
*
|
|
402
|
+
* Called after `iterateCheckpoint` completes, receiving the full iteration result
|
|
403
|
+
* including checkpoint index, cursor state, results, and raw snapshots. Useful for
|
|
404
|
+
* progress logging, metrics, or external state accumulation.
|
|
405
|
+
*
|
|
406
|
+
* @param checkpointResults - Complete iteration result for this checkpoint
|
|
256
407
|
*/
|
|
257
408
|
useCheckpointResult?(checkpointResults: IterateFirestoreDocumentSnapshotCheckpointsIterationResult<T, R>): PromiseOrValue<void>;
|
|
258
409
|
}
|
|
@@ -268,13 +419,32 @@ export interface IterateFirestoreDocumentSnapshotCheckpointsConfig<T, R> {
|
|
|
268
419
|
*/
|
|
269
420
|
export type IterateFirestoreDocumentSnapshotCheckpointsFilterCheckpointSnapshotsFunction<T> = (snapshot: QueryDocumentSnapshot<T>[]) => PromiseOrValue<QueryDocumentSnapshot<T>[]>;
|
|
270
421
|
/**
|
|
271
|
-
* Creates a
|
|
422
|
+
* Creates a checkpoint filter that deduplicates documents across checkpoints.
|
|
423
|
+
*
|
|
424
|
+
* Repeat documents can appear when a document is updated during iteration and
|
|
425
|
+
* re-matches the query in a subsequent checkpoint. This factory returns a stateful
|
|
426
|
+
* filter that tracks seen document keys and removes duplicates.
|
|
427
|
+
*
|
|
428
|
+
* The filter maintains state across checkpoints — use a single instance for the
|
|
429
|
+
* entire iteration run. Pair with `handleRepeatCursor: false` to also terminate
|
|
430
|
+
* iteration when cursor-level repeats are detected.
|
|
272
431
|
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
432
|
+
* @param readKeyFunction - Extracts a unique key from each snapshot; defaults to `snapshot.id`
|
|
433
|
+
* @returns A stateful filter function suitable for `filterCheckpointSnapshots`
|
|
275
434
|
*
|
|
276
|
-
* @
|
|
277
|
-
*
|
|
435
|
+
* @example
|
|
436
|
+
* ```typescript
|
|
437
|
+
* const result = await iterateFirestoreDocumentSnapshotCheckpoints({
|
|
438
|
+
* queryFactory,
|
|
439
|
+
* constraintsFactory: [orderBy('updatedAt')],
|
|
440
|
+
* limitPerCheckpoint: 100,
|
|
441
|
+
* filterCheckpointSnapshots: filterRepeatCheckpointSnapshots(),
|
|
442
|
+
* handleRepeatCursor: false,
|
|
443
|
+
* iterateCheckpoint: async (snapshots) => {
|
|
444
|
+
* return snapshots.map((s) => s.data());
|
|
445
|
+
* }
|
|
446
|
+
* });
|
|
447
|
+
* ```
|
|
278
448
|
*/
|
|
279
449
|
export declare function filterRepeatCheckpointSnapshots<T>(readKeyFunction?: ReadKeyFunction<QueryDocumentSnapshot<T>>): IterateFirestoreDocumentSnapshotCheckpointsFilterCheckpointSnapshotsFunction<T>;
|
|
280
450
|
/**
|
|
@@ -356,25 +526,59 @@ export interface IterateFirestoreDocumentSnapshotCheckpointsResult {
|
|
|
356
526
|
readonly totalSnapshotsLimitReached: boolean;
|
|
357
527
|
}
|
|
358
528
|
/**
|
|
359
|
-
*
|
|
529
|
+
* Core cursor-based pagination engine for iterating through Firestore query results.
|
|
360
530
|
*
|
|
361
|
-
* This is the
|
|
362
|
-
*
|
|
363
|
-
*
|
|
531
|
+
* This is the foundational function in the Firestore iteration hierarchy. It drives
|
|
532
|
+
* sequential cursor-based pagination: each "checkpoint" executes a Firestore query,
|
|
533
|
+
* uses the last document as a `startAfter` cursor for the next query, and passes
|
|
534
|
+
* results to the `iterateCheckpoint` callback.
|
|
364
535
|
*
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
*
|
|
368
|
-
*
|
|
536
|
+
* The iteration loop continues until one of these conditions is met:
|
|
537
|
+
* - A query returns no results (no more matching documents)
|
|
538
|
+
* - The `totalSnapshotsLimit` is reached
|
|
539
|
+
* - A repeat cursor is detected and `handleRepeatCursor` returns `false`
|
|
540
|
+
* - The effective `limitPerCheckpoint` calculates to 0 remaining
|
|
541
|
+
*
|
|
542
|
+
* Higher-level functions build on this:
|
|
543
|
+
* - {@link iterateFirestoreDocumentSnapshotBatches} — subdivides checkpoints into smaller batches
|
|
544
|
+
* - {@link iterateFirestoreDocumentSnapshots} — processes one snapshot at a time
|
|
545
|
+
* - {@link iterateFirestoreDocumentSnapshotPairs} — loads typed document wrappers per snapshot
|
|
546
|
+
*
|
|
547
|
+
* @param config - Complete configuration for pagination, processing, and termination behavior
|
|
548
|
+
* @returns Statistics including total checkpoints executed, snapshots visited, and whether the limit was hit
|
|
549
|
+
*
|
|
550
|
+
* @example
|
|
551
|
+
* ```typescript
|
|
552
|
+
* const result = await iterateFirestoreDocumentSnapshotCheckpoints({
|
|
553
|
+
* queryFactory,
|
|
554
|
+
* constraintsFactory: [where('createdAt', '<=', cutoffDate), orderBy('createdAt')],
|
|
555
|
+
* limitPerCheckpoint: 200,
|
|
556
|
+
* totalSnapshotsLimit: 5000,
|
|
557
|
+
* handleRepeatCursor: false,
|
|
558
|
+
* iterateCheckpoint: async (snapshots, querySnapshot) => {
|
|
559
|
+
* return snapshots.map((s) => ({ id: s.id, data: s.data() }));
|
|
560
|
+
* },
|
|
561
|
+
* useCheckpointResult: (result) => {
|
|
562
|
+
* console.log(`Checkpoint ${result.i}: processed ${result.docSnapshots.length} docs`);
|
|
563
|
+
* }
|
|
564
|
+
* });
|
|
565
|
+
* ```
|
|
369
566
|
*/
|
|
370
567
|
export declare function iterateFirestoreDocumentSnapshotCheckpoints<T, R>(config: IterateFirestoreDocumentSnapshotCheckpointsConfig<T, R>): Promise<IterateFirestoreDocumentSnapshotCheckpointsResult>;
|
|
371
568
|
/**
|
|
372
|
-
* Creates a filter that allows each document snapshot
|
|
569
|
+
* Creates a stateful filter that allows each document snapshot through only once,
|
|
570
|
+
* keyed by its full Firestore model path.
|
|
571
|
+
*
|
|
572
|
+
* Unlike {@link filterRepeatCheckpointSnapshots} which uses document ID by default,
|
|
573
|
+
* this filter uses the full document path ({@link readFirestoreModelKeyFromDocumentSnapshot}),
|
|
574
|
+
* making it suitable for cross-collection iteration where document IDs alone may collide.
|
|
373
575
|
*
|
|
374
|
-
*
|
|
375
|
-
* already been seen based on their path.
|
|
576
|
+
* @returns A reusable filter function that passes each unique document path exactly once
|
|
376
577
|
*
|
|
377
|
-
* @
|
|
378
|
-
*
|
|
578
|
+
* @example
|
|
579
|
+
* ```typescript
|
|
580
|
+
* const onceFilter = allowDocumentSnapshotWithPathOnceFilter();
|
|
581
|
+
* const uniqueSnapshots = allSnapshots.filter(onceFilter);
|
|
582
|
+
* ```
|
|
379
583
|
*/
|
|
380
584
|
export declare function allowDocumentSnapshotWithPathOnceFilter<T extends DocumentSnapshot>(): AllowValueOnceFilter<T, FirestoreModelKey>;
|