import type { Accessor } from '../../accessor/base.ts'; import type { IndexEntry } from '../../cache/index/config.ts'; import { type ReaddirFn } from './probe.ts'; import { type DetectFn, type ScopeMatch } from './scope.ts'; /** * A listing that also proves descendant listings. * * For a backend whose one fetch answers more than one directory: a * dated-message day fetch yields the day's own children AND the contents of * its `files/` subdirectory, and a mail label listing yields the date * directories AND each date's messages AND each message's attachment * directory. Returning the extra listings as seeds lets the kit cache them, * so entering a seeded directory costs no second identical fetch. `seeds` * keys are paths relative to the listed directory (`files`, * `2026-01-05/Report__17`). * * `partial` says the entries are a filtered or truncated view rather than the * directory's contents, so they must not be cached as the directory: a * glob-scoped listing, or one the provider did not finish. The entries * themselves are real either way, so the kit caches those and lets the next * readdir re-list. `seeds` stay full listings of the children this fetch did * report, so they are cached as directories as usual. */ export interface DirListing { entries: [string, IndexEntry][]; seeds: Readonly>; partial?: boolean; } export type Listed = [string, IndexEntry][] | DirListing; export type Lister = (accessor: A, match: ScopeMatch) => Promise; export type EntryLister = (accessor: A, match: ScopeMatch, entry: IndexEntry) => Promise; export type Guard = (accessor: A, match: ScopeMatch, virtual: string) => Promise; export type PatternTest = (pattern: string) => boolean; /** * Build a hierarchy readdir: dispatch, guards, index, name joins. * * A lister fetches one directory kind and returns `[vfsName, IndexEntry]` * pairs; everything else — classification, existence guards, the index probe * and write-back, and virtual name construction — happens here, identically * for every backend. A dot-prefixed name is dropped from the listing: the * classifier refuses every dot-leading segment, so listing one would * advertise a path that stat, read and child readdir all report absent. * A lister may answer null instead of a listing: the directory's container * does not exist, reported as ENOENT on the virtual path. * * An entry lister is for a directory whose existence and contents are * already proven by its parent's listing: the kit resolves the directory's * own index entry through `resolveEntry` (warming parent listings, each one * cached) and hands it over, so entering a directory a traversal just listed * costs no API call at all. A container lister that instead re-fetched its * ancestor chain per directory made a recursive walk quadratic in listing * payloads. The facts a child listing needs beyond the API's own answers * ride the parent listing's `IndexEntry.extra` (trello stashes each * `card.json` size on the card's directory entry). * * A lister may answer a `DirListing` to seed descendant listings its fetch * already proved; entering a seeded directory then reads the index instead of * refetching (the entry-lister branch re-checks the listing after resolving, * because the resolve itself may have run the seeding parent). * * A parent-entry lister (`parentEntryListers`) is for a directory whose * existence is decided by its PARENT's entry rather than its own: a * dated-message day dir is real for any well-formed date under a channel that * exists, including dates the channel's bounded listing window never minted, * so the proof is the channel entry and the fetch takes the date from the * match. A kind appears in at most one of the three tables. * * `listers` holds one lister per directory kind; include `root` for a * dynamic mount root. `entryListers` holds listers for kinds resolved * through their parent's listing; a kind appears in exactly one of the two * tables. `staticRoot` names fixed top-level entries, for backends whose * root never changes; it bypasses the index. `guards` are existence checks * that run before the index probe, so a vanished container is ENOENT even on * a warm cache. `patternKinds` holds one entry per kind whose listing is a * bounded window, the test for whether a glob is one its lister can move the * window to (`hasGlobSpan` for a date-keyed listing). A glob that passes * reaches the lister and the index is not read first, because a cached * listing is that same window and would answer the glob with it; any other * glob, and any other kind, keeps the cached listing and never sees a * pattern. `leafError` is what listing * a leaf raises; fixed hierarchies historically answer ENOENT. */ export declare function makeReaddir(detect: DetectFn, options: { listers: Readonly>>; entryListers?: Readonly>>; parentEntryListers?: Readonly>>; staticRoot?: readonly string[]; guards?: Readonly>>; patternKinds?: Readonly>; leafError?: 'enoent' | 'enotdir'; }): ReaddirFn; //# sourceMappingURL=readdir.d.ts.map