| 32 | * dedupe.reset() |
| 33 | */ |
| 34 | export class DeduplicatedLoadSubset { |
| 35 | // The underlying loadSubset function to wrap |
| 36 | private readonly _loadSubset: ( |
| 37 | options: LoadSubsetOptions, |
| 38 | ) => true | Promise<void> |
| 39 | |
| 40 | // An optional callback function that is invoked when a loadSubset call is deduplicated. |
| 41 | private readonly onDeduplicate: |
| 42 | | ((options: LoadSubsetOptions) => void) |
| 43 | | undefined |
| 44 | |
| 45 | // Combined where predicate for all unlimited calls (no limit) |
| 46 | private unlimitedWhere: BasicExpression<boolean> | undefined = undefined |
| 47 | |
| 48 | // Flag to track if we've loaded all data (unlimited call with no where clause) |
| 49 | private hasLoadedAllData = false |
| 50 | |
| 51 | // List of all limited calls (with limit, possibly with orderBy) |
| 52 | // We clone options before storing to prevent mutation of stored predicates |
| 53 | private limitedCalls: Array<LoadSubsetOptions> = [] |
| 54 | |
| 55 | // Track in-flight calls to prevent concurrent duplicate requests |
| 56 | // We store both the options and the promise so we can apply subset logic |
| 57 | private inflightCalls: Array<{ |
| 58 | options: LoadSubsetOptions |
| 59 | promise: Promise<void> |
| 60 | }> = [] |
| 61 | |
| 62 | // Generation counter to invalidate in-flight requests after reset() |
| 63 | // When reset() is called, this increments, and any in-flight completion handlers |
| 64 | // check if their captured generation matches before updating tracking state |
| 65 | private generation = 0 |
| 66 | |
| 67 | constructor(opts: { |
| 68 | loadSubset: (options: LoadSubsetOptions) => true | Promise<void> |
| 69 | onDeduplicate?: (options: LoadSubsetOptions) => void |
| 70 | }) { |
| 71 | this._loadSubset = opts.loadSubset |
| 72 | this.onDeduplicate = opts.onDeduplicate |
| 73 | } |
| 74 | |
| 75 | /** |
| 76 | * Load a subset of data, with automatic deduplication based on previously |
| 77 | * loaded predicates and in-flight requests. |
| 78 | * |
| 79 | * This method is auto-bound, so it can be safely passed as a callback without |
| 80 | * losing its `this` context (e.g., `loadSubset: dedupe.loadSubset` in a sync config). |
| 81 | * |
| 82 | * @param options - The predicate options (where, orderBy, limit) |
| 83 | * @returns true if data is already loaded, or a Promise that resolves when data is loaded |
| 84 | */ |
| 85 | loadSubset = (options: LoadSubsetOptions): true | Promise<void> => { |
| 86 | // If we've loaded all data, everything is covered |
| 87 | if (this.hasLoadedAllData) { |
| 88 | this.onDeduplicate?.(options) |
| 89 | return true |
| 90 | } |
| 91 |
nothing calls this directly
no test coverage detected