{"version":3,"file":"index.cjs","names":["path","fs","path","ScreenshotFileSystem","path","ScreenshotFileSystem","ScreenshotTool","path","fs","path","path","Command"],"sources":["../package.json","../src/features/config/getPlugins.ts","../src/features/config/loadConfig.ts","../src/features/config/getConfig.ts","../src/utils/groupScreenshots.ts","../src/commands/approve.ts","../src/commands/capture.ts","../src/features/config/default.ts","../src/commands/init.ts","../src/commands/review.ts","../src/utils/describeChanges.ts","../src/commands/status.ts","../src/index.ts"],"sourcesContent":["","import type { PluginDef, UserConfig } from \"@cappa/core\";\n\nexport async function getPlugins(\n  plugins: UserConfig[\"plugins\"],\n): Promise<PluginDef[]> {\n  if (!plugins) {\n    return [];\n  }\n\n  const loadedPlugins: PluginDef[] = [];\n\n  for (const plugin of plugins) {\n    if (typeof plugin === \"function\") {\n      // Plugin is a function that returns PluginDef\n      const pluginDef = plugin();\n      loadedPlugins.push(pluginDef);\n    } else {\n      // Plugin is already a PluginDef\n      loadedPlugins.push(plugin);\n    }\n  }\n\n  return loadedPlugins;\n}\n\nexport function isPromise(value: unknown): value is Promise<unknown> {\n  return (\n    value !== null &&\n    typeof value === \"object\" &&\n    \"then\" in value &&\n    typeof (value as any).then === \"function\"\n  );\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { defineConfig, UserConfig } from \"@cappa/core\";\nimport { createJiti } from \"jiti\";\n\nexport type ConfigResult = {\n  filepath: string;\n  config: ReturnType<typeof defineConfig> | UserConfig;\n};\n\nconst tsLoader = async (configFile: string) => {\n  const jiti = createJiti(import.meta.url, {\n    jsx: {\n      runtime: \"automatic\",\n      importSource: \"@cappa/core\",\n    },\n    sourceMaps: true,\n  });\n\n  const mod = await jiti.import(configFile, { default: true });\n\n  return mod;\n};\n\nexport async function loadConfig(): Promise<ConfigResult> {\n  const configPath = path.resolve(process.cwd(), \"cappa.config.ts\");\n\n  if (!fs.existsSync(configPath)) {\n    throw new Error(\n      \"Config not found. Please create a cappa.config.ts file in the current directory.\",\n    );\n  }\n\n  try {\n    const config = await tsLoader(configPath);\n\n    if (!config) {\n      throw new Error(\n        \"Config file is empty or does not export a valid configuration.\",\n      );\n    }\n\n    return {\n      filepath: configPath,\n      config,\n    };\n  } catch (error) {\n    throw new Error(\n      `Failed to load config from ${configPath}: ${error instanceof Error ? error.message : String(error)}`,\n    );\n  }\n}\n","import type { ConfigEnv, UserConfig } from \"@cappa/core\";\nimport { getLogger } from \"@cappa/logger\";\nimport { getPlugins, isPromise } from \"./getPlugins\";\nimport type { ConfigResult } from \"./loadConfig\";\nimport { loadConfig } from \"./loadConfig\";\n\ntype ResolvedUserConfig = Required<Omit<UserConfig, \"onFail\">> &\n  Pick<UserConfig, \"onFail\">;\n\n/**\n * Converting UserConfig to Config without a change in the object beside the JSON convert.\n */\nexport async function getConfig(\n  loadResult?: ConfigResult,\n): Promise<ResolvedUserConfig> {\n  const result = loadResult ?? (await loadConfig());\n\n  const configData = result?.config;\n  let cappaUserConfig: Promise<UserConfig> = Promise.resolve(\n    configData as UserConfig,\n  );\n\n  const configEnv: ConfigEnv = {\n    command: process.argv[2],\n    mode: process.env.NODE_ENV || \"development\",\n    env: process.env,\n  };\n\n  // for ts or js files\n  if (typeof configData === \"function\") {\n    const possiblePromise = (configData as (env: ConfigEnv) => any)(configEnv);\n    if (isPromise(possiblePromise)) {\n      cappaUserConfig = possiblePromise as Promise<UserConfig>;\n    } else {\n      cappaUserConfig = Promise.resolve(possiblePromise as UserConfig);\n    }\n  }\n\n  const userConfig = await cappaUserConfig;\n\n  if (!userConfig || typeof userConfig === \"function\") {\n    throw new Error(\"Invalid configuration: no valid config found\");\n  }\n\n  const diffConfig: UserConfig[\"diff\"] = (() => {\n    if (userConfig.diff?.type !== \"gmsd\") {\n      return {\n        type: \"pixel\",\n        threshold: userConfig.diff?.threshold ?? 0.1,\n        includeAA: userConfig.diff?.includeAA ?? false,\n        fastBufferCheck: userConfig.diff?.fastBufferCheck ?? true,\n        maxDiffPixels: userConfig.diff?.maxDiffPixels ?? 0,\n        maxDiffPercentage: userConfig.diff?.maxDiffPercentage ?? 0,\n        interpret: userConfig.diff?.interpret ?? false,\n      };\n    }\n\n    return {\n      type: \"gmsd\",\n      threshold: userConfig.diff.threshold ?? 0.1,\n      downsample: userConfig.diff.downsample ?? 0,\n      c: userConfig.diff.c ?? 170,\n    };\n  })();\n\n  const configWithDefaults = {\n    outputDir: userConfig.outputDir || \"./screenshots\",\n    retries: userConfig.retries || 2,\n    concurrency: userConfig.concurrency || 1,\n    logConsoleEvents: userConfig.logConsoleEvents ?? true,\n    diff: diffConfig,\n    plugins: userConfig.plugins ? await getPlugins(userConfig.plugins) : [],\n    onFail: userConfig.onFail,\n    screenshot: {\n      fullPage: userConfig.screenshot?.fullPage ?? true,\n      viewport: userConfig.screenshot?.viewport ?? {\n        width: 1920,\n        height: 1080,\n      },\n    },\n    review: {\n      theme: userConfig.review?.theme ?? \"light\",\n      port: userConfig.review?.port ?? 3000,\n    },\n    connectionTimeout: userConfig.connectionTimeout ?? 20000,\n  };\n\n  getLogger().debug(\n    \"Configuration loaded:\",\n    JSON.stringify(configWithDefaults, null, 2),\n  );\n\n  return configWithDefaults;\n}\n","import { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport { readDiffMeta, type Screenshot } from \"@cappa/core\";\n\nexport const groupScreenshots = async (\n  actualScreenshots: string[],\n  expectedScreenshots: string[],\n  diffScreenshots: string[],\n  outputDir: string,\n): Promise<Screenshot[]> => {\n  const screenshotRepresentations: Screenshot[] = [];\n\n  // Build Maps for O(1) lookups instead of O(n) .find() calls\n  const expectedByRelativePath = new Map<string, string>();\n  for (const screenshot of expectedScreenshots) {\n    const relativePath = path.relative(`${outputDir}/expected`, screenshot);\n    expectedByRelativePath.set(relativePath, screenshot);\n  }\n\n  const diffByRelativePath = new Map<string, string>();\n  for (const screenshot of diffScreenshots) {\n    const relativePath = path.relative(`${outputDir}/diff`, screenshot);\n    diffByRelativePath.set(relativePath, screenshot);\n  }\n\n  const actualRelativePaths = new Set<string>();\n\n  for (const screenshot of actualScreenshots) {\n    const relativePath = path.relative(`${outputDir}/actual`, screenshot);\n    actualRelativePaths.add(relativePath);\n\n    const name = relativePath.replace(\".png\", \"\");\n    const id = createHash(\"sha256\").update(relativePath).digest(\"hex\");\n\n    const expectedScreenshot = expectedByRelativePath.get(relativePath);\n    const diffScreenshot = diffByRelativePath.get(relativePath);\n\n    // Load the diff metadata sidecar (stats + interpretation) for changed\n    // screenshots so it can be surfaced in the review UI and CLI.\n    const diffMeta = diffScreenshot\n      ? await readDiffMeta(diffScreenshot)\n      : undefined;\n\n    screenshotRepresentations.push({\n      id: id,\n      name: name,\n      category: buildCategory(expectedScreenshot, diffScreenshot),\n      expectedPath: expectedScreenshot\n        ? path.relative(outputDir, expectedScreenshot)\n        : undefined,\n      diffPath: diffScreenshot\n        ? path.relative(outputDir, diffScreenshot)\n        : undefined,\n      actualPath: path.relative(outputDir, screenshot),\n      ...(diffMeta ? { diffMeta } : {}),\n    } as Screenshot);\n  }\n\n  for (const expectedScreenshot of expectedScreenshots) {\n    const relativePath = path.relative(\n      `${outputDir}/expected`,\n      expectedScreenshot,\n    );\n\n    // If the actual screenshot exists, it means we already added it\n    if (actualRelativePaths.has(relativePath)) {\n      continue;\n    }\n\n    const name = relativePath.replace(\".png\", \"\");\n    const id = createHash(\"sha256\").update(relativePath).digest(\"hex\");\n\n    screenshotRepresentations.push({\n      id: id,\n      name: name,\n      category: \"deleted\",\n      expectedPath: path.relative(outputDir, expectedScreenshot),\n    });\n  }\n\n  return screenshotRepresentations.sort((a, b) => {\n    return CATEGORY_ORDER[a.category] - CATEGORY_ORDER[b.category];\n  });\n};\n\nconst buildCategory = (\n  expectedScreenshot: string | undefined,\n  diffScreenshot: string | undefined,\n) => {\n  if (expectedScreenshot && diffScreenshot) {\n    return \"changed\";\n  }\n  if (expectedScreenshot) {\n    return \"passed\";\n  }\n\n  return \"new\";\n};\n\nconst CATEGORY_ORDER: Record<Screenshot[\"category\"], number> = {\n  new: 0,\n  deleted: 1,\n  changed: 2,\n  passed: 3,\n};\n","import type { Screenshot } from \"@cappa/core\";\nimport { ScreenshotFileSystem } from \"@cappa/core\";\nimport { getLogger } from \"@cappa/logger\";\nimport { getConfig } from \"../features/config\";\nimport { groupScreenshots } from \"../utils/groupScreenshots\";\n\nexport const approve = async (options: { filter?: string[] }) => {\n  const logger = getLogger();\n\n  const config = await getConfig();\n\n  logger.start(\"Approving screenshots...\");\n\n  const fileSystem = new ScreenshotFileSystem(config.outputDir);\n\n  const [actualScreenshots, diffScreenshots, expectedScreenshots] =\n    await Promise.all([\n      fileSystem.getActualScreenshots(),\n      fileSystem.getDiffScreenshots(),\n      fileSystem.getExpectedScreenshots(),\n    ]);\n\n  let screenshotsToApprove = await groupScreenshots(\n    actualScreenshots,\n    expectedScreenshots,\n    diffScreenshots,\n    config.outputDir,\n  );\n\n  const filters =\n    options.filter?.map((filter: string) => filter.toLowerCase()) ?? [];\n\n  if (filters.length > 0) {\n    logger.debug(\n      `Filtering actual screenshots by filter: ${filters.join(\", \")}`,\n    );\n\n    screenshotsToApprove = filterScreenshots(screenshotsToApprove, filters);\n\n    if (screenshotsToApprove.length === 0) {\n      logger.warn(\"No screenshots matched the provided filter(s)\");\n      return;\n    }\n  }\n\n  await fileSystem.approveScreenshots(screenshotsToApprove, config.diff);\n\n  if (filters.length > 0) {\n    logger.success(\n      `${screenshotsToApprove.length} screenshot(s) approved (filtered)`,\n    );\n  } else {\n    logger.success(\"All screenshots approved\");\n  }\n};\n\nexport const filterScreenshots = (\n  screenshots: Screenshot[],\n  filters: string[],\n) => {\n  return screenshots.filter((screenshot) => {\n    return filters.some((filter: string) => {\n      const nameMatches = screenshot.name.toLowerCase().includes(filter);\n      const pathMatches =\n        \"actualPath\" in screenshot &&\n        screenshot.actualPath?.toLowerCase().includes(filter);\n      return nameMatches || pathMatches;\n    });\n  });\n};\n","import { glob } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { PluginTask } from \"@cappa/core\";\nimport {\n  type FailedScreenshot,\n  mapWithConcurrency,\n  ScreenshotFileSystem,\n  ScreenshotTool,\n} from \"@cappa/core\";\nimport { getLogger } from \"@cappa/logger\";\nimport chalk from \"chalk\";\nimport type { Command } from \"commander\";\nimport { getConfig } from \"../features/config\";\nimport { groupScreenshots } from \"../utils/groupScreenshots\";\n\ntype PluginCaptureResult = {\n  success?: boolean;\n  skipped?: boolean;\n  isNew?: boolean;\n  error?: unknown;\n  filepath?: string;\n  storyId?: string;\n  storyName?: string;\n  [key: string]: unknown;\n};\n\ntype FailedScreenshotInfo = {\n  taskId: string;\n  taskUrl: string;\n  result: PluginCaptureResult;\n  pluginName: string;\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n  typeof value === \"object\" && value !== null;\n\nexport const didScreenshotFail = (result: unknown): boolean => {\n  if (!isObject(result)) {\n    return false;\n  }\n\n  if (\"error\" in result && result.error != null) {\n    return true;\n  }\n\n  if (\"success\" in result) {\n    const { success } = result as PluginCaptureResult;\n    if (success === false) {\n      return true;\n    }\n  }\n\n  if (\"filepath\" in result) {\n    const { filepath, skipped } = result as PluginCaptureResult;\n    if (!filepath && skipped !== true) {\n      return true;\n    }\n  }\n\n  return false;\n};\n\nasync function executeOnFailCallback(\n  config: Awaited<ReturnType<typeof getConfig>>,\n): Promise<void> {\n  const logger = getLogger();\n\n  if (!config.onFail) {\n    return;\n  }\n\n  const actualScreenshotsPromise = glob(\n    path.resolve(config.outputDir, \"actual\", \"**/*.png\"),\n  );\n  const expectedScreenshotsPromise = glob(\n    path.resolve(config.outputDir, \"expected\", \"**/*.png\"),\n  );\n  const diffScreenshotsPromise = glob(\n    path.resolve(config.outputDir, \"diff\", \"**/*.png\"),\n  );\n\n  const [actualScreenshots, expectedScreenshots, diffScreenshots] =\n    await Promise.all([\n      actualScreenshotsPromise,\n      expectedScreenshotsPromise,\n      diffScreenshotsPromise,\n    ]);\n\n  const groupedScreenshots = await groupScreenshots(\n    await Array.fromAsync(actualScreenshots),\n    await Array.fromAsync(expectedScreenshots),\n    await Array.fromAsync(diffScreenshots),\n    config.outputDir,\n  );\n\n  const failingScreenshots: FailedScreenshot[] = groupedScreenshots\n    .filter((screenshot) => screenshot.category !== \"passed\")\n    .map((screenshot) => ({\n      ...screenshot,\n      absoluteActualPath:\n        \"actualPath\" in screenshot && screenshot.actualPath\n          ? path.resolve(config.outputDir, screenshot.actualPath)\n          : undefined,\n      absoluteExpectedPath:\n        \"expectedPath\" in screenshot && screenshot.expectedPath\n          ? path.resolve(config.outputDir, screenshot.expectedPath)\n          : undefined,\n      absoluteDiffPath:\n        \"diffPath\" in screenshot && screenshot.diffPath\n          ? path.resolve(config.outputDir, screenshot.diffPath)\n          : undefined,\n    }));\n\n  if (failingScreenshots.length > 0) {\n    logger.debug(\n      `Executing onFail callback with ${failingScreenshots.length} failing screenshot(s)`,\n    );\n\n    try {\n      await config.onFail(failingScreenshots);\n    } catch (error) {\n      logger.error(\"Error executing onFail callback:\", error);\n    }\n  }\n}\n\nexport function formatProgress(\n  completed: number,\n  total: number,\n  taskId: string,\n): string {\n  return `[${completed}/${total}] captured ${taskId}`;\n}\n\nexport function formatDuration(ms: number): string {\n  const seconds = Math.floor(ms / 1000);\n  const minutes = Math.floor(seconds / 60);\n  const remainingSeconds = seconds % 60;\n\n  if (minutes > 0) {\n    return `${minutes}m ${remainingSeconds}s`;\n  }\n  return `${(ms / 1000).toFixed(2)}s`;\n}\n\nfunction generateFailureReportMessage(\n  failedScreenshots: FailedScreenshotInfo[],\n  deletedScreenshots: string[],\n): string {\n  const total = failedScreenshots.length + deletedScreenshots.length;\n  if (total === 0) {\n    return \"\";\n  }\n\n  const lines: string[] = [];\n  lines.push(`${chalk.red(`Total failures: ${total}`)}\\n`);\n\n  // Group by plugin\n  const byPlugin = new Map<string, FailedScreenshotInfo[]>();\n  for (const failed of failedScreenshots) {\n    const pluginFailures = byPlugin.get(failed.pluginName);\n    if (pluginFailures) {\n      pluginFailures.push(failed);\n    } else {\n      byPlugin.set(failed.pluginName, [failed]);\n    }\n  }\n\n  for (const [pluginName, failures] of byPlugin.entries()) {\n    lines.push(`\\n${chalk.bold(`Plugin: ${pluginName}`)}`);\n\n    for (const failed of failures) {\n      lines.push(`\\n  ${chalk.dim(\"Task ID:\")} ${failed.taskId}`);\n\n      const result = failed.result;\n      if (result.storyName) {\n        lines.push(`  ${chalk.dim(\"Story:\")} ${result.storyName}`);\n      }\n      if (result.error) {\n        const errorMsg =\n          typeof result.error === \"string\"\n            ? result.error\n            : result.error instanceof Error\n              ? result.error.message\n              : String(result.error);\n        lines.push(`  ${chalk.red(\"Error:\")} ${errorMsg}`);\n      }\n      if (result.success === false) {\n        if (result.isNew) {\n          lines.push(\n            `  ${chalk.yellow(\"Status:\")} New screenshot (no baseline — run 'cappa approve' to accept)`,\n          );\n        } else {\n          lines.push(`  ${chalk.red(\"Status:\")} Failed (comparison failed)`);\n        }\n      }\n      if (!result.filepath && result.skipped !== true) {\n        lines.push(`  ${chalk.red(\"Status:\")} Failed (no filepath generated)`);\n      }\n    }\n  }\n\n  if (deletedScreenshots.length > 0) {\n    lines.push(`\\n${chalk.bold(\"Deleted baselines:\")}`);\n    for (const screenshotPath of deletedScreenshots) {\n      lines.push(\n        `  ${chalk.dim(\"Name:\")} ${screenshotPath.replace(/\\.png$/, \"\")}`,\n      );\n    }\n  }\n\n  return lines.join(\"\\n\");\n}\n\nexport async function getDeletedScreenshots(\n  outputDir: string,\n): Promise<string[]> {\n  const actualDir = path.resolve(outputDir, \"actual\");\n  const expectedDir = path.resolve(outputDir, \"expected\");\n\n  const [actualFiles, expectedFiles] = await Promise.all([\n    Array.fromAsync(glob(path.join(actualDir, \"**/*.png\"))),\n    Array.fromAsync(glob(path.join(expectedDir, \"**/*.png\"))),\n  ]);\n\n  const actualRelative = new Set(\n    actualFiles.map((p) => path.relative(actualDir, p)),\n  );\n\n  return expectedFiles\n    .map((p) => path.relative(expectedDir, p))\n    .filter((rel) => !actualRelative.has(rel));\n}\n\ntype CaptureOptions = {\n  ci?: boolean;\n  filter?: string;\n};\n\nexport function filterTasks(tasks: PluginTask[], filter: string): PluginTask[] {\n  return tasks.filter((task) => path.matchesGlob(task.id, filter));\n}\n\nexport function registerSignalHandlers(\n  screenshotTool: ScreenshotTool,\n  exitFn: (code: number) => void = process.exit,\n): () => void {\n  const handleSignal = async () => {\n    await screenshotTool.close();\n    exitFn(130);\n  };\n\n  process.once(\"SIGINT\", handleSignal);\n  process.once(\"SIGTERM\", handleSignal);\n\n  return () => {\n    process.off(\"SIGINT\", handleSignal);\n    process.off(\"SIGTERM\", handleSignal);\n  };\n}\n\nconst runCapture = async (options: CaptureOptions = {}): Promise<void> => {\n  const logger = getLogger();\n  const captureStart = performance.now();\n\n  const config = await getConfig();\n\n  logger.debug(`Cleaning output directory: ${config.outputDir}`);\n  const fileSystem = new ScreenshotFileSystem(config.outputDir);\n  fileSystem.clearActual();\n  fileSystem.clearDiff();\n\n  const screenshotTool = new ScreenshotTool({\n    outputDir: config.outputDir,\n    diff: config.diff,\n    retries: config.retries,\n    concurrency: config.concurrency,\n    logConsoleEvents: config.logConsoleEvents,\n    fullPage: config.screenshot?.fullPage ?? true,\n    viewport: config.screenshot?.viewport ?? { width: 1920, height: 1080 },\n    connectionTimeout: config.connectionTimeout,\n  });\n\n  const unregisterSignalHandlers = registerSignalHandlers(screenshotTool);\n\n  let captureError: unknown;\n  let hasScreenshotFailure = false;\n  let anyTasksRan = false;\n  const failedScreenshots: FailedScreenshotInfo[] = [];\n\n  try {\n    await screenshotTool.init();\n\n    const plugins = (config.plugins || []) as any[];\n\n    // Phase 1: Discover all tasks in parallel across plugins\n    const pluginTasks = await Promise.all(\n      plugins.map(async (plugin) => {\n        logger.debug(`Discovering tasks for plugin: ${plugin.name}`);\n        const tasks = await plugin.discover(screenshotTool);\n        logger.info(`Found ${tasks.length} tasks for ${plugin.name}`);\n        return { plugin, tasks };\n      }),\n    );\n\n    if (options.filter) {\n      logger.box({\n        title: \"Filter Active\",\n        message: `Only capturing tasks matching: ${chalk.cyan(options.filter)}`,\n      });\n\n      for (const entry of pluginTasks) {\n        const before = entry.tasks.length;\n        entry.tasks = filterTasks(entry.tasks, options.filter);\n        logger.info(\n          `${entry.plugin.name}: ${entry.tasks.length}/${before} tasks match filter`,\n        );\n      }\n    }\n\n    for (const { plugin, tasks } of pluginTasks) {\n      if (tasks.length === 0) {\n        continue;\n      }\n\n      anyTasksRan = true;\n      let pluginHasFailure = false;\n\n      logger.debug(\n        `Processing ${tasks.length} tasks with concurrency ${screenshotTool.concurrency}`,\n      );\n\n      let completedTasks = 0;\n      const pageContexts = new Map<number, any>();\n\n      const allResults = await mapWithConcurrency(\n        screenshotTool.concurrency,\n        tasks,\n        async (task: any, workerIndex) => {\n          const page = screenshotTool.getPageFromPool(workerIndex);\n\n          if (!pageContexts.has(workerIndex) && plugin.initPage) {\n            pageContexts.set(\n              workerIndex,\n              await plugin.initPage(page, screenshotTool),\n            );\n          }\n          const context = pageContexts.get(workerIndex);\n\n          logger.debug(`Executing task: ${task.id}`);\n          const result = await plugin.execute(\n            task,\n            page,\n            screenshotTool,\n            context,\n          );\n\n          completedTasks++;\n          logger.info(formatProgress(completedTasks, tasks.length, task.id));\n\n          if (didScreenshotFail(result)) {\n            pluginHasFailure = true;\n            hasScreenshotFailure = true;\n            failedScreenshots.push({\n              taskId: task.id,\n              taskUrl: task.url,\n              result: result as PluginCaptureResult,\n              pluginName: plugin.name,\n            });\n          }\n\n          return result;\n        },\n      );\n\n      const results = allResults;\n      if (pluginHasFailure) {\n        logger.error(\n          `Plugin ${plugin.name} completed with failures: ${results.length} results`,\n        );\n      } else {\n        logger.success(\n          `Plugin ${plugin.name} completed: ${results.length} results`,\n        );\n      }\n    }\n  } catch (error) {\n    logger.error(\"Error during plugin execution:\", error);\n    captureError = error;\n    throw error;\n  } finally {\n    unregisterSignalHandlers();\n    await screenshotTool.close();\n  }\n\n  let deletedScreenshots: string[] = [];\n  if (anyTasksRan) {\n    try {\n      deletedScreenshots = await getDeletedScreenshots(config.outputDir);\n      if (deletedScreenshots.length > 0) {\n        hasScreenshotFailure = true;\n      }\n    } catch (err) {\n      logger.warn(\"Could not check for deleted screenshots:\", err);\n    }\n  }\n\n  const isCi = options.ci || process.env.CI === \"true\";\n\n  if (!captureError && isCi) {\n    await executeOnFailCallback(config);\n  }\n\n  const duration = formatDuration(performance.now() - captureStart);\n\n  if (hasScreenshotFailure) {\n    const reportMessage = generateFailureReportMessage(\n      failedScreenshots,\n      deletedScreenshots,\n    );\n    logger.box({\n      title: \"Failed Screenshots\",\n      message: reportMessage,\n    });\n    logger.error(\n      `One or more screenshots failed in ${duration}. See report above for details.`,\n    );\n    process.exit(1);\n  } else {\n    logger.success(`All plugins completed successfully in ${duration}`);\n  }\n};\n\nexport const registerCaptureCommand = (program: Command): void => {\n  program\n    .command(\"capture\")\n    .description(\"Capture screenshots\")\n    .option(\"--ci\", \"run capture in CI mode and execute onFail callback\")\n    .option(\n      \"-f, --filter <pattern>\",\n      \"only capture tasks whose id matches the given glob pattern\",\n    )\n    .action(async (options: CaptureOptions) => {\n      await runCapture(options);\n    });\n};\n","export const defaultConfig = `import { defineConfig } from \"@cappa/core\";\n\nexport default defineConfig({\n  outputDir: \"./screenshots\",\n  retries: 3,\n  diff: {\n    threshold: 0.1,\n    includeAA: false,\n    fastBufferCheck: true,\n    maxDiffPixels: 0,\n    maxDiffPercentage: 0,\n  },\n  plugins: [],\n});\n`;\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getLogger } from \"@cappa/logger\";\nimport { defaultConfig } from \"../features/config/default\";\n\nexport const init = async () => {\n  const logger = getLogger();\n\n  const configPath = path.resolve(process.cwd(), \"cappa.config.ts\");\n  const packageJsonPath = path.resolve(process.cwd(), \"package.json\");\n\n  // Create cappa.config.ts\n  if (fs.existsSync(configPath)) {\n    logger.warn(\"cappa.config.ts already exists, skipping...\");\n  } else {\n    fs.writeFileSync(configPath, defaultConfig);\n    logger.success(\"Created cappa.config.ts\");\n  }\n\n  // Add scripts to package.json\n  if (fs.existsSync(packageJsonPath)) {\n    try {\n      const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n\n      if (!packageJson.scripts) {\n        packageJson.scripts = {};\n      }\n\n      if (packageJson.scripts.cappa) {\n        logger.warn(\n          \"'cappa' script already exists in package.json, skipping...\",\n        );\n      } else {\n        packageJson.scripts.cappa = \"cappa capture\";\n      }\n\n      if (packageJson.scripts[\"cappa:review\"]) {\n        logger.warn(\n          \"'cappa:review' script already exists in package.json, skipping...\",\n        );\n      } else {\n        packageJson.scripts[\"cappa:review\"] = \"cappa review\";\n      }\n\n      fs.writeFileSync(\n        packageJsonPath,\n        `${JSON.stringify(packageJson, null, 2)}\\n`,\n      );\n      logger.success(\"Added 'cappa' scripts to package.json\");\n    } catch (error) {\n      logger.error(\"Failed to update package.json:\", error);\n    }\n  } else {\n    logger.warn(\"package.json not found, skipping script addition\");\n  }\n\n  logger.success(\"Cappa initialization complete!\");\n  logger.warn(\n    \"cappa relies on playwright to capture screenshots. Please install playwright and browsers before running cappa.\",\n  );\n};\n","import { glob } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getLogger } from \"@cappa/logger\";\nimport { createServer } from \"@cappa/server\";\nimport { getConfig } from \"../features/config\";\nimport { groupScreenshots } from \"../utils/groupScreenshots\";\n\nexport const review = async () => {\n  const logger = getLogger();\n\n  const config = await getConfig();\n\n  const actualScreenshotsPromise = glob(\n    path.resolve(config.outputDir, \"actual\", \"**/*.png\"),\n  );\n  const expectedScreenshotsPromise = glob(\n    path.resolve(config.outputDir, \"expected\", \"**/*.png\"),\n  );\n  const diffScreenshotsPromise = glob(\n    path.resolve(config.outputDir, \"diff\", \"**/*.png\"),\n  );\n\n  const [actualScreenshots, expectedScreenshots, diffScreenshots] =\n    await Promise.all([\n      actualScreenshotsPromise,\n      expectedScreenshotsPromise,\n      diffScreenshotsPromise,\n    ]);\n\n  const groupedScreenshots = await groupScreenshots(\n    await Array.fromAsync(actualScreenshots),\n    await Array.fromAsync(expectedScreenshots),\n    await Array.fromAsync(diffScreenshots),\n    config.outputDir,\n  );\n\n  const server = await createServer({\n    isProd: true,\n    outputDir: path.resolve(config.outputDir),\n    screenshots: groupedScreenshots,\n    logger: getLogger().level >= 4,\n    theme: config.review.theme,\n    diff: config.diff,\n  });\n\n  logger.success(\n    `Review UI available at http://localhost:${config.review.port}`,\n  );\n  await server.listen({ port: config.review.port });\n};\n","import type { Screenshot } from \"@cappa/core\";\nimport chalk from \"chalk\";\n\nconst severityColor = (severity: string) => {\n  switch (severity) {\n    case \"High\":\n      return chalk.red;\n    case \"Medium\":\n      return chalk.yellow;\n    case \"Low\":\n      return chalk.green;\n    default:\n      return chalk.gray;\n  }\n};\n\n/**\n * Build human-readable lines describing the changed screenshots, surfacing the\n * pixel-diff percentage and (when `diff.interpret` is enabled) the structured\n * interpretation: severity, region count and summary.\n *\n * Returns an empty array when there are no changed screenshots.\n */\nexport const describeChanges = (screenshots: Screenshot[]): string[] => {\n  const changed = screenshots.filter(\n    (screenshot) => screenshot.category === \"changed\",\n  );\n\n  if (changed.length === 0) {\n    return [];\n  }\n\n  const lines: string[] = [];\n\n  for (const screenshot of changed) {\n    const meta = screenshot.diffMeta;\n    const interpretation = meta?.interpretation;\n\n    const parts: string[] = [];\n    if (interpretation) {\n      parts.push(\n        severityColor(interpretation.severity)(\n          interpretation.severity.toUpperCase(),\n        ),\n      );\n    }\n    if (meta) {\n      parts.push(`${meta.percentDifference.toFixed(2)}%`);\n    }\n    if (interpretation) {\n      const { totalRegions } = interpretation;\n      parts.push(\n        `${totalRegions} ${totalRegions === 1 ? \"region\" : \"regions\"}`,\n      );\n    }\n\n    const suffix =\n      parts.length > 0\n        ? `  ${chalk.dim(\"·\")} ${parts.join(chalk.dim(\" · \"))}`\n        : \"\";\n    lines.push(`${chalk.bold(screenshot.name)}${suffix}`);\n\n    if (interpretation?.summary) {\n      lines.push(`  ${chalk.dim(interpretation.summary)}`);\n    }\n  }\n\n  return lines;\n};\n","import { glob } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getLogger } from \"@cappa/logger\";\nimport chalk from \"chalk\";\nimport { getConfig } from \"../features/config\";\nimport { describeChanges } from \"../utils/describeChanges\";\nimport { groupScreenshots } from \"../utils/groupScreenshots\";\n\nexport const status = async () => {\n  const logger = getLogger();\n\n  const config = await getConfig();\n\n  const actualScreenshotsPromise = glob(\n    path.resolve(config.outputDir, \"actual\", \"**/*.png\"),\n  );\n  const expectedScreenshotsPromise = glob(\n    path.resolve(config.outputDir, \"expected\", \"**/*.png\"),\n  );\n  const diffScreenshotsPromise = glob(\n    path.resolve(config.outputDir, \"diff\", \"**/*.png\"),\n  );\n\n  const [actualScreenshots, expectedScreenshots, diffScreenshots] =\n    await Promise.all([\n      actualScreenshotsPromise,\n      expectedScreenshotsPromise,\n      diffScreenshotsPromise,\n    ]);\n\n  const groupedScreenshots = await groupScreenshots(\n    await Array.fromAsync(actualScreenshots),\n    await Array.fromAsync(expectedScreenshots),\n    await Array.fromAsync(diffScreenshots),\n    config.outputDir,\n  );\n\n  logger.debug(\n    \"All screenshot information:\",\n    JSON.stringify(groupedScreenshots, null, 2),\n  );\n\n  logger.box({\n    title: \"Screenshot Status\",\n    message: `${chalk.yellow(\"New screenshots:\")} ${groupedScreenshots.filter((r) => r.category === \"new\").length}\\n${chalk.red(\"Deleted screenshots:\")} ${groupedScreenshots.filter((r) => r.category === \"deleted\").length}\\n${chalk.green(\"Changed screenshots:\")} ${groupedScreenshots.filter((r) => r.category === \"changed\").length}\\n${chalk.blue(\"Passed screenshots:\")} ${groupedScreenshots.filter((r) => r.category === \"passed\").length}`,\n  });\n\n  const changeLines = describeChanges(groupedScreenshots);\n  if (changeLines.length > 0) {\n    logger.box({\n      title: \"Changed Screenshots\",\n      message: changeLines.join(\"\\n\"),\n    });\n  }\n\n  if (\n    groupedScreenshots.some((s) =>\n      [\"new\", \"changed\", \"deleted\"].includes(s.category),\n    )\n  ) {\n    process.exitCode = 1;\n  }\n};\n","import { initLogger } from \"@cappa/logger\";\nimport { Command } from \"commander\";\nimport { version } from \"../package.json\";\nimport { approve } from \"./commands/approve\";\nimport { registerCaptureCommand } from \"./commands/capture\";\nimport { init } from \"./commands/init\";\nimport { review } from \"./commands/review\";\nimport { status } from \"./commands/status\";\n\nconst program = new Command();\n\nprogram\n  .name(\"cappa\")\n  .description(\"Cappa CLI\")\n  .version(version)\n  .option(\n    \"-l, --log-level <level>\",\n    \"set log level (0: fatal and error, 1: warn, 2: log, 3: info, 4: debug, 5: trace)\",\n    \"3\",\n  )\n  .hook(\"preAction\", (thisCommand) => {\n    const logLevel = parseInt(thisCommand.opts().logLevel, 10);\n    const logger = initLogger(logLevel);\n    logger?.debug(`Log level set to: ${logLevel}`);\n  });\n\nregisterCaptureCommand(program);\n\nprogram.command(\"review\").description(\"Review screenshots\").action(review);\n\nprogram\n  .command(\"approve\")\n  .description(\"Approve screenshots\")\n  .option(\n    \"-f, --filter <filter...>\",\n    \"only approve screenshots whose name includes the provided filter value(s)\",\n  )\n  .action(approve);\n\nprogram\n  .command(\"status\")\n  .description(\"Get status of screenshots\")\n  .action(status);\n\nprogram\n  .command(\"init\")\n  .description(\"Initialize Cappa in the current directory\")\n  .action(init);\n\nexport async function run(): Promise<void> {\n  await program.parseAsync();\n}\n"],"mappings":"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"}