@docker-doctor/cli 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -4
- package/dist/cli.cjs +475 -62
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +427 -15
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +8 -17
- package/dist/index.d.mts +8 -17
- package/dist/index.mjs +1 -1
- package/dist/{src-Bt3AB-Xl.mjs → src-EqtziccA.mjs} +277 -111
- package/dist/src-EqtziccA.mjs.map +1 -0
- package/dist/{src-BUYNqQd8.cjs → src-TEhFWhpk.cjs} +277 -113
- package/dist/src-TEhFWhpk.cjs.map +1 -0
- package/package.json +2 -2
- package/dist/src-BUYNqQd8.cjs.map +0 -1
- package/dist/src-Bt3AB-Xl.mjs.map +0 -1
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.cjs","names":["border","findRule","path","fs","allRules","runDockerfileRules","parseDockerfile","runComposeRules","parseCompose","findRule","Command","packageJson","loadConfig","discoverProject","calculateScore","os","toJsonReport"],"sources":["../src/formatters/terminal.ts","../src/cli.ts"],"sourcesContent":["import { setTimeout } from \"node:timers/promises\";\n\nimport type { Diagnostic, ProjectInfo } from \"@docker-doctor/core\";\nimport { findRule } from \"@docker-doctor/core\";\nimport chalk from \"chalk\";\n\nconst printCodeFrame = (\n content: string | undefined,\n line: number | undefined,\n severityColor: (msg: string) => string\n): void => {\n if (!content || !line) {\n return;\n }\n const lines = content.split(/\\r?\\n/u);\n const start = Math.max(1, line - 1);\n const end = Math.min(lines.length, line + 1);\n\n for (let i = start; i <= end; i += 1) {\n const rawLine = lines[i - 1];\n const isTarget = i === line;\n const lineNumberStr = String(i).padStart(5, \" \");\n if (isTarget) {\n console.log(\n ` ${severityColor(\">\")} ${chalk.bold(lineNumberStr)} │ ${chalk.white(rawLine)}`\n );\n } else {\n console.log(` ${chalk.dim(lineNumberStr)} │ ${chalk.dim(rawLine)}`);\n }\n }\n console.log();\n};\n\nconst printDiscoveredFiles = (project: ProjectInfo): void => {\n console.log(`\\nDiscovered Files:`);\n console.log(\n ` Dockerfile(s): ${project.dockerfiles.length ? project.dockerfiles.map((f) => chalk.cyan(f)).join(\", \") : chalk.dim(\"None\")}`\n );\n console.log(\n ` Compose file(s): ${project.composeFiles.length ? project.composeFiles.map((f) => chalk.cyan(f)).join(\", \") : chalk.dim(\"None\")}`\n );\n};\n\nconst printDiagnostics = (\n diagnostics: Diagnostic[],\n verbose: boolean,\n fileContents: Record<string, string>,\n categoryIssueCounts: Record<string, number>\n): void => {\n if (diagnostics.length === 0) {\n console.log(\n `\\n${chalk.green.bold(\"✔ No issues found! Your Docker setup looks healthy.\")}`\n );\n return;\n }\n\n if (!verbose) {\n console.log(`\\n All ${chalk.bold(diagnostics.length)} issues\\n`);\n\n const categories = [\n \"Security\",\n \"Performance\",\n \"Best Practices\",\n \"Compose\",\n \"Image Size\",\n ];\n\n for (const cat of categories) {\n const count = categoryIssueCounts[cat];\n const issueLabel = count === 1 ? \"1 issue\" : `${count} issues`;\n console.log(` ${cat} › ${chalk.dim(issueLabel)}`);\n }\n\n console.log(\n `\\n Run ${chalk.cyan(\"docker-doctor --verbose\")} to list every error and warning`\n );\n\n // Migration-scale checks\n const ruleCounts: Record<string, number> = {};\n for (const d of diagnostics) {\n ruleCounts[d.rule] = (ruleCounts[d.rule] || 0) + 1;\n }\n const migrationRules = Object.entries(ruleCounts).filter(\n ([_, count]) => count >= 5\n );\n if (migrationRules.length > 0) {\n console.log();\n console.log(\n ` ${chalk.yellow(\"⚠ Migration-scale change: sample before you sweep\")}`\n );\n for (const [rule, count] of migrationRules) {\n console.log(` ${chalk.cyan(rule)} ×${count} across ${count} files`);\n }\n console.log(\n ` Fixing all of them at once is hard to review and prone to`\n );\n console.log(\n ` subtle mistakes across the whole repo. Fix a representative`\n );\n console.log(\n ` few first and confirm the recipe holds. Then get the code`\n );\n console.log(` owner's sign-off before changing the rest.`);\n console.log(` Scope it down one area at a time: docker-doctor <path>`);\n }\n return;\n }\n\n console.log(`\\nFound ${chalk.bold(diagnostics.length)} issue(s):`);\n\n // Group by file\n const filesGrouped: Record<string, Diagnostic[]> = {};\n for (const d of diagnostics) {\n if (!filesGrouped[d.file]) {\n filesGrouped[d.file] = [];\n }\n filesGrouped[d.file].push(d);\n }\n\n for (const [file, fileDiags] of Object.entries(filesGrouped)) {\n console.log(`\\n${chalk.underline.bold(file)}`);\n for (const d of fileDiags) {\n let sevColor = chalk.cyan;\n let prefix = \"ℹ INFO\";\n if (d.severity === \"error\") {\n sevColor = chalk.red.bold;\n prefix = \"✖ ERROR\";\n } else if (d.severity === \"warning\") {\n sevColor = chalk.yellow;\n prefix = \"⚠ WARN\";\n }\n\n const lineInfo = d.line ? `:${d.line}` : \"\";\n console.log(` ${sevColor(prefix)} [${chalk.dim(d.rule)}]${lineInfo}`);\n\n // Print Code Frame\n const content = fileContents[file];\n printCodeFrame(content, d.line, sevColor);\n\n console.log(` ${chalk.white(d.message)}`);\n console.log(` ${chalk.dim(\"Help:\")} ${d.help}`);\n console.log();\n }\n }\n};\n\nconst getWhaleMascot = (\n score: number,\n border: (text: string) => string\n): string[] => {\n let eyes = \"x x\";\n let spout = \" \";\n if (score >= 75) {\n eyes = \"◠ ◠\";\n spout = chalk.cyan(' \":\" ');\n } else if (score >= 50) {\n eyes = \"• •\";\n spout = chalk.cyan(\" . \");\n }\n\n return [\n spout,\n border(\" .---. \"),\n border(`( ${eyes} )>`),\n border(\" \\\\___/ \"),\n ];\n};\n\nconst easeOutCubic = (x: number): number => 1 - (1 - x) ** 3;\n\nconst printScoreBox = async (\n score: number,\n label: string,\n categoryIssueCounts: Record<string, number>\n): Promise<void> => {\n const { isTTY } = process.stdout;\n const shouldAnimate =\n isTTY &&\n !process.env.CI &&\n !process.env.NO_ANIMATION &&\n process.env.TERM !== \"dumb\" &&\n process.env.NODE_ENV !== \"test\";\n\n let scoreColor = chalk.red.bold;\n if (score >= 90) {\n scoreColor = chalk.green.bold;\n } else if (score >= 75) {\n scoreColor = chalk.yellow.bold;\n } else if (score >= 50) {\n scoreColor = chalk.magenta.bold;\n }\n const border = scoreColor;\n const whaleLines = getWhaleMascot(score, border);\n\n const totalIssues = Object.values(categoryIssueCounts).reduce(\n (a, b) => a + b,\n 0\n );\n const shareUrl = `https://github.com/PunGrumpy/docker-doctor/share?s=${score}&w=${totalIssues}`;\n\n if (shouldAnimate) {\n const frameCount = 20;\n const frameDelay = 15;\n\n // Hide cursor\n process.stdout.write(\"\\u001B[?25l\");\n try {\n for (let frame = 0; frame <= frameCount; frame += 1) {\n const progress = easeOutCubic(frame / frameCount);\n const currentScore = Math.round(score * progress);\n const filledBlocks = Math.round(currentScore / 2);\n const emptyBlocks = 50 - filledBlocks;\n\n const bar =\n scoreColor(\"█\".repeat(filledBlocks)) +\n chalk.dim(\"░\".repeat(emptyBlocks));\n\n if (frame > 0) {\n // Move cursor up 4 lines and carriage return\n process.stdout.write(\"\\u001B[4A\\r\");\n } else {\n // print an extra newline first to start\n console.log();\n }\n\n process.stdout.write(\n ` ${whaleLines[0]} ${scoreColor(`${currentScore} / 100`)} ${scoreColor(label)}\\n` +\n ` ${whaleLines[1]} ${bar}\\n` +\n ` ${whaleLines[2]} ${chalk.dim(\"Docker Doctor (https://github.com/PunGrumpy/docker-doctor)\")}\\n` +\n ` ${whaleLines[3]}\\n`\n );\n\n if (frame < frameCount) {\n // eslint-disable-next-line no-await-in-loop\n await setTimeout(frameDelay);\n }\n }\n } finally {\n // Show cursor\n process.stdout.write(\"\\u001B[?25h\");\n }\n } else {\n // Non-TTY fall back to static print\n const filledBlocks = Math.round(score / 2);\n const emptyBlocks = 50 - filledBlocks;\n const bar =\n scoreColor(\"█\".repeat(filledBlocks)) + chalk.dim(\"░\".repeat(emptyBlocks));\n\n console.log(\n `\\n ${whaleLines[0]} ${scoreColor(`${score} / 100`)} ${scoreColor(label)}`\n );\n console.log(` ${whaleLines[1]} ${bar}`);\n console.log(\n ` ${whaleLines[2]} ${chalk.dim(\"Docker Doctor (https://github.com/PunGrumpy/docker-doctor)\")}`\n );\n console.log(` ${whaleLines[3]}`);\n }\n\n console.log(\n `\\n ${chalk.dim(\"────────────────────────────────────────────────────────────\")}\\n`\n );\n console.log(` Share: ${chalk.cyan(shareUrl)}`);\n console.log(` Tell others how you did on socials\\n`);\n console.log(\n ` Docs: ${chalk.cyan(\"https://github.com/PunGrumpy/docker-doctor/docs\")}`\n );\n console.log(` Learn more about fixing issues, setting up CI/CD, and`);\n console.log(` configuring rules with a config file\\n`);\n console.log(\n ` GitHub: ${chalk.cyan(\"https://github.com/PunGrumpy/docker-doctor\")}`\n );\n console.log(` Report issues and star the repository!`);\n};\n\nexport const formatTerminal = async (\n diagnostics: Diagnostic[],\n score: number,\n label: string,\n project: ProjectInfo,\n verbose = false,\n fileContents: Record<string, string> = {}\n): Promise<void> => {\n if (verbose) {\n console.log(`\\n${chalk.bold(\"Docker Doctor Diagnostics\")}`);\n console.log(`=================================`);\n printDiscoveredFiles(project);\n }\n\n // Calculate scores per category once\n const categoryIssueCounts: Record<string, number> = {\n \"Best Practices\": 0,\n Compose: 0,\n \"Image Size\": 0,\n Performance: 0,\n Security: 0,\n };\n\n for (const d of diagnostics) {\n const ruleDef = findRule(d.rule);\n const category = ruleDef?.category || \"Best Practices\";\n categoryIssueCounts[category] = (categoryIssueCounts[category] || 0) + 1;\n }\n\n printDiagnostics(diagnostics, verbose, fileContents, categoryIssueCounts);\n\n await printScoreBox(score, label, categoryIssueCounts);\n};\n","import fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport readline from \"node:readline\";\nimport { setTimeout } from \"node:timers/promises\";\n\nimport type { Diagnostic, RuleSeverity } from \"@docker-doctor/core\";\nimport {\n discoverProject,\n parseDockerfile,\n parseCompose,\n runDockerfileRules,\n runComposeRules,\n calculateScore,\n loadConfig,\n allRules,\n findRule,\n toJsonReport,\n} from \"@docker-doctor/core\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\n\nimport packageJson from \"../package.json\" with { type: \"json\" };\nimport { formatTerminal } from \"./formatters/terminal\";\n\ninterface KeypressKey {\n name?: string;\n ctrl?: boolean;\n meta?: boolean;\n shift?: boolean;\n}\n\nconst askConfirm = (question: string, defaultYes = false): Promise<boolean> => {\n const isRaw = process.stdin.isTTY;\n if (!isRaw) {\n return Promise.resolve(defaultYes);\n }\n\n /* eslint-disable promise/avoid-new */\n return new Promise((resolve) => {\n let value = defaultYes;\n\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n // Hide cursor during prompt\n process.stdout.write(\"\\u001B[?25l\");\n\n const render = (firstTime = false) => {\n if (!firstTime) {\n process.stdout.write(\"\\u001B[3A\\r\");\n }\n\n process.stdout.write(\n `\\r\\u001B[K ${chalk.green(\"✔\")} ${chalk.bold(question)}\\n`\n );\n\n // Print options vertically\n const yesPrefix = value ? chalk.cyan(\"❯ \") : \" \";\n const yesText = value ? chalk.cyan.bold(\"Yes\") : chalk.dim(\"Yes\");\n process.stdout.write(`\\r\\u001B[K${yesPrefix}${yesText}\\n`);\n\n const noPrefix = value ? \" \" : chalk.cyan(\"❯ \");\n const noText = value ? chalk.dim(\"No\") : chalk.cyan.bold(\"No\");\n process.stdout.write(`\\r\\u001B[K${noPrefix}${noText}\\n`);\n };\n\n render(true);\n\n const handleKeypress = (str: string, key: KeypressKey) => {\n const cleanup = () => {\n process.stdin.removeListener(\"keypress\", handleKeypress);\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(false);\n }\n process.stdin.pause();\n process.stdout.write(\"\\u001B[?25h\");\n };\n\n if (\n key.name === \"left\" ||\n key.name === \"right\" ||\n key.name === \"up\" ||\n key.name === \"down\" ||\n key.name === \"h\" ||\n key.name === \"l\" ||\n key.name === \"j\" ||\n key.name === \"k\"\n ) {\n value = !value;\n render();\n } else if (str === \"y\" || str === \"Y\") {\n value = true;\n render();\n } else if (str === \"n\" || str === \"N\") {\n value = false;\n render();\n } else if (\n key.name === \"return\" ||\n key.name === \"enter\" ||\n str === \"\\r\" ||\n str === \"\\n\"\n ) {\n cleanup();\n // Overwrite and resolve vertical layout cleanly\n process.stdout.write(\"\\u001B[3A\\r\\u001B[K\");\n process.stdout.write(\n ` ${chalk.green(\"✔\")} ${chalk.bold(question)} › ${value ? chalk.cyan(\"Yes\") : chalk.dim(\"No\")}\\n`\n );\n process.stdout.write(\"\\r\\u001B[K\\n\");\n process.stdout.write(\"\\r\\u001B[K\\n\");\n process.stdout.write(\"\\u001B[2A\");\n resolve(value);\n } else if (key.ctrl && key.name === \"c\") {\n cleanup();\n process.stdout.write(\"\\n\");\n process.exit(130);\n }\n };\n\n process.stdin.on(\"keypress\", handleKeypress);\n });\n /* eslint-enable promise/avoid-new */\n};\n\nconst askSelect = (\n question: string,\n options: string[],\n defaultIndex = 0\n): Promise<number> => {\n const isRaw = process.stdin.isTTY;\n if (!isRaw) {\n return Promise.resolve(defaultIndex);\n }\n\n /* eslint-disable promise/avoid-new */\n return new Promise((resolve) => {\n let index = defaultIndex;\n\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n // Hide cursor during prompt\n process.stdout.write(\"\\u001B[?25l\");\n\n const render = (firstTime = false) => {\n if (!firstTime) {\n // Move back up to overwrite previous render\n process.stdout.write(`\\u001B[${options.length + 1}A\\r`);\n }\n\n process.stdout.write(\n `\\r\\u001B[K ${chalk.green(\"✔\")} ${chalk.bold(question)}\\n`\n );\n\n // Print options\n let i = 0;\n for (const option of options) {\n const isSelected = i === index;\n const prefix = isSelected ? chalk.cyan(\"❯ \") : \" \";\n const text = isSelected ? chalk.cyan.bold(option) : chalk.dim(option);\n process.stdout.write(`\\r\\u001B[K${prefix}${text}\\n`);\n i += 1;\n }\n };\n\n render(true);\n\n const handleKeypress = (str: string, key: KeypressKey) => {\n const cleanup = () => {\n process.stdin.removeListener(\"keypress\", handleKeypress);\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(false);\n }\n process.stdin.pause();\n process.stdout.write(\"\\u001B[?25h\");\n };\n\n if (key.name === \"up\" || key.name === \"k\") {\n index = (index - 1 + options.length) % options.length;\n render();\n } else if (key.name === \"down\" || key.name === \"j\") {\n index = (index + 1) % options.length;\n render();\n } else if (\n key.name === \"return\" ||\n key.name === \"enter\" ||\n str === \"\\r\" ||\n str === \"\\n\"\n ) {\n cleanup();\n // Overwrite and resolve\n process.stdout.write(`\\u001B[${options.length + 1}A\\r\\u001B[K`);\n process.stdout.write(\n ` ${chalk.green(\"✔\")} ${chalk.bold(question)} › ${chalk.cyan(options[index])}\\n`\n );\n for (const _ of options) {\n process.stdout.write(\"\\r\\u001B[K\\n\");\n }\n process.stdout.write(`\\u001B[${options.length}A`);\n resolve(index);\n } else if (key.ctrl && key.name === \"c\") {\n cleanup();\n process.stdout.write(\"\\n\");\n process.exit(130);\n }\n };\n\n process.stdin.on(\"keypress\", handleKeypress);\n });\n /* eslint-enable promise/avoid-new */\n};\n\nconst runInteractiveWizard = async (): Promise<void> => {\n try {\n const addGhActions = await askConfirm(\n \"Add Docker Doctor to GitHub Actions?\"\n );\n if (addGhActions) {\n const workflowDir = path.resolve(\".github/workflows\");\n await fs.mkdir(workflowDir, { recursive: true });\n const workflowPath = path.join(workflowDir, \"docker-doctor.yml\");\n const workflowYaml = `name: Docker Doctor Scan\non:\n push:\n branches: [ main, master ]\n pull_request:\n branches: [ main, master ]\njobs:\n docker-doctor:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Setup Bun\n uses: oven-sh/setup-bun@v2\n - name: Install dependencies\n run: bun install\n - name: Run docker-doctor\n run: bunx docker-doctor .\n`;\n await fs.writeFile(workflowPath, workflowYaml, \"utf-8\");\n console.log(\n `\\n ${chalk.green(\"✨\")} Created ${chalk.cyan(\".github/workflows/docker-doctor.yml\")}!`\n );\n console.log(\n ` Scan every pull request to prevent new Docker issues while you fix the backlog.`\n );\n }\n\n const nextChoice = await askSelect(\"What would you like to do next?\", [\n \"View rules list\",\n \"Skip\",\n ]);\n\n if (nextChoice === 0) {\n console.log(`\\n ${chalk.bold(\"Available Rules:\")}`);\n for (const r of allRules) {\n console.log(\n ` - ${chalk.cyan(r.key)}: ${r.message} (${chalk.dim(r.category)})`\n );\n }\n }\n } catch {\n // Ignore prompt errors\n }\n};\n\nconst runRulesEngine = async (\n rootDir: string,\n project: { dockerfiles: string[]; composeFiles: string[] },\n rulesConfig: Record<string, RuleSeverity> | undefined,\n projectFilesList: string[],\n fileContents: Record<string, string>,\n options: { score?: boolean; json?: boolean },\n setStatus: (text: string) => void\n): Promise<Diagnostic[]> => {\n const diagnostics: Diagnostic[] = [];\n\n const isSilent = options.score || options.json;\n\n if (process.stdout.isTTY && !isSilent) {\n setStatus(`Analyzing ${project.dockerfiles.length} Dockerfile(s)...`);\n await setTimeout(100);\n }\n\n // 1. Scan Dockerfiles in parallel\n const dockerfileResults = await Promise.all(\n project.dockerfiles.map(async (df) => {\n const fullPath = path.join(rootDir, df);\n try {\n const content = await fs.readFile(fullPath, \"utf-8\");\n fileContents[df] = content;\n const instructions = parseDockerfile(content);\n return runDockerfileRules(\n instructions,\n df,\n projectFilesList,\n rulesConfig\n );\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`Failed to analyze Dockerfile ${df}: ${msg}`);\n return [];\n }\n })\n );\n for (const diags of dockerfileResults) {\n diagnostics.push(...diags);\n }\n\n if (process.stdout.isTTY && !isSilent) {\n setStatus(`Analyzing ${project.composeFiles.length} Compose file(s)...`);\n await setTimeout(100);\n }\n\n // 2. Scan Compose files in parallel\n const composeResults = await Promise.all(\n project.composeFiles.map(async (cf) => {\n const fullPath = path.join(rootDir, cf);\n try {\n const content = await fs.readFile(fullPath, \"utf-8\");\n fileContents[cf] = content;\n const composeObj = parseCompose(content, cf);\n return runComposeRules(composeObj, cf, rulesConfig);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`Failed to analyze Compose file ${cf}: ${msg}`);\n return [];\n }\n })\n );\n for (const diags of composeResults) {\n diagnostics.push(...diags);\n }\n\n return diagnostics;\n};\n\nconst filterDiagnostics = (\n diagnostics: Diagnostic[],\n categories?: Record<string, RuleSeverity>\n): Diagnostic[] => {\n if (!categories) {\n return diagnostics;\n }\n return diagnostics.filter((d) => {\n const ruleDef = findRule(d.rule);\n if (ruleDef) {\n const catSeverity = categories[ruleDef.category];\n if (catSeverity === \"off\") {\n return false;\n }\n }\n return true;\n });\n};\n\nconst program = new Command();\n\nprogram\n .name(\"docker-doctor\")\n .description(\"Static analysis for Dockerfile and Docker Compose files\")\n .version(packageJson.version, \"-V, --version\", \"display the version number\");\n\n// Default scan command\nprogram\n .argument(\"[dir]\", \"directory to scan\", \".\")\n .option(\"-v, --verbose\", \"show verbose diagnostics description\", false)\n .option(\"-s, --score\", \"only output numeric health score\", false)\n .option(\"-j, --json\", \"output results as JSON report\", false)\n .option(\"-c, --config <path>\", \"custom config file path\")\n .action(async (dir, options) => {\n const isSilent = options.score || options.json;\n\n // Helper to safely show terminal cursor\n const restoreCursor = (): void => {\n if (process.stdout.isTTY && !isSilent) {\n process.stdout.write(\"\\u001B[?25h\");\n }\n };\n\n // Set signal handlers to restore cursor on aborts\n process.on(\"exit\", restoreCursor);\n process.once(\"SIGINT\", () => {\n restoreCursor();\n process.exit(130);\n });\n process.once(\"SIGTERM\", () => {\n restoreCursor();\n process.exit(143);\n });\n\n try {\n const rootDir = path.resolve(dir);\n const startTime = Date.now();\n\n let statusText = \"Discovering workspace...\";\n const spinnerFrames = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n let frameIndex = 0;\n let spinnerInterval: NodeJS.Timeout | null = null;\n\n const setStatus = (text: string) => {\n statusText = text;\n };\n\n if (process.stdout.isTTY && !isSilent) {\n // Hide cursor during progress/spinner\n process.stdout.write(\"\\u001B[?25l\");\n process.stdout.write(`${chalk.cyan(spinnerFrames[0])} ${statusText}`);\n spinnerInterval = setInterval(() => {\n process.stdout.write(\n `\\r\\u001B[K${chalk.cyan(spinnerFrames[frameIndex])} ${statusText}`\n );\n frameIndex = (frameIndex + 1) % spinnerFrames.length;\n }, 80);\n }\n\n try {\n if (process.stdout.isTTY && !isSilent) {\n await setTimeout(150);\n }\n\n setStatus(\"Loading configuration...\");\n // Load config first\n const config = await loadConfig(rootDir, options.config);\n\n setStatus(\"Scanning workspace files...\");\n // Project discovery\n const project = await discoverProject(rootDir);\n\n // Collect all diagnostics\n const fileContents: Record<string, string> = {};\n\n const projectFilesList = [\n ...project.dockerfiles,\n ...project.composeFiles,\n ...(project.dockerignores || []),\n ];\n\n const diagnostics = await runRulesEngine(\n rootDir,\n project,\n config.rules,\n projectFilesList,\n fileContents,\n options,\n setStatus\n );\n\n // Filter by category config if needed\n const filteredDiagnostics = filterDiagnostics(\n diagnostics,\n config.categories\n );\n\n // Calculate score\n const { score, label } = calculateScore(filteredDiagnostics);\n\n const duration = ((Date.now() - startTime) / 1000).toFixed(1);\n const concurrency = os.cpus().length;\n\n if (spinnerInterval !== null) {\n clearInterval(spinnerInterval);\n spinnerInterval = null;\n // Clear spinner line and restore cursor\n process.stdout.write(\"\\r\\u001B[K\\u001B[?25h\");\n }\n\n if (process.stdout.isTTY && !isSilent) {\n console.log(\n `${chalk.green(\"✔\")} Scanned ${projectFilesList.length} files in ${duration}s [~${concurrency} workers]`\n );\n }\n\n if (options.score) {\n console.log(score);\n process.exit(score < 50 ? 1 : 0);\n } else if (options.json) {\n const report = toJsonReport(\n filteredDiagnostics,\n score,\n label,\n project\n );\n console.log(JSON.stringify(report, null, 2));\n const hasErrors = filteredDiagnostics.some(\n (d) => d.severity === \"error\"\n );\n process.exit(hasErrors ? 1 : 0);\n } else {\n await formatTerminal(\n filteredDiagnostics,\n score,\n label,\n project,\n options.verbose,\n fileContents\n );\n\n // Exit with non-zero code if there are any error severity diagnostics\n const hasErrors = filteredDiagnostics.some(\n (d) => d.severity === \"error\"\n );\n\n if (process.stdout.isTTY && process.stdin.isTTY) {\n await runInteractiveWizard();\n }\n process.exit(hasErrors ? 1 : 0);\n }\n } finally {\n if (spinnerInterval !== null) {\n clearInterval(spinnerInterval);\n process.stdout.write(\"\\r\\u001B[K\\u001B[?25h\");\n }\n }\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`Error: ${msg}`);\n process.exit(1);\n }\n });\n\n// Rules subcommand group\nconst rules = program\n .command(\"rules\")\n .description(\"manage and list configuration rules\");\n\nrules\n .command(\"list\")\n .description(\"list all available rules\")\n .action(() => {\n console.log(\"\\nAvailable Rules:\");\n console.log(\"================\\n\");\n for (const rule of allRules) {\n console.log(`- ${rule.key} (${rule.category})`);\n console.log(` Default Severity: ${rule.defaultSeverity}`);\n console.log(` Description: ${rule.message}\\n`);\n }\n });\n\nrules\n .command(\"explain <rule>\")\n .description(\"explain a specific rule in detail\")\n .action((ruleKey) => {\n const rule = findRule(ruleKey);\n if (!rule) {\n console.error(`Rule '${ruleKey}' not found.`);\n process.exit(1);\n }\n console.log(`\\nRule: ${rule.key}`);\n console.log(`Category: ${rule.category}`);\n console.log(`Default Severity: ${rule.defaultSeverity}`);\n console.log(`Description: ${rule.message}`);\n console.log(`Help / Fix: ${rule.help}\\n`);\n });\n\nprogram.parse(process.argv);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.cjs","names":["styles","process","os","tty","border","findRule","path","fs","allRules","runDockerfileRules","parseDockerfile","runComposeRules","parseCompose","findRule","Command","packageJson","loadConfig","discoverProject","calculateScore","os","toJsonReport"],"sources":["../../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js","../../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/supports-color/index.js","../../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/utilities.js","../../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/index.js","../src/formatters/terminal.ts","../src/cli.ts"],"sourcesContent":["const ANSI_BACKGROUND_OFFSET = 10;\n\nconst wrapAnsi16 = (offset = 0) => code => `\\u001B[${code + offset}m`;\n\nconst wrapAnsi256 = (offset = 0) => code => `\\u001B[${38 + offset};5;${code}m`;\n\nconst wrapAnsi16m = (offset = 0) => (red, green, blue) => `\\u001B[${38 + offset};2;${red};${green};${blue}m`;\n\nconst styles = {\n\tmodifier: {\n\t\treset: [0, 0],\n\t\t// 21 isn't widely supported and 22 does the same thing\n\t\tbold: [1, 22],\n\t\tdim: [2, 22],\n\t\titalic: [3, 23],\n\t\tunderline: [4, 24],\n\t\toverline: [53, 55],\n\t\tinverse: [7, 27],\n\t\thidden: [8, 28],\n\t\tstrikethrough: [9, 29],\n\t},\n\tcolor: {\n\t\tblack: [30, 39],\n\t\tred: [31, 39],\n\t\tgreen: [32, 39],\n\t\tyellow: [33, 39],\n\t\tblue: [34, 39],\n\t\tmagenta: [35, 39],\n\t\tcyan: [36, 39],\n\t\twhite: [37, 39],\n\n\t\t// Bright color\n\t\tblackBright: [90, 39],\n\t\tgray: [90, 39], // Alias of `blackBright`\n\t\tgrey: [90, 39], // Alias of `blackBright`\n\t\tredBright: [91, 39],\n\t\tgreenBright: [92, 39],\n\t\tyellowBright: [93, 39],\n\t\tblueBright: [94, 39],\n\t\tmagentaBright: [95, 39],\n\t\tcyanBright: [96, 39],\n\t\twhiteBright: [97, 39],\n\t},\n\tbgColor: {\n\t\tbgBlack: [40, 49],\n\t\tbgRed: [41, 49],\n\t\tbgGreen: [42, 49],\n\t\tbgYellow: [43, 49],\n\t\tbgBlue: [44, 49],\n\t\tbgMagenta: [45, 49],\n\t\tbgCyan: [46, 49],\n\t\tbgWhite: [47, 49],\n\n\t\t// Bright color\n\t\tbgBlackBright: [100, 49],\n\t\tbgGray: [100, 49], // Alias of `bgBlackBright`\n\t\tbgGrey: [100, 49], // Alias of `bgBlackBright`\n\t\tbgRedBright: [101, 49],\n\t\tbgGreenBright: [102, 49],\n\t\tbgYellowBright: [103, 49],\n\t\tbgBlueBright: [104, 49],\n\t\tbgMagentaBright: [105, 49],\n\t\tbgCyanBright: [106, 49],\n\t\tbgWhiteBright: [107, 49],\n\t},\n};\n\nexport const modifierNames = Object.keys(styles.modifier);\nexport const foregroundColorNames = Object.keys(styles.color);\nexport const backgroundColorNames = Object.keys(styles.bgColor);\nexport const colorNames = [...foregroundColorNames, ...backgroundColorNames];\n\nfunction assembleStyles() {\n\tconst codes = new Map();\n\n\tfor (const [groupName, group] of Object.entries(styles)) {\n\t\tfor (const [styleName, style] of Object.entries(group)) {\n\t\t\tstyles[styleName] = {\n\t\t\t\topen: `\\u001B[${style[0]}m`,\n\t\t\t\tclose: `\\u001B[${style[1]}m`,\n\t\t\t};\n\n\t\t\tgroup[styleName] = styles[styleName];\n\n\t\t\tcodes.set(style[0], style[1]);\n\t\t}\n\n\t\tObject.defineProperty(styles, groupName, {\n\t\t\tvalue: group,\n\t\t\tenumerable: false,\n\t\t});\n\t}\n\n\tObject.defineProperty(styles, 'codes', {\n\t\tvalue: codes,\n\t\tenumerable: false,\n\t});\n\n\tstyles.color.close = '\\u001B[39m';\n\tstyles.bgColor.close = '\\u001B[49m';\n\n\tstyles.color.ansi = wrapAnsi16();\n\tstyles.color.ansi256 = wrapAnsi256();\n\tstyles.color.ansi16m = wrapAnsi16m();\n\tstyles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);\n\tstyles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);\n\tstyles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);\n\n\t// From https://github.com/Qix-/color-convert/blob/3f0e0d4e92e235796ccb17f6e85c72094a651f49/conversions.js\n\tObject.defineProperties(styles, {\n\t\trgbToAnsi256: {\n\t\t\tvalue(red, green, blue) {\n\t\t\t\t// We use the extended greyscale palette here, with the exception of\n\t\t\t\t// black and white. normal palette only has 4 greyscale shades.\n\t\t\t\tif (red === green && green === blue) {\n\t\t\t\t\tif (red < 8) {\n\t\t\t\t\t\treturn 16;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (red > 248) {\n\t\t\t\t\t\treturn 231;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn Math.round(((red - 8) / 247) * 24) + 232;\n\t\t\t\t}\n\n\t\t\t\treturn 16\n\t\t\t\t\t+ (36 * Math.round(red / 255 * 5))\n\t\t\t\t\t+ (6 * Math.round(green / 255 * 5))\n\t\t\t\t\t+ Math.round(blue / 255 * 5);\n\t\t\t},\n\t\t\tenumerable: false,\n\t\t},\n\t\thexToRgb: {\n\t\t\tvalue(hex) {\n\t\t\t\tconst matches = /[a-f\\d]{6}|[a-f\\d]{3}/i.exec(hex.toString(16));\n\t\t\t\tif (!matches) {\n\t\t\t\t\treturn [0, 0, 0];\n\t\t\t\t}\n\n\t\t\t\tlet [colorString] = matches;\n\n\t\t\t\tif (colorString.length === 3) {\n\t\t\t\t\tcolorString = [...colorString].map(character => character + character).join('');\n\t\t\t\t}\n\n\t\t\t\tconst integer = Number.parseInt(colorString, 16);\n\n\t\t\t\treturn [\n\t\t\t\t\t/* eslint-disable no-bitwise */\n\t\t\t\t\t(integer >> 16) & 0xFF,\n\t\t\t\t\t(integer >> 8) & 0xFF,\n\t\t\t\t\tinteger & 0xFF,\n\t\t\t\t\t/* eslint-enable no-bitwise */\n\t\t\t\t];\n\t\t\t},\n\t\t\tenumerable: false,\n\t\t},\n\t\thexToAnsi256: {\n\t\t\tvalue: hex => styles.rgbToAnsi256(...styles.hexToRgb(hex)),\n\t\t\tenumerable: false,\n\t\t},\n\t\tansi256ToAnsi: {\n\t\t\tvalue(code) {\n\t\t\t\tif (code < 8) {\n\t\t\t\t\treturn 30 + code;\n\t\t\t\t}\n\n\t\t\t\tif (code < 16) {\n\t\t\t\t\treturn 90 + (code - 8);\n\t\t\t\t}\n\n\t\t\t\tlet red;\n\t\t\t\tlet green;\n\t\t\t\tlet blue;\n\n\t\t\t\tif (code >= 232) {\n\t\t\t\t\tred = (((code - 232) * 10) + 8) / 255;\n\t\t\t\t\tgreen = red;\n\t\t\t\t\tblue = red;\n\t\t\t\t} else {\n\t\t\t\t\tcode -= 16;\n\n\t\t\t\t\tconst remainder = code % 36;\n\n\t\t\t\t\tred = Math.floor(code / 36) / 5;\n\t\t\t\t\tgreen = Math.floor(remainder / 6) / 5;\n\t\t\t\t\tblue = (remainder % 6) / 5;\n\t\t\t\t}\n\n\t\t\t\tconst value = Math.max(red, green, blue) * 2;\n\n\t\t\t\tif (value === 0) {\n\t\t\t\t\treturn 30;\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-bitwise\n\t\t\t\tlet result = 30 + ((Math.round(blue) << 2) | (Math.round(green) << 1) | Math.round(red));\n\n\t\t\t\tif (value === 2) {\n\t\t\t\t\tresult += 60;\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t},\n\t\t\tenumerable: false,\n\t\t},\n\t\trgbToAnsi: {\n\t\t\tvalue: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),\n\t\t\tenumerable: false,\n\t\t},\n\t\thexToAnsi: {\n\t\t\tvalue: hex => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),\n\t\t\tenumerable: false,\n\t\t},\n\t});\n\n\treturn styles;\n}\n\nconst ansiStyles = assembleStyles();\n\nexport default ansiStyles;\n","import process from 'node:process';\nimport os from 'node:os';\nimport tty from 'node:tty';\n\n// From: https://github.com/sindresorhus/has-flag/blob/main/index.js\n/// function hasFlag(flag, argv = globalThis.Deno?.args ?? process.argv) {\nfunction hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process.argv) {\n\tconst prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');\n\tconst position = argv.indexOf(prefix + flag);\n\tconst terminatorPosition = argv.indexOf('--');\n\treturn position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);\n}\n\nconst {env} = process;\n\nlet flagForceColor;\nif (\n\thasFlag('no-color')\n\t|| hasFlag('no-colors')\n\t|| hasFlag('color=false')\n\t|| hasFlag('color=never')\n) {\n\tflagForceColor = 0;\n} else if (\n\thasFlag('color')\n\t|| hasFlag('colors')\n\t|| hasFlag('color=true')\n\t|| hasFlag('color=always')\n) {\n\tflagForceColor = 1;\n}\n\nfunction envForceColor() {\n\tif ('FORCE_COLOR' in env) {\n\t\tif (env.FORCE_COLOR === 'true') {\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (env.FORCE_COLOR === 'false') {\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);\n\t}\n}\n\nfunction translateLevel(level) {\n\tif (level === 0) {\n\t\treturn false;\n\t}\n\n\treturn {\n\t\tlevel,\n\t\thasBasic: true,\n\t\thas256: level >= 2,\n\t\thas16m: level >= 3,\n\t};\n}\n\nfunction _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {\n\tconst noFlagForceColor = envForceColor();\n\tif (noFlagForceColor !== undefined) {\n\t\tflagForceColor = noFlagForceColor;\n\t}\n\n\tconst forceColor = sniffFlags ? flagForceColor : noFlagForceColor;\n\n\tif (forceColor === 0) {\n\t\treturn 0;\n\t}\n\n\tif (sniffFlags) {\n\t\tif (hasFlag('color=16m')\n\t\t\t|| hasFlag('color=full')\n\t\t\t|| hasFlag('color=truecolor')) {\n\t\t\treturn 3;\n\t\t}\n\n\t\tif (hasFlag('color=256')) {\n\t\t\treturn 2;\n\t\t}\n\t}\n\n\t// Check for Azure DevOps pipelines.\n\t// Has to be above the `!streamIsTTY` check.\n\tif ('TF_BUILD' in env && 'AGENT_NAME' in env) {\n\t\treturn 1;\n\t}\n\n\tif (haveStream && !streamIsTTY && forceColor === undefined) {\n\t\treturn 0;\n\t}\n\n\tconst min = forceColor || 0;\n\n\tif (env.TERM === 'dumb') {\n\t\treturn min;\n\t}\n\n\tif (process.platform === 'win32') {\n\t\t// Windows 10 build 10586 is the first Windows release that supports 256 colors.\n\t\t// Windows 10 build 14931 is the first release that supports 16m/TrueColor.\n\t\tconst osRelease = os.release().split('.');\n\t\tif (\n\t\t\tNumber(osRelease[0]) >= 10\n\t\t\t&& Number(osRelease[2]) >= 10_586\n\t\t) {\n\t\t\treturn Number(osRelease[2]) >= 14_931 ? 3 : 2;\n\t\t}\n\n\t\treturn 1;\n\t}\n\n\tif ('CI' in env) {\n\t\tif (['GITHUB_ACTIONS', 'GITEA_ACTIONS', 'CIRCLECI'].some(key => key in env)) {\n\t\t\treturn 3;\n\t\t}\n\n\t\tif (['TRAVIS', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {\n\t\t\treturn 1;\n\t\t}\n\n\t\treturn min;\n\t}\n\n\tif ('TEAMCITY_VERSION' in env) {\n\t\treturn /^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;\n\t}\n\n\tif (env.COLORTERM === 'truecolor') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'xterm-kitty') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'xterm-ghostty') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'wezterm') {\n\t\treturn 3;\n\t}\n\n\tif ('TERM_PROGRAM' in env) {\n\t\tconst version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);\n\n\t\tswitch (env.TERM_PROGRAM) {\n\t\t\tcase 'iTerm.app': {\n\t\t\t\treturn version >= 3 ? 3 : 2;\n\t\t\t}\n\n\t\t\tcase 'Apple_Terminal': {\n\t\t\t\treturn 2;\n\t\t\t}\n\t\t\t// No default\n\t\t}\n\t}\n\n\tif (/-256(color)?$/i.test(env.TERM)) {\n\t\treturn 2;\n\t}\n\n\tif (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {\n\t\treturn 1;\n\t}\n\n\tif ('COLORTERM' in env) {\n\t\treturn 1;\n\t}\n\n\treturn min;\n}\n\nexport function createSupportsColor(stream, options = {}) {\n\tconst level = _supportsColor(stream, {\n\t\tstreamIsTTY: stream && stream.isTTY,\n\t\t...options,\n\t});\n\n\treturn translateLevel(level);\n}\n\nconst supportsColor = {\n\tstdout: createSupportsColor({isTTY: tty.isatty(1)}),\n\tstderr: createSupportsColor({isTTY: tty.isatty(2)}),\n};\n\nexport default supportsColor;\n","// TODO: When targeting Node.js 16, use `String.prototype.replaceAll`.\nexport function stringReplaceAll(string, substring, replacer) {\n\tlet index = string.indexOf(substring);\n\tif (index === -1) {\n\t\treturn string;\n\t}\n\n\tconst substringLength = substring.length;\n\tlet endIndex = 0;\n\tlet returnValue = '';\n\tdo {\n\t\treturnValue += string.slice(endIndex, index) + substring + replacer;\n\t\tendIndex = index + substringLength;\n\t\tindex = string.indexOf(substring, endIndex);\n\t} while (index !== -1);\n\n\treturnValue += string.slice(endIndex);\n\treturn returnValue;\n}\n\nexport function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {\n\tlet endIndex = 0;\n\tlet returnValue = '';\n\tdo {\n\t\tconst gotCR = string[index - 1] === '\\r';\n\t\treturnValue += string.slice(endIndex, (gotCR ? index - 1 : index)) + prefix + (gotCR ? '\\r\\n' : '\\n') + postfix;\n\t\tendIndex = index + 1;\n\t\tindex = string.indexOf('\\n', endIndex);\n\t} while (index !== -1);\n\n\treturnValue += string.slice(endIndex);\n\treturn returnValue;\n}\n","import ansiStyles from '#ansi-styles';\nimport supportsColor from '#supports-color';\nimport { // eslint-disable-line import/order\n\tstringReplaceAll,\n\tstringEncaseCRLFWithFirstIndex,\n} from './utilities.js';\n\nconst {stdout: stdoutColor, stderr: stderrColor} = supportsColor;\n\nconst GENERATOR = Symbol('GENERATOR');\nconst STYLER = Symbol('STYLER');\nconst IS_EMPTY = Symbol('IS_EMPTY');\n\n// `supportsColor.level` → `ansiStyles.color[name]` mapping\nconst levelMapping = [\n\t'ansi',\n\t'ansi',\n\t'ansi256',\n\t'ansi16m',\n];\n\nconst styles = Object.create(null);\n\nconst applyOptions = (object, options = {}) => {\n\tif (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {\n\t\tthrow new Error('The `level` option should be an integer from 0 to 3');\n\t}\n\n\t// Detect level if not set manually\n\tconst colorLevel = stdoutColor ? stdoutColor.level : 0;\n\tobject.level = options.level === undefined ? colorLevel : options.level;\n};\n\nexport class Chalk {\n\tconstructor(options) {\n\t\t// eslint-disable-next-line no-constructor-return\n\t\treturn chalkFactory(options);\n\t}\n}\n\nconst chalkFactory = options => {\n\tconst chalk = (...strings) => strings.join(' ');\n\tapplyOptions(chalk, options);\n\n\tObject.setPrototypeOf(chalk, createChalk.prototype);\n\n\treturn chalk;\n};\n\nfunction createChalk(options) {\n\treturn chalkFactory(options);\n}\n\nObject.setPrototypeOf(createChalk.prototype, Function.prototype);\n\nfor (const [styleName, style] of Object.entries(ansiStyles)) {\n\tstyles[styleName] = {\n\t\tget() {\n\t\t\tconst builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);\n\t\t\tObject.defineProperty(this, styleName, {value: builder});\n\t\t\treturn builder;\n\t\t},\n\t};\n}\n\nstyles.visible = {\n\tget() {\n\t\tconst builder = createBuilder(this, this[STYLER], true);\n\t\tObject.defineProperty(this, 'visible', {value: builder});\n\t\treturn builder;\n\t},\n};\n\nconst getModelAnsi = (model, level, type, ...arguments_) => {\n\tif (model === 'rgb') {\n\t\tif (level === 'ansi16m') {\n\t\t\treturn ansiStyles[type].ansi16m(...arguments_);\n\t\t}\n\n\t\tif (level === 'ansi256') {\n\t\t\treturn ansiStyles[type].ansi256(ansiStyles.rgbToAnsi256(...arguments_));\n\t\t}\n\n\t\treturn ansiStyles[type].ansi(ansiStyles.rgbToAnsi(...arguments_));\n\t}\n\n\tif (model === 'hex') {\n\t\treturn getModelAnsi('rgb', level, type, ...ansiStyles.hexToRgb(...arguments_));\n\t}\n\n\treturn ansiStyles[type][model](...arguments_);\n};\n\nconst usedModels = ['rgb', 'hex', 'ansi256'];\n\nfor (const model of usedModels) {\n\tstyles[model] = {\n\t\tget() {\n\t\t\tconst {level} = this;\n\t\t\treturn function (...arguments_) {\n\t\t\t\tconst styler = createStyler(getModelAnsi(model, levelMapping[level], 'color', ...arguments_), ansiStyles.color.close, this[STYLER]);\n\t\t\t\treturn createBuilder(this, styler, this[IS_EMPTY]);\n\t\t\t};\n\t\t},\n\t};\n\n\tconst bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);\n\tstyles[bgModel] = {\n\t\tget() {\n\t\t\tconst {level} = this;\n\t\t\treturn function (...arguments_) {\n\t\t\t\tconst styler = createStyler(getModelAnsi(model, levelMapping[level], 'bgColor', ...arguments_), ansiStyles.bgColor.close, this[STYLER]);\n\t\t\t\treturn createBuilder(this, styler, this[IS_EMPTY]);\n\t\t\t};\n\t\t},\n\t};\n}\n\nconst proto = Object.defineProperties(() => {}, {\n\t...styles,\n\tlevel: {\n\t\tenumerable: true,\n\t\tget() {\n\t\t\treturn this[GENERATOR].level;\n\t\t},\n\t\tset(level) {\n\t\t\tthis[GENERATOR].level = level;\n\t\t},\n\t},\n});\n\nconst createStyler = (open, close, parent) => {\n\tlet openAll;\n\tlet closeAll;\n\tif (parent === undefined) {\n\t\topenAll = open;\n\t\tcloseAll = close;\n\t} else {\n\t\topenAll = parent.openAll + open;\n\t\tcloseAll = close + parent.closeAll;\n\t}\n\n\treturn {\n\t\topen,\n\t\tclose,\n\t\topenAll,\n\t\tcloseAll,\n\t\tparent,\n\t};\n};\n\nconst createBuilder = (self, _styler, _isEmpty) => {\n\t// Single argument is hot path, implicit coercion is faster than anything\n\t// eslint-disable-next-line no-implicit-coercion\n\tconst builder = (...arguments_) => applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));\n\n\t// We alter the prototype because we must return a function, but there is\n\t// no way to create a function with a different prototype\n\tObject.setPrototypeOf(builder, proto);\n\n\tbuilder[GENERATOR] = self;\n\tbuilder[STYLER] = _styler;\n\tbuilder[IS_EMPTY] = _isEmpty;\n\n\treturn builder;\n};\n\nconst applyStyle = (self, string) => {\n\tif (self.level <= 0 || !string) {\n\t\treturn self[IS_EMPTY] ? '' : string;\n\t}\n\n\tlet styler = self[STYLER];\n\n\tif (styler === undefined) {\n\t\treturn string;\n\t}\n\n\tconst {openAll, closeAll} = styler;\n\tif (string.includes('\\u001B')) {\n\t\twhile (styler !== undefined) {\n\t\t\t// Replace any instances already present with a re-opening code\n\t\t\t// otherwise only the part of the string until said closing code\n\t\t\t// will be colored, and the rest will simply be 'plain'.\n\t\t\tstring = stringReplaceAll(string, styler.close, styler.open);\n\n\t\t\tstyler = styler.parent;\n\t\t}\n\t}\n\n\t// We can move both next actions out of loop, because remaining actions in loop won't have\n\t// any/visible effect on parts we add here. Close the styling before a linebreak and reopen\n\t// after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92\n\tconst lfIndex = string.indexOf('\\n');\n\tif (lfIndex !== -1) {\n\t\tstring = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);\n\t}\n\n\treturn openAll + string + closeAll;\n};\n\nObject.defineProperties(createChalk.prototype, styles);\n\nconst chalk = createChalk();\nexport const chalkStderr = createChalk({level: stderrColor ? stderrColor.level : 0});\n\nexport {\n\tmodifierNames,\n\tforegroundColorNames,\n\tbackgroundColorNames,\n\tcolorNames,\n\n\t// TODO: Remove these aliases in the next major version\n\tmodifierNames as modifiers,\n\tforegroundColorNames as foregroundColors,\n\tbackgroundColorNames as backgroundColors,\n\tcolorNames as colors,\n} from './vendor/ansi-styles/index.js';\n\nexport {\n\tstdoutColor as supportsColor,\n\tstderrColor as supportsColorStderr,\n};\n\nexport default chalk;\n","import { setTimeout } from \"node:timers/promises\";\n\nimport type { Diagnostic, ProjectInfo } from \"@docker-doctor/core\";\nimport { findRule } from \"@docker-doctor/core\";\nimport chalk from \"chalk\";\n\nconst printCodeFrame = (\n content: string | undefined,\n line: number | undefined,\n severityColor: (msg: string) => string\n): void => {\n if (!content || !line) {\n return;\n }\n const lines = content.split(/\\r?\\n/u);\n const start = Math.max(1, line - 1);\n const end = Math.min(lines.length, line + 1);\n\n for (let i = start; i <= end; i += 1) {\n const rawLine = lines[i - 1];\n const isTarget = i === line;\n const lineNumberStr = String(i).padStart(5, \" \");\n if (isTarget) {\n console.log(\n ` ${severityColor(\">\")} ${chalk.bold(lineNumberStr)} │ ${chalk.white(rawLine)}`\n );\n } else {\n console.log(` ${chalk.dim(lineNumberStr)} │ ${chalk.dim(rawLine)}`);\n }\n }\n console.log();\n};\n\nconst printDiscoveredFiles = (project: ProjectInfo): void => {\n console.log(`\\nDiscovered Files:`);\n console.log(\n ` Dockerfile(s): ${project.dockerfiles.length ? project.dockerfiles.map((f) => chalk.cyan(f)).join(\", \") : chalk.dim(\"None\")}`\n );\n console.log(\n ` Compose file(s): ${project.composeFiles.length ? project.composeFiles.map((f) => chalk.cyan(f)).join(\", \") : chalk.dim(\"None\")}`\n );\n};\n\nconst printDiagnostics = (\n diagnostics: Diagnostic[],\n verbose: boolean,\n fileContents: Record<string, string>,\n categoryIssueCounts: Record<string, number>\n): void => {\n if (diagnostics.length === 0) {\n console.log(\n `\\n${chalk.green.bold(\"✔ No issues found! Your Docker setup looks healthy.\")}`\n );\n return;\n }\n\n if (!verbose) {\n console.log(`\\n All ${chalk.bold(diagnostics.length)} issues\\n`);\n\n const categories = [\n \"Security\",\n \"Performance\",\n \"Best Practices\",\n \"Compose\",\n \"Image Size\",\n ];\n\n for (const cat of categories) {\n const count = categoryIssueCounts[cat];\n const issueLabel = count === 1 ? \"1 issue\" : `${count} issues`;\n console.log(` ${cat} › ${chalk.dim(issueLabel)}`);\n }\n\n console.log(\n `\\n Run ${chalk.cyan(\"docker-doctor --verbose\")} to list every error and warning`\n );\n\n // Migration-scale checks\n const ruleCounts: Record<string, number> = {};\n for (const d of diagnostics) {\n ruleCounts[d.rule] = (ruleCounts[d.rule] || 0) + 1;\n }\n const migrationRules = Object.entries(ruleCounts).filter(\n ([_, count]) => count >= 5\n );\n if (migrationRules.length > 0) {\n console.log();\n console.log(\n ` ${chalk.yellow(\"⚠ Migration-scale change: sample before you sweep\")}`\n );\n for (const [rule, count] of migrationRules) {\n console.log(` ${chalk.cyan(rule)} ×${count} across ${count} files`);\n }\n console.log(\n ` Fixing all of them at once is hard to review and prone to`\n );\n console.log(\n ` subtle mistakes across the whole repo. Fix a representative`\n );\n console.log(\n ` few first and confirm the recipe holds. Then get the code`\n );\n console.log(` owner's sign-off before changing the rest.`);\n console.log(` Scope it down one area at a time: docker-doctor <path>`);\n }\n return;\n }\n\n console.log(`\\nFound ${chalk.bold(diagnostics.length)} issue(s):`);\n\n // Group by file\n const filesGrouped: Record<string, Diagnostic[]> = {};\n for (const d of diagnostics) {\n if (!filesGrouped[d.file]) {\n filesGrouped[d.file] = [];\n }\n filesGrouped[d.file].push(d);\n }\n\n for (const [file, fileDiags] of Object.entries(filesGrouped)) {\n console.log(`\\n${chalk.underline.bold(file)}`);\n for (const d of fileDiags) {\n let sevColor = chalk.cyan;\n let prefix = \"ℹ INFO\";\n if (d.severity === \"error\") {\n sevColor = chalk.red.bold;\n prefix = \"✖ ERROR\";\n } else if (d.severity === \"warning\") {\n sevColor = chalk.yellow;\n prefix = \"⚠ WARN\";\n }\n\n const lineInfo = d.line ? `:${d.line}` : \"\";\n console.log(` ${sevColor(prefix)} [${chalk.dim(d.rule)}]${lineInfo}`);\n\n // Print Code Frame\n const content = fileContents[file];\n printCodeFrame(content, d.line, sevColor);\n\n console.log(` ${chalk.white(d.message)}`);\n console.log(` ${chalk.dim(\"Help:\")} ${d.help}`);\n console.log();\n }\n }\n};\n\nconst getWhaleMascot = (\n score: number,\n border: (text: string) => string\n): string[] => {\n let eyes = \"x x\";\n let spout = \" \";\n if (score >= 75) {\n eyes = \"◠ ◠\";\n spout = chalk.cyan(' \":\" ');\n } else if (score >= 50) {\n eyes = \"• •\";\n spout = chalk.cyan(\" . \");\n }\n\n return [\n spout,\n border(\" .---. \"),\n border(`( ${eyes} )>`),\n border(\" \\\\___/ \"),\n ];\n};\n\nconst easeOutCubic = (x: number): number => 1 - (1 - x) ** 3;\n\nconst printScoreBox = async (\n score: number,\n label: string,\n categoryIssueCounts: Record<string, number>,\n warningsCount: number,\n errorsCount: number\n): Promise<void> => {\n const { isTTY } = process.stdout;\n const shouldAnimate =\n isTTY &&\n !process.env.CI &&\n !process.env.NO_ANIMATION &&\n process.env.TERM !== \"dumb\" &&\n process.env.NODE_ENV !== \"test\";\n\n let scoreColor = chalk.red.bold;\n if (score >= 90) {\n scoreColor = chalk.green.bold;\n } else if (score >= 75) {\n scoreColor = chalk.yellow.bold;\n } else if (score >= 50) {\n scoreColor = chalk.magenta.bold;\n }\n const border = scoreColor;\n const whaleLines = getWhaleMascot(score, border);\n\n const shareUrl = `https://docker-doctor.vercel.app/share?s=${score}&w=${warningsCount}&e=${errorsCount}`;\n\n if (shouldAnimate) {\n const frameCount = 20;\n const frameDelay = 15;\n\n // Hide cursor\n process.stdout.write(\"\\u001B[?25l\");\n try {\n for (let frame = 0; frame <= frameCount; frame += 1) {\n const progress = easeOutCubic(frame / frameCount);\n const currentScore = Math.round(score * progress);\n const filledBlocks = Math.round(currentScore / 2);\n const emptyBlocks = 50 - filledBlocks;\n\n const bar =\n scoreColor(\"█\".repeat(filledBlocks)) +\n chalk.dim(\"░\".repeat(emptyBlocks));\n\n if (frame > 0) {\n // Move cursor up 4 lines and carriage return\n process.stdout.write(\"\\u001B[4A\\r\");\n } else {\n // print an extra newline first to start\n console.log();\n }\n\n process.stdout.write(\n ` ${whaleLines[0]} ${scoreColor(`${currentScore} / 100`)} ${scoreColor(label)}\\n` +\n ` ${whaleLines[1]} ${bar}\\n` +\n ` ${whaleLines[2]} ${chalk.dim(\"Docker Doctor (https://docker-doctor.vercel.app)\")}\\n` +\n ` ${whaleLines[3]}\\n`\n );\n\n if (frame < frameCount) {\n // eslint-disable-next-line no-await-in-loop\n await setTimeout(frameDelay);\n }\n }\n } finally {\n // Show cursor\n process.stdout.write(\"\\u001B[?25h\");\n }\n } else {\n // Non-TTY fall back to static print\n const filledBlocks = Math.round(score / 2);\n const emptyBlocks = 50 - filledBlocks;\n const bar =\n scoreColor(\"█\".repeat(filledBlocks)) + chalk.dim(\"░\".repeat(emptyBlocks));\n\n console.log(\n `\\n ${whaleLines[0]} ${scoreColor(`${score} / 100`)} ${scoreColor(label)}`\n );\n console.log(` ${whaleLines[1]} ${bar}`);\n console.log(\n ` ${whaleLines[2]} ${chalk.dim(\"Docker Doctor (https://docker-doctor.vercel.app)\")}`\n );\n console.log(` ${whaleLines[3]}`);\n }\n\n console.log(\n `\\n ${chalk.dim(\"────────────────────────────────────────────────────────────\")}\\n`\n );\n console.log(` Share: ${chalk.cyan(shareUrl)}`);\n console.log(` Tell others how you did on socials\\n`);\n console.log(` Docs: ${chalk.cyan(\"https://docker-doctor.vercel.app\")}`);\n console.log(` Learn more about fixing issues, setting up CI/CD, and`);\n console.log(` configuring rules with a config file\\n`);\n console.log(\n ` GitHub: ${chalk.cyan(\"https://github.com/PunGrumpy/docker-doctor\")}`\n );\n console.log(` Report issues and star the repository!`);\n};\n\nexport const formatTerminal = async (\n diagnostics: Diagnostic[],\n score: number,\n label: string,\n project: ProjectInfo,\n verbose = false,\n fileContents: Record<string, string> = {}\n): Promise<void> => {\n if (verbose) {\n console.log(`\\n${chalk.bold(\"Docker Doctor Diagnostics\")}`);\n console.log(`=================================`);\n printDiscoveredFiles(project);\n }\n\n // Calculate scores per category once\n const categoryIssueCounts: Record<string, number> = {\n \"Best Practices\": 0,\n Compose: 0,\n \"Image Size\": 0,\n Performance: 0,\n Security: 0,\n };\n\n let warningsCount = 0;\n let errorsCount = 0;\n\n for (const d of diagnostics) {\n const ruleDef = findRule(d.rule);\n const category = ruleDef?.category || \"Best Practices\";\n categoryIssueCounts[category] = (categoryIssueCounts[category] || 0) + 1;\n\n if (d.severity === \"warning\") {\n warningsCount += 1;\n } else if (d.severity === \"error\") {\n errorsCount += 1;\n }\n }\n\n printDiagnostics(diagnostics, verbose, fileContents, categoryIssueCounts);\n\n await printScoreBox(\n score,\n label,\n categoryIssueCounts,\n warningsCount,\n errorsCount\n );\n};\n","import fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport readline from \"node:readline\";\nimport { setTimeout } from \"node:timers/promises\";\n\nimport type { Diagnostic, RuleSeverity } from \"@docker-doctor/core\";\nimport {\n discoverProject,\n parseDockerfile,\n parseCompose,\n runDockerfileRules,\n runComposeRules,\n calculateScore,\n loadConfig,\n allRules,\n findRule,\n toJsonReport,\n} from \"@docker-doctor/core\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\n\nimport packageJson from \"../package.json\" with { type: \"json\" };\nimport { formatTerminal } from \"./formatters/terminal\";\n\ninterface KeypressKey {\n name?: string;\n ctrl?: boolean;\n meta?: boolean;\n shift?: boolean;\n}\n\nconst askConfirm = (question: string, defaultYes = false): Promise<boolean> => {\n const isRaw = process.stdin.isTTY;\n if (!isRaw) {\n return Promise.resolve(defaultYes);\n }\n\n /* eslint-disable promise/avoid-new */\n return new Promise((resolve) => {\n let value = defaultYes;\n\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n // Hide cursor during prompt\n process.stdout.write(\"\\u001B[?25l\");\n\n const render = (firstTime = false) => {\n if (!firstTime) {\n process.stdout.write(\"\\u001B[3A\\r\");\n }\n\n process.stdout.write(\n `\\r\\u001B[K ${chalk.green(\"✔\")} ${chalk.bold(question)}\\n`\n );\n\n // Print options vertically\n const yesPrefix = value ? chalk.cyan(\"❯ \") : \" \";\n const yesText = value ? chalk.cyan.bold(\"Yes\") : chalk.dim(\"Yes\");\n process.stdout.write(`\\r\\u001B[K${yesPrefix}${yesText}\\n`);\n\n const noPrefix = value ? \" \" : chalk.cyan(\"❯ \");\n const noText = value ? chalk.dim(\"No\") : chalk.cyan.bold(\"No\");\n process.stdout.write(`\\r\\u001B[K${noPrefix}${noText}\\n`);\n };\n\n render(true);\n\n const handleKeypress = (str: string, key: KeypressKey) => {\n const cleanup = () => {\n process.stdin.removeListener(\"keypress\", handleKeypress);\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(false);\n }\n process.stdin.pause();\n process.stdout.write(\"\\u001B[?25h\");\n };\n\n if (\n key.name === \"left\" ||\n key.name === \"right\" ||\n key.name === \"up\" ||\n key.name === \"down\" ||\n key.name === \"h\" ||\n key.name === \"l\" ||\n key.name === \"j\" ||\n key.name === \"k\"\n ) {\n value = !value;\n render();\n } else if (str === \"y\" || str === \"Y\") {\n value = true;\n render();\n } else if (str === \"n\" || str === \"N\") {\n value = false;\n render();\n } else if (\n key.name === \"return\" ||\n key.name === \"enter\" ||\n str === \"\\r\" ||\n str === \"\\n\"\n ) {\n cleanup();\n // Overwrite and resolve vertical layout cleanly\n process.stdout.write(\"\\u001B[3A\\r\\u001B[K\");\n process.stdout.write(\n ` ${chalk.green(\"✔\")} ${chalk.bold(question)} › ${value ? chalk.cyan(\"Yes\") : chalk.dim(\"No\")}\\n`\n );\n process.stdout.write(\"\\r\\u001B[K\\n\");\n process.stdout.write(\"\\r\\u001B[K\\n\");\n process.stdout.write(\"\\u001B[2A\");\n resolve(value);\n } else if (key.ctrl && key.name === \"c\") {\n cleanup();\n process.stdout.write(\"\\n\");\n process.exit(130);\n }\n };\n\n process.stdin.on(\"keypress\", handleKeypress);\n });\n /* eslint-enable promise/avoid-new */\n};\n\nconst askSelect = (\n question: string,\n options: string[],\n defaultIndex = 0\n): Promise<number> => {\n const isRaw = process.stdin.isTTY;\n if (!isRaw) {\n return Promise.resolve(defaultIndex);\n }\n\n /* eslint-disable promise/avoid-new */\n return new Promise((resolve) => {\n let index = defaultIndex;\n\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n process.stdin.resume();\n\n // Hide cursor during prompt\n process.stdout.write(\"\\u001B[?25l\");\n\n const render = (firstTime = false) => {\n if (!firstTime) {\n // Move back up to overwrite previous render\n process.stdout.write(`\\u001B[${options.length + 1}A\\r`);\n }\n\n process.stdout.write(\n `\\r\\u001B[K ${chalk.green(\"✔\")} ${chalk.bold(question)}\\n`\n );\n\n // Print options\n let i = 0;\n for (const option of options) {\n const isSelected = i === index;\n const prefix = isSelected ? chalk.cyan(\"❯ \") : \" \";\n const text = isSelected ? chalk.cyan.bold(option) : chalk.dim(option);\n process.stdout.write(`\\r\\u001B[K${prefix}${text}\\n`);\n i += 1;\n }\n };\n\n render(true);\n\n const handleKeypress = (str: string, key: KeypressKey) => {\n const cleanup = () => {\n process.stdin.removeListener(\"keypress\", handleKeypress);\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(false);\n }\n process.stdin.pause();\n process.stdout.write(\"\\u001B[?25h\");\n };\n\n if (key.name === \"up\" || key.name === \"k\") {\n index = (index - 1 + options.length) % options.length;\n render();\n } else if (key.name === \"down\" || key.name === \"j\") {\n index = (index + 1) % options.length;\n render();\n } else if (\n key.name === \"return\" ||\n key.name === \"enter\" ||\n str === \"\\r\" ||\n str === \"\\n\"\n ) {\n cleanup();\n // Overwrite and resolve\n process.stdout.write(`\\u001B[${options.length + 1}A\\r\\u001B[K`);\n process.stdout.write(\n ` ${chalk.green(\"✔\")} ${chalk.bold(question)} › ${chalk.cyan(options[index])}\\n`\n );\n for (const _ of options) {\n process.stdout.write(\"\\r\\u001B[K\\n\");\n }\n process.stdout.write(`\\u001B[${options.length}A`);\n resolve(index);\n } else if (key.ctrl && key.name === \"c\") {\n cleanup();\n process.stdout.write(\"\\n\");\n process.exit(130);\n }\n };\n\n process.stdin.on(\"keypress\", handleKeypress);\n });\n /* eslint-enable promise/avoid-new */\n};\n\nconst runInteractiveWizard = async (): Promise<void> => {\n try {\n const addGhActions = await askConfirm(\n \"Add Docker Doctor to GitHub Actions?\"\n );\n if (addGhActions) {\n const workflowDir = path.resolve(\".github/workflows\");\n await fs.mkdir(workflowDir, { recursive: true });\n const workflowPath = path.join(workflowDir, \"docker-doctor.yml\");\n const workflowYaml = `name: Docker Doctor Scan\non:\n push:\n branches: [ main, master ]\n pull_request:\n branches: [ main, master ]\njobs:\n docker-doctor:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Setup Bun\n uses: oven-sh/setup-bun@v2\n - name: Install dependencies\n run: bun install\n - name: Run docker-doctor\n run: bunx docker-doctor .\n`;\n await fs.writeFile(workflowPath, workflowYaml, \"utf-8\");\n console.log(\n `\\n ${chalk.green(\"✨\")} Created ${chalk.cyan(\".github/workflows/docker-doctor.yml\")}!`\n );\n console.log(\n ` Scan every pull request to prevent new Docker issues while you fix the backlog.`\n );\n }\n\n const nextChoice = await askSelect(\"What would you like to do next?\", [\n \"View rules list\",\n \"Skip\",\n ]);\n\n if (nextChoice === 0) {\n console.log(`\\n ${chalk.bold(\"Available Rules:\")}`);\n for (const r of allRules) {\n console.log(\n ` - ${chalk.cyan(r.key)}: ${r.message} (${chalk.dim(r.category)})`\n );\n }\n }\n } catch {\n // Ignore prompt errors\n }\n};\n\nconst runRulesEngine = async (\n rootDir: string,\n project: { dockerfiles: string[]; composeFiles: string[] },\n rulesConfig: Record<string, RuleSeverity> | undefined,\n projectFilesList: string[],\n fileContents: Record<string, string>,\n options: { score?: boolean; json?: boolean },\n setStatus: (text: string) => void\n): Promise<Diagnostic[]> => {\n const diagnostics: Diagnostic[] = [];\n\n const isSilent = options.score || options.json;\n\n if (process.stdout.isTTY && !isSilent) {\n setStatus(`Analyzing ${project.dockerfiles.length} Dockerfile(s)...`);\n await setTimeout(100);\n }\n\n // 1. Scan Dockerfiles in parallel\n const dockerfileResults = await Promise.all(\n project.dockerfiles.map(async (df) => {\n const fullPath = path.join(rootDir, df);\n try {\n const content = await fs.readFile(fullPath, \"utf-8\");\n fileContents[df] = content;\n const instructions = parseDockerfile(content);\n return runDockerfileRules(\n instructions,\n df,\n projectFilesList,\n rulesConfig\n );\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`Failed to analyze Dockerfile ${df}: ${msg}`);\n return [];\n }\n })\n );\n for (const diags of dockerfileResults) {\n diagnostics.push(...diags);\n }\n\n if (process.stdout.isTTY && !isSilent) {\n setStatus(`Analyzing ${project.composeFiles.length} Compose file(s)...`);\n await setTimeout(100);\n }\n\n // 2. Scan Compose files in parallel\n const composeResults = await Promise.all(\n project.composeFiles.map(async (cf) => {\n const fullPath = path.join(rootDir, cf);\n try {\n const content = await fs.readFile(fullPath, \"utf-8\");\n fileContents[cf] = content;\n const composeObj = parseCompose(content, cf);\n return runComposeRules(composeObj, cf, rulesConfig);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`Failed to analyze Compose file ${cf}: ${msg}`);\n return [];\n }\n })\n );\n for (const diags of composeResults) {\n diagnostics.push(...diags);\n }\n\n return diagnostics;\n};\n\nconst filterDiagnostics = (\n diagnostics: Diagnostic[],\n categories?: Record<string, RuleSeverity>\n): Diagnostic[] => {\n if (!categories) {\n return diagnostics;\n }\n return diagnostics.filter((d) => {\n const ruleDef = findRule(d.rule);\n if (ruleDef) {\n const catSeverity = categories[ruleDef.category];\n if (catSeverity === \"off\") {\n return false;\n }\n }\n return true;\n });\n};\n\nconst program = new Command();\n\nprogram\n .name(\"docker-doctor\")\n .description(\"Static analysis for Dockerfile and Docker Compose files\")\n .version(packageJson.version, \"-V, --version\", \"display the version number\");\n\n// Default scan command\nprogram\n .argument(\"[dir]\", \"directory to scan\", \".\")\n .option(\"-v, --verbose\", \"show verbose diagnostics description\", false)\n .option(\"-s, --score\", \"only output numeric health score\", false)\n .option(\"-j, --json\", \"output results as JSON report\", false)\n .option(\"-c, --config <path>\", \"custom config file path\")\n .action(async (dir, options) => {\n const isSilent = options.score || options.json;\n\n // Helper to safely show terminal cursor\n const restoreCursor = (): void => {\n if (process.stdout.isTTY && !isSilent) {\n process.stdout.write(\"\\u001B[?25h\");\n }\n };\n\n // Set signal handlers to restore cursor on aborts\n process.on(\"exit\", restoreCursor);\n process.once(\"SIGINT\", () => {\n restoreCursor();\n process.exit(130);\n });\n process.once(\"SIGTERM\", () => {\n restoreCursor();\n process.exit(143);\n });\n\n try {\n const rootDir = path.resolve(dir);\n const startTime = Date.now();\n\n let statusText = \"Discovering workspace...\";\n const spinnerFrames = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n let frameIndex = 0;\n let spinnerInterval: NodeJS.Timeout | null = null;\n\n const setStatus = (text: string) => {\n statusText = text;\n };\n\n if (process.stdout.isTTY && !isSilent) {\n // Hide cursor during progress/spinner\n process.stdout.write(\"\\u001B[?25l\");\n process.stdout.write(`${chalk.cyan(spinnerFrames[0])} ${statusText}`);\n spinnerInterval = setInterval(() => {\n process.stdout.write(\n `\\r\\u001B[K${chalk.cyan(spinnerFrames[frameIndex])} ${statusText}`\n );\n frameIndex = (frameIndex + 1) % spinnerFrames.length;\n }, 80);\n }\n\n try {\n if (process.stdout.isTTY && !isSilent) {\n await setTimeout(150);\n }\n\n setStatus(\"Loading configuration...\");\n // Load config first\n const config = await loadConfig(rootDir, options.config);\n\n setStatus(\"Scanning workspace files...\");\n // Project discovery\n const project = await discoverProject(rootDir);\n\n // Collect all diagnostics\n const fileContents: Record<string, string> = {};\n\n const projectFilesList = [\n ...project.dockerfiles,\n ...project.composeFiles,\n ...(project.dockerignores || []),\n ];\n\n const diagnostics = await runRulesEngine(\n rootDir,\n project,\n config.rules,\n projectFilesList,\n fileContents,\n options,\n setStatus\n );\n\n // Filter by category config if needed\n const filteredDiagnostics = filterDiagnostics(\n diagnostics,\n config.categories\n );\n\n // Calculate score\n const { score, label } = calculateScore(filteredDiagnostics);\n\n const duration = ((Date.now() - startTime) / 1000).toFixed(1);\n const concurrency = os.cpus().length;\n\n if (spinnerInterval !== null) {\n clearInterval(spinnerInterval);\n spinnerInterval = null;\n // Clear spinner line and restore cursor\n process.stdout.write(\"\\r\\u001B[K\\u001B[?25h\");\n }\n\n if (process.stdout.isTTY && !isSilent) {\n console.log(\n `${chalk.green(\"✔\")} Scanned ${projectFilesList.length} files in ${duration}s [~${concurrency} workers]`\n );\n }\n\n if (options.score) {\n console.log(score);\n process.exitCode = score < 50 ? 1 : 0;\n return;\n } else if (options.json) {\n const report = toJsonReport(\n filteredDiagnostics,\n score,\n label,\n project\n );\n console.log(JSON.stringify(report, null, 2));\n const hasErrors = filteredDiagnostics.some(\n (d) => d.severity === \"error\"\n );\n process.exitCode = hasErrors ? 1 : 0;\n return;\n }\n await formatTerminal(\n filteredDiagnostics,\n score,\n label,\n project,\n options.verbose,\n fileContents\n );\n\n // Exit with non-zero code if there are any error severity diagnostics\n const hasErrors = filteredDiagnostics.some(\n (d) => d.severity === \"error\"\n );\n\n if (process.stdout.isTTY && process.stdin.isTTY) {\n await runInteractiveWizard();\n }\n process.exitCode = hasErrors ? 1 : 0;\n } finally {\n if (spinnerInterval !== null) {\n clearInterval(spinnerInterval);\n process.stdout.write(\"\\r\\u001B[K\\u001B[?25h\");\n }\n }\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`Error: ${msg}`);\n process.exit(1);\n }\n });\n\n// Rules subcommand group\nconst rules = program\n .command(\"rules\")\n .description(\"manage and list configuration rules\");\n\nrules\n .command(\"list\")\n .description(\"list all available rules\")\n .action(() => {\n console.log(\"\\nAvailable Rules:\");\n console.log(\"================\\n\");\n for (const rule of allRules) {\n console.log(`- ${rule.key} (${rule.category})`);\n console.log(` Default Severity: ${rule.defaultSeverity}`);\n console.log(` Description: ${rule.message}\\n`);\n }\n });\n\nrules\n .command(\"explain <rule>\")\n .description(\"explain a specific rule in detail\")\n .action((ruleKey) => {\n const rule = findRule(ruleKey);\n if (!rule) {\n console.error(`Rule '${ruleKey}' not found.`);\n process.exit(1);\n }\n console.log(`\\nRule: ${rule.key}`);\n console.log(`Category: ${rule.category}`);\n console.log(`Default Severity: ${rule.defaultSeverity}`);\n console.log(`Description: ${rule.message}`);\n console.log(`Help / Fix: ${rule.help}\\n`);\n });\n\nprogram.parse(process.argv);\n"],"x_google_ignoreList":[0,1,2,3],"mappings":"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"}
|