@mcesystems/apple-kit 1.0.3 → 1.0.5

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/dist/index.js CHANGED
@@ -466,6 +466,10 @@ async function startPortForwardAsync(localPort, devicePort, udid, _timeout = 5e3
466
466
  }
467
467
  return result;
468
468
  }
469
+ async function closePortForward(udid) {
470
+ logTask(`Closing port forward for device ${udid}`);
471
+ await runIDeviceTool("iproxy", ["-u", udid, "-c"]);
472
+ }
469
473
 
470
474
  // src/logic/appleDeviceKit.ts
471
475
  var AppleDeviceKit = class {
@@ -608,6 +612,9 @@ var AppleDeviceKit = class {
608
612
  getPort() {
609
613
  return this.port;
610
614
  }
615
+ async closePortForward() {
616
+ return closePortForward(this.deviceId);
617
+ }
611
618
  };
612
619
 
613
620
  // src/logic/devicesMonitor.ts
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/utils/debug.ts", "../src/logic/actions/device.ts", "../src/logic/dataParser.ts", "../src/logic/actions/activation.ts", "../src/logic/actions/pair.ts", "../src/logic/actions/install.ts", "../src/logic/actions/proxy.ts", "../src/logic/appleDeviceKit.ts", "../src/logic/devicesMonitor.ts"],
4
- "sourcesContent": ["import createDebug from \"debug\";\r\n\r\nconst debug = createDebug(\"apple-kit\");\r\nconst debugTask = createDebug(\"apple-kit:task\");\r\nconst debugWarning = createDebug(\"apple-kit:warning\");\r\nconst debugError = createDebug(\"apple-kit:error\");\r\n\r\n/**\r\n * Log general information\r\n */\r\nexport function logInfo(message: string): void {\r\n\tdebug(message);\r\n}\r\n\r\n/**\r\n * Log task-specific information\r\n */\r\nexport function logTask(message: string): void {\r\n\tdebugTask(message);\r\n}\r\n\r\n/**\r\n * Log warning messages\r\n */\r\nexport function logWarning(message: string): void {\r\n\tdebugWarning(message);\r\n}\r\n\r\n/**\r\n * Log error messages\r\n */\r\nexport function logError(message: string): void {\r\n\tdebugError(message);\r\n}\r\n\r\n", "import { type ExecOptions, exec as execCallback } from \"node:child_process\";\r\nimport { existsSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\nimport { promisify } from \"node:util\";\r\nimport type { AppleToolType, DeviceListEntry } from \"@/types\";\r\nimport type { iOSDeviceInfo } from \"@/types\";\r\nimport { logTask } from \"@/utils/debug\";\r\nimport { parseDeviceList, parsePlistOutput } from \"../dataParser\";\r\n\r\nconst execAsync = promisify(execCallback);\r\n\r\nexport interface ExecResult {\r\n\tstdout: string;\r\n\tstderr: string;\r\n}\r\n\r\nexport async function getDeviceInfo(udid: string): Promise<iOSDeviceInfo> {\r\n\tlogTask(`Getting device info for ${udid}`);\r\n\r\n\tconst result = await runIDeviceTool(\"ideviceinfo\", [\"-u\", udid]);\r\n\tif (!result) {\r\n\t\tthrow new Error(\"Failed to get device info\");\r\n\t}\r\n\r\n\tconst props = parsePlistOutput(result.stdout);\r\n\r\n\treturn {\r\n\t\tdeviceName: props.DeviceName || \"\",\r\n\t\tproductType: props.ProductType || \"\",\r\n\t\tproductVersion: props.ProductVersion || \"\",\r\n\t\tbuildVersion: props.BuildVersion || \"\",\r\n\t\tserialNumber: props.SerialNumber || \"\",\r\n\t\tudid: props.UniqueDeviceID || udid,\r\n\t\twifiAddress: props.WiFiAddress || \"\",\r\n\t\tbluetoothAddress: props.BluetoothAddress || \"\",\r\n\t\tphoneNumber: props.PhoneNumber || \"\",\r\n\t\tcpuArchitecture: props.CPUArchitecture || \"\",\r\n\t\thardwareModel: props.HardwareModel || \"\",\r\n\t\tmodelNumber: props.ModelNumber || \"\",\r\n\t\tregionInfo: props.RegionInfo || \"\",\r\n\t\ttimeZone: props.TimeZone || \"\",\r\n\t\tuniqueChipID: props.UniqueChipID || \"\",\r\n\t\tisPaired: true, // If we can get info, device is paired\r\n\t};\r\n}\r\n\r\nexport async function listDevices(): Promise<DeviceListEntry[]> {\r\n\ttry {\r\n\t\tconst result = await runIDeviceTool(\"idevice_id\", [\"-l\"]);\r\n\t\tif (!result) {\r\n\t\t\treturn [];\r\n\t\t}\r\n\r\n\t\treturn parseDeviceList(result.stdout);\r\n\t} catch {\r\n\t\treturn [];\r\n\t}\r\n}\r\n\r\n/**\r\n * Execute an idevice tool command\r\n */\r\nexport async function runIDeviceTool(\r\n\ttoolName: AppleToolType,\r\n\targs: string[] = [],\r\n\toptions: ExecOptions = {}\r\n): Promise<ExecResult> {\r\n\tconst command = `\"${toolName}${process.platform === \"win32\" ? \".exe\" : \"\"}\" ${args.map((a) => `\"${a}\"`).join(\" \")}`;\r\n\treturn execIDevice(command, options);\r\n}\r\n\r\n/**\r\n * Execute a command with idevice tools in PATH\r\n */\r\nasync function execIDevice(command: string, options: ExecOptions = {}): Promise<ExecResult> {\r\n\tconst binPath = getIDeviceBinPath();\r\n\r\n\toptions.cwd = binPath;\r\n\r\n\tconst result = await execAsync(command, {\r\n\t\t...options,\r\n\t\tenv: process.env,\r\n\t\twindowsHide: true,\r\n\t\tencoding: \"utf8\",\r\n\t});\r\n\r\n\treturn {\r\n\t\tstdout: result.stdout.toString(),\r\n\t\tstderr: result.stderr.toString(),\r\n\t};\r\n}\r\n\r\n/**\r\n * Get the path to idevice binaries from resources\r\n */\r\nfunction getResourcesBinPath(): string {\r\n\tconst binPath = process.env.IDeviceBinPath;\r\n\tif (!binPath) {\r\n\t\tthrow new Error(\"IDeviceBinPath is not set\");\r\n\t}\r\n\treturn binPath;\r\n}\r\n\r\n/**\r\n * Get the path to a specific idevice tool\r\n */\r\nfunction getIDeviceToolPath(toolName: string): string | null {\r\n\tconst binPath = getResourcesBinPath();\r\n\tconst ext = process.platform === \"win32\" ? \".exe\" : \"\";\r\n\tconst toolPath = join(binPath, `${toolName}${ext}`);\r\n\r\n\tif (existsSync(toolPath)) {\r\n\t\treturn toolPath;\r\n\t}\r\n\r\n\treturn null;\r\n}\r\n\r\n/**\r\n * Get paths to all required idevice tools\r\n */\r\nexport function getIDeviceTools() {\r\n\treturn {\r\n\t\tidevice_id: getIDeviceToolPath(\"idevice_id\"),\r\n\t\tideviceinfo: getIDeviceToolPath(\"ideviceinfo\"),\r\n\t\tideviceinstaller: getIDeviceToolPath(\"ideviceinstaller\"),\r\n\t\tidevicepair: getIDeviceToolPath(\"idevicepair\"),\r\n\t\tidevicename: getIDeviceToolPath(\"idevicename\"),\r\n\t\tidevicedebug: getIDeviceToolPath(\"idevicedebug\"),\r\n\t\tiproxy: getIDeviceToolPath(\"iproxy\"),\r\n\t\tideviceactivation: getIDeviceToolPath(\"ideviceactivation\"),\r\n\t};\r\n}\r\n\r\n/**\r\n * Get the bin path for PATH environment variable\r\n */\r\nfunction getIDeviceBinPath(): string {\r\n\treturn getResourcesBinPath();\r\n}\r\n", "import type { AppInfo, DeviceListEntry } from \"../types\";\r\n\r\n\r\n/**\r\n * Parse plist-style output from ideviceinfo\r\n * \r\n * @param output ideviceinfo output\r\n * @returns Plist output\r\n */\r\nexport function parsePlistOutput(output: string): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n const lines = output.split(\"\\n\");\r\n\r\n for (const line of lines) {\r\n const colonIndex = line.indexOf(\":\");\r\n if (colonIndex > 0) {\r\n const key = line.substring(0, colonIndex).trim();\r\n const value = line.substring(colonIndex + 1).trim();\r\n result[key] = value;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Parse idevice_id output\r\n * \r\n * @param output idevice_id output\r\n * @returns Device list\r\n */\r\nexport function parseDeviceList(output: string): DeviceListEntry[] {\r\n const devices: DeviceListEntry[] = [];\r\n const lines = output.trim().split(\"\\n\");\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (trimmed) {\r\n // Format: \"UDID (connection type)\" or just \"UDID\"\r\n const match = trimmed.match(/^([A-Fa-f0-9-]+)(?:\\s+\\((\\w+)\\))?/);\r\n if (match) {\r\n devices.push({\r\n udid: match[1],\r\n connectionType: match[2] === \"Network\" ? 2 : 1,\r\n });\r\n }\r\n }\r\n }\r\n\r\n return devices;\r\n}\r\n\r\n/**\r\n * Parse ideviceinstaller list output\r\n * \r\n * @param output ideviceinstaller list output\r\n * @returns App list\r\n */\r\nexport function parseAppList(output: string): AppInfo[] {\r\n const apps: AppInfo[] = [];\r\n const lines = output.trim().split(\"\\n\");\r\n\r\n for (const line of lines) {\r\n // Format: \"com.example.app, Version, \"Display Name\"\"\r\n const match = line.match(/^([^,]+),\\s*([^,]+),\\s*\"?([^\"]+)\"?/);\r\n if (match) {\r\n apps.push({\r\n bundleId: match[1].trim(),\r\n version: match[2].trim(),\r\n displayName: match[3].trim(),\r\n bundleVersion: \"\",\r\n });\r\n }\r\n }\r\n\r\n return apps;\r\n}", "import type { ActivationState } from \"@/types\";\r\nimport { logTask } from \"@/utils/debug\";\r\nimport { runIDeviceTool } from \"./device\";\r\n\r\nexport async function getActivationState(udid: string): Promise<ActivationState> {\r\n\tlogTask(`Getting activation state for device ${udid}`);\r\n\r\n\ttry {\r\n\t\tconst result = await runIDeviceTool(\"ideviceinfo\", [\"-u\", udid, \"-k\", \"ActivationState\"]);\r\n\t\tif (!result) {\r\n\t\t\treturn {\r\n\t\t\t\tisActivated: false,\r\n\t\t\t\tactivationState: \"Unknown\",\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tconst { stdout } = result;\r\n\t\tconst state = stdout.trim();\r\n\r\n\t\treturn {\r\n\t\t\tisActivated: state === \"Activated\",\r\n\t\t\tactivationState: state,\r\n\t\t};\r\n\t} catch {\r\n\t\treturn {\r\n\t\t\tisActivated: false,\r\n\t\t\tactivationState: \"Unknown\",\r\n\t\t};\r\n\t}\r\n}\r\n\r\nexport async function activate(udid: string): Promise<boolean> {\r\n\tlogTask(`Activating device ${udid}`);\r\n\r\n\ttry {\r\n\t\tconst result = await runIDeviceTool(\"ideviceactivation\", [\"-u\", udid, \"activate\"]);\r\n\t\tif (!result) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\treturn (\r\n\t\t\tresult.stdout.toLowerCase().includes(\"success\") ||\r\n\t\t\tresult.stdout.toLowerCase().includes(\"activated\")\r\n\t\t);\r\n\t} catch (error) {\r\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\tthrow new Error(`Activation failed: ${errorMsg}`);\r\n\t}\r\n}\r\n\r\nexport interface ApplicationConfig {\r\n\tname: string;\r\n\tbundleId: string;\r\n\tversion: string;\r\n\tbuild: string;\r\n\ticon: string;\r\n\ticonData: Buffer;\r\n}\r\n", "import { logInfo, logTask } from \"@/utils/debug\";\r\nimport { runIDeviceTool } from \"./device\";\r\n\r\n\r\nexport async function isPaired(udid: string): Promise<boolean> {\r\n logTask(`Checking pairing status for ${udid}`);\r\n\r\n try {\r\n const result = await runIDeviceTool(\"idevicepair\", [\r\n \"-u\",\r\n udid,\r\n \"validate\",\r\n ]);\r\n if (!result) {\r\n return false;\r\n }\r\n\r\n return result.stdout.toLowerCase().includes(\"success\");\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport async function trustDevice(udid: string, timeout = 60000, onWaitingForTrust?: () => void): Promise<boolean> {\r\n logTask(`Trusting device ${udid}`);\r\n\r\n // Check if already paired\r\n if (await isPaired(udid)) {\r\n logInfo(`Device ${udid} is already trusted`);\r\n return true;\r\n }\r\n\r\n // Initiate pairing - this shows the trust dialog on the device\r\n logInfo(`Initiating pairing for device ${udid}`);\r\n const pairResult = await pair(udid);\r\n\r\n if (pairResult) {\r\n logInfo(`Device ${udid} paired successfully`);\r\n return true;\r\n }\r\n\r\n // Pairing initiated but user needs to accept on device\r\n logInfo(\"Please accept the trust dialog on the device...\");\r\n onWaitingForTrust?.();\r\n\r\n // Wait for user to accept\r\n try {\r\n await waitForPairing(udid, timeout, 1000);\r\n logInfo(`Device ${udid} is now trusted`);\r\n return true;\r\n } catch {\r\n logInfo(`Timeout waiting for trust acceptance on device ${udid}`);\r\n return false;\r\n }\r\n}\r\n\r\nexport async function waitForPairing(udid: string, timeout = 120000, pollInterval = 1000): Promise<boolean> {\r\n logTask(`Waiting for pairing on device ${udid}`);\r\n\r\n const startTime = Date.now();\r\n\r\n while (Date.now() - startTime < timeout) {\r\n if (await isPaired(udid)) {\r\n logInfo(`Device ${udid} is now paired`);\r\n return true;\r\n }\r\n\r\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\r\n }\r\n\r\n throw new Error(`Timeout waiting for device pairing after ${timeout}ms`);\r\n}\r\n\r\nexport async function pair(udid: string): Promise<boolean> {\r\n logTask(`Initiating pairing for device ${udid}`);\r\n\r\n try {\r\n const result = await runIDeviceTool(\"idevicepair\", [\"-u\", udid, \"pair\"]);\r\n if (!result) {\r\n return false;\r\n }\r\n\r\n return result.stdout.toLowerCase().includes(\"success\");\r\n } catch (error) {\r\n const errorMsg = error instanceof Error ? error.message : String(error);\r\n if (errorMsg.includes(\"Please accept the trust dialog\")) {\r\n // Pairing dialog shown on device\r\n return false;\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\nexport async function unpair(udid: string): Promise<boolean> {\r\n logTask(`Un-pairing device ${udid}`);\r\n\r\n try {\r\n const result = await runIDeviceTool(\"idevicepair\", [\r\n \"-u\",\r\n udid,\r\n \"unpair\",\r\n ]);\r\n if (!result) {\r\n return false;\r\n }\r\n\r\n return result.stdout.toLowerCase().includes(\"success\");\r\n } catch {\r\n return false;\r\n }\r\n}", "import type { AppInfo } from \"@/types\";\r\nimport { logInfo, logTask } from \"@/utils/debug\";\r\nimport { parseAppList } from \"../dataParser\";\r\nimport { runIDeviceTool } from \"./device\";\r\nimport { isPaired, waitForPairing } from \"./pair\";\r\n\r\nexport async function installApp(ipaPath: string, udid: string): Promise<void> {\r\n\tlogTask(`Installing app ${ipaPath} on device ${udid}`);\r\n\r\n\tif (!(await isPaired(udid))) {\r\n\t\tawait waitForPairing(udid, 10000);\r\n\t}\r\n\r\n\tawait runIDeviceTool(\"ideviceinstaller\", [\"-u\", udid, \"-i\", ipaPath]);\r\n}\r\n\r\nexport async function uninstallApp(bundleId: string, udid: string): Promise<void> {\r\n\tlogTask(`Uninstalling app ${bundleId} from device ${udid}`);\r\n\r\n\tif (!(await isPaired(udid))) {\r\n\t\tawait waitForPairing(udid, 10000);\r\n\t}\r\n\r\n\tawait runIDeviceTool(\"ideviceinstaller\", [\"-u\", udid, \"-U\", bundleId]);\r\n}\r\n\r\nexport async function listApps(udid: string): Promise<AppInfo[]> {\r\n\tlogTask(`Listing apps on device ${udid}`);\r\n\r\n\tif (!(await isPaired(udid))) {\r\n\t\tawait waitForPairing(udid, 10000);\r\n\t}\r\n\r\n\ttry {\r\n\t\tconst result = await runIDeviceTool(\"ideviceinstaller\", [\"-u\", udid, \"-l\"]);\r\n\t\tif (!result) {\r\n\t\t\treturn [];\r\n\t\t}\r\n\r\n\t\tconst { stdout } = result;\r\n\t\treturn parseAppList(stdout);\r\n\t} catch {\r\n\t\treturn [];\r\n\t}\r\n}\r\n\r\nexport async function isAppInstalled(bundleId: string, udid: string): Promise<boolean> {\r\n\tlogTask(`Checking if app ${bundleId} is installed on device ${udid}`);\r\n\r\n\tconst apps = await listApps(udid);\r\n\treturn apps.some((app) => app.bundleId === bundleId);\r\n}\r\n\r\nexport async function wakeDevice(udid: string): Promise<void> {\r\n\ttry {\r\n\t\tlogInfo(\"Attempting to wake device screen...\");\r\n\r\n\t\t// Try multiple methods to wake the device\r\n\t\t// Method 1: Query device info (wakes some devices)\r\n\t\tawait runIDeviceTool(\"ideviceinfo\", [\"-u\", udid, \"-k\", \"DeviceName\"]);\r\n\r\n\t\t// Method 2: Try to get activation state (another wake trigger)\r\n\t\ttry {\r\n\t\t\tawait runIDeviceTool(\"ideviceinfo\", [\"-u\", udid, \"-k\", \"ActivationState\"]);\r\n\t\t} catch {\r\n\t\t\t// Ignore\r\n\t\t}\r\n\r\n\t\t// Method 3: Try to validate pairing (another interaction that might wake)\r\n\t\ttry {\r\n\t\t\tawait runIDeviceTool(\"idevicepair\", [\"-u\", udid, \"validate\"]);\r\n\t\t} catch {\r\n\t\t\t// Ignore\r\n\t\t}\r\n\r\n\t\t// Longer delay to let screen wake and stabilize\r\n\t\tawait new Promise((resolve) => setTimeout(resolve, 1000));\r\n\r\n\t\tlogInfo(\"Device wake attempt completed\");\r\n\t} catch (error) {\r\n\t\t// Log but don't fail - waking is best effort\r\n\t\tlogInfo(\r\n\t\t\t`Device wake attempt failed (non-critical): ${error instanceof Error ? error.message : String(error)}`\r\n\t\t);\r\n\t}\r\n}\r\n\r\nexport async function launchApp(bundleId: string, args: string[], udid: string): Promise<void> {\r\n\tlogTask(`Launching app ${bundleId} on device ${udid}`);\r\n\r\n\tif (!(await isPaired(udid))) {\r\n\t\tawait waitForPairing(udid, 10000);\r\n\t}\r\n\r\n\t// Wake device screen first to ensure app appears\r\n\tawait wakeDevice(udid);\r\n\r\n\t// Try idevicedebug first (works for iOS 16 and earlier)\r\n\ttry {\r\n\t\tlogInfo(`Attempting to launch ${bundleId} using idevicedebug...`);\r\n\t\tconst result = await runIDeviceTool(\"idevicedebug\", [\"-u\", udid, \"run\", bundleId, ...args]);\r\n\t\tconst output = (result?.stdout ?? \"\") + (result?.stderr ?? \"\");\r\n\r\n\t\t// Log output for debugging\r\n\t\tif (output.trim()) {\r\n\t\t\tlogInfo(`idevicedebug output: ${output.substring(0, 200)}`);\r\n\t\t}\r\n\r\n\t\t// Check if it failed due to missing debugserver\r\n\t\tif (\r\n\t\t\toutput.toLowerCase().includes(\"could not start\") &&\r\n\t\t\toutput.toLowerCase().includes(\"debugserver\")\r\n\t\t) {\r\n\t\t\tlogInfo(\"idevicedebug requires debugserver, falling back to pymobiledevice3...\");\r\n\t\t\tthrow new Error(\"debugserver_not_available\");\r\n\t\t}\r\n\r\n\t\t// Success - app should be launched\r\n\t\tlogInfo(`App ${bundleId} launched successfully using idevicedebug`);\r\n\r\n\t\t// Additional delay to ensure app appears\r\n\t\tawait new Promise((resolve) => setTimeout(resolve, 1000));\r\n\t\treturn;\r\n\t} catch (error) {\r\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\r\n\t\t// If debugserver is not available, try pymobiledevice3 (iOS 17+)\r\n\t\tif (\r\n\t\t\terrorMsg.includes(\"debugserver_not_available\") ||\r\n\t\t\terrorMsg.toLowerCase().includes(\"could not start\") ||\r\n\t\t\terrorMsg.toLowerCase().includes(\"debugserver\")\r\n\t\t) {\r\n\t\t\tlogInfo(\"idevicedebug failed, trying pymobiledevice3 for iOS 17+...\");\r\n\t\t\tawait launchAppWithPymobiledevice3(bundleId, args, udid);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Re-throw other errors\r\n\t\tthrow error;\r\n\t}\r\n}\r\n\r\nexport async function launchAppWithPymobiledevice3(\r\n\tbundleId: string,\r\n\targs: string[],\r\n\tudid: string\r\n): Promise<void> {\r\n\tlogTask(`Launching app ${bundleId} using pymobiledevice3`);\r\n\r\n\tconst { exec } = await import(\"node:child_process\");\r\n\tconst { promisify } = await import(\"node:util\");\r\n\tconst execAsync = promisify(exec);\r\n\r\n\ttry {\r\n\t\t// Build command: python -m pymobiledevice3 developer dvt launch --udid <UDID> --tunnel \"\" --kill-existing <bundle-id> [args...]\r\n\t\t// Use --tunnel \"\" to auto-detect/create tunnel for iOS 17+\r\n\t\t// Use --kill-existing to ensure app comes to foreground\r\n\t\t// Use python -m to avoid PATH issues\r\n\t\t// Try without tunnel first (works for some iOS versions)\r\n\t\t// If that fails, we'll try with tunnel\r\n\t\tlet cmdArgs = [\r\n\t\t\t\"-m\",\r\n\t\t\t\"pymobiledevice3\",\r\n\t\t\t\"developer\",\r\n\t\t\t\"dvt\",\r\n\t\t\t\"launch\",\r\n\t\t\t\"--udid\",\r\n\t\t\tudid,\r\n\t\t\t\"--kill-existing\", // Kill existing instance to bring app to foreground\r\n\t\t\tbundleId,\r\n\t\t\t...args,\r\n\t\t];\r\n\r\n\t\tlet command = `python ${cmdArgs.map((a) => `\"${a}\"`).join(\" \")}`;\r\n\r\n\t\tlogInfo(`Executing: ${command}`);\r\n\r\n\t\tconst result = await execAsync(command, {\r\n\t\t\twindowsHide: true,\r\n\t\t\tencoding: \"utf8\",\r\n\t\t\ttimeout: 30000, // 30 second timeout\r\n\t\t});\r\n\r\n\t\tconst output = result.stdout.toString() + result.stderr.toString();\r\n\r\n\t\t// Log output for debugging\r\n\t\tif (output.trim()) {\r\n\t\t\tlogInfo(`pymobiledevice3 output: ${output.substring(0, 200)}`);\r\n\t\t}\r\n\r\n\t\t// Check for common errors\r\n\t\tif (\r\n\t\t\toutput.toLowerCase().includes(\"developer mode\") &&\r\n\t\t\toutput.toLowerCase().includes(\"not enabled\")\r\n\t\t) {\r\n\t\t\tthrow new Error(\r\n\t\t\t\t\"Developer Mode is not enabled on the device.\\n\" +\r\n\t\t\t\t\t\"Please enable it: Settings \u2192 Privacy & Security \u2192 Developer Mode \u2192 Enable\"\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\t// If tunnel error, try again with tunnel option\r\n\t\tif (\r\n\t\t\toutput.toLowerCase().includes(\"tunneld\") &&\r\n\t\t\t(output.toLowerCase().includes(\"unable to connect\") ||\r\n\t\t\t\toutput.toLowerCase().includes(\"invalidserviceerror\"))\r\n\t\t) {\r\n\t\t\tlogInfo(\"Tunnel required, retrying with tunnel option...\");\r\n\r\n\t\t\t// Retry with tunnel\r\n\t\t\tcmdArgs = [\r\n\t\t\t\t\"-m\",\r\n\t\t\t\t\"pymobiledevice3\",\r\n\t\t\t\t\"developer\",\r\n\t\t\t\t\"dvt\",\r\n\t\t\t\t\"launch\",\r\n\t\t\t\t\"--udid\",\r\n\t\t\t\tudid,\r\n\t\t\t\t\"--tunnel\",\r\n\t\t\t\tudid, // Use UDID for tunnel\r\n\t\t\t\t\"--kill-existing\",\r\n\t\t\t\tbundleId,\r\n\t\t\t\t...args,\r\n\t\t\t];\r\n\r\n\t\t\tcommand = `python ${cmdArgs.map((a) => `\"${a}\"`).join(\" \")}`;\r\n\t\t\tlogInfo(`Retrying with tunnel: ${command}`);\r\n\r\n\t\t\ttry {\r\n\t\t\t\tconst retryResult = await execAsync(command, {\r\n\t\t\t\t\twindowsHide: true,\r\n\t\t\t\t\tencoding: \"utf8\",\r\n\t\t\t\t\ttimeout: 30000,\r\n\t\t\t\t});\r\n\r\n\t\t\t\tconst retryOutput = retryResult.stdout.toString() + retryResult.stderr.toString();\r\n\t\t\t\tif (retryOutput.trim()) {\r\n\t\t\t\t\tlogInfo(`pymobiledevice3 retry output: ${retryOutput.substring(0, 200)}`);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Check if still failing\r\n\t\t\t\tif (\r\n\t\t\t\t\tretryOutput.toLowerCase().includes(\"tunneld\") &&\r\n\t\t\t\t\tretryOutput.toLowerCase().includes(\"unable to connect\")\r\n\t\t\t\t) {\r\n\t\t\t\t\tthrow new Error(\r\n\t\t\t\t\t\t\"Tunnel connection failed. For iOS 17+, you may need to start tunneld:\\n\" +\r\n\t\t\t\t\t\t\t\" python -m pymobiledevice3 remote tunneld\\n\" +\r\n\t\t\t\t\t\t\t\"Or ensure Developer Mode is enabled and device is unlocked.\"\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Success on retry\r\n\t\t\t\tlogInfo(`App ${bundleId} launched successfully using pymobiledevice3 with tunnel`);\r\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 500));\r\n\t\t\t\treturn;\r\n\t\t\t} catch {\r\n\t\t\t\t// If retry also fails, throw the original tunnel error\r\n\t\t\t\tthrow new Error(\r\n\t\t\t\t\t\"Tunnel connection failed. For iOS 17+, you may need to start tunneld:\\n\" +\r\n\t\t\t\t\t\t\" python -m pymobiledevice3 remote tunneld\\n\" +\r\n\t\t\t\t\t\t\"Or ensure Developer Mode is enabled and device is unlocked.\"\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (\r\n\t\t\toutput.toLowerCase().includes(\"not found\") ||\r\n\t\t\toutput.toLowerCase().includes(\"command not found\") ||\r\n\t\t\toutput.toLowerCase().includes(\"cannot find\")\r\n\t\t) {\r\n\t\t\tthrow new Error(\r\n\t\t\t\t\"pymobiledevice3 is not installed.\\n\" +\r\n\t\t\t\t\t\"Install it with: python -m pip install --user pymobiledevice3\"\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\t// Check if there are any errors in output\r\n\t\tif (output.toLowerCase().includes(\"error\") && !output.toLowerCase().includes(\"warning\")) {\r\n\t\t\t// Some errors might be non-fatal, but log them\r\n\t\t\tlogInfo(`Warning: pymobiledevice3 reported errors: ${output.substring(0, 300)}`);\r\n\t\t}\r\n\r\n\t\tlogInfo(`App ${bundleId} launched successfully using pymobiledevice3`);\r\n\r\n\t\t// Longer delay to ensure app appears on screen and device wakes\r\n\t\tawait new Promise((resolve) => setTimeout(resolve, 1000));\r\n\t} catch (error) {\r\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\r\n\t\t// Check if it's a command not found error\r\n\t\tif (\r\n\t\t\terrorMsg.includes(\"not found\") ||\r\n\t\t\terrorMsg.includes(\"command not found\") ||\r\n\t\t\terrorMsg.includes(\"cannot find\") ||\r\n\t\t\terrorMsg.includes(\"No module named\")\r\n\t\t) {\r\n\t\t\tthrow new Error(\r\n\t\t\t\t\"pymobiledevice3 is not installed or Python is not available.\\n\" +\r\n\t\t\t\t\t\"Install it with: python -m pip install --user pymobiledevice3\\n\" +\r\n\t\t\t\t\t\"For iOS 17+, Developer Mode must also be enabled on the device.\"\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tthrow error;\r\n\t}\r\n}\r\n", "import type { PortForwardResult } from \"@/types\";\r\nimport { logTask } from \"@/utils/debug\";\r\nimport { runIDeviceTool } from \"./device\";\r\n\r\nasync function startPortForward(\r\n\tlocalPort: number,\r\n\tdevicePort: number,\r\n\tudid: string\r\n): Promise<PortForwardResult> {\r\n\tlogTask(`Starting port forward ${localPort} -> ${devicePort} for device ${udid}`);\r\n\r\n\tconst result = await runIDeviceTool(\"iproxy\", [\r\n\t\tlocalPort.toString(),\r\n\t\tdevicePort.toString(),\r\n\t\t\"-u\",\r\n\t\tudid,\r\n\t]);\r\n\r\n\treturn {\r\n\t\tlocalPort,\r\n\t\tdevicePort,\r\n\t\t...result,\r\n\t};\r\n}\r\n\r\nexport async function startPortForwardAsync(\r\n\tlocalPort: number,\r\n\tdevicePort: number,\r\n\tudid: string,\r\n\t_timeout = 5000\r\n): Promise<PortForwardResult> {\r\n\tconst result = await startPortForward(localPort, devicePort, udid);\r\n\r\n\t// Give iproxy a moment to start\r\n\tawait new Promise((resolve) => setTimeout(resolve, 500));\r\n\r\n\t// Check if process is still running\r\n\tif (result.stdout.includes(\"error\") || result.stderr.includes(\"error\")) {\r\n\t\tthrow new Error(\"Port forwarding failed to start\");\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n", "import type { ActivationState, AppInfo, PortForwardResult, iOSDeviceInfo } from \"../types\";\r\nimport { logInfo } from \"../utils/debug\";\r\nimport { activate, getActivationState } from \"./actions/activation\";\r\nimport { getDeviceInfo } from \"./actions/device\";\r\nimport { installApp, isAppInstalled, launchApp, listApps, uninstallApp } from \"./actions/install\";\r\nimport { isPaired, pair, trustDevice, unpair, waitForPairing } from \"./actions/pair\";\r\nimport { startPortForwardAsync } from \"./actions/proxy\";\r\n\r\n/**\r\n * AppleDeviceKit - iOS device operations wrapper\r\n *\r\n * Uses idevice command-line tools for iOS device operations.\r\n * Each instance is associated with a specific device by UDID.\r\n */\r\nexport class AppleDeviceKit {\r\n\tprivate deviceId: string;\r\n\r\n\tconstructor(\r\n\t\tudid: string,\r\n\t\tprivate readonly port: number\r\n\t) {\r\n\t\tthis.deviceId = udid;\r\n\t\tlogInfo(`AppleDeviceKit initialized for device: ${this.deviceId}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Get detailed device information\r\n\t */\r\n\tpublic async getDeviceInfo(): Promise<iOSDeviceInfo> {\r\n\t\treturn getDeviceInfo(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Check if device is paired/trusted with this computer\r\n\t */\r\n\tpublic async isPaired(): Promise<boolean> {\r\n\t\treturn isPaired(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Wait for device to be paired\r\n\t * Polls the pairing status until successful or timeout\r\n\t *\r\n\t * @param timeout Timeout in milliseconds (default: 120000)\r\n\t * @param pollInterval Poll interval in milliseconds (default: 1000)\r\n\t */\r\n\tpublic async waitForPairing(timeout = 120000, pollInterval = 1000): Promise<boolean> {\r\n\t\treturn waitForPairing(this.deviceId, timeout, pollInterval);\r\n\t}\r\n\r\n\t/**\r\n\t * Attempt to pair/trust the device\r\n\t * User must accept the trust dialog on the device\r\n\t */\r\n\tpublic async pair(): Promise<boolean> {\r\n\t\treturn pair(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Trust/pair the device - initiates pairing and waits for user to accept\r\n\t *\r\n\t * This is the recommended method for establishing trust with a device.\r\n\t * It will:\r\n\t * 1. Check if already paired\r\n\t * 2. If not, initiate pairing (shows \"Trust This Computer?\" on device)\r\n\t * 3. Wait for user to accept the trust dialog\r\n\t *\r\n\t * @param timeout Timeout in milliseconds to wait for user acceptance (default: 60000)\r\n\t * @param onWaitingForTrust Callback when waiting for user to accept trust dialog\r\n\t * @returns true if device is now trusted\r\n\t */\r\n\tpublic async trustDevice(timeout = 60000, onWaitingForTrust?: () => void): Promise<boolean> {\r\n\t\treturn trustDevice(this.deviceId, timeout, onWaitingForTrust);\r\n\t}\r\n\r\n\t/**\r\n\t * Unpair/untrust the device\r\n\t */\r\n\tpublic async unpair(): Promise<boolean> {\r\n\t\treturn unpair(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Install an IPA file on the device (install agent)\r\n\t *\r\n\t * @param ipaPath Path to the IPA file\r\n\t */\r\n\tpublic async installApp(ipaPath: string): Promise<void> {\r\n\t\tinstallApp(ipaPath, this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Uninstall an app by bundle ID (uninstall agent)\r\n\t *\r\n\t * @param bundleId Application bundle identifier\r\n\t */\r\n\tpublic async uninstallApp(bundleId: string): Promise<void> {\r\n\t\tuninstallApp(bundleId, this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Check if an app is installed on the device\r\n\t *\r\n\t * @param bundleId Application bundle identifier\r\n\t */\r\n\tpublic async isAppInstalled(bundleId: string): Promise<boolean> {\r\n\t\treturn isAppInstalled(bundleId, this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * List all installed user applications\r\n\t */\r\n\tpublic async listApps(): Promise<AppInfo[]> {\r\n\t\treturn listApps(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Launch an application on the device\r\n\t *\r\n\t * @param bundleId Application bundle identifier\r\n\t * @param args Application arguments\r\n\t */\r\n\tpublic async launchApp(bundleId: string, args: string[] = []): Promise<void> {\r\n\t\treturn launchApp(bundleId, args, this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Start port forwarding and wait for it to be ready.\r\n\t * we need port forwarding to be able to connect to the device from the computer\r\n\t * and communicate with it using the local port.\r\n\t *\r\n\t * @param localPort Local port to listen on\r\n\t * @param devicePort Device port to forward to\r\n\t * @param _timeout Timeout in milliseconds (reserved for future use)\r\n\t */\r\n\tpublic async startPortForwardAsync(\r\n\t\tlocalPort: number,\r\n\t\tdevicePort: number,\r\n\t\t_timeout = 5000\r\n\t): Promise<PortForwardResult> {\r\n\t\treturn startPortForwardAsync(localPort, devicePort, this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Get the activation state of the device\r\n\t */\r\n\tpublic async getActivationState(): Promise<ActivationState> {\r\n\t\treturn getActivationState(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Activate the device (register in apple servers), an activated device belongs to someone (a user/company).\r\n\t * A device that is on hello screen cannot pass the wifi step unless it is activated.\r\n\t * the activate save us the need of the device to be connected to the internet to do the activation\r\n\t * and register in apple servers.\r\n\t *\r\n\t * Note: This requires a valid activation record or Apple server access\r\n\t *\r\n\t * precondition: the device must be paired and trusted\r\n\t */\r\n\tpublic async activate(): Promise<boolean> {\r\n\t\treturn activate(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Get the device UDID\r\n\t */\r\n\tpublic getDeviceId(): string {\r\n\t\treturn this.deviceId;\r\n\t}\r\n\r\n\t/**\r\n\t * Get the logical port number\r\n\t */\r\n\tpublic getPort(): number {\r\n\t\treturn this.port;\r\n\t}\r\n}\r\n", "import EventEmitter from \"node:events\";\r\nimport usbDeviceListener from \"@mcesystems/usb-device-listener\";\r\nimport type { DeviceInfo, ListenerConfig } from \"@mcesystems/usb-device-listener\";\r\nimport type { AppleListenerConfig } from \"../types\";\r\nimport { logInfo } from \"../utils/debug\";\r\nimport { listDevices } from \"./actions/device\";\r\nimport { AppleDeviceKit } from \"./appleDeviceKit\";\r\n\r\n// Apple vendor ID\r\nconst APPLE_VID = 0x05ac;\r\n\r\n/**\r\n * DevicesMonitor - Monitor iOS device connections via USB\r\n *\r\n * Uses usb-device-listener for plug-and-play detection and filters\r\n * for Apple devices (VID 0x05AC).\r\n */\r\nexport class DevicesMonitor {\r\n\tprivate kits: Map<string, AppleDeviceKit> = new Map();\r\n\tprivate eventEmitter?: EventEmitter;\r\n\r\n\tconstructor(\r\n\t\tprivate config: AppleListenerConfig = {},\r\n\t\tprivate identifyAlreadyConnected = false\r\n\t) {}\r\n\r\n\t/**\r\n\t * Start tracking iOS device connections\r\n\t *\r\n\t * @returns EventEmitter that emits:\r\n\t * - 'added': (deviceKit: AppleDeviceKit) when a device is connected\r\n\t * - 'removed': (deviceId: string, port: number) when a device is disconnected\r\n\t */\r\n\tpublic async startTracking(): Promise<EventEmitter> {\r\n\t\tlogInfo(\"Starting iOS devices monitor\");\r\n\r\n\t\t// Build listener config with Apple device filter\r\n\t\tconst listenerConfig: ListenerConfig = {\r\n\t\t\tlogicalPortMap: this.config.logicalPortMap,\r\n\t\t\t// Filter for Apple devices only\r\n\t\t\tlistenOnlyDevices: [{ vid: APPLE_VID.toString(16).toUpperCase().padStart(4, \"0\"), pid: \"\" }],\r\n\t\t};\r\n\r\n\t\tusbDeviceListener.startListening(listenerConfig);\r\n\t\tthis.eventEmitter = new EventEmitter();\r\n\r\n\t\tif (this.identifyAlreadyConnected || this.config.identifyAlreadyConnected) {\r\n\t\t\tawait this.identifyConnectedDevices();\r\n\t\t}\r\n\r\n\t\tusbDeviceListener.onDeviceAdd((device: DeviceInfo) => {\r\n\t\t\t// Check if this is an Apple device\r\n\t\t\tif (device.vid !== APPLE_VID) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tlogInfo(`Apple device connected: ${device.deviceId}`);\r\n\r\n\t\t\t// Get the UDID by querying connected iOS devices\r\n\t\t\tthis.findAndEmitDevice(device);\r\n\t\t});\r\n\r\n\t\tusbDeviceListener.onDeviceRemove((device: DeviceInfo) => {\r\n\t\t\t// Check if this is an Apple device\r\n\t\t\tif (device.vid !== APPLE_VID) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tlogInfo(`Apple device disconnected: ${device.deviceId}`);\r\n\r\n\t\t\t// Find and remove the kit by location\r\n\t\t\tfor (const [udid, kit] of this.kits.entries()) {\r\n\t\t\t\tif (kit.getPort() === device.logicalPort) {\r\n\t\t\t\t\tthis.kits.delete(udid);\r\n\t\t\t\t\tthis.eventEmitter?.emit(\"removed\", udid, device.logicalPort);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\treturn this.eventEmitter;\r\n\t}\r\n\r\n\t/**\r\n\t * Stop tracking device connections\r\n\t */\r\n\tpublic async stopTracking(): Promise<void> {\r\n\t\tif (!this.eventEmitter) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tlogInfo(\"Stopping iOS devices monitor\");\r\n\t\tthis.eventEmitter.removeAllListeners();\r\n\t\tthis.kits.clear();\r\n\t\tthis.eventEmitter = undefined;\r\n\t\tusbDeviceListener.stopListening();\r\n\t}\r\n\r\n\t/**\r\n\t * Get all currently tracked device kits\r\n\t */\r\n\tpublic getKits(): Map<string, AppleDeviceKit> {\r\n\t\treturn new Map(this.kits);\r\n\t}\r\n\r\n\t/**\r\n\t * Get a specific device kit by UDID\r\n\t */\r\n\tpublic getKit(udid: string): AppleDeviceKit | undefined {\r\n\t\treturn this.kits.get(udid);\r\n\t}\r\n\r\n\t/**\r\n\t * Find connected iOS device and emit event\r\n\t */\r\n\tprivate async findAndEmitDevice(usbDevice: DeviceInfo): Promise<void> {\r\n\t\t// Query libimobiledevice for connected iOS devices\r\n\t\tconst iOSDevices = await listDevices();\r\n\r\n\t\tif (iOSDevices.length === 0) {\r\n\t\t\t// Device might not be ready yet, retry after a short delay\r\n\t\t\tsetTimeout(() => this.findAndEmitDevice(usbDevice), 500);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// For now, match by order of appearance\r\n\t\t// In a production scenario, you might want to correlate by additional means\r\n\t\tfor (const iDevice of iOSDevices) {\r\n\t\t\tif (this.kits.has(iDevice.udid)) {\r\n\t\t\t\tcontinue; // Already tracking this device\r\n\t\t\t}\r\n\r\n\t\t\tconst port = usbDevice.logicalPort ?? 0;\r\n\t\t\tconst kit = new AppleDeviceKit(iDevice.udid, port);\r\n\t\t\tthis.kits.set(iDevice.udid, kit);\r\n\r\n\t\t\t// Emit after a short delay to allow device to settle\r\n\t\t\tsetTimeout(() => {\r\n\t\t\t\tthis.eventEmitter?.emit(\"added\", kit);\r\n\t\t\t}, 0);\r\n\r\n\t\t\tbreak; // Only match one device per USB event\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Identify already connected iOS devices\r\n\t */\r\n\tprivate async identifyConnectedDevices(): Promise<void> {\r\n\t\tlogInfo(\"Identifying already connected iOS devices\");\r\n\r\n\t\tconst iOSDevices = await listDevices();\r\n\t\tconst usbDevices = usbDeviceListener.listDevices().filter((d) => d.vid === APPLE_VID);\r\n\r\n\t\tfor (let i = 0; i < iOSDevices.length; i++) {\r\n\t\t\tconst iDevice = iOSDevices[i];\r\n\t\t\tconst usbDevice = usbDevices[i];\r\n\r\n\t\t\tif (this.kits.has(iDevice.udid)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tconst port = usbDevice?.logicalPort ?? 0;\r\n\t\t\tconst kit = new AppleDeviceKit(iDevice.udid, port);\r\n\t\t\tthis.kits.set(iDevice.udid, kit);\r\n\r\n\t\t\t// Emit events asynchronously\r\n\t\t\tsetTimeout(() => {\r\n\t\t\t\tthis.eventEmitter?.emit(\"added\", kit);\r\n\t\t\t}, 0);\r\n\t\t}\r\n\t}\r\n}\r\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import createDebug from \"debug\";\r\n\r\nconst debug = createDebug(\"apple-kit\");\r\nconst debugTask = createDebug(\"apple-kit:task\");\r\nconst debugWarning = createDebug(\"apple-kit:warning\");\r\nconst debugError = createDebug(\"apple-kit:error\");\r\n\r\n/**\r\n * Log general information\r\n */\r\nexport function logInfo(message: string): void {\r\n\tdebug(message);\r\n}\r\n\r\n/**\r\n * Log task-specific information\r\n */\r\nexport function logTask(message: string): void {\r\n\tdebugTask(message);\r\n}\r\n\r\n/**\r\n * Log warning messages\r\n */\r\nexport function logWarning(message: string): void {\r\n\tdebugWarning(message);\r\n}\r\n\r\n/**\r\n * Log error messages\r\n */\r\nexport function logError(message: string): void {\r\n\tdebugError(message);\r\n}\r\n\r\n", "import { type ExecOptions, exec as execCallback } from \"node:child_process\";\r\nimport { existsSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\nimport { promisify } from \"node:util\";\r\nimport type { AppleToolType, DeviceListEntry } from \"@/types\";\r\nimport type { iOSDeviceInfo } from \"@/types\";\r\nimport { logTask } from \"@/utils/debug\";\r\nimport { parseDeviceList, parsePlistOutput } from \"../dataParser\";\r\n\r\nconst execAsync = promisify(execCallback);\r\n\r\nexport interface ExecResult {\r\n\tstdout: string;\r\n\tstderr: string;\r\n}\r\n\r\nexport async function getDeviceInfo(udid: string): Promise<iOSDeviceInfo> {\r\n\tlogTask(`Getting device info for ${udid}`);\r\n\r\n\tconst result = await runIDeviceTool(\"ideviceinfo\", [\"-u\", udid]);\r\n\tif (!result) {\r\n\t\tthrow new Error(\"Failed to get device info\");\r\n\t}\r\n\r\n\tconst props = parsePlistOutput(result.stdout);\r\n\r\n\treturn {\r\n\t\tdeviceName: props.DeviceName || \"\",\r\n\t\tproductType: props.ProductType || \"\",\r\n\t\tproductVersion: props.ProductVersion || \"\",\r\n\t\tbuildVersion: props.BuildVersion || \"\",\r\n\t\tserialNumber: props.SerialNumber || \"\",\r\n\t\tudid: props.UniqueDeviceID || udid,\r\n\t\twifiAddress: props.WiFiAddress || \"\",\r\n\t\tbluetoothAddress: props.BluetoothAddress || \"\",\r\n\t\tphoneNumber: props.PhoneNumber || \"\",\r\n\t\tcpuArchitecture: props.CPUArchitecture || \"\",\r\n\t\thardwareModel: props.HardwareModel || \"\",\r\n\t\tmodelNumber: props.ModelNumber || \"\",\r\n\t\tregionInfo: props.RegionInfo || \"\",\r\n\t\ttimeZone: props.TimeZone || \"\",\r\n\t\tuniqueChipID: props.UniqueChipID || \"\",\r\n\t\tisPaired: true, // If we can get info, device is paired\r\n\t};\r\n}\r\n\r\nexport async function listDevices(): Promise<DeviceListEntry[]> {\r\n\ttry {\r\n\t\tconst result = await runIDeviceTool(\"idevice_id\", [\"-l\"]);\r\n\t\tif (!result) {\r\n\t\t\treturn [];\r\n\t\t}\r\n\r\n\t\treturn parseDeviceList(result.stdout);\r\n\t} catch {\r\n\t\treturn [];\r\n\t}\r\n}\r\n\r\n/**\r\n * Execute an idevice tool command\r\n */\r\nexport async function runIDeviceTool(\r\n\ttoolName: AppleToolType,\r\n\targs: string[] = [],\r\n\toptions: ExecOptions = {}\r\n): Promise<ExecResult> {\r\n\tconst command = `\"${toolName}${process.platform === \"win32\" ? \".exe\" : \"\"}\" ${args.map((a) => `\"${a}\"`).join(\" \")}`;\r\n\treturn execIDevice(command, options);\r\n}\r\n\r\n/**\r\n * Execute a command with idevice tools in PATH\r\n */\r\nasync function execIDevice(command: string, options: ExecOptions = {}): Promise<ExecResult> {\r\n\tconst binPath = getIDeviceBinPath();\r\n\r\n\toptions.cwd = binPath;\r\n\r\n\tconst result = await execAsync(command, {\r\n\t\t...options,\r\n\t\tenv: process.env,\r\n\t\twindowsHide: true,\r\n\t\tencoding: \"utf8\",\r\n\t});\r\n\r\n\treturn {\r\n\t\tstdout: result.stdout.toString(),\r\n\t\tstderr: result.stderr.toString(),\r\n\t};\r\n}\r\n\r\n/**\r\n * Get the path to idevice binaries from resources\r\n */\r\nfunction getResourcesBinPath(): string {\r\n\tconst binPath = process.env.IDeviceBinPath;\r\n\tif (!binPath) {\r\n\t\tthrow new Error(\"IDeviceBinPath is not set\");\r\n\t}\r\n\treturn binPath;\r\n}\r\n\r\n/**\r\n * Get the path to a specific idevice tool\r\n */\r\nfunction getIDeviceToolPath(toolName: string): string | null {\r\n\tconst binPath = getResourcesBinPath();\r\n\tconst ext = process.platform === \"win32\" ? \".exe\" : \"\";\r\n\tconst toolPath = join(binPath, `${toolName}${ext}`);\r\n\r\n\tif (existsSync(toolPath)) {\r\n\t\treturn toolPath;\r\n\t}\r\n\r\n\treturn null;\r\n}\r\n\r\n/**\r\n * Get paths to all required idevice tools\r\n */\r\nexport function getIDeviceTools() {\r\n\treturn {\r\n\t\tidevice_id: getIDeviceToolPath(\"idevice_id\"),\r\n\t\tideviceinfo: getIDeviceToolPath(\"ideviceinfo\"),\r\n\t\tideviceinstaller: getIDeviceToolPath(\"ideviceinstaller\"),\r\n\t\tidevicepair: getIDeviceToolPath(\"idevicepair\"),\r\n\t\tidevicename: getIDeviceToolPath(\"idevicename\"),\r\n\t\tidevicedebug: getIDeviceToolPath(\"idevicedebug\"),\r\n\t\tiproxy: getIDeviceToolPath(\"iproxy\"),\r\n\t\tideviceactivation: getIDeviceToolPath(\"ideviceactivation\"),\r\n\t};\r\n}\r\n\r\n/**\r\n * Get the bin path for PATH environment variable\r\n */\r\nfunction getIDeviceBinPath(): string {\r\n\treturn getResourcesBinPath();\r\n}\r\n", "import type { AppInfo, DeviceListEntry } from \"../types\";\r\n\r\n\r\n/**\r\n * Parse plist-style output from ideviceinfo\r\n * \r\n * @param output ideviceinfo output\r\n * @returns Plist output\r\n */\r\nexport function parsePlistOutput(output: string): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n const lines = output.split(\"\\n\");\r\n\r\n for (const line of lines) {\r\n const colonIndex = line.indexOf(\":\");\r\n if (colonIndex > 0) {\r\n const key = line.substring(0, colonIndex).trim();\r\n const value = line.substring(colonIndex + 1).trim();\r\n result[key] = value;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Parse idevice_id output\r\n * \r\n * @param output idevice_id output\r\n * @returns Device list\r\n */\r\nexport function parseDeviceList(output: string): DeviceListEntry[] {\r\n const devices: DeviceListEntry[] = [];\r\n const lines = output.trim().split(\"\\n\");\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (trimmed) {\r\n // Format: \"UDID (connection type)\" or just \"UDID\"\r\n const match = trimmed.match(/^([A-Fa-f0-9-]+)(?:\\s+\\((\\w+)\\))?/);\r\n if (match) {\r\n devices.push({\r\n udid: match[1],\r\n connectionType: match[2] === \"Network\" ? 2 : 1,\r\n });\r\n }\r\n }\r\n }\r\n\r\n return devices;\r\n}\r\n\r\n/**\r\n * Parse ideviceinstaller list output\r\n * \r\n * @param output ideviceinstaller list output\r\n * @returns App list\r\n */\r\nexport function parseAppList(output: string): AppInfo[] {\r\n const apps: AppInfo[] = [];\r\n const lines = output.trim().split(\"\\n\");\r\n\r\n for (const line of lines) {\r\n // Format: \"com.example.app, Version, \"Display Name\"\"\r\n const match = line.match(/^([^,]+),\\s*([^,]+),\\s*\"?([^\"]+)\"?/);\r\n if (match) {\r\n apps.push({\r\n bundleId: match[1].trim(),\r\n version: match[2].trim(),\r\n displayName: match[3].trim(),\r\n bundleVersion: \"\",\r\n });\r\n }\r\n }\r\n\r\n return apps;\r\n}", "import type { ActivationState } from \"@/types\";\r\nimport { logTask } from \"@/utils/debug\";\r\nimport { runIDeviceTool } from \"./device\";\r\n\r\nexport async function getActivationState(udid: string): Promise<ActivationState> {\r\n\tlogTask(`Getting activation state for device ${udid}`);\r\n\r\n\ttry {\r\n\t\tconst result = await runIDeviceTool(\"ideviceinfo\", [\"-u\", udid, \"-k\", \"ActivationState\"]);\r\n\t\tif (!result) {\r\n\t\t\treturn {\r\n\t\t\t\tisActivated: false,\r\n\t\t\t\tactivationState: \"Unknown\",\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tconst { stdout } = result;\r\n\t\tconst state = stdout.trim();\r\n\r\n\t\treturn {\r\n\t\t\tisActivated: state === \"Activated\",\r\n\t\t\tactivationState: state,\r\n\t\t};\r\n\t} catch {\r\n\t\treturn {\r\n\t\t\tisActivated: false,\r\n\t\t\tactivationState: \"Unknown\",\r\n\t\t};\r\n\t}\r\n}\r\n\r\nexport async function activate(udid: string): Promise<boolean> {\r\n\tlogTask(`Activating device ${udid}`);\r\n\r\n\ttry {\r\n\t\tconst result = await runIDeviceTool(\"ideviceactivation\", [\"-u\", udid, \"activate\"]);\r\n\t\tif (!result) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\treturn (\r\n\t\t\tresult.stdout.toLowerCase().includes(\"success\") ||\r\n\t\t\tresult.stdout.toLowerCase().includes(\"activated\")\r\n\t\t);\r\n\t} catch (error) {\r\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\t\tthrow new Error(`Activation failed: ${errorMsg}`);\r\n\t}\r\n}\r\n\r\nexport interface ApplicationConfig {\r\n\tname: string;\r\n\tbundleId: string;\r\n\tversion: string;\r\n\tbuild: string;\r\n\ticon: string;\r\n\ticonData: Buffer;\r\n}\r\n", "import { logInfo, logTask } from \"@/utils/debug\";\r\nimport { runIDeviceTool } from \"./device\";\r\n\r\n\r\nexport async function isPaired(udid: string): Promise<boolean> {\r\n logTask(`Checking pairing status for ${udid}`);\r\n\r\n try {\r\n const result = await runIDeviceTool(\"idevicepair\", [\r\n \"-u\",\r\n udid,\r\n \"validate\",\r\n ]);\r\n if (!result) {\r\n return false;\r\n }\r\n\r\n return result.stdout.toLowerCase().includes(\"success\");\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport async function trustDevice(udid: string, timeout = 60000, onWaitingForTrust?: () => void): Promise<boolean> {\r\n logTask(`Trusting device ${udid}`);\r\n\r\n // Check if already paired\r\n if (await isPaired(udid)) {\r\n logInfo(`Device ${udid} is already trusted`);\r\n return true;\r\n }\r\n\r\n // Initiate pairing - this shows the trust dialog on the device\r\n logInfo(`Initiating pairing for device ${udid}`);\r\n const pairResult = await pair(udid);\r\n\r\n if (pairResult) {\r\n logInfo(`Device ${udid} paired successfully`);\r\n return true;\r\n }\r\n\r\n // Pairing initiated but user needs to accept on device\r\n logInfo(\"Please accept the trust dialog on the device...\");\r\n onWaitingForTrust?.();\r\n\r\n // Wait for user to accept\r\n try {\r\n await waitForPairing(udid, timeout, 1000);\r\n logInfo(`Device ${udid} is now trusted`);\r\n return true;\r\n } catch {\r\n logInfo(`Timeout waiting for trust acceptance on device ${udid}`);\r\n return false;\r\n }\r\n}\r\n\r\nexport async function waitForPairing(udid: string, timeout = 120000, pollInterval = 1000): Promise<boolean> {\r\n logTask(`Waiting for pairing on device ${udid}`);\r\n\r\n const startTime = Date.now();\r\n\r\n while (Date.now() - startTime < timeout) {\r\n if (await isPaired(udid)) {\r\n logInfo(`Device ${udid} is now paired`);\r\n return true;\r\n }\r\n\r\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\r\n }\r\n\r\n throw new Error(`Timeout waiting for device pairing after ${timeout}ms`);\r\n}\r\n\r\nexport async function pair(udid: string): Promise<boolean> {\r\n logTask(`Initiating pairing for device ${udid}`);\r\n\r\n try {\r\n const result = await runIDeviceTool(\"idevicepair\", [\"-u\", udid, \"pair\"]);\r\n if (!result) {\r\n return false;\r\n }\r\n\r\n return result.stdout.toLowerCase().includes(\"success\");\r\n } catch (error) {\r\n const errorMsg = error instanceof Error ? error.message : String(error);\r\n if (errorMsg.includes(\"Please accept the trust dialog\")) {\r\n // Pairing dialog shown on device\r\n return false;\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\nexport async function unpair(udid: string): Promise<boolean> {\r\n logTask(`Un-pairing device ${udid}`);\r\n\r\n try {\r\n const result = await runIDeviceTool(\"idevicepair\", [\r\n \"-u\",\r\n udid,\r\n \"unpair\",\r\n ]);\r\n if (!result) {\r\n return false;\r\n }\r\n\r\n return result.stdout.toLowerCase().includes(\"success\");\r\n } catch {\r\n return false;\r\n }\r\n}", "import type { AppInfo } from \"@/types\";\r\nimport { logInfo, logTask } from \"@/utils/debug\";\r\nimport { parseAppList } from \"../dataParser\";\r\nimport { runIDeviceTool } from \"./device\";\r\nimport { isPaired, waitForPairing } from \"./pair\";\r\n\r\nexport async function installApp(ipaPath: string, udid: string): Promise<void> {\r\n\tlogTask(`Installing app ${ipaPath} on device ${udid}`);\r\n\r\n\tif (!(await isPaired(udid))) {\r\n\t\tawait waitForPairing(udid, 10000);\r\n\t}\r\n\r\n\tawait runIDeviceTool(\"ideviceinstaller\", [\"-u\", udid, \"-i\", ipaPath]);\r\n}\r\n\r\nexport async function uninstallApp(bundleId: string, udid: string): Promise<void> {\r\n\tlogTask(`Uninstalling app ${bundleId} from device ${udid}`);\r\n\r\n\tif (!(await isPaired(udid))) {\r\n\t\tawait waitForPairing(udid, 10000);\r\n\t}\r\n\r\n\tawait runIDeviceTool(\"ideviceinstaller\", [\"-u\", udid, \"-U\", bundleId]);\r\n}\r\n\r\nexport async function listApps(udid: string): Promise<AppInfo[]> {\r\n\tlogTask(`Listing apps on device ${udid}`);\r\n\r\n\tif (!(await isPaired(udid))) {\r\n\t\tawait waitForPairing(udid, 10000);\r\n\t}\r\n\r\n\ttry {\r\n\t\tconst result = await runIDeviceTool(\"ideviceinstaller\", [\"-u\", udid, \"-l\"]);\r\n\t\tif (!result) {\r\n\t\t\treturn [];\r\n\t\t}\r\n\r\n\t\tconst { stdout } = result;\r\n\t\treturn parseAppList(stdout);\r\n\t} catch {\r\n\t\treturn [];\r\n\t}\r\n}\r\n\r\nexport async function isAppInstalled(bundleId: string, udid: string): Promise<boolean> {\r\n\tlogTask(`Checking if app ${bundleId} is installed on device ${udid}`);\r\n\r\n\tconst apps = await listApps(udid);\r\n\treturn apps.some((app) => app.bundleId === bundleId);\r\n}\r\n\r\nexport async function wakeDevice(udid: string): Promise<void> {\r\n\ttry {\r\n\t\tlogInfo(\"Attempting to wake device screen...\");\r\n\r\n\t\t// Try multiple methods to wake the device\r\n\t\t// Method 1: Query device info (wakes some devices)\r\n\t\tawait runIDeviceTool(\"ideviceinfo\", [\"-u\", udid, \"-k\", \"DeviceName\"]);\r\n\r\n\t\t// Method 2: Try to get activation state (another wake trigger)\r\n\t\ttry {\r\n\t\t\tawait runIDeviceTool(\"ideviceinfo\", [\"-u\", udid, \"-k\", \"ActivationState\"]);\r\n\t\t} catch {\r\n\t\t\t// Ignore\r\n\t\t}\r\n\r\n\t\t// Method 3: Try to validate pairing (another interaction that might wake)\r\n\t\ttry {\r\n\t\t\tawait runIDeviceTool(\"idevicepair\", [\"-u\", udid, \"validate\"]);\r\n\t\t} catch {\r\n\t\t\t// Ignore\r\n\t\t}\r\n\r\n\t\t// Longer delay to let screen wake and stabilize\r\n\t\tawait new Promise((resolve) => setTimeout(resolve, 1000));\r\n\r\n\t\tlogInfo(\"Device wake attempt completed\");\r\n\t} catch (error) {\r\n\t\t// Log but don't fail - waking is best effort\r\n\t\tlogInfo(\r\n\t\t\t`Device wake attempt failed (non-critical): ${error instanceof Error ? error.message : String(error)}`\r\n\t\t);\r\n\t}\r\n}\r\n\r\nexport async function launchApp(bundleId: string, args: string[], udid: string): Promise<void> {\r\n\tlogTask(`Launching app ${bundleId} on device ${udid}`);\r\n\r\n\tif (!(await isPaired(udid))) {\r\n\t\tawait waitForPairing(udid, 10000);\r\n\t}\r\n\r\n\t// Wake device screen first to ensure app appears\r\n\tawait wakeDevice(udid);\r\n\r\n\t// Try idevicedebug first (works for iOS 16 and earlier)\r\n\ttry {\r\n\t\tlogInfo(`Attempting to launch ${bundleId} using idevicedebug...`);\r\n\t\tconst result = await runIDeviceTool(\"idevicedebug\", [\"-u\", udid, \"run\", bundleId, ...args]);\r\n\t\tconst output = (result?.stdout ?? \"\") + (result?.stderr ?? \"\");\r\n\r\n\t\t// Log output for debugging\r\n\t\tif (output.trim()) {\r\n\t\t\tlogInfo(`idevicedebug output: ${output.substring(0, 200)}`);\r\n\t\t}\r\n\r\n\t\t// Check if it failed due to missing debugserver\r\n\t\tif (\r\n\t\t\toutput.toLowerCase().includes(\"could not start\") &&\r\n\t\t\toutput.toLowerCase().includes(\"debugserver\")\r\n\t\t) {\r\n\t\t\tlogInfo(\"idevicedebug requires debugserver, falling back to pymobiledevice3...\");\r\n\t\t\tthrow new Error(\"debugserver_not_available\");\r\n\t\t}\r\n\r\n\t\t// Success - app should be launched\r\n\t\tlogInfo(`App ${bundleId} launched successfully using idevicedebug`);\r\n\r\n\t\t// Additional delay to ensure app appears\r\n\t\tawait new Promise((resolve) => setTimeout(resolve, 1000));\r\n\t\treturn;\r\n\t} catch (error) {\r\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\r\n\t\t// If debugserver is not available, try pymobiledevice3 (iOS 17+)\r\n\t\tif (\r\n\t\t\terrorMsg.includes(\"debugserver_not_available\") ||\r\n\t\t\terrorMsg.toLowerCase().includes(\"could not start\") ||\r\n\t\t\terrorMsg.toLowerCase().includes(\"debugserver\")\r\n\t\t) {\r\n\t\t\tlogInfo(\"idevicedebug failed, trying pymobiledevice3 for iOS 17+...\");\r\n\t\t\tawait launchAppWithPymobiledevice3(bundleId, args, udid);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Re-throw other errors\r\n\t\tthrow error;\r\n\t}\r\n}\r\n\r\nexport async function launchAppWithPymobiledevice3(\r\n\tbundleId: string,\r\n\targs: string[],\r\n\tudid: string\r\n): Promise<void> {\r\n\tlogTask(`Launching app ${bundleId} using pymobiledevice3`);\r\n\r\n\tconst { exec } = await import(\"node:child_process\");\r\n\tconst { promisify } = await import(\"node:util\");\r\n\tconst execAsync = promisify(exec);\r\n\r\n\ttry {\r\n\t\t// Build command: python -m pymobiledevice3 developer dvt launch --udid <UDID> --tunnel \"\" --kill-existing <bundle-id> [args...]\r\n\t\t// Use --tunnel \"\" to auto-detect/create tunnel for iOS 17+\r\n\t\t// Use --kill-existing to ensure app comes to foreground\r\n\t\t// Use python -m to avoid PATH issues\r\n\t\t// Try without tunnel first (works for some iOS versions)\r\n\t\t// If that fails, we'll try with tunnel\r\n\t\tlet cmdArgs = [\r\n\t\t\t\"-m\",\r\n\t\t\t\"pymobiledevice3\",\r\n\t\t\t\"developer\",\r\n\t\t\t\"dvt\",\r\n\t\t\t\"launch\",\r\n\t\t\t\"--udid\",\r\n\t\t\tudid,\r\n\t\t\t\"--kill-existing\", // Kill existing instance to bring app to foreground\r\n\t\t\tbundleId,\r\n\t\t\t...args,\r\n\t\t];\r\n\r\n\t\tlet command = `python ${cmdArgs.map((a) => `\"${a}\"`).join(\" \")}`;\r\n\r\n\t\tlogInfo(`Executing: ${command}`);\r\n\r\n\t\tconst result = await execAsync(command, {\r\n\t\t\twindowsHide: true,\r\n\t\t\tencoding: \"utf8\",\r\n\t\t\ttimeout: 30000, // 30 second timeout\r\n\t\t});\r\n\r\n\t\tconst output = result.stdout.toString() + result.stderr.toString();\r\n\r\n\t\t// Log output for debugging\r\n\t\tif (output.trim()) {\r\n\t\t\tlogInfo(`pymobiledevice3 output: ${output.substring(0, 200)}`);\r\n\t\t}\r\n\r\n\t\t// Check for common errors\r\n\t\tif (\r\n\t\t\toutput.toLowerCase().includes(\"developer mode\") &&\r\n\t\t\toutput.toLowerCase().includes(\"not enabled\")\r\n\t\t) {\r\n\t\t\tthrow new Error(\r\n\t\t\t\t\"Developer Mode is not enabled on the device.\\n\" +\r\n\t\t\t\t\t\"Please enable it: Settings \u2192 Privacy & Security \u2192 Developer Mode \u2192 Enable\"\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\t// If tunnel error, try again with tunnel option\r\n\t\tif (\r\n\t\t\toutput.toLowerCase().includes(\"tunneld\") &&\r\n\t\t\t(output.toLowerCase().includes(\"unable to connect\") ||\r\n\t\t\t\toutput.toLowerCase().includes(\"invalidserviceerror\"))\r\n\t\t) {\r\n\t\t\tlogInfo(\"Tunnel required, retrying with tunnel option...\");\r\n\r\n\t\t\t// Retry with tunnel\r\n\t\t\tcmdArgs = [\r\n\t\t\t\t\"-m\",\r\n\t\t\t\t\"pymobiledevice3\",\r\n\t\t\t\t\"developer\",\r\n\t\t\t\t\"dvt\",\r\n\t\t\t\t\"launch\",\r\n\t\t\t\t\"--udid\",\r\n\t\t\t\tudid,\r\n\t\t\t\t\"--tunnel\",\r\n\t\t\t\tudid, // Use UDID for tunnel\r\n\t\t\t\t\"--kill-existing\",\r\n\t\t\t\tbundleId,\r\n\t\t\t\t...args,\r\n\t\t\t];\r\n\r\n\t\t\tcommand = `python ${cmdArgs.map((a) => `\"${a}\"`).join(\" \")}`;\r\n\t\t\tlogInfo(`Retrying with tunnel: ${command}`);\r\n\r\n\t\t\ttry {\r\n\t\t\t\tconst retryResult = await execAsync(command, {\r\n\t\t\t\t\twindowsHide: true,\r\n\t\t\t\t\tencoding: \"utf8\",\r\n\t\t\t\t\ttimeout: 30000,\r\n\t\t\t\t});\r\n\r\n\t\t\t\tconst retryOutput = retryResult.stdout.toString() + retryResult.stderr.toString();\r\n\t\t\t\tif (retryOutput.trim()) {\r\n\t\t\t\t\tlogInfo(`pymobiledevice3 retry output: ${retryOutput.substring(0, 200)}`);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Check if still failing\r\n\t\t\t\tif (\r\n\t\t\t\t\tretryOutput.toLowerCase().includes(\"tunneld\") &&\r\n\t\t\t\t\tretryOutput.toLowerCase().includes(\"unable to connect\")\r\n\t\t\t\t) {\r\n\t\t\t\t\tthrow new Error(\r\n\t\t\t\t\t\t\"Tunnel connection failed. For iOS 17+, you may need to start tunneld:\\n\" +\r\n\t\t\t\t\t\t\t\" python -m pymobiledevice3 remote tunneld\\n\" +\r\n\t\t\t\t\t\t\t\"Or ensure Developer Mode is enabled and device is unlocked.\"\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Success on retry\r\n\t\t\t\tlogInfo(`App ${bundleId} launched successfully using pymobiledevice3 with tunnel`);\r\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 500));\r\n\t\t\t\treturn;\r\n\t\t\t} catch {\r\n\t\t\t\t// If retry also fails, throw the original tunnel error\r\n\t\t\t\tthrow new Error(\r\n\t\t\t\t\t\"Tunnel connection failed. For iOS 17+, you may need to start tunneld:\\n\" +\r\n\t\t\t\t\t\t\" python -m pymobiledevice3 remote tunneld\\n\" +\r\n\t\t\t\t\t\t\"Or ensure Developer Mode is enabled and device is unlocked.\"\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (\r\n\t\t\toutput.toLowerCase().includes(\"not found\") ||\r\n\t\t\toutput.toLowerCase().includes(\"command not found\") ||\r\n\t\t\toutput.toLowerCase().includes(\"cannot find\")\r\n\t\t) {\r\n\t\t\tthrow new Error(\r\n\t\t\t\t\"pymobiledevice3 is not installed.\\n\" +\r\n\t\t\t\t\t\"Install it with: python -m pip install --user pymobiledevice3\"\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\t// Check if there are any errors in output\r\n\t\tif (output.toLowerCase().includes(\"error\") && !output.toLowerCase().includes(\"warning\")) {\r\n\t\t\t// Some errors might be non-fatal, but log them\r\n\t\t\tlogInfo(`Warning: pymobiledevice3 reported errors: ${output.substring(0, 300)}`);\r\n\t\t}\r\n\r\n\t\tlogInfo(`App ${bundleId} launched successfully using pymobiledevice3`);\r\n\r\n\t\t// Longer delay to ensure app appears on screen and device wakes\r\n\t\tawait new Promise((resolve) => setTimeout(resolve, 1000));\r\n\t} catch (error) {\r\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\r\n\r\n\t\t// Check if it's a command not found error\r\n\t\tif (\r\n\t\t\terrorMsg.includes(\"not found\") ||\r\n\t\t\terrorMsg.includes(\"command not found\") ||\r\n\t\t\terrorMsg.includes(\"cannot find\") ||\r\n\t\t\terrorMsg.includes(\"No module named\")\r\n\t\t) {\r\n\t\t\tthrow new Error(\r\n\t\t\t\t\"pymobiledevice3 is not installed or Python is not available.\\n\" +\r\n\t\t\t\t\t\"Install it with: python -m pip install --user pymobiledevice3\\n\" +\r\n\t\t\t\t\t\"For iOS 17+, Developer Mode must also be enabled on the device.\"\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tthrow error;\r\n\t}\r\n}\r\n", "import type { PortForwardResult } from \"@/types\";\r\nimport { logTask } from \"@/utils/debug\";\r\nimport { runIDeviceTool } from \"./device\";\r\n\r\nasync function startPortForward(\r\n\tlocalPort: number,\r\n\tdevicePort: number,\r\n\tudid: string\r\n): Promise<PortForwardResult> {\r\n\tlogTask(`Starting port forward ${localPort} -> ${devicePort} for device ${udid}`);\r\n\r\n\tconst result = await runIDeviceTool(\"iproxy\", [\r\n\t\tlocalPort.toString(),\r\n\t\tdevicePort.toString(),\r\n\t\t\"-u\",\r\n\t\tudid,\r\n\t]);\r\n\r\n\treturn {\r\n\t\tlocalPort,\r\n\t\tdevicePort,\r\n\t\t...result,\r\n\t};\r\n}\r\n\r\nexport async function startPortForwardAsync(\r\n\tlocalPort: number,\r\n\tdevicePort: number,\r\n\tudid: string,\r\n\t_timeout = 5000\r\n): Promise<PortForwardResult> {\r\n\tconst result = await startPortForward(localPort, devicePort, udid);\r\n\r\n\t// Give iproxy a moment to start\r\n\tawait new Promise((resolve) => setTimeout(resolve, 500));\r\n\r\n\t// Check if process is still running\r\n\tif (result.stdout.includes(\"error\") || result.stderr.includes(\"error\")) {\r\n\t\tthrow new Error(\"Port forwarding failed to start\");\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\nexport async function closePortForward(udid: string): Promise<void> {\r\n\tlogTask(`Closing port forward for device ${udid}`);\r\n\tawait runIDeviceTool(\"iproxy\", [\"-u\", udid, \"-c\"]);\r\n}\r\n", "import type { ActivationState, AppInfo, PortForwardResult, iOSDeviceInfo } from \"../types\";\r\nimport { logInfo } from \"../utils/debug\";\r\nimport { activate, getActivationState } from \"./actions/activation\";\r\nimport { getDeviceInfo } from \"./actions/device\";\r\nimport { installApp, isAppInstalled, launchApp, listApps, uninstallApp } from \"./actions/install\";\r\nimport { isPaired, pair, trustDevice, unpair, waitForPairing } from \"./actions/pair\";\r\nimport { closePortForward, startPortForwardAsync } from \"./actions/proxy\";\r\n\r\n/**\r\n * AppleDeviceKit - iOS device operations wrapper\r\n *\r\n * Uses idevice command-line tools for iOS device operations.\r\n * Each instance is associated with a specific device by UDID.\r\n */\r\nexport class AppleDeviceKit {\r\n\tprivate deviceId: string;\r\n\r\n\tconstructor(\r\n\t\tudid: string,\r\n\t\tprivate readonly port: number\r\n\t) {\r\n\t\tthis.deviceId = udid;\r\n\t\tlogInfo(`AppleDeviceKit initialized for device: ${this.deviceId}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Get detailed device information\r\n\t */\r\n\tpublic async getDeviceInfo(): Promise<iOSDeviceInfo> {\r\n\t\treturn getDeviceInfo(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Check if device is paired/trusted with this computer\r\n\t */\r\n\tpublic async isPaired(): Promise<boolean> {\r\n\t\treturn isPaired(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Wait for device to be paired\r\n\t * Polls the pairing status until successful or timeout\r\n\t *\r\n\t * @param timeout Timeout in milliseconds (default: 120000)\r\n\t * @param pollInterval Poll interval in milliseconds (default: 1000)\r\n\t */\r\n\tpublic async waitForPairing(timeout = 120000, pollInterval = 1000): Promise<boolean> {\r\n\t\treturn waitForPairing(this.deviceId, timeout, pollInterval);\r\n\t}\r\n\r\n\t/**\r\n\t * Attempt to pair/trust the device\r\n\t * User must accept the trust dialog on the device\r\n\t */\r\n\tpublic async pair(): Promise<boolean> {\r\n\t\treturn pair(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Trust/pair the device - initiates pairing and waits for user to accept\r\n\t *\r\n\t * This is the recommended method for establishing trust with a device.\r\n\t * It will:\r\n\t * 1. Check if already paired\r\n\t * 2. If not, initiate pairing (shows \"Trust This Computer?\" on device)\r\n\t * 3. Wait for user to accept the trust dialog\r\n\t *\r\n\t * @param timeout Timeout in milliseconds to wait for user acceptance (default: 60000)\r\n\t * @param onWaitingForTrust Callback when waiting for user to accept trust dialog\r\n\t * @returns true if device is now trusted\r\n\t */\r\n\tpublic async trustDevice(timeout = 60000, onWaitingForTrust?: () => void): Promise<boolean> {\r\n\t\treturn trustDevice(this.deviceId, timeout, onWaitingForTrust);\r\n\t}\r\n\r\n\t/**\r\n\t * Unpair/untrust the device\r\n\t */\r\n\tpublic async unpair(): Promise<boolean> {\r\n\t\treturn unpair(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Install an IPA file on the device (install agent)\r\n\t *\r\n\t * @param ipaPath Path to the IPA file\r\n\t */\r\n\tpublic async installApp(ipaPath: string): Promise<void> {\r\n\t\tinstallApp(ipaPath, this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Uninstall an app by bundle ID (uninstall agent)\r\n\t *\r\n\t * @param bundleId Application bundle identifier\r\n\t */\r\n\tpublic async uninstallApp(bundleId: string): Promise<void> {\r\n\t\tuninstallApp(bundleId, this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Check if an app is installed on the device\r\n\t *\r\n\t * @param bundleId Application bundle identifier\r\n\t */\r\n\tpublic async isAppInstalled(bundleId: string): Promise<boolean> {\r\n\t\treturn isAppInstalled(bundleId, this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * List all installed user applications\r\n\t */\r\n\tpublic async listApps(): Promise<AppInfo[]> {\r\n\t\treturn listApps(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Launch an application on the device\r\n\t *\r\n\t * @param bundleId Application bundle identifier\r\n\t * @param args Application arguments\r\n\t */\r\n\tpublic async launchApp(bundleId: string, args: string[] = []): Promise<void> {\r\n\t\treturn launchApp(bundleId, args, this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Start port forwarding and wait for it to be ready.\r\n\t * we need port forwarding to be able to connect to the device from the computer\r\n\t * and communicate with it using the local port.\r\n\t *\r\n\t * @param localPort Local port to listen on\r\n\t * @param devicePort Device port to forward to\r\n\t * @param _timeout Timeout in milliseconds (reserved for future use)\r\n\t */\r\n\tpublic async startPortForwardAsync(\r\n\t\tlocalPort: number,\r\n\t\tdevicePort: number,\r\n\t\t_timeout = 5000\r\n\t): Promise<PortForwardResult> {\r\n\t\treturn startPortForwardAsync(localPort, devicePort, this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Get the activation state of the device\r\n\t */\r\n\tpublic async getActivationState(): Promise<ActivationState> {\r\n\t\treturn getActivationState(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Activate the device (register in apple servers), an activated device belongs to someone (a user/company).\r\n\t * A device that is on hello screen cannot pass the wifi step unless it is activated.\r\n\t * the activate save us the need of the device to be connected to the internet to do the activation\r\n\t * and register in apple servers.\r\n\t *\r\n\t * Note: This requires a valid activation record or Apple server access\r\n\t *\r\n\t * precondition: the device must be paired and trusted\r\n\t */\r\n\tpublic async activate(): Promise<boolean> {\r\n\t\treturn activate(this.deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * Get the device UDID\r\n\t */\r\n\tpublic getDeviceId(): string {\r\n\t\treturn this.deviceId;\r\n\t}\r\n\r\n\t/**\r\n\t * Get the logical port number\r\n\t */\r\n\tpublic getPort(): number {\r\n\t\treturn this.port;\r\n\t}\r\n\r\n\tpublic async closePortForward(): Promise<void> {\r\n\t\treturn closePortForward(this.deviceId);\r\n\t}\r\n}\r\n", "import EventEmitter from \"node:events\";\r\nimport usbDeviceListener from \"@mcesystems/usb-device-listener\";\r\nimport type { DeviceInfo, ListenerConfig } from \"@mcesystems/usb-device-listener\";\r\nimport type { AppleListenerConfig } from \"../types\";\r\nimport { logInfo } from \"../utils/debug\";\r\nimport { listDevices } from \"./actions/device\";\r\nimport { AppleDeviceKit } from \"./appleDeviceKit\";\r\n\r\n// Apple vendor ID\r\nconst APPLE_VID = 0x05ac;\r\n\r\n/**\r\n * DevicesMonitor - Monitor iOS device connections via USB\r\n *\r\n * Uses usb-device-listener for plug-and-play detection and filters\r\n * for Apple devices (VID 0x05AC).\r\n */\r\nexport class DevicesMonitor {\r\n\tprivate kits: Map<string, AppleDeviceKit> = new Map();\r\n\tprivate eventEmitter?: EventEmitter;\r\n\r\n\tconstructor(\r\n\t\tprivate config: AppleListenerConfig = {},\r\n\t\tprivate identifyAlreadyConnected = false\r\n\t) {}\r\n\r\n\t/**\r\n\t * Start tracking iOS device connections\r\n\t *\r\n\t * @returns EventEmitter that emits:\r\n\t * - 'added': (deviceKit: AppleDeviceKit) when a device is connected\r\n\t * - 'removed': (deviceId: string, port: number) when a device is disconnected\r\n\t */\r\n\tpublic async startTracking(): Promise<EventEmitter> {\r\n\t\tlogInfo(\"Starting iOS devices monitor\");\r\n\r\n\t\t// Build listener config with Apple device filter\r\n\t\tconst listenerConfig: ListenerConfig = {\r\n\t\t\tlogicalPortMap: this.config.logicalPortMap,\r\n\t\t\t// Filter for Apple devices only\r\n\t\t\tlistenOnlyDevices: [{ vid: APPLE_VID.toString(16).toUpperCase().padStart(4, \"0\"), pid: \"\" }],\r\n\t\t};\r\n\r\n\t\tusbDeviceListener.startListening(listenerConfig);\r\n\t\tthis.eventEmitter = new EventEmitter();\r\n\r\n\t\tif (this.identifyAlreadyConnected || this.config.identifyAlreadyConnected) {\r\n\t\t\tawait this.identifyConnectedDevices();\r\n\t\t}\r\n\r\n\t\tusbDeviceListener.onDeviceAdd((device: DeviceInfo) => {\r\n\t\t\t// Check if this is an Apple device\r\n\t\t\tif (device.vid !== APPLE_VID) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tlogInfo(`Apple device connected: ${device.deviceId}`);\r\n\r\n\t\t\t// Get the UDID by querying connected iOS devices\r\n\t\t\tthis.findAndEmitDevice(device);\r\n\t\t});\r\n\r\n\t\tusbDeviceListener.onDeviceRemove((device: DeviceInfo) => {\r\n\t\t\t// Check if this is an Apple device\r\n\t\t\tif (device.vid !== APPLE_VID) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tlogInfo(`Apple device disconnected: ${device.deviceId}`);\r\n\r\n\t\t\t// Find and remove the kit by location\r\n\t\t\tfor (const [udid, kit] of this.kits.entries()) {\r\n\t\t\t\tif (kit.getPort() === device.logicalPort) {\r\n\t\t\t\t\tthis.kits.delete(udid);\r\n\t\t\t\t\tthis.eventEmitter?.emit(\"removed\", udid, device.logicalPort);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\treturn this.eventEmitter;\r\n\t}\r\n\r\n\t/**\r\n\t * Stop tracking device connections\r\n\t */\r\n\tpublic async stopTracking(): Promise<void> {\r\n\t\tif (!this.eventEmitter) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tlogInfo(\"Stopping iOS devices monitor\");\r\n\t\tthis.eventEmitter.removeAllListeners();\r\n\t\tthis.kits.clear();\r\n\t\tthis.eventEmitter = undefined;\r\n\t\tusbDeviceListener.stopListening();\r\n\t}\r\n\r\n\t/**\r\n\t * Get all currently tracked device kits\r\n\t */\r\n\tpublic getKits(): Map<string, AppleDeviceKit> {\r\n\t\treturn new Map(this.kits);\r\n\t}\r\n\r\n\t/**\r\n\t * Get a specific device kit by UDID\r\n\t */\r\n\tpublic getKit(udid: string): AppleDeviceKit | undefined {\r\n\t\treturn this.kits.get(udid);\r\n\t}\r\n\r\n\t/**\r\n\t * Find connected iOS device and emit event\r\n\t */\r\n\tprivate async findAndEmitDevice(usbDevice: DeviceInfo): Promise<void> {\r\n\t\t// Query libimobiledevice for connected iOS devices\r\n\t\tconst iOSDevices = await listDevices();\r\n\r\n\t\tif (iOSDevices.length === 0) {\r\n\t\t\t// Device might not be ready yet, retry after a short delay\r\n\t\t\tsetTimeout(() => this.findAndEmitDevice(usbDevice), 500);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// For now, match by order of appearance\r\n\t\t// In a production scenario, you might want to correlate by additional means\r\n\t\tfor (const iDevice of iOSDevices) {\r\n\t\t\tif (this.kits.has(iDevice.udid)) {\r\n\t\t\t\tcontinue; // Already tracking this device\r\n\t\t\t}\r\n\r\n\t\t\tconst port = usbDevice.logicalPort ?? 0;\r\n\t\t\tconst kit = new AppleDeviceKit(iDevice.udid, port);\r\n\t\t\tthis.kits.set(iDevice.udid, kit);\r\n\r\n\t\t\t// Emit after a short delay to allow device to settle\r\n\t\t\tsetTimeout(() => {\r\n\t\t\t\tthis.eventEmitter?.emit(\"added\", kit);\r\n\t\t\t}, 0);\r\n\r\n\t\t\tbreak; // Only match one device per USB event\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Identify already connected iOS devices\r\n\t */\r\n\tprivate async identifyConnectedDevices(): Promise<void> {\r\n\t\tlogInfo(\"Identifying already connected iOS devices\");\r\n\r\n\t\tconst iOSDevices = await listDevices();\r\n\t\tconst usbDevices = usbDeviceListener.listDevices().filter((d) => d.vid === APPLE_VID);\r\n\r\n\t\tfor (let i = 0; i < iOSDevices.length; i++) {\r\n\t\t\tconst iDevice = iOSDevices[i];\r\n\t\t\tconst usbDevice = usbDevices[i];\r\n\r\n\t\t\tif (this.kits.has(iDevice.udid)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tconst port = usbDevice?.logicalPort ?? 0;\r\n\t\t\tconst kit = new AppleDeviceKit(iDevice.udid, port);\r\n\t\t\tthis.kits.set(iDevice.udid, kit);\r\n\r\n\t\t\t// Emit events asynchronously\r\n\t\t\tsetTimeout(() => {\r\n\t\t\t\tthis.eventEmitter?.emit(\"added\", kit);\r\n\t\t\t}, 0);\r\n\t\t}\r\n\t}\r\n}\r\n"],
5
+ "mappings": "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",
6
6
  "names": ["promisify", "execAsync"]
7
7
  }
@@ -1,3 +1,4 @@
1
1
  import type { PortForwardResult } from "@/types";
2
2
  export declare function startPortForwardAsync(localPort: number, devicePort: number, udid: string, _timeout?: number): Promise<PortForwardResult>;
3
+ export declare function closePortForward(udid: string): Promise<void>;
3
4
  //# sourceMappingURL=proxy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../../../src/logic/actions/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAyBjD,wBAAsB,qBAAqB,CAC1C,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,QAAQ,SAAO,GACb,OAAO,CAAC,iBAAiB,CAAC,CAY5B"}
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../../../src/logic/actions/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAyBjD,wBAAsB,qBAAqB,CAC1C,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,QAAQ,SAAO,GACb,OAAO,CAAC,iBAAiB,CAAC,CAY5B;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlE"}
@@ -110,5 +110,6 @@ export declare class AppleDeviceKit {
110
110
  * Get the logical port number
111
111
  */
112
112
  getPort(): number;
113
+ closePortForward(): Promise<void>;
113
114
  }
114
115
  //# sourceMappingURL=appleDeviceKit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"appleDeviceKit.d.ts","sourceRoot":"","sources":["../../../src/logic/appleDeviceKit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAQ3F;;;;;GAKG;AACH,qBAAa,cAAc;IAKzB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJtB,OAAO,CAAC,QAAQ,CAAS;gBAGxB,IAAI,EAAE,MAAM,EACK,IAAI,EAAE,MAAM;IAM9B;;OAEG;IACU,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC;IAIpD;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzC;;;;;;OAMG;IACU,cAAc,CAAC,OAAO,SAAS,EAAE,YAAY,SAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAIpF;;;OAGG;IACU,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;;;;;;;;;;;OAYG;IACU,WAAW,CAAC,OAAO,SAAQ,EAAE,iBAAiB,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3F;;OAEG;IACU,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAIvC;;;;OAIG;IACU,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD;;;;OAIG;IACU,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D;;;;OAIG;IACU,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI/D;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAI3C;;;;;OAKG;IACU,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5E;;;;;;;;OAQG;IACU,qBAAqB,CACjC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,QAAQ,SAAO,GACb,OAAO,CAAC,iBAAiB,CAAC;IAI7B;;OAEG;IACU,kBAAkB,IAAI,OAAO,CAAC,eAAe,CAAC;IAI3D;;;;;;;;;OASG;IACU,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzC;;OAEG;IACI,WAAW,IAAI,MAAM;IAI5B;;OAEG;IACI,OAAO,IAAI,MAAM;CAGxB"}
1
+ {"version":3,"file":"appleDeviceKit.d.ts","sourceRoot":"","sources":["../../../src/logic/appleDeviceKit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAQ3F;;;;;GAKG;AACH,qBAAa,cAAc;IAKzB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJtB,OAAO,CAAC,QAAQ,CAAS;gBAGxB,IAAI,EAAE,MAAM,EACK,IAAI,EAAE,MAAM;IAM9B;;OAEG;IACU,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC;IAIpD;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzC;;;;;;OAMG;IACU,cAAc,CAAC,OAAO,SAAS,EAAE,YAAY,SAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAIpF;;;OAGG;IACU,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;;;;;;;;;;;OAYG;IACU,WAAW,CAAC,OAAO,SAAQ,EAAE,iBAAiB,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3F;;OAEG;IACU,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAIvC;;;;OAIG;IACU,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD;;;;OAIG;IACU,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D;;;;OAIG;IACU,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI/D;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAI3C;;;;;OAKG;IACU,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5E;;;;;;;;OAQG;IACU,qBAAqB,CACjC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,QAAQ,SAAO,GACb,OAAO,CAAC,iBAAiB,CAAC;IAI7B;;OAEG;IACU,kBAAkB,IAAI,OAAO,CAAC,eAAe,CAAC;IAI3D;;;;;;;;;OASG;IACU,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzC;;OAEG;IACI,WAAW,IAAI,MAAM;IAI5B;;OAEG;IACI,OAAO,IAAI,MAAM;IAIX,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;CAG9C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcesystems/apple-kit",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "iOS device management toolkit using libimobiledevice command-line tools",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "debug": "^4.4.3",
35
- "@mcesystems/usb-device-listener": "1.0.6"
35
+ "@mcesystems/usb-device-listener": "1.0.11"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/debug": "^4.1.12",