UNPKG

@socketsecurity/lib

Version:

Core utilities and infrastructure for Socket.dev security tools

541 lines (540 loc) 17.7 kB
/** * Options for git diff operations. * * Controls how git diff results are processed and returned. * * @example * ```typescript * // Get absolute file paths * const files = await getChangedFiles({ absolute: true }) * // => ['/path/to/repo/src/file.ts'] * * // Get relative paths with caching disabled * const files = await getChangedFiles({ cache: false }) * // => ['src/file.ts'] * * // Get files from specific directory * const files = await getChangedFiles({ cwd: '/path/to/repo/src' }) * ``` */ export interface GitDiffOptions { /** * Return absolute file paths instead of relative paths. * * @default false */ absolute?: boolean | undefined; /** * Cache git diff results to avoid repeated git subprocess calls. * * Caching is keyed by the git command and options used, so different * option combinations maintain separate cache entries. * * @default true */ cache?: boolean | undefined; /** * Working directory for git operations. * * Git operations will be run from this directory, and returned paths * will be relative to the git repository root. Symlinks are resolved * using `fs.realpathSync()`. * * @default process.cwd() */ cwd?: string | undefined; /** * Parse git porcelain format output (status codes like `M`, `A`, `??`). * * When `true`, strips the two-character status code and space from the * beginning of each line. Automatically enabled for `getChangedFiles()`. * * @default false */ porcelain?: boolean | undefined; /** * Return results as a `Set` instead of an array. * * @default false */ asSet?: boolean | undefined; /** * Additional options passed to glob matcher. * * Supports options like `dot`, `ignore`, `nocase` for filtering results. */ [key: string]: unknown; } /** * Options for filtering packages by git changes. * * Used to determine which packages in a monorepo have changed files. * * @example * ```typescript * // Filter packages with changes * const changed = filterPackagesByChanges(packages) * * // Force include all packages * const all = filterPackagesByChanges(packages, { force: true }) * * // Use custom package key * const changed = filterPackagesByChanges( * packages, * { packageKey: 'directory' } * ) * ``` */ export interface FilterPackagesByChangesOptions { /** * Force include all packages regardless of changes. * * @default false */ force?: boolean | undefined; /** * Key to access package path in package objects. * * @default 'path' */ packageKey?: string | undefined; /** * Additional options for filtering. */ [key: string]: unknown; } /** * Find git repository root by walking up from the given directory. * * Searches for a `.git` directory or file by traversing parent directories * upward until found or filesystem root is reached. Returns the original path * if no git repository is found. * * This function is exported primarily for testing purposes. * * @param startPath - Directory path to start searching from. * @returns Git repository root path, or `startPath` if not found. * * @example * ```typescript * const root = findGitRoot('/path/to/repo/src/subdir') * // => '/path/to/repo' * * const notFound = findGitRoot('/not/a/repo') * // => '/not/a/repo' * ``` */ export declare function findGitRoot(startPath: string): string; /** * Get all changed files including staged, unstaged, and untracked files. * * Uses `git status --porcelain` which returns the full working tree status * with status codes: * - `M` - Modified * - `A` - Added * - `D` - Deleted * - `??` - Untracked * - `R` - Renamed * - `C` - Copied * * This is the most comprehensive check - captures everything that differs * from the last commit, including: * - Files modified and staged with `git add` * - Files modified but not staged * - New files not yet tracked by git * * Status codes are automatically stripped from the output. * * @param options - Options controlling path format and filtering. * @returns Promise resolving to array of changed file paths. * * @example * ```typescript * // Get all changed files as relative paths * const files = await getChangedFiles() * // => ['src/foo.ts', 'src/bar.ts', 'newfile.ts'] * * // Get absolute paths * const files = await getChangedFiles({ absolute: true }) * // => ['/path/to/repo/src/foo.ts', ...] * * // Get changed files in specific directory * const files = await getChangedFiles({ cwd: '/path/to/repo/src' }) * // => ['foo.ts', 'bar.ts'] * ``` */ export declare function getChangedFiles(options?: GitDiffOptions | undefined): Promise<string[]>; /** * Get all changed files including staged, unstaged, and untracked files. * * Synchronous version of `getChangedFiles()`. Uses `git status --porcelain` * which returns the full working tree status with status codes: * - `M` - Modified * - `A` - Added * - `D` - Deleted * - `??` - Untracked * - `R` - Renamed * - `C` - Copied * * This is the most comprehensive check - captures everything that differs * from the last commit, including: * - Files modified and staged with `git add` * - Files modified but not staged * - New files not yet tracked by git * * Status codes are automatically stripped from the output. * * @param options - Options controlling path format and filtering. * @returns Array of changed file paths. * * @example * ```typescript * // Get all changed files as relative paths * const files = getChangedFilesSync() * // => ['src/foo.ts', 'src/bar.ts', 'newfile.ts'] * * // Get absolute paths * const files = getChangedFilesSync({ absolute: true }) * // => ['/path/to/repo/src/foo.ts', ...] * * // Get changed files in specific directory * const files = getChangedFilesSync({ cwd: '/path/to/repo/src' }) * // => ['foo.ts', 'bar.ts'] * ``` */ export declare function getChangedFilesSync(options?: GitDiffOptions | undefined): string[]; /** * Get unstaged modified files (changes not yet staged for commit). * * Uses `git diff --name-only` which returns only unstaged modifications * to tracked files. Does NOT include: * - Untracked files (new files not added to git) * - Staged changes (files added with `git add`) * * This is a focused check for uncommitted changes to existing tracked files. * Useful for detecting work-in-progress modifications before staging. * * @param options - Options controlling path format and filtering. * @returns Promise resolving to array of unstaged file paths. * * @example * ```typescript * // Get unstaged files * const files = await getUnstagedFiles() * // => ['src/foo.ts', 'src/bar.ts'] * * // After staging some files * await spawn('git', ['add', 'src/foo.ts']) * const files = await getUnstagedFiles() * // => ['src/bar.ts'] (foo.ts no longer included) * * // Get absolute paths * const files = await getUnstagedFiles({ absolute: true }) * // => ['/path/to/repo/src/bar.ts'] * ``` */ export declare function getUnstagedFiles(options?: GitDiffOptions | undefined): Promise<string[]>; /** * Get unstaged modified files (changes not yet staged for commit). * * Synchronous version of `getUnstagedFiles()`. Uses `git diff --name-only` * which returns only unstaged modifications to tracked files. Does NOT include: * - Untracked files (new files not added to git) * - Staged changes (files added with `git add`) * * This is a focused check for uncommitted changes to existing tracked files. * Useful for detecting work-in-progress modifications before staging. * * @param options - Options controlling path format and filtering. * @returns Array of unstaged file paths. * * @example * ```typescript * // Get unstaged files * const files = getUnstagedFilesSync() * // => ['src/foo.ts', 'src/bar.ts'] * * // After staging some files * spawnSync('git', ['add', 'src/foo.ts']) * const files = getUnstagedFilesSync() * // => ['src/bar.ts'] (foo.ts no longer included) * * // Get absolute paths * const files = getUnstagedFilesSync({ absolute: true }) * // => ['/path/to/repo/src/bar.ts'] * ``` */ export declare function getUnstagedFilesSync(options?: GitDiffOptions | undefined): string[]; /** * Get staged files ready for commit (changes added with `git add`). * * Uses `git diff --cached --name-only` which returns only staged changes. * Does NOT include: * - Unstaged modifications (changes not added with `git add`) * - Untracked files (new files not added to git) * * This is a focused check for what will be included in the next commit. * Useful for validating changes before committing or running pre-commit hooks. * * @param options - Options controlling path format and filtering. * @returns Promise resolving to array of staged file paths. * * @example * ```typescript * // Get currently staged files * const files = await getStagedFiles() * // => ['src/foo.ts'] * * // Stage more files * await spawn('git', ['add', 'src/bar.ts']) * const files = await getStagedFiles() * // => ['src/foo.ts', 'src/bar.ts'] * * // Get absolute paths * const files = await getStagedFiles({ absolute: true }) * // => ['/path/to/repo/src/foo.ts', ...] * ``` */ export declare function getStagedFiles(options?: GitDiffOptions | undefined): Promise<string[]>; /** * Get staged files ready for commit (changes added with `git add`). * * Synchronous version of `getStagedFiles()`. Uses `git diff --cached --name-only` * which returns only staged changes. Does NOT include: * - Unstaged modifications (changes not added with `git add`) * - Untracked files (new files not added to git) * * This is a focused check for what will be included in the next commit. * Useful for validating changes before committing or running pre-commit hooks. * * @param options - Options controlling path format and filtering. * @returns Array of staged file paths. * * @example * ```typescript * // Get currently staged files * const files = getStagedFilesSync() * // => ['src/foo.ts'] * * // Stage more files * spawnSync('git', ['add', 'src/bar.ts']) * const files = getStagedFilesSync() * // => ['src/foo.ts', 'src/bar.ts'] * * // Get absolute paths * const files = getStagedFilesSync({ absolute: true }) * // => ['/path/to/repo/src/foo.ts', ...] * ``` */ export declare function getStagedFilesSync(options?: GitDiffOptions | undefined): string[]; /** * Check if a file or directory has any git changes. * * Checks if the given pathname has any changes including: * - Staged modifications (added with `git add`) * - Unstaged modifications (not yet staged) * - Untracked status (new file/directory not in git) * * For directories, returns `true` if ANY file within the directory has changes. * * Symlinks in the pathname and cwd are automatically resolved using * `fs.realpathSync()` before comparison. * * @param pathname - File or directory path to check. * @param options - Options for the git status check. * @returns Promise resolving to `true` if path has any changes, `false` otherwise. * * @example * ```typescript * // Check if file is changed * const changed = await isChanged('src/foo.ts') * // => true * * // Check if directory has any changes * const changed = await isChanged('src/') * // => true (if any file in src/ is changed) * * // Check from different cwd * const changed = await isChanged( * '/path/to/repo/src/foo.ts', * { cwd: '/path/to/repo' } * ) * ``` */ export declare function isChanged(pathname: string, options?: GitDiffOptions | undefined): Promise<boolean>; /** * Check if a file or directory has any git changes. * * Synchronous version of `isChanged()`. Checks if the given pathname has * any changes including: * - Staged modifications (added with `git add`) * - Unstaged modifications (not yet staged) * - Untracked status (new file/directory not in git) * * For directories, returns `true` if ANY file within the directory has changes. * * Symlinks in the pathname and cwd are automatically resolved using * `fs.realpathSync()` before comparison. * * @param pathname - File or directory path to check. * @param options - Options for the git status check. * @returns `true` if path has any changes, `false` otherwise. * * @example * ```typescript * // Check if file is changed * const changed = isChangedSync('src/foo.ts') * // => true * * // Check if directory has any changes * const changed = isChangedSync('src/') * // => true (if any file in src/ is changed) * * // Check from different cwd * const changed = isChangedSync( * '/path/to/repo/src/foo.ts', * { cwd: '/path/to/repo' } * ) * ``` */ export declare function isChangedSync(pathname: string, options?: GitDiffOptions | undefined): boolean; /** * Check if a file or directory has unstaged changes. * * Checks if the given pathname has modifications that are not yet staged * for commit (changes not added with `git add`). Does NOT include: * - Staged changes (already added with `git add`) * - Untracked files (new files not in git) * * For directories, returns `true` if ANY file within the directory has * unstaged changes. * * Symlinks in the pathname and cwd are automatically resolved using * `fs.realpathSync()` before comparison. * * @param pathname - File or directory path to check. * @param options - Options for the git diff check. * @returns Promise resolving to `true` if path has unstaged changes, `false` otherwise. * * @example * ```typescript * // Check if file has unstaged changes * const unstaged = await isUnstaged('src/foo.ts') * // => true * * // After staging the file * await spawn('git', ['add', 'src/foo.ts']) * const unstaged = await isUnstaged('src/foo.ts') * // => false * * // Check directory * const unstaged = await isUnstaged('src/') * // => true (if any file in src/ has unstaged changes) * ``` */ export declare function isUnstaged(pathname: string, options?: GitDiffOptions | undefined): Promise<boolean>; /** * Check if a file or directory has unstaged changes. * * Synchronous version of `isUnstaged()`. Checks if the given pathname has * modifications that are not yet staged for commit (changes not added with * `git add`). Does NOT include: * - Staged changes (already added with `git add`) * - Untracked files (new files not in git) * * For directories, returns `true` if ANY file within the directory has * unstaged changes. * * Symlinks in the pathname and cwd are automatically resolved using * `fs.realpathSync()` before comparison. * * @param pathname - File or directory path to check. * @param options - Options for the git diff check. * @returns `true` if path has unstaged changes, `false` otherwise. * * @example * ```typescript * // Check if file has unstaged changes * const unstaged = isUnstagedSync('src/foo.ts') * // => true * * // After staging the file * spawnSync('git', ['add', 'src/foo.ts']) * const unstaged = isUnstagedSync('src/foo.ts') * // => false * * // Check directory * const unstaged = isUnstagedSync('src/') * // => true (if any file in src/ has unstaged changes) * ``` */ export declare function isUnstagedSync(pathname: string, options?: GitDiffOptions | undefined): boolean; /** * Check if a file or directory is staged for commit. * * Checks if the given pathname has changes staged with `git add` that will * be included in the next commit. Does NOT include: * - Unstaged modifications (changes not added with `git add`) * - Untracked files (new files not in git) * * For directories, returns `true` if ANY file within the directory is staged. * * Symlinks in the pathname and cwd are automatically resolved using * `fs.realpathSync()` before comparison. * * @param pathname - File or directory path to check. * @param options - Options for the git diff check. * @returns Promise resolving to `true` if path is staged, `false` otherwise. * * @example * ```typescript * // Check if file is staged * const staged = await isStaged('src/foo.ts') * // => false * * // Stage the file * await spawn('git', ['add', 'src/foo.ts']) * const staged = await isStaged('src/foo.ts') * // => true * * // Check directory * const staged = await isStaged('src/') * // => true (if any file in src/ is staged) * ``` */ export declare function isStaged(pathname: string, options?: GitDiffOptions | undefined): Promise<boolean>; /** * Check if a file or directory is staged for commit. * * Synchronous version of `isStaged()`. Checks if the given pathname has * changes staged with `git add` that will be included in the next commit. * Does NOT include: * - Unstaged modifications (changes not added with `git add`) * - Untracked files (new files not in git) * * For directories, returns `true` if ANY file within the directory is staged. * * Symlinks in the pathname and cwd are automatically resolved using * `fs.realpathSync()` before comparison. * * @param pathname - File or directory path to check. * @param options - Options for the git diff check. * @returns `true` if path is staged, `false` otherwise. * * @example * ```typescript * // Check if file is staged * const staged = isStagedSync('src/foo.ts') * // => false * * // Stage the file * spawnSync('git', ['add', 'src/foo.ts']) * const staged = isStagedSync('src/foo.ts') * // => true * * // Check directory * const staged = isStagedSync('src/') * // => true (if any file in src/ is staged) * ``` */ export declare function isStagedSync(pathname: string, options?: GitDiffOptions | undefined): boolean;