@socketsecurity/lib
Version:
Core utilities and infrastructure for Socket.dev security tools
541 lines (540 loc) • 17.7 kB
TypeScript
/**
* 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;