UNPKG

trufflehog-js

Version:

TypeScript wrapper for TruffleHog secret scanner

211 lines (181 loc) 5.67 kB
/** * Copyright (c) 2025 maloma7. All rights reserved. * SPDX-License-Identifier: MIT */ import { ExitCode } from "./types.ts"; export class TruffleHogError extends Error { public readonly exitCode: ExitCode; public override readonly cause?: Error; constructor( message: string, exitCode: ExitCode = ExitCode.ERROR, cause?: Error, ) { super(message); this.name = "TruffleHogError"; this.exitCode = exitCode; if (cause !== undefined) { this.cause = cause; } } } export class BinaryNotFoundError extends TruffleHogError { constructor(binaryPath: string, cause?: Error) { super( `TruffleHog binary not found at: ${binaryPath}`, ExitCode.ERROR, cause, ); this.name = "BinaryNotFoundError"; } } export class BinaryDownloadError extends TruffleHogError { constructor(url: string, cause?: Error) { super( `Failed to download TruffleHog binary from: ${url}`, ExitCode.ERROR, cause, ); this.name = "BinaryDownloadError"; } } export class BinaryVerificationError extends TruffleHogError { constructor(reason: string, cause?: Error) { super(`Binary verification failed: ${reason}`, ExitCode.ERROR, cause); this.name = "BinaryVerificationError"; } } export class BinaryExecutionError extends TruffleHogError { constructor(command: string, stderr?: string, cause?: Error) { const message = stderr ? `TruffleHog execution failed: ${stderr}` : `TruffleHog execution failed: ${command}`; super(message, ExitCode.ERROR, cause); this.name = "BinaryExecutionError"; } } export class ScanTimeoutError extends TruffleHogError { constructor(timeout: number, cause?: Error) { super(`Scan timed out after ${timeout}ms`, ExitCode.ERROR, cause); this.name = "ScanTimeoutError"; } } export class SecretsFoundError extends TruffleHogError { public readonly secretCount: number; constructor(secretCount: number) { super( `Found ${secretCount} secret${secretCount === 1 ? "" : "s"}`, ExitCode.SECRETS_FOUND, ); this.name = "SecretsFoundError"; this.secretCount = secretCount; } } export class GitError extends TruffleHogError { constructor(operation: string, cause?: Error) { super(`Git operation failed: ${operation}`, ExitCode.ERROR, cause); this.name = "GitError"; } } export class PlatformNotSupportedError extends TruffleHogError { constructor(platform: string, arch: string, cause?: Error) { super(`Platform not supported: ${platform}-${arch}`, ExitCode.ERROR, cause); this.name = "PlatformNotSupportedError"; } } export class ConfigurationError extends TruffleHogError { constructor(reason: string, cause?: Error) { super(`Configuration error: ${reason}`, ExitCode.ERROR, cause); this.name = "ConfigurationError"; } } export class NetworkError extends TruffleHogError { constructor(operation: string, cause?: Error) { super(`Network error during ${operation}`, ExitCode.ERROR, cause); this.name = "NetworkError"; } } export class CacheError extends TruffleHogError { constructor(operation: string, cause?: Error) { super(`Cache error during ${operation}`, ExitCode.ERROR, cause); this.name = "CacheError"; } } export class FileSystemError extends TruffleHogError { constructor(operation: string, path: string, cause?: Error) { super( `Filesystem error during ${operation}: ${path}`, ExitCode.ERROR, cause, ); this.name = "FileSystemError"; } } export function isRecoverableError(error: Error): boolean { return ( error instanceof NetworkError || error instanceof BinaryDownloadError || error instanceof CacheError || (error instanceof BinaryExecutionError && !error.message.includes("not found")) ); } export function getExitCodeFromError(error: Error): ExitCode { if (error instanceof TruffleHogError) { return error.exitCode; } return ExitCode.ERROR; } export function formatErrorForCLI( error: Error, verbose: boolean = false, ): string { if (error instanceof SecretsFoundError) { return `🚨 Secrets detected! Please remove before committing. (${error.secretCount} found)`; } if (error instanceof BinaryNotFoundError) { return verbose ? `❌ TruffleHog binary not found. Try running: bun install trufflehog-js\n${error.message}` : "❌ TruffleHog binary not found. Run: bun install trufflehog-js"; } if (error instanceof PlatformNotSupportedError) { return verbose ? `❌ Platform not supported. Set TRUFFLEHOG_BINARY_PATH to use custom binary.\n${error.message}` : "❌ Platform not supported. Set TRUFFLEHOG_BINARY_PATH for custom binary."; } if (error instanceof ScanTimeoutError) { return verbose ? `⏱️ Scan timed out. Increase timeout or check large files.\n${error.message}` : "⏱️ Scan timed out. Increase timeout or check large files."; } if (error instanceof BinaryExecutionError) { return verbose ? `❌ TruffleHog execution failed:\n${error.message}` : "❌ TruffleHog execution failed. Run with --verbose for details."; } if (error instanceof GitError) { return verbose ? `❌ Git error (not in repository or no staged files?):\n${error.message}` : "❌ Git error. Ensure you are in a git repository with staged files."; } if (verbose) { return `❌ Unexpected error:\n${error.message}`; } return "❌ Unexpected error. Run with --verbose for details."; } export function handleProcessExit( error: Error, logger?: { error: (msg: string) => void }, ): never { const exitCode = getExitCodeFromError(error); const message = formatErrorForCLI( error, Bun.env.TRUFFLEHOG_VERBOSE === "true", ); if (logger) { logger.error(message); } else { globalThis.console.error(message); } process.exit(exitCode); }