import type { CacheStats, DirectoryEntry, FSAdapter, FSAdapterConfig, ResolvedContentContext } from "./types.js"; import type { FileInfo, ResolveFileOptions, SourceSnapshotFreshnessOptions } from "../../base.js"; import { VeryfrontApiClient } from "../../veryfront-api-client/index.js"; import type { Project } from "../../veryfront-api-client/index.js"; export declare class VeryfrontFSAdapter implements FSAdapter { #private; readonly sourceSnapshotFreshnessOptionsVersion: 1; readonly maxWholeFileReadBytes: number; readonly symlinkSemantics: "none"; readonly projectContextSemantics: "fixed" | undefined; private client; private cache; private normalizer; private readOps; private dirOps; private statOps; private initialized; private initializationPromise; private initializationGeneration; private exactReadInitializationPromise; private exactReadInitializationGeneration; /** Resolves when file list initialization is complete (for coordinating reads) */ private fileListReadyResolve; /** Single-flight background rewarm when the file list cache disappears */ private fileListWarmupPromise; private fileListWarmupKey; /** * Last listing this adapter fetched or was poked with, kept in memory because * a cache write is not guaranteed to retain it: writes are skipped entirely * when caching is disabled, oversized listings are dropped by the memory * cache, and backend writes can fail. Without this, every module lookup of a * render would miss the cache and await its own full listing fetch -- more * API traffic than the per-file probing this replaced. It expires with the * same TTL as the cache entry it stands in for and is dropped by every * invalidation, so it is never fresher or staler than a retained cache write. */ private retainedFileList; private readonly fileListRetentionMs; /** Single-flight foreground refresh when a branch preview read misses a newly pushed file. */ private branchMissRecoveryPromise; private branchMissRecoveryGeneration; private readonly branchMissRecoveryFailures; /** Last successful source check and generation of the materialized snapshot. */ private sourceSnapshotCheckedAt; private sourceSnapshotVersion; private sourceSnapshotIdentity; private sourceSnapshotFiles; private sourceSnapshotFingerprint; private sourceSnapshotRefreshPromise; private sourceSnapshotMutationTail; private projectData?; private apiBaseUrl; private apiToken; private activeRequestToken; private projectSlug; private invalidationCallbacks; private styleCallbacks; private wsManager; private manifestFetcherCleanup; /** Per-request branch override (for branch preview URLs) */ private requestBranch; /** Content source configuration from config */ private contentSource; /** Resolved content context after initialization (includes resolved releaseId for env/domain) */ private contentContext; /** Whether running in proxy mode (shared adapter with per-request OAuth tokens) */ private proxyMode; private getCurrentFileListCacheKey; private syncClientContext; private getCachedFileListSync; private getCachedFileListAsync; /** Keep `files` answerable from memory for as long as a cache write would. */ private retainFileList; private clearRetainedFileList; /** * The retained listing, if it still describes the snapshot the caller is * reading. Anything that supersedes the snapshot -- a poke, a refresh, a * branch or token change -- either drops it outright or moves the snapshot * version past it, so a superseded listing can never answer a read. */ private readRetainedFileList; /** * Wait for the in-flight file-list warmup for `cacheKey` and return the * fetched listing. SSR module resolution reads this list for every module of * a page; when the cached listing has expired, answering "no list" makes each * module fall back to its own per-file/per-extension API probing (dozens of * sequential fetches per render). Paying for one awaited listing fetch keeps * that fan-out at a single API call while staying exactly as fresh: the * listing is fetched from the API at request time. Warmup failures resolve to * undefined so callers keep the legacy per-file fallback. */ private awaitFileListWarmup; constructor(config: FSAdapterConfig); initialize(): Promise; private shouldBackgroundPregenerateStyles; private scheduleFileListWarmup; /** * Drop every in-memory view of the current source snapshot. Used by pokes * that invalidate without carrying replacement files inline, so the next read * re-derives everything from the API rather than from a superseded listing. */ private clearMemoryCaches; private markSourceSnapshotChanged; private replaceSourceSnapshot; refreshSourceSnapshot(reason?: string): Promise; ensureSourceSnapshotFresh(reason?: string, options?: SourceSnapshotFreshnessOptions, initializedByManager?: boolean): Promise; getSourceSnapshotVersion(): number; getSourceSnapshotFingerprint(): Promise; /** * Names the branch/environment/release the snapshot currently targets, so a * caller that established freshness earlier in a request can detect a * context change (for example `setRequestBranch` on this reused adapter) * before trusting that establishment. */ getSourceSnapshotIdentity(): string | undefined; getPokeMetrics(): { received: number; invalidationsTriggered: number; lastPokeTime: number; connectionId: string | null; }; readFile(path: string): Promise; readFileBytes(path: string): Promise; readFileBytesWithinLimit(path: string, byteLimit: number): Promise; readTextFile(path: string): Promise; readOptionalTextFile(path: string): Promise; readdir(path: string): Promise; stat(path: string): Promise; exists(path: string): Promise; resolveFile(basePath: string, options?: ResolveFileOptions): Promise; dispose(): void; getCacheStats(): CacheStats; getProjectData(): Project | undefined; /** * @param options.waitForWarmup wait for an in-flight file-list fetch instead * of answering empty. Off by default: most callers can proceed without the * list and must not pay for the fetch, but a caller that has no other way to * obtain it -- CSP derivation on a release-backed context, where nothing else * populates the cache -- would otherwise read empty on every request forever. */ getAllSourceFiles(options?: { waitForWarmup?: boolean; }): Promise>; getEntityIdForPath(path: string): string | undefined; getFilePathByEntityId(entityId: string): string | undefined; getFilePathByEntityIdAsync(entityId: string): Promise<{ path: string; body?: string; } | undefined>; setRequestToken(token: string): void; clearRequestToken(): void; private invalidateRequestAuthoritySnapshot; setRequestBranch(branch: string | null): void; getRequestBranch(): string | null; clearRequestBranch(): void; setContentContext(context: ResolvedContentContext): void; getContentContext(): ResolvedContentContext | null; getClient(): VeryfrontApiClient; /** * Trigger CSS pre-generation for faster first-request latency. * * Runs CSS extraction and generation in parallel with other initialization. * Uses dynamic import to avoid circular dependencies. */ private triggerCSSPregeneration; } //# sourceMappingURL=adapter.d.ts.map