{"version":3,"sources":["../../src/xcode/platform.ts","../../src/snapshot/simulator.ts","../../src/snapshot/index.ts"],"names":["join","existsSync","mkdirSync","writeFileSync","promisify","execFile","execFileAsync","setInterfaceStyle","spawn","readdirSync","extname","basename","copyFileSync"],"mappings":"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","file":"index.cjs","sourcesContent":["export function requireMacOS(feature: string): void {\n  if (process.platform !== \"darwin\") {\n    throw new Error(\n      `${feature} requires macOS. This operation uses Xcode command-line tools ` +\n      `which are not available on ${process.platform}.`\n    );\n  }\n}\n\nexport function isMacOS(): boolean {\n  return process.platform === \"darwin\";\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { requireMacOS } from \"../xcode/platform.js\";\n\nconst execFileAsync = promisify(execFile);\n\n// ── Types ──────────────────────────────────────────────────────────────────\n\nexport interface SimDevice {\n  udid: string;\n  name: string;\n  state: \"Booted\" | \"Shutdown\" | \"Shutting Down\" | \"Creating\";\n  isAvailable: boolean;\n  runtime: string;\n  deviceTypeIdentifier: string;\n}\n\ninterface SimctlDevicesJson {\n  devices: Record<\n    string,\n    Array<{\n      udid: string;\n      name: string;\n      state: string;\n      isAvailable: boolean;\n      deviceTypeIdentifier: string;\n    }>\n  >;\n}\n\n// ── Simulator Listing & Lookup ─────────────────────────────────────────────\n\nexport async function listSimulators(): Promise<SimDevice[]> {\n  requireMacOS(\"Simulator management\");\n  const { stdout } = await execFileAsync(\"xcrun\", [\"simctl\", \"list\", \"devices\", \"-j\"]);\n  const parsed: SimctlDevicesJson = JSON.parse(stdout);\n  const devices: SimDevice[] = [];\n  for (const [runtimeId, runtimeDevices] of Object.entries(parsed.devices)) {\n    for (const dev of runtimeDevices) {\n      devices.push({\n        udid: dev.udid,\n        name: dev.name,\n        state: dev.state as SimDevice[\"state\"],\n        isAvailable: dev.isAvailable,\n        runtime: runtimeId,\n        deviceTypeIdentifier: dev.deviceTypeIdentifier,\n      });\n    }\n  }\n  return devices;\n}\n\nexport async function findDevice(\n  deviceName: string,\n  runtimeFilter?: string,\n): Promise<SimDevice | null> {\n  const devices = await listSimulators();\n  const candidates = devices.filter((d) => {\n    if (!d.isAvailable) return false;\n    if (d.name !== deviceName) return false;\n    if (runtimeFilter && !d.runtime.includes(runtimeFilter)) return false;\n    return true;\n  });\n  if (candidates.length === 0) return null;\n  const booted = candidates.find((d) => d.state === \"Booted\");\n  return booted ?? candidates[0];\n}\n\n// ── Boot / Shutdown / Erase ────────────────────────────────────────────────\n\nexport async function bootSimulator(udid: string): Promise<void> {\n  requireMacOS(\"Simulator management\");\n  const devices = await listSimulators();\n  const device = devices.find((d) => d.udid === udid);\n  if (device?.state === \"Booted\") return;\n  await execFileAsync(\"xcrun\", [\"simctl\", \"boot\", udid]);\n  const deadline = Date.now() + 30_000;\n  while (Date.now() < deadline) {\n    const refreshed = await listSimulators();\n    const current = refreshed.find((d) => d.udid === udid);\n    if (current?.state === \"Booted\") return;\n    await new Promise((r) => setTimeout(r, 1000));\n  }\n}\n\nexport async function shutdownAll(): Promise<void> {\n  requireMacOS(\"Simulator management\");\n  await execFileAsync(\"xcrun\", [\"simctl\", \"shutdown\", \"all\"]);\n}\n\nexport async function eraseSimulator(udid: string): Promise<void> {\n  requireMacOS(\"Simulator management\");\n  const devices = await listSimulators();\n  const device = devices.find((d) => d.udid === udid);\n  if (device?.state === \"Booted\") {\n    await execFileAsync(\"xcrun\", [\"simctl\", \"shutdown\", udid]);\n  }\n  await execFileAsync(\"xcrun\", [\"simctl\", \"erase\", udid]);\n}\n\n// ── Locale / Language ──────────────────────────────────────────────────────\n\nexport async function localizeSimulator(\n  udid: string,\n  language: string,\n  locale?: string,\n): Promise<void> {\n  requireMacOS(\"Simulator management\");\n  const deviceDataPath = getDeviceDataPath(udid);\n  const prefsDir = join(deviceDataPath, \"data\", \"Library\", \"Preferences\");\n  const prefsFile = join(prefsDir, \".GlobalPreferences.plist\");\n  if (!existsSync(prefsDir)) {\n    mkdirSync(prefsDir, { recursive: true });\n  }\n  const effectiveLocale = locale ?? language.replace(\"-\", \"_\");\n  const plistXml = [\n    '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n    '<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">',\n    '<plist version=\"1.0\">',\n    \"<dict>\",\n    \"  <key>AppleLanguages</key>\",\n    \"  <array>\",\n    \"    <string>\" + escapeXml(language) + \"</string>\",\n    \"  </array>\",\n    \"  <key>AppleLocale</key>\",\n    \"  <string>\" + escapeXml(effectiveLocale) + \"</string>\",\n    \"  <key>AppleKeyboards</key>\",\n    \"  <array>\",\n    \"    <string>\" + escapeXml(effectiveLocale) + \"@sw=QWERTY;hw=Automatic</string>\",\n    \"  </array>\",\n    \"  <key>AppleKeyboardsExpanded</key>\",\n    \"  <integer>1</integer>\",\n    \"</dict>\",\n    \"</plist>\",\n  ].join(\"\\n\");\n  writeFileSync(prefsFile, plistXml, \"utf-8\");\n  try {\n    await execFileAsync(\"plutil\", [\"-convert\", \"binary1\", prefsFile]);\n  } catch {\n    // XML plist is still readable\n  }\n}\n\n// ── UI Customization ───────────────────────────────────────────────────────\n\nexport async function setInterfaceStyle(\n  udid: string,\n  style: \"light\" | \"dark\",\n): Promise<void> {\n  requireMacOS(\"Simulator management\");\n  const appearance = style === \"dark\" ? \"dark\" : \"light\";\n  await execFileAsync(\"xcrun\", [\"simctl\", \"ui\", udid, \"appearance\", appearance]);\n}\n\nexport async function overrideStatusBar(\n  udid: string,\n  options?: {\n    time?: string;\n    batteryLevel?: number;\n    batteryState?: \"charged\" | \"charging\" | \"discharging\";\n    wifiMode?: \"active\" | \"searching\" | \"failed\";\n    cellularMode?: \"active\" | \"searching\" | \"failed\" | \"notSupported\";\n    dataNetwork?: \"wifi\" | \"3g\" | \"4g\" | \"lte\" | \"lte-a\" | \"lte+\" | \"5g\" | \"5g+\" | \"5g-uwb\";\n  },\n): Promise<void> {\n  requireMacOS(\"Simulator management\");\n  const args = [\n    \"simctl\", \"status_bar\", udid, \"override\",\n    \"--time\", options?.time ?? \"9:41\",\n    \"--batteryLevel\", String(options?.batteryLevel ?? 100),\n    \"--batteryState\", options?.batteryState ?? \"charged\",\n    \"--wifiMode\", options?.wifiMode ?? \"active\",\n    \"--wifiBars\", \"3\",\n    \"--cellularMode\", options?.cellularMode ?? \"active\",\n    \"--cellularBars\", \"4\",\n  ];\n  if (options?.dataNetwork) {\n    args.push(\"--dataNetwork\", options.dataNetwork);\n  }\n  await execFileAsync(\"xcrun\", args);\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\nfunction getDeviceDataPath(udid: string): string {\n  const home = process.env.HOME ?? process.env.USERPROFILE ?? \"/tmp\";\n  return join(home, \"Library\", \"Developer\", \"CoreSimulator\", \"Devices\", udid);\n}\n\nfunction escapeXml(str: string): string {\n  return str\n    .replace(/&/g, \"&amp;\")\n    .replace(/</g, \"&lt;\")\n    .replace(/>/g, \"&gt;\")\n    .replace(/\"/g, \"&quot;\")\n    .replace(/'/g, \"&apos;\");\n}\n","import { execFile, spawn } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { existsSync, mkdirSync, readdirSync, copyFileSync } from \"node:fs\";\nimport { join, basename, extname } from \"node:path\";\nimport { requireMacOS } from \"../xcode/platform.js\";\nimport {\n  findDevice,\n  bootSimulator,\n  shutdownAll,\n  localizeSimulator,\n  overrideStatusBar,\n  eraseSimulator,\n} from \"./simulator.js\";\nimport type { SimDevice } from \"./simulator.js\";\n\nconst execFileAsync = promisify(execFile);\n\n// ── Re-export simulator utilities ──────────────────────────────────────────\n\nexport {\n  listSimulators,\n  findDevice,\n  bootSimulator,\n  shutdownAll,\n  eraseSimulator,\n  localizeSimulator,\n  setInterfaceStyle,\n  overrideStatusBar,\n} from \"./simulator.js\";\n\nexport type { SimDevice } from \"./simulator.js\";\n\n// ── Types ──────────────────────────────────────────────────────────────────\n\nexport interface SnapshotOptions {\n  scheme?: string;\n  workspace?: string;\n  project?: string;\n  devices: string[];\n  languages: string[];\n  outputDirectory?: string;\n  clearPreviousScreenshots?: boolean;\n  launchArguments?: string[];\n  concurrent?: boolean;\n  numberOfRetries?: number;\n  darkMode?: boolean;\n  overrideStatusBar?: boolean;\n  eraseSimulatorBeforeRun?: boolean;\n  derivedDataPath?: string;\n  testPlan?: string;\n  configuration?: string;\n  xcargs?: string;\n  onOutput?: (chunk: string) => void;\n}\n\nexport interface ScreenshotResult {\n  success: boolean;\n  screenshots: Record<string, Record<string, string[]>>;\n  failedDevices: string[];\n}\n\n// ── Main Entry Point ───────────────────────────────────────────────────────\n\n/**\n * Capture screenshots across a device x language matrix.\n *\n * Mirrors Fastlane snapshot's runner:\n *  1. Validate macOS\n *  2. Build device x language matrix\n *  3. For each combination: boot sim, set locale, run xcodebuild test, collect screenshots\n *  4. Return aggregated ScreenshotResult\n */\nexport async function captureScreenshots(\n  options: SnapshotOptions,\n): Promise<ScreenshotResult> {\n  requireMacOS(\"Screenshot capture\");\n\n  // Validate required options\n  if (!options.scheme && !options.workspace && !options.project) {\n    throw new Error(\n      \"At least one of scheme, workspace, or project must be specified\",\n    );\n  }\n  if (options.devices.length === 0) {\n    throw new Error(\"At least one device must be specified\");\n  }\n  if (options.languages.length === 0) {\n    throw new Error(\"At least one language must be specified\");\n  }\n\n  const outputDir = options.outputDirectory ?? join(process.cwd(), \"screenshots\");\n  const retries = options.numberOfRetries ?? 1;\n\n  // Clear previous screenshots if requested\n  if (options.clearPreviousScreenshots && existsSync(outputDir)) {\n    const { rm } = await import(\"node:fs/promises\");\n    await rm(outputDir, { recursive: true, force: true });\n  }\n\n  mkdirSync(outputDir, { recursive: true });\n\n  const screenshots: Record<string, Record<string, string[]>> = {};\n  const failedDevices: string[] = [];\n\n  // Build the device x language matrix\n  const matrix = buildMatrix(options.devices, options.languages);\n\n  if (options.concurrent) {\n    // Run all combinations in parallel\n    const results = await Promise.allSettled(\n      matrix.map((entry) =>\n        runSingleCombination(entry, options, outputDir, retries),\n      ),\n    );\n\n    for (let i = 0; i < results.length; i++) {\n      const result = results[i];\n      const entry = matrix[i];\n      if (result.status === \"fulfilled\") {\n        mergeScreenshots(screenshots, result.value);\n      } else {\n        const key = entry.device + \" / \" + entry.language;\n        failedDevices.push(key);\n      }\n    }\n  } else {\n    // Run sequentially\n    for (const entry of matrix) {\n      try {\n        const result = await runSingleCombination(\n          entry,\n          options,\n          outputDir,\n          retries,\n        );\n        mergeScreenshots(screenshots, result);\n      } catch {\n        const key = entry.device + \" / \" + entry.language;\n        failedDevices.push(key);\n      }\n    }\n  }\n\n  return {\n    success: failedDevices.length === 0,\n    screenshots,\n    failedDevices,\n  };\n}\n\n// ── Internal: Matrix Construction ──────────────────────────────────────────\n\ninterface MatrixEntry {\n  device: string;\n  language: string;\n}\n\nfunction buildMatrix(devices: string[], languages: string[]): MatrixEntry[] {\n  const entries: MatrixEntry[] = [];\n  for (const device of devices) {\n    for (const language of languages) {\n      entries.push({ device, language });\n    }\n  }\n  return entries;\n}\n\n// ── Internal: Single Combination Runner ────────────────────────────────────\n\nasync function runSingleCombination(\n  entry: MatrixEntry,\n  options: SnapshotOptions,\n  outputDir: string,\n  retries: number,\n): Promise<Record<string, Record<string, string[]>>> {\n  const { device: deviceName, language } = entry;\n\n  // Find the simulator device\n  const simDevice = await findDevice(deviceName);\n  if (!simDevice) {\n    throw new Error(\"Simulator device not found: \" + deviceName);\n  }\n\n  let lastError: Error | null = null;\n\n  for (let attempt = 0; attempt < retries; attempt++) {\n    try {\n      return await runOnSimulator(simDevice, language, options, outputDir);\n    } catch (err) {\n      lastError = err instanceof Error ? err : new Error(String(err));\n      options.onOutput?.(\n        \"Attempt \" + (attempt + 1) + \" failed for \" + deviceName + \" / \" + language + \": \" + lastError.message + \"\\n\",\n      );\n    }\n  }\n\n  throw lastError ?? new Error(\"All retries exhausted\");\n}\n\nasync function runOnSimulator(\n  simDevice: SimDevice,\n  language: string,\n  options: SnapshotOptions,\n  outputDir: string,\n): Promise<Record<string, Record<string, string[]>>> {\n  const udid = simDevice.udid;\n  const deviceName = simDevice.name;\n\n  // Erase simulator if requested\n  if (options.eraseSimulatorBeforeRun) {\n    await eraseSimulator(udid);\n  }\n\n  // Shut down, localize, then boot\n  try {\n    await execFileAsync(\"xcrun\", [\"simctl\", \"shutdown\", udid]);\n  } catch {\n    // May already be shutdown\n  }\n\n  await localizeSimulator(udid, language);\n  await bootSimulator(udid);\n\n  // Override status bar for clean screenshots\n  if (options.overrideStatusBar !== false) {\n    try {\n      await overrideStatusBar(udid);\n    } catch {\n      // Status bar override may fail on older simulators\n    }\n  }\n\n  // Set dark mode if requested\n  if (options.darkMode) {\n    try {\n      const { setInterfaceStyle } = await import(\"./simulator.js\");\n      await setInterfaceStyle(udid, \"dark\");\n    } catch {\n      // Dark mode may not be available\n    }\n  }\n\n  // Determine the derived data path (used to find screenshots)\n  const derivedDataPath =\n    options.derivedDataPath ??\n    join(outputDir, \".derived-data\", deviceName + \"-\" + language);\n  mkdirSync(derivedDataPath, { recursive: true });\n\n  // Run xcodebuild test\n  const exitCode = await runXcodebuildTest(\n    udid,\n    derivedDataPath,\n    options,\n  );\n\n  if (exitCode !== 0 && exitCode !== 65) {\n    // Exit code 65 = test failures but screenshots may still exist\n    throw new Error(\n      \"xcodebuild test failed with exit code \" + exitCode,\n    );\n  }\n\n  // Collect screenshots from derived data and the simulator's data dir\n  const deviceOutputDir = join(outputDir, deviceName, language);\n  mkdirSync(deviceOutputDir, { recursive: true });\n\n  const collectedPaths = collectScreenshots(derivedDataPath, deviceOutputDir);\n\n  // Also collect from the simulator's screenshot directory\n  const simScreenshotDir = getSimulatorScreenshotDir(udid);\n  if (existsSync(simScreenshotDir)) {\n    const simPaths = collectScreenshots(simScreenshotDir, deviceOutputDir);\n    collectedPaths.push(...simPaths);\n  }\n\n  const result: Record<string, Record<string, string[]>> = {};\n  if (!result[deviceName]) result[deviceName] = {};\n  result[deviceName][language] = collectedPaths;\n\n  return result;\n}\n\n// ── Internal: xcodebuild test ──────────────────────────────────────────────\n\nfunction runXcodebuildTest(\n  udid: string,\n  derivedDataPath: string,\n  options: SnapshotOptions,\n): Promise<number> {\n  return new Promise((resolve) => {\n    const args = buildXcodebuildArgs(udid, derivedDataPath, options);\n\n    const proc = spawn(\"xcodebuild\", args, {\n      stdio: [\"ignore\", \"pipe\", \"pipe\"],\n    });\n\n    let output = \"\";\n\n    proc.stdout.on(\"data\", (chunk: Buffer) => {\n      const text = chunk.toString();\n      output += text;\n      options.onOutput?.(text);\n    });\n\n    proc.stderr.on(\"data\", (chunk: Buffer) => {\n      const text = chunk.toString();\n      output += text;\n      options.onOutput?.(text);\n    });\n\n    proc.on(\"close\", (code) => {\n      resolve(code ?? 1);\n    });\n\n    proc.on(\"error\", () => {\n      resolve(1);\n    });\n  });\n}\n\nfunction buildXcodebuildArgs(\n  udid: string,\n  derivedDataPath: string,\n  options: SnapshotOptions,\n): string[] {\n  const args: string[] = [];\n\n  if (options.workspace) {\n    args.push(\"-workspace\", options.workspace);\n  } else if (options.project) {\n    args.push(\"-project\", options.project);\n  }\n\n  if (options.scheme) {\n    args.push(\"-scheme\", options.scheme);\n  }\n\n  if (options.configuration) {\n    args.push(\"-configuration\", options.configuration);\n  }\n\n  args.push(\n    \"-destination\",\n    \"platform=iOS Simulator,id=\" + udid,\n    \"-derivedDataPath\",\n    derivedDataPath,\n    \"test\",\n  );\n\n  if (options.testPlan) {\n    args.push(\"-testPlan\", options.testPlan);\n  }\n\n  // Append launch arguments as build settings\n  if (options.launchArguments && options.launchArguments.length > 0) {\n    const launchArgsStr = options.launchArguments\n      .map((a) => \"'\" + a + \"'\")\n      .join(\" \");\n    args.push(\"SNAPSHOT_LAUNCH_ARGUMENTS=\" + launchArgsStr);\n  }\n\n  if (options.xcargs) {\n    // Split xcargs by spaces (simple split, doesn't handle quoted strings)\n    args.push(...options.xcargs.split(/\\s+/).filter(Boolean));\n  }\n\n  return args;\n}\n\n// ── Internal: Screenshot Collection ────────────────────────────────────────\n\nfunction collectScreenshots(\n  sourceDir: string,\n  destDir: string,\n): string[] {\n  const collected: string[] = [];\n\n  if (!existsSync(sourceDir)) return collected;\n\n  const screenshotExtensions = new Set([\".png\", \".jpg\", \".jpeg\"]);\n\n  function walk(dir: string): void {\n    let entries: string[];\n    try {\n      entries = readdirSync(dir, { withFileTypes: true }).map((e) => {\n        if (e.isDirectory()) {\n          walk(join(dir, e.name));\n          return \"\";\n        }\n        return e.name;\n      }).filter(Boolean);\n    } catch {\n      return;\n    }\n\n    for (const name of entries) {\n      const ext = extname(name).toLowerCase();\n      if (screenshotExtensions.has(ext)) {\n        const srcPath = join(dir, name);\n        const destPath = join(destDir, basename(name));\n        try {\n          copyFileSync(srcPath, destPath);\n          collected.push(destPath);\n        } catch {\n          // Skip files we can't copy\n        }\n      }\n    }\n  }\n\n  walk(sourceDir);\n  return collected;\n}\n\nfunction getSimulatorScreenshotDir(udid: string): string {\n  const home = process.env.HOME ?? process.env.USERPROFILE ?? \"/tmp\";\n  return join(\n    home,\n    \"Library\",\n    \"Developer\",\n    \"CoreSimulator\",\n    \"Devices\",\n    udid,\n    \"data\",\n    \"tmp\",\n    \"Screenshots\",\n  );\n}\n\n// ── Internal: Merge screenshot results ─────────────────────────────────────\n\nfunction mergeScreenshots(\n  target: Record<string, Record<string, string[]>>,\n  source: Record<string, Record<string, string[]>>,\n): void {\n  for (const [device, languages] of Object.entries(source)) {\n    if (!target[device]) target[device] = {};\n    for (const [lang, paths] of Object.entries(languages)) {\n      if (!target[device][lang]) target[device][lang] = [];\n      target[device][lang].push(...paths);\n    }\n  }\n}\n"]}