/** * @module Firestore Paged Item Accessor * * Internal read/write orchestration for {@link PagedItemFirestoreCollection}. * The accessor distributes a logical `T[]` across N page documents and a * single index document under a parent, then merges them back on read. * * The accessor goes lower-level than the standard * {@link FirestoreSingleDocumentAccessor}: it bypasses per-collection * converters because page documents (`PagedItemPageData`) and the index * document (`PagedItemIndexData`) have different shapes that can't be * expressed by a single document converter. */ import { type Maybe, type Building } from '@dereekb/util'; import { type Transaction } from '../types'; import { type FirestoreDocumentAccessorContextExtension } from './document'; import { type CollectionReferenceRef, type FirestoreContextReference } from '../reference'; import { type PagedItemConverter, type PagedItemDistributionScheme, type PagedItemIndexData, type PagedItemPageData } from '../collection/subcollection.paged'; /** * Accessor for reading and writing paged item data. * * Replaces the per-page document accessor exposed on a standard * {@link FirestoreCollectionWithParent}. All methods orchestrate the * multi-document index/page layout internally. * * @template T - The item type stored across pages * * @example * ```ts * // Read all items (loads index, then all pages in parallel) * const allItems = await pagedCollection.loadAllItems(); * * // Read specific pages (static mode — caller knows the scheme) * const cItems = await pagedCollection.loadItemsForPages(['c']); * * // Replace the full T[] (collection handles distribution) * await pagedCollection.writeAllItems(allItems); * ``` */ export interface FirestorePagedItemAccessor { /** * ID of the index document. */ readonly indexDocumentId: string; /** * The static distribution scheme, if configured. */ readonly distributionScheme: Maybe>; /** * True when a static distribution scheme is configured. */ readonly isStaticDistribution: boolean; /** * Loads only the index document. * * Returns `undefined` when the paged collection has never been written * (the index document does not yet exist). */ loadIndex(): Promise>; /** * Loads all pages and returns the merged `T[]`. * * Reads the index, then all listed pages in parallel, merging items in * page order. Returns an empty array when the collection has never been * written. */ loadAllItems(): Promise; /** * Loads items from specific page IDs only. * * In static mode this skips the index read — callers know which pages to * fetch from the distribution scheme. In dynamic mode the IDs are numeric * strings (`'0'`, `'1'`, ...) and callers should typically discover them * via {@link loadIndex} first. * * Pages that don't exist are silently skipped. * * @param pageIds - The page IDs to read */ loadItemsForPages(pageIds: string[]): Promise; /** * Replaces the full `T[]` contents of the paged collection. * * Distributes items into pages, writes/updates page documents, deletes * pages no longer needed, and updates the index — all in a single * WriteBatch. * * @param items - The full set of items to store */ writeAllItems(items: T[]): Promise; /** * Same as {@link writeAllItems} but participates in an existing transaction. * * The accessor reads existing pages within the transaction, computes the * new distribution, and writes all changes within the same transaction. * * Cost: N reads (current pages) + M writes (new pages + deletes + index). * For a typical 2–6 page collection this is well within Firestore's * transaction limits. * * @param transaction - Active Firestore transaction * @param items - The full set of items to store */ writeAllItemsInTransaction(transaction: Transaction, items: T[]): Promise; } /** * Configuration for {@link extendFirestoreCollectionWithPagedItemAccessor}. * * @template T - The item type stored across pages */ export interface PagedItemAccessorExtensionConfig { readonly indexDocumentId: string; readonly distributionScheme: Maybe>; readonly maxItemsPerPage: number; readonly itemConverter: Maybe>; /** * Standard document accessor extension for the underlying collection. * Currently unused (page CRUD goes through the raw driver) but accepted * for parity with {@link extendFirestoreCollectionWithSingleDocumentAccessor} * and future use. */ readonly accessors: FirestoreDocumentAccessorContextExtension>; } /** * Extends a Firestore collection object in-place with paged item accessor methods. * * The collection must already expose {@link CollectionReferenceRef} and * {@link FirestoreContextReference} from its base — both are provided by * {@link makeFirestoreCollectionWithParent}. * * @param x - The collection object to extend. * @param config - Paged accessor configuration. */ export declare function extendFirestoreCollectionWithPagedItemAccessor & CollectionReferenceRef & FirestoreContextReference, T>(x: Building, config: PagedItemAccessorExtensionConfig): void;