/** * SSR Dependency Validator * * Validates and processes local and cross-project dependencies for SSR modules. * Handles pre-flight checks, recursive dependency resolution, and missing dependency reporting. * * @module module-system/react-loader/ssr-module-loader/ssr-dependency-validator */ import type { CrossProjectImport, LocalImport, MissingImport } from "../../../transforms/esm/import-parser.js"; import { createFileSystem } from "../../../platform/compat/fs.js"; import type { RuntimeAdapter } from "../../../platform/adapters/base.js"; import type { ModuleCacheEntry } from "./types.js"; import { type DependencyHashCache } from "../../../cache/dependency-graph.js"; export interface ResolvedCachedDependencies { localImportPaths: Map; crossProjectPaths: Map; } export interface DependencyTransformCacheOptions { skipDistributedCache?: boolean; skipMdxPathCache?: boolean; } /** * Whether cached transformed code points at every dependency output produced * from the current source tree. * * Dependency module paths include their transformed-content hash. A parent * whose source is unchanged can therefore retain an old child path across a * dev-server restart even though that old file still exists. Validate actual * import specifiers, not arbitrary strings or file existence, before reusing * the parent. */ export declare function cachedCodeUsesResolvedDependencies(code: string, dependencies: ResolvedCachedDependencies): Promise; /** * Manages dependency validation for SSR module loading: * - Pre-flight checks for local file existence * - Recursive dependency resolution * - Missing dependency collection and error reporting */ export declare class SSRDependencyValidator { private transformWithDependencies; private transformCrossProjectImport; private adapter; private projectDir; /** Accumulated missing dependencies across the transform tree. */ missingDependencies: MissingImport[]; /** Bound, no-follow snapshot read capability captured from the adapter. */ private readonly projectSnapshotReader?; /** The adapter's own contract that its paths cannot traverse symlinks. */ private readonly symlinkFreeFs; /** Authenticated optional methods used to canonicalize stable in-project links. */ private readonly projectLstat?; private readonly projectRealPath?; constructor(transformWithDependencies: (filePath: string, source: string | undefined, depth: number, dependencyHashCache: DependencyHashCache, signal?: AbortSignal, options?: DependencyTransformCacheOptions) => Promise, transformCrossProjectImport: (crossProjectImport: CrossProjectImport, signal?: AbortSignal) => Promise, adapter: RuntimeAdapter, projectDir: string); /** Reset missing dependencies for a new load cycle. */ reset(): void; /** * Throw a structured error with all accumulated missing dependencies. */ throwMissingDependencies(filePath: string): never; /** * Ensure all dependencies of a cached module exist by recursively * processing local imports and cross-project imports. */ ensureDependenciesExist(code: string, filePath: string, depth?: number, signal?: AbortSignal): Promise; /** * Process cross-project imports in batches, building a map of * specifier -> temp file path. * * Non-terminal failures are aggregated into {@link missingDependencies} so the * caller can report every unresolved specifier at once. A terminal HTTP module * fetch failure is rethrown untouched instead: it means the source could not be * retrieved at all, so reporting it as a missing dependency would mislabel a * transient network failure as a broken component. */ processCrossProjectImports(crossProjectImports: CrossProjectImport[], filePath: string, signal?: AbortSignal): Promise>; /** * Process local imports in batches, recursively transforming dependencies * and building a map of specifier -> temp file path. */ processLocalImports(imports: LocalImport[], fromFilePath: string, depth: number, localFs: ReturnType, dependencyHashCache: DependencyHashCache, signal?: AbortSignal, options?: DependencyTransformCacheOptions): Promise>; private isProjectAbsolutePath; /** * Read an approved in-project dependency without trusting the path twice. * * Import containment approves a canonical pathname, but on a native * filesystem the file or one of its parents can be replaced with a symlink * between that approval and this read. The captured snapshot capability * binds the two: it re-verifies no-follow containment beneath the project * root atomically with the read, so a link retargeted outside the project * is refused instead of followed. A filesystem whose own contract rules out * symlink traversal cannot be retargeted, so its plain read is already * bound; adapters providing neither authority keep the direct read they * always had. */ private readProjectImportSource; /** * Resolve a stable in-project symlink to its canonical target before the * no-follow snapshot read, which refuses any terminal symbolic link. * Containment stays enforced by the snapshot read itself: it re-verifies * the handed path beneath the project root, so a link whose target escapes * the project is still refused rather than followed. Anything uncertain -- * an adapter without lstat or realPath authority, a vanished path, a broken * link -- keeps the original path so the bound read stays the sole arbiter. */ private canonicalizeProjectImportPath; /** Register CSS with a read that revalidates containment at consumption. */ registerContainedCSSImport(cssImport: LocalImport): void; private readLocalImportSource; } //# sourceMappingURL=ssr-dependency-validator.d.ts.map