/** * Path Utilities Module * * Provides cross-platform path manipulation utilities for: * - Path normalization (absolute paths, separator normalization) * - Relative path conversion (always forward-slash separated) * - Path traversal prevention (security) * - Index storage path helpers * - Path length validation (Windows MAX_PATH) * - Unicode normalization (NFC) */ /** * Maximum path length for Windows (traditional MAX_PATH limit) * Note: Long path support exists but is not universally enabled */ export declare const MAX_PATH_LENGTH_WINDOWS = 260; /** * Maximum path length for Unix-like systems (PATH_MAX) */ export declare const MAX_PATH_LENGTH_UNIX = 4096; /** * Normalize a path to absolute form with consistent separators * * - Resolves to absolute path * - Normalizes separators (removes redundant separators) * - Removes trailing slashes (except for root paths) * * @param inputPath - The path to normalize * @returns Normalized absolute path using platform-native separators * * @example * ```typescript * normalizePath('./src/utils') * // => '/Users/dev/project/src/utils' (Unix) * // => 'C:\\Users\\dev\\project\\src\\utils' (Windows) * * normalizePath('C:\\Users\\dev\\project\\') * // => 'C:\\Users\\dev\\project' (trailing slash removed) * ``` */ export declare function normalizePath(inputPath: string): string; /** * Normalize Unicode characters in a path to NFC form * * Different operating systems may use different Unicode normalization forms: * - macOS uses NFD (decomposed) * - Windows and Linux typically use NFC (composed) * * This function normalizes paths to NFC for consistent comparison and storage. * * @param filePath - The path to normalize * @returns Path with Unicode characters normalized to NFC form * * @example * ```typescript * // The character 'e' can be represented as: * // - NFC: 'e' (single code point U+00E9) * // - NFD: 'e' + combining acute accent (U+0065 + U+0301) * normalizeUnicode('cafe\u0301') // => 'cafe' (with composed e) * ``` */ export declare function normalizeUnicode(filePath: string): string; /** * Validate that a path length is within acceptable limits * * Windows traditionally has a MAX_PATH limit of 260 characters. * Unix-like systems typically allow up to 4096 characters. * * @param absolutePath - The absolute path to validate * @returns true if the path length is acceptable * * @example * ```typescript * validatePathLength('/home/user/project/file.ts') // => true * validatePathLength('C:\\very\\long\\path...') // => depends on length * ``` */ export declare function validatePathLength(absolutePath: string): boolean; /** * Check if a path is too long for the current platform * * Returns detailed information about path length issues. * * @param absolutePath - The absolute path to check * @returns Object with validation result and details */ export declare function checkPathLength(absolutePath: string): { valid: boolean; length: number; maxLength: number; exceededBy: number; }; /** * Convert an absolute path to a relative path with forward slashes * * Returns a relative path from basePath to absolutePath, always using * forward slashes for consistency across platforms (for storage in indexes). * * @param absolutePath - The absolute path to convert * @param basePath - The base path to make relative to * @returns Forward-slash separated relative path * * @example * ```typescript * toRelativePath('/Users/dev/project/src/utils/hash.ts', '/Users/dev/project') * // => 'src/utils/hash.ts' * * toRelativePath('C:\\Users\\dev\\project\\src\\utils\\hash.ts', 'C:\\Users\\dev\\project') * // => 'src/utils/hash.ts' * ``` */ export declare function toRelativePath(absolutePath: string, basePath: string): string; /** * Convert a relative path (with forward slashes) to an absolute path * * @param relativePath - Forward-slash separated relative path * @param basePath - The base path to resolve from * @returns Absolute path using platform-native separators * * @example * ```typescript * toAbsolutePath('src/utils/hash.ts', '/Users/dev/project') * // => '/Users/dev/project/src/utils/hash.ts' * ``` */ export declare function toAbsolutePath(relativePath: string, basePath: string): string; /** * Check if a relative path contains path traversal patterns * * Detects attempts to escape the base directory using: * - Parent directory references (..) * - Absolute paths in relative context * - Various encoding tricks * * @param relativePath - The relative path to check * @returns true if path traversal is detected * * @example * ```typescript * isPathTraversal('../../../etc/passwd') // => true * isPathTraversal('src/../config.ts') // => true (contains ..) * isPathTraversal('/etc/passwd') // => true (absolute path) * isPathTraversal('src/utils/hash.ts') // => false * ``` */ export declare function isPathTraversal(relativePath: string): boolean; /** * Safely join a base path with a relative path * * Joins the paths and validates that the result stays within the base directory. * Returns null if path traversal is detected. * * SECURITY: This function rejects ALL paths containing: * - Parent directory references (..) * - Absolute paths * - Null bytes (poison null byte attack) * - Paths that would escape the base directory * * @param basePath - The base directory path * @param relativePath - The relative path to join * @returns The joined absolute path, or null if traversal detected * * @example * ```typescript * safeJoin('/project', 'src/utils/hash.ts') * // => '/project/src/utils/hash.ts' * * safeJoin('/project', '../../../etc/passwd') * // => null (traversal detected) * * safeJoin('/project', 'src/../config.ts') * // => null (contains .., always rejected for security) * ``` */ export declare function safeJoin(basePath: string, relativePath: string): string | null; /** * Check if a path is within a directory * * @param targetPath - The path to check * @param directoryPath - The directory that should contain the target * @returns true if targetPath is within directoryPath */ export declare function isWithinDirectory(targetPath: string, directoryPath: string): boolean; /** * Get the global storage root directory * * Returns ~/.mcp/search/ and creates it if it doesn't exist. * * BUG #10 FIX: Uses caching to avoid repeated sync filesystem operations. * Once the directory is created and cached, subsequent calls return immediately. * * @returns Absolute path to the storage root directory * * @example * ```typescript * getStorageRoot() * // => '/Users/dev/.mcp/search' (Unix) * // => 'C:\\Users\\dev\\.mcp\\search' (Windows) * ``` */ export declare function getStorageRoot(): string; /** * Get the global storage root directory (async version) * * Async version that uses fs.promises for non-blocking operations. * Caches the result for subsequent calls. * * BUG #10 FIX: Added async version to avoid blocking the event loop. * * @returns Promise resolving to the absolute path to the storage root directory * * @example * ```typescript * await getStorageRootAsync() * // => '/Users/dev/.mcp/search' (Unix) * // => 'C:\\Users\\dev\\.mcp\\search' (Windows) * ``` */ export declare function getStorageRootAsync(): Promise; /** * Clear the storage root cache (for testing purposes) */ export declare function clearStorageRootCache(): void; /** * Get the index storage path for a project * * Returns ~/.mcp/search/indexes// where hash is derived from the project path. * Creates the directory if it doesn't exist. * * SMCP-057: Migration support - checks for existing legacy (16-char) index first. * If a legacy index exists, returns that path to avoid breaking existing installations. * New indexes are created with 32-char hashes. * * @param projectPath - Absolute path to the project root * @returns Absolute path to the project's index directory * * @example * ```typescript * getIndexPath('/Users/dev/my-project') * // => '/Users/dev/.mcp/search/indexes/a1b2c3d4e5f6789012345678901234ab' (32 chars) * // or '/Users/dev/.mcp/search/indexes/a1b2c3d4e5f67890' (16 chars for legacy) * ``` */ export declare function getIndexPath(projectPath: string): string; /** * SMCP-057: Check if an index exists for a project (checking both old and new hash formats) * * @param projectPath - Absolute path to the project root * @returns true if an index exists (either legacy or new format) */ export declare function indexPathExists(projectPath: string): boolean; /** * SMCP-057: Check if an index is using the legacy (16-char) hash format * * @param projectPath - Absolute path to the project root * @returns true if the index uses legacy format, false if new format or doesn't exist */ export declare function isLegacyIndex(projectPath: string): boolean; /** * Get the indexes directory path (without creating a specific index) * * @returns Absolute path to the indexes directory */ export declare function getIndexesDir(): string; /** * Get the logs directory path for an index * * @param indexPath - Absolute path to the index directory * @returns Absolute path to the logs subdirectory */ export declare function getLogsPath(indexPath: string): string; /** * Get the config file path for an index * * @param indexPath - Absolute path to the index directory * @returns Absolute path to config.json */ export declare function getConfigPath(indexPath: string): string; /** * Get the metadata file path for an index * * @param indexPath - Absolute path to the index directory * @returns Absolute path to metadata.json */ export declare function getMetadataPath(indexPath: string): string; /** * Get the fingerprints file path for an index * * @param indexPath - Absolute path to the index directory * @returns Absolute path to fingerprints.json */ export declare function getFingerprintsPath(indexPath: string): string; /** * Get the LanceDB directory path for an index * * @param indexPath - Absolute path to the index directory * @returns Absolute path to the index.lancedb directory */ export declare function getLanceDbPath(indexPath: string): string; /** * Get the docs fingerprints file path for an index * * @param indexPath - Absolute path to the index directory * @returns Absolute path to docs-fingerprints.json */ export declare function getDocsFingerprintsPath(indexPath: string): string; /** * Get the Docs LanceDB directory path for an index * * @param indexPath - Absolute path to the index directory * @returns Absolute path to the docs.lancedb directory */ export declare function getDocsLanceDbPath(indexPath: string): string; /** * Get the dirty files JSON path for an index * * Used by the lazy indexing strategy to track files pending indexing. * * @param indexPath - Absolute path to the index directory * @returns Absolute path to dirty-files.json */ export declare function getDirtyFilesPath(indexPath: string): string; /** * Get the FTS index file path for code search * * @param indexPath - Absolute path to the index directory * @returns Absolute path to code-fts.json */ export declare function getCodeFTSIndexPath(indexPath: string): string; /** * Get the FTS index file path for docs search * * @param indexPath - Absolute path to the index directory * @returns Absolute path to docs-fts.json */ export declare function getDocsFTSIndexPath(indexPath: string): string; /** * Expand tilde (~) to home directory in a path * * @param inputPath - Path that may contain ~ * @returns Path with ~ expanded to home directory */ export declare function expandTilde(inputPath: string): string; /** * Get the file extension from a path (without the dot) * * @param filePath - Path to get extension from * @returns File extension without dot, or empty string if none * * @example * ```typescript * getExtension('/path/to/file.ts') // => 'ts' * getExtension('/path/to/file') // => '' * getExtension('/path/to/.gitignore') // => 'gitignore' * ``` */ export declare function getExtension(filePath: string): string; /** * Get the file name without extension * * @param filePath - Path to get base name from * @returns File name without extension */ export declare function getBaseName(filePath: string): string; /** * Sanitize a path for display in error messages * * Replaces sensitive information like home directory and user names * with safe placeholders to prevent information disclosure. * * @param fullPath - The full path to sanitize * @param projectPath - Optional project path to make relative to * @returns Sanitized path safe for display in error messages * * @example * ```typescript * sanitizePath('/Users/john/.mcp/search/indexes/abc123') * // => '~/.mcp/search/indexes/abc123' * * sanitizePath('/Users/john/projects/myapp/src/file.ts', '/Users/john/projects/myapp') * // => './src/file.ts' * * sanitizePath('C:\\Users\\john\\Documents\\project') * // => '~\\Documents\\project' (Windows) * ``` */ export declare function sanitizePath(fullPath: string, projectPath?: string): string; /** * Sanitize an index path for display * * Specifically handles index paths, showing a generic format * without exposing the full hash or system paths. * * @param indexPath - The index path to sanitize * @returns Sanitized index path description * * @example * ```typescript * sanitizeIndexPath('/Users/john/.mcp/search/indexes/abc123def456') * // => '~/.mcp/search/indexes/' * ``` */ export declare function sanitizeIndexPath(indexPath: string): string; //# sourceMappingURL=paths.d.ts.map