{"version":3,"sources":["../../src/core/config.ts","../../src/xcode/platform.ts","../../src/core/transporter.ts","../../src/core/ipa-analyzer.ts","../../src/core/provisioning-profile.ts","../../src/core/simulator.ts","../../src/core/credentials.ts"],"names":["spawn","promisify","execFile","mkdtemp","join","tmpdir","readFile","plist","rm","execFileAsync","writeFile","plist2","unlink"],"mappings":"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","file":"index.cjs","sourcesContent":["export interface FastnodeConfig {\n  keyId?: string;\n  issuerId?: string;\n  privateKeyPath?: string;\n  teamId?: string;\n  bundleIdentifier?: string;\n  platform?: string;\n}\n\nexport function resolveConfig(_overrides?: Partial<FastnodeConfig>): FastnodeConfig {\n  return {\n    keyId: process.env.APP_STORE_CONNECT_API_KEY_KEY_ID,\n    issuerId: process.env.APP_STORE_CONNECT_API_KEY_ISSUER_ID,\n    privateKeyPath: process.env.APP_STORE_CONNECT_API_KEY_KEY_FILEPATH,\n    teamId: process.env.FASTLANE_TEAM_ID,\n    bundleIdentifier: process.env.FASTLANE_APP_IDENTIFIER,\n    platform: process.env.FASTLANE_PLATFORM_NAME,\n    ..._overrides,\n  };\n}\n","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 { spawn } from \"node:child_process\";\nimport { requireMacOS } from \"../xcode/platform.js\";\n\nexport class ItunesTransporter {\n  async upload(options: {\n    packagePath: string;\n    apiKeyId?: string;\n    apiIssuerId?: string;\n    onOutput?: (chunk: string) => void;\n  }): Promise<{ success: boolean; output: string }> {\n    requireMacOS(\"iTunes Transporter\");\n\n    const args = [\"altool\", \"--upload-app\", \"-f\", options.packagePath, \"-t\", \"ios\"];\n    if (options.apiKeyId) args.push(\"--apiKey\", options.apiKeyId);\n    if (options.apiIssuerId) args.push(\"--apiIssuer\", options.apiIssuerId);\n\n    return this.run(args, options.onOutput);\n  }\n\n  async verify(options: {\n    packagePath: string;\n    apiKeyId?: string;\n    apiIssuerId?: string;\n  }): Promise<{ success: boolean; output: string }> {\n    requireMacOS(\"iTunes Transporter\");\n\n    const args = [\"altool\", \"--validate-app\", \"-f\", options.packagePath, \"-t\", \"ios\"];\n    if (options.apiKeyId) args.push(\"--apiKey\", options.apiKeyId);\n    if (options.apiIssuerId) args.push(\"--apiIssuer\", options.apiIssuerId);\n\n    return this.run(args);\n  }\n\n  private run(args: string[], onOutput?: (chunk: string) => void): Promise<{ success: boolean; output: string }> {\n    return new Promise((resolve) => {\n      const child = spawn(\"xcrun\", args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n      let output = \"\";\n\n      child.stdout.on(\"data\", (data: Buffer) => {\n        const chunk = data.toString();\n        output += chunk;\n        onOutput?.(chunk);\n      });\n      child.stderr.on(\"data\", (data: Buffer) => {\n        const chunk = data.toString();\n        output += chunk;\n        onOutput?.(chunk);\n      });\n      child.on(\"close\", (code) => resolve({ success: code === 0, output }));\n    });\n  }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { mkdtemp, readFile, rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport * as plist from \"plist\";\n\nconst execFileAsync = promisify(execFile);\n\nexport interface IpaInfo {\n  bundleIdentifier: string;\n  bundleVersion: string;\n  bundleShortVersion: string;\n  appName: string;\n  minimumOSVersion: string;\n}\n\nexport async function analyzeIpa(ipaPath: string): Promise<IpaInfo> {\n  const tmpDir = await mkdtemp(join(tmpdir(), \"fastnode-ipa-\"));\n\n  try {\n    // Unzip every Info.plist under Payload/. Modern IPAs ship the main app\n    // alongside WatchKit apps, app extensions, intents, widgets, and more —\n    // we need enough to identify the main one and skip the rest.\n    await execFileAsync(\"unzip\", [\"-o\", ipaPath, \"Payload/**/Info.plist\", \"-d\", tmpDir]);\n\n    const { stdout } = await execFileAsync(\"find\", [\n      tmpDir,\n      \"-name\",\n      \"Info.plist\",\n      \"-path\",\n      \"*/Payload/*\",\n    ]);\n    const allPlistPaths = stdout\n      .trim()\n      .split(\"\\n\")\n      .filter((p) => p.length > 0);\n    if (allPlistPaths.length === 0) {\n      throw new Error(\"Info.plist not found in IPA\");\n    }\n\n    // Pick the main app's Info.plist. Fastlane's approach is to prefer the\n    // plist with the shortest path (main app lives at the top of Payload/,\n    // extensions/watch apps live nested underneath). We also skip any plist\n    // whose `WKWatchKitApp=true` to positively exclude WatchKit embeds.\n    const candidates = [...allPlistPaths].sort(\n      (a, b) => a.length - b.length\n    );\n\n    let plistPath: string | null = null;\n    let parsed: Record<string, any> | null = null;\n\n    for (const candidate of candidates) {\n      try {\n        await execFileAsync(\"plutil\", [\"-convert\", \"xml1\", candidate]);\n      } catch {\n        // May already be XML\n      }\n      const content = await readFile(candidate, \"utf-8\");\n      const data = plist.parse(content) as Record<string, any>;\n      if (data.WKWatchKitApp === true) continue; // skip WatchKit embed\n      plistPath = candidate;\n      parsed = data;\n      break;\n    }\n\n    if (!parsed) {\n      // Every candidate was a WatchKit embed — fall back to the shortest path.\n      plistPath = candidates[0];\n      const content = await readFile(plistPath, \"utf-8\");\n      parsed = plist.parse(content) as Record<string, any>;\n    }\n\n    return {\n      bundleIdentifier: parsed.CFBundleIdentifier ?? \"\",\n      bundleVersion: String(parsed.CFBundleVersion ?? \"\"),\n      bundleShortVersion: parsed.CFBundleShortVersionString ?? \"\",\n      appName: parsed.CFBundleName ?? parsed.CFBundleDisplayName ?? \"\",\n      minimumOSVersion: parsed.MinimumOSVersion ?? \"\",\n    };\n  } finally {\n    await rm(tmpDir, { recursive: true, force: true });\n  }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { writeFile, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport * as plist from \"plist\";\n\nconst execFileAsync = promisify(execFile);\n\nexport interface ProvisioningProfileInfo {\n  uuid: string;\n  name: string;\n  appIdName: string;\n  teamIdentifier: string[];\n  teamName: string;\n  creationDate: Date;\n  expirationDate: Date;\n  certificates: Buffer[];\n  provisionedDevices: string[];\n  entitlements: Record<string, unknown>;\n}\n\nexport async function parseProvisioningProfile(\n  data: Buffer\n): Promise<ProvisioningProfileInfo> {\n  // Write to temp file\n  const tempPath = join(tmpdir(), `fastnode-profile-${Date.now()}.mobileprovision`);\n  await writeFile(tempPath, data);\n\n  try {\n    // Extract the plist from the CMS/PKCS#7 envelope\n    const { stdout } = await execFileAsync(\"security\", [\"cms\", \"-D\", \"-i\", tempPath]);\n\n    const parsed = plist.parse(stdout) as Record<string, any>;\n\n    return {\n      uuid: parsed.UUID ?? \"\",\n      name: parsed.Name ?? \"\",\n      appIdName: parsed.AppIDName ?? \"\",\n      teamIdentifier: parsed.TeamIdentifier ?? [],\n      teamName: parsed.TeamName ?? \"\",\n      creationDate: new Date(parsed.CreationDate ?? 0),\n      expirationDate: new Date(parsed.ExpirationDate ?? 0),\n      certificates: (parsed.DeveloperCertificates ?? []).map((c: any) =>\n        Buffer.from(c, \"base64\")\n      ),\n      provisionedDevices: parsed.ProvisionedDevices ?? [],\n      entitlements: parsed.Entitlements ?? {},\n    };\n  } finally {\n    await unlink(tempPath).catch(() => {});\n  }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { requireMacOS } from \"../xcode/platform.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport interface Simulator {\n  udid: string;\n  name: string;\n  deviceType: string;\n  runtime: string;\n  state: \"Booted\" | \"Shutdown\";\n}\n\nexport class SimulatorManager {\n  async list(): Promise<Simulator[]> {\n    requireMacOS(\"simulator\");\n    const { stdout } = await execFileAsync(\"xcrun\", [\"simctl\", \"list\", \"devices\", \"-j\"]);\n    const data = JSON.parse(stdout);\n    const simulators: Simulator[] = [];\n\n    for (const [runtime, devices] of Object.entries(data.devices ?? {})) {\n      for (const device of devices as any[]) {\n        if (device.isAvailable) {\n          simulators.push({\n            udid: device.udid,\n            name: device.name,\n            deviceType: device.deviceTypeIdentifier ?? \"\",\n            runtime,\n            state: device.state === \"Booted\" ? \"Booted\" : \"Shutdown\",\n          });\n        }\n      }\n    }\n\n    return simulators;\n  }\n\n  async boot(udid: string): Promise<void> {\n    requireMacOS(\"simulator\");\n    try {\n      await execFileAsync(\"xcrun\", [\"simctl\", \"boot\", udid]);\n    } catch (err: unknown) {\n      const msg = err instanceof Error ? err.message : \"\";\n      if (!msg.includes(\"current state: Booted\")) throw err;\n    }\n  }\n\n  async shutdown(udid: string): Promise<void> {\n    requireMacOS(\"simulator\");\n    try {\n      await execFileAsync(\"xcrun\", [\"simctl\", \"shutdown\", udid]);\n    } catch {\n      // May already be shut down\n    }\n  }\n\n  async reset(udid: string): Promise<void> {\n    requireMacOS(\"simulator\");\n    await this.shutdown(udid);\n    await execFileAsync(\"xcrun\", [\"simctl\", \"erase\", udid]);\n  }\n\n  async install(udid: string, appPath: string): Promise<void> {\n    requireMacOS(\"simulator\");\n    await execFileAsync(\"xcrun\", [\"simctl\", \"install\", udid, appPath]);\n  }\n\n  async findBestMatch(deviceName: string, runtime?: string): Promise<Simulator | null> {\n    const all = await this.list();\n    const matching = all.filter((s) =>\n      s.name.toLowerCase().includes(deviceName.toLowerCase()) &&\n      (!runtime || s.runtime.includes(runtime))\n    );\n\n    if (matching.length === 0) return null;\n    // Prefer latest runtime\n    matching.sort((a, b) => b.runtime.localeCompare(a.runtime));\n    return matching[0];\n  }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nexport class CredentialManager {\n  private serviceName: string;\n\n  constructor(serviceName = \"fastnode\") {\n    this.serviceName = serviceName;\n  }\n\n  async get(service: string, account: string): Promise<string | null> {\n    // Check env vars first\n    const envKey = `${service.toUpperCase()}_${account.toUpperCase()}`.replace(/[^A-Z0-9]/g, \"_\");\n    if (process.env[envKey]) return process.env[envKey]!;\n\n    // Try macOS keychain\n    if (process.platform === \"darwin\") {\n      try {\n        const { stdout } = await execFileAsync(\"security\", [\n          \"find-generic-password\",\n          \"-s\", service,\n          \"-a\", account,\n          \"-w\",\n        ]);\n        return stdout.trim();\n      } catch {\n        return null;\n      }\n    }\n\n    return null;\n  }\n\n  async set(service: string, account: string, password: string): Promise<void> {\n    if (process.platform === \"darwin\") {\n      await execFileAsync(\"security\", [\n        \"add-generic-password\",\n        \"-U\",\n        \"-s\", service,\n        \"-a\", account,\n        \"-w\", password,\n      ]);\n    }\n  }\n\n  async delete(service: string, account: string): Promise<void> {\n    if (process.platform === \"darwin\") {\n      try {\n        await execFileAsync(\"security\", [\n          \"delete-generic-password\",\n          \"-s\", service,\n          \"-a\", account,\n        ]);\n      } catch {\n        // May not exist\n      }\n    }\n  }\n}\n"]}