#!/usr/bin/env node
import { execFileSync } from "child_process";
import fs from "fs";
import { glob } from "glob";
const SECRET_PATTERNS = [
  {
    pattern: /lin_api_[a-zA-Z0-9]{40}/,
    name: "Linear API Key",
    envVar: "LINEAR_API_KEY"
  },
  {
    pattern: /lin_oauth_[a-zA-Z0-9]{64}/,
    name: "Linear OAuth Token",
    envVar: "LINEAR_OAUTH_TOKEN"
  },
  {
    pattern: /sk-[a-zA-Z0-9]{48}/,
    name: "OpenAI API Key",
    envVar: "OPENAI_API_KEY"
  },
  { pattern: /npm_[a-zA-Z0-9]{36}/, name: "NPM Token", envVar: "NPM_TOKEN" },
  {
    pattern: /ghp_[a-zA-Z0-9]{36}/,
    name: "GitHub Token",
    envVar: "GITHUB_TOKEN"
  },
  {
    pattern: /ghs_[a-zA-Z0-9]{36}/,
    name: "GitHub Secret",
    envVar: "GITHUB_SECRET"
  },
  {
    pattern: /pk_live_[a-zA-Z0-9]{24,}/,
    name: "Stripe Live Key",
    envVar: "STRIPE_LIVE_KEY"
  },
  {
    pattern: /sk_live_[a-zA-Z0-9]{24,}/,
    name: "Stripe Secret Key",
    envVar: "STRIPE_SECRET_KEY"
  }
];
class SecuritySecretsScanner {
  detectedSecrets = /* @__PURE__ */ new Map();
  /**
   * Scan files for hardcoded secrets
   */
  async scanForSecrets(patterns = [
    "**/*.js",
    "**/*.ts",
    "**/*.jsx",
    "**/*.tsx",
    "**/*.sh"
  ]) {
    console.log("\u{1F50D} Scanning for hardcoded secrets...\n");
    for (const pattern of patterns) {
      const files = await glob(pattern, {
        ignore: ["node_modules/**", "dist/**", "build/**", ".git/**"]
      });
      for (const file of files) {
        await this.scanFile(file);
      }
    }
    this.reportFindings();
  }
  /**
   * Scan a single file for secrets
   */
  async scanFile(filePath) {
    const content = fs.readFileSync(filePath, "utf-8");
    const lines = content.split("\n");
    lines.forEach((line, index) => {
      for (const secretPattern of SECRET_PATTERNS) {
        if (secretPattern.pattern.test(line)) {
          if (!this.detectedSecrets.has(filePath)) {
            this.detectedSecrets.set(filePath, /* @__PURE__ */ new Set());
          }
          const secrets = this.detectedSecrets.get(filePath);
          if (secrets) {
            secrets.add(
              `Line ${index + 1}: ${secretPattern.name} detected (use ${secretPattern.envVar})`
            );
          }
        }
      }
    });
  }
  /**
   * Report findings
   */
  reportFindings() {
    if (this.detectedSecrets.size === 0) {
      console.log("\u2705 No hardcoded secrets detected!\n");
      return;
    }
    console.log(
      `\u26A0\uFE0F  Found hardcoded secrets in ${this.detectedSecrets.size} files:
`
    );
    for (const [file, secrets] of this.detectedSecrets) {
      console.log(`\u{1F4C4} ${file}:`);
      for (const secret of secrets) {
        console.log(`   ${secret}`);
      }
      console.log();
    }
    console.log("\u{1F4DD} How to fix:");
    console.log("1. Replace hardcoded values with process.env.VARIABLE_NAME");
    console.log(`2. Add "import 'dotenv/config'" at the top of the file`);
    console.log("3. Add the actual values to your .env file");
    console.log("4. Never commit .env files to git\n");
  }
  /**
   * Auto-fix secrets in files
   */
  async autoFix() {
    console.log("\u{1F527} Auto-fixing hardcoded secrets...\n");
    for (const [filePath] of this.detectedSecrets) {
      let content = fs.readFileSync(filePath, "utf-8");
      let modified = false;
      if ((filePath.endsWith(".js") || filePath.endsWith(".ts")) && !content.includes("dotenv/config") && !content.includes("require('dotenv')")) {
        if (content.startsWith("#!/")) {
          const firstNewline = content.indexOf("\n");
          content = content.slice(0, firstNewline + 1) + "\nimport 'dotenv/config';\n" + content.slice(firstNewline + 1);
        } else {
          content = "import 'dotenv/config';\n\n" + content;
        }
        modified = true;
      }
      for (const pattern of SECRET_PATTERNS) {
        const regex = new RegExp(
          `(['"\`])(${pattern.pattern.source})(['"\`])`,
          "g"
        );
        const replacement = `process.env.${pattern.envVar}`;
        if (regex.test(content)) {
          content = content.replace(regex, replacement);
          modified = true;
          const varPattern = new RegExp(
            `const\\s+(\\w+)\\s*=\\s*process\\.env\\.${pattern.envVar}`
          );
          const match = content.match(varPattern);
          if (match) {
            const varName = match[1];
            const checkCode = `
if (!${varName}) {
  console.error('\u274C ${pattern.envVar} environment variable not set');
  console.log('Please set ${pattern.envVar} in your .env file or export it in your shell');
  process.exit(1);
}
`;
            const insertPos = content.indexOf(match[0]) + match[0].length;
            content = content.slice(0, insertPos) + checkCode + content.slice(insertPos);
          }
        }
      }
      if (modified) {
        fs.writeFileSync(filePath, content);
        console.log(`\u2705 Fixed ${filePath}`);
      }
    }
    console.log("\n\u{1F4CB} Next steps:");
    console.log("1. Review the changes");
    console.log("2. Add actual values to .env file");
    console.log("3. Test that everything still works");
    console.log("4. Commit the fixes\n");
  }
  /**
   * Check git history for secrets
   */
  async checkGitHistory() {
    console.log("\u{1F50D} Checking git history for secrets...\n");
    try {
      for (const pattern of SECRET_PATTERNS) {
        let result;
        try {
          const gitOutput = execFileSync(
            "git",
            [
              "log",
              "-p",
              "--all",
              `-G${pattern.pattern.source}`,
              "--format=%H %s"
            ],
            {
              encoding: "utf-8",
              stdio: "pipe"
            }
          );
          result = gitOutput.split("\n").slice(0, 20).join("\n").trim();
        } catch {
          continue;
        }
        if (result) {
          console.log(`\u26A0\uFE0F  Found ${pattern.name} in git history:`);
          console.log(result.split("\n").slice(0, 3).join("\n"));
          console.log("...\n");
        }
      }
      console.log("\u{1F4DD} To clean git history:");
      console.log("1. Use BFG Repo-Cleaner: bfg --replace-text passwords.txt");
      console.log("2. Or interactive rebase: git rebase -i <commit>");
      console.log("3. Or allow via GitHub: Check push error for allow URLs\n");
    } catch {
      console.log("Could not check git history");
    }
  }
  /**
   * Generate pre-commit hook
   */
  generatePreCommitHook() {
    const hookContent = `#!/bin/sh
# Pre-commit hook to check for hardcoded secrets

echo "\u{1F50D} Checking for hardcoded secrets..."

# Patterns to check
patterns=(
  "lin_api_[a-zA-Z0-9]{40}"
  "lin_oauth_[a-zA-Z0-9]{64}"
  "sk-[a-zA-Z0-9]{48}"
  "npm_[a-zA-Z0-9]{36}"
  "ghp_[a-zA-Z0-9]{36}"
  "pk_live_[a-zA-Z0-9]{24,}"
  "sk_live_[a-zA-Z0-9]{24,}"
)

# Check staged files
for pattern in "\${patterns[@]}"; do
  if git diff --staged --no-color | grep -E "$pattern"; then
    echo "\u274C Found hardcoded secret matching: $pattern"
    echo "Please use environment variables instead!"
    exit 1
  fi
done

echo "\u2705 No hardcoded secrets detected"
exit 0
`;
    const hookPath = ".git/hooks/pre-commit";
    fs.writeFileSync(hookPath, hookContent);
    fs.chmodSync(hookPath, "755");
    console.log("\u2705 Generated pre-commit hook at .git/hooks/pre-commit");
    console.log(
      "This will prevent committing hardcoded secrets in the future.\n"
    );
  }
}
if (import.meta.url === `file://${process.argv[1]}`) {
  const scanner = new SecuritySecretsScanner();
  const command = process.argv[2];
  (async () => {
    switch (command) {
      case "scan":
        await scanner.scanForSecrets();
        break;
      case "fix":
        await scanner.scanForSecrets();
        await scanner.autoFix();
        break;
      case "history":
        await scanner.checkGitHistory();
        break;
      case "hook":
        scanner.generatePreCommitHook();
        break;
      default:
        console.log("Usage: security-secrets-scanner [scan|fix|history|hook]");
        console.log("  scan    - Scan for hardcoded secrets");
        console.log("  fix     - Auto-fix hardcoded secrets");
        console.log("  history - Check git history for secrets");
        console.log("  hook    - Generate pre-commit hook");
    }
  })();
}
export {
  SecuritySecretsScanner
};
//# sourceMappingURL=security-secrets-scanner.js.map
