import { type FirestorePagedItemAccessor } from '../accessor/document.paged'; import { type FirestoreDocument } from '../accessor/document'; import { type FirestoreCollectionWithParent, type FirestoreCollectionWithParentConfig } from './subcollection'; import { type SnapshotConverterFunctions } from '../snapshot/snapshot.type'; /** * Default ID for the index document inside a paged subcollection. * * The underscore prefix visually distinguishes the index from page documents * and sorts before numeric/alphabetic page IDs. */ export declare const DEFAULT_PAGED_ITEM_INDEX_DOCUMENT_ID = "_index"; /** * Default maximum number of items per page document when using dynamic * (count-based) distribution. */ export declare const DEFAULT_PAGED_ITEM_MAX_ITEMS_PER_PAGE = 500; /** * Defines how items are distributed across page documents. * * The scheme must be deterministic — for any item, {@link distribute} always * returns the same page ID. This determinism is what enables selective reads * in static mode: callers can read a specific page directly without first * consulting the index document. * * @template T - The item type stored in the paged collection * * @example * ```ts * // Alphabetic distribution: items bucketed by first letter * const alphaScheme: PagedItemDistributionScheme = { * pageIds: 'abcdefghijklmnopqrstuvwxyz'.split(''), * distribute: (entry) => entry.name[0]?.toLowerCase() ?? 'a' * }; * ``` */ export interface PagedItemDistributionScheme { /** * All possible page IDs in this scheme, in deterministic order. * * Defines the full set of page documents that may exist. Empty pages are * not written, so this is the universe of allowed IDs, not necessarily * the set of pages currently present. */ readonly pageIds: readonly string[]; /** * Maps an item to its target page ID. * * Must return a value that exists in {@link pageIds}. If it returns an * unknown ID, the write throws. */ readonly distribute: (item: T) => string; } /** * Ref to a {@link PagedItemDistributionScheme}. */ export interface PagedItemDistributionSchemeRef { readonly distributionScheme: PagedItemDistributionScheme; } /** * Converts individual items to/from their Firestore POJO representation. * * Distinct from a {@link FirestoreDataConverter}: this operates on individual * items inside a page's items array, not on whole DocumentSnapshots. The * collection wraps these per-item conversions inside the paged page envelope * (`{ i, c }`) automatically. * * @template T - The item type the consumer sees in memory */ export interface PagedItemConverter { /** * Convert from a Firestore POJO to in-memory T. */ readonly fromData: (data: object) => T; /** * Convert from in-memory T to a Firestore-safe POJO. */ readonly toData: (item: T) => object; } /** * Data stored in the index document of a paged subcollection. * * Field names are short to keep the index document small; this is internal * framework data, not developer-facing state. */ export interface PagedItemIndexData { /** * Total item count across all pages. */ readonly tc: number; /** * Page IDs that currently contain at least one item, in insertion order. * * For dynamic mode: `['0', '1', '2', ...]`. * For static mode: a subset of the scheme's `pageIds` (only pages with items). */ readonly p: string[]; /** * Per-page item counts, keyed by page ID. Lets consumers know how many * items are on each page without reading the page document itself. */ readonly pc: Record; /** * Timestamp (ms) of the last write operation. Useful for staleness checks. */ readonly u: number; } /** * Data stored in each page document of a paged subcollection. * * The {@link i} array contains the actual `T[]` slice. The `c` field is a * denormalized count, available without deserializing `i`. * * @template T - The item type stored in the paged collection */ export interface PagedItemPageData { /** * Items on this page. Each item is converted via {@link PagedItemConverter}. */ readonly i: T[]; /** * Item count on this page (denormalized). */ readonly c: number; } /** * Configuration for creating a {@link PagedItemFirestoreCollection}. * * Extends {@link FirestoreCollectionWithParentConfig} for parent/identity/context. * The page-document data type is the {@link PagedItemPageData} envelope so the * standard accessor returns the actual stored shape (mirroring the * {@link SystemState}/{@link SystemStateDocument} pattern). The paged accessor * methods bypass the converter and operate on the raw collection so the index * document — which has a different shape — is read/written correctly. * * The {@link converter} field is optional: when omitted, the collection uses * {@link defaultPagedItemPageDataConverter}, a pass-through converter for the * envelope. Provide a custom converter only when you need per-field handling on * the page document. * * @template T - The item type stored across page documents * @template PT - The parent document data type * @template D - The page document type (data shape: {@link PagedItemPageData}) * @template PD - The parent document type */ export interface PagedItemFirestoreCollectionConfig> = FirestoreDocument>, PD extends FirestoreDocument = FirestoreDocument> extends Omit, PT, D, PD>, 'converter'> { /** * Optional snapshot converter for the page document envelope. Defaults to * {@link defaultPagedItemPageDataConverter} when omitted. */ readonly converter?: FirestoreCollectionWithParentConfig, PT, D, PD>['converter']; /** * ID of the index document. Defaults to {@link DEFAULT_PAGED_ITEM_INDEX_DOCUMENT_ID}. */ readonly indexDocumentId?: string; /** * Static distribution scheme. When provided, the collection uses * scheme-based static distribution. When omitted, the collection uses * dynamic count-based paging. */ readonly distributionScheme?: PagedItemDistributionScheme; /** * Max items per page document. Only used in dynamic mode. Defaults to * {@link DEFAULT_PAGED_ITEM_MAX_ITEMS_PER_PAGE}. */ readonly maxItemsPerPage?: number; /** * Per-item converter applied to individual `T`s when reading/writing the * `i` array of a page document. If omitted, items are stored as-is and * must already be Firestore-safe POJOs. */ readonly itemConverter?: PagedItemConverter; } /** * A subcollection that stores a logical `T[]` distributed across multiple * page documents under a parent. * * Combines {@link FirestoreCollectionWithParent} (for parent/context/identity) * with {@link FirestorePagedItemAccessor} (for paged read/write operations). * * The standard document accessor methods inherited from * {@link FirestoreCollectionWithParent} return the raw {@link PagedItemPageData} * envelope. In normal usage callers should use the paged accessor methods * (e.g. {@link FirestorePagedItemAccessor.loadAllItems}) which apply the * configured {@link PagedItemConverter} per item. * * @template T - The item type stored across pages * @template PT - The parent document data type * @template D - The page document type (data shape: {@link PagedItemPageData}) * @template PD - The parent document type */ export interface PagedItemFirestoreCollection> = FirestoreDocument>, PD extends FirestoreDocument = FirestoreDocument> extends FirestoreCollectionWithParent, PT, D, PD>, FirestorePagedItemAccessor { } /** * Builds the default snapshot converter used by {@link PagedItemFirestoreCollection} * when no consumer-supplied converter is provided. * * The page envelope is the framework's internal storage shape: `i` is the array of * raw entries (already Firestore-safe at this level — per-entry conversion is * handled by the paged accessor's {@link PagedItemConverter}) and `c` is the * denormalized count. * * @returns A snapshot converter for {@link PagedItemPageData}. * * @template T - The item type stored across pages * * @__NO_SIDE_EFFECTS__ */ export declare function defaultPagedItemPageDataConverter(): SnapshotConverterFunctions>; /** * Creates a {@link PagedItemFirestoreCollection}. * * Mirrors the `build()` + extend pattern used by * {@link makeSingleItemFirestoreCollection}: the base * {@link FirestoreCollectionWithParent} provides parent/identity/context, and * {@link extendFirestoreCollectionWithPagedItemAccessor} attaches the paged * read/write methods. When the config does not supply a `converter`, the * default {@link defaultPagedItemPageDataConverter} is used so consumers don't * have to model the envelope shape themselves. * * @param config - Paged collection configuration. * @returns A configured paged subcollection. * * @template T - The item type stored across pages * @template PT - The parent document data type * @template D - The page document type * @template PD - The parent document type * * @__NO_SIDE_EFFECTS__ */ export declare function makePagedItemFirestoreCollection> = FirestoreDocument>, PD extends FirestoreDocument = FirestoreDocument>(config: PagedItemFirestoreCollectionConfig): PagedItemFirestoreCollection;