@mcesystems/apple-kit 1.0.40 → 1.0.44

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.mjs CHANGED
@@ -940,46 +940,18 @@ function logInfo(message) {
940
940
  function logTask(message) {
941
941
  debugTask(message);
942
942
  }
943
+ function logError(message) {
944
+ debugError(message);
945
+ }
943
946
 
944
- // src/logic/actions/device.ts
947
+ // src/logic/actions/tool.ts
945
948
  import { exec as execCallback } from "node:child_process";
946
- import { existsSync } from "node:fs";
947
- import { dirname, join } from "node:path";
949
+ import { join as join2 } from "node:path";
948
950
  import { promisify } from "node:util";
949
951
 
950
- // src/logic/dataParser.ts
951
- function parsePlistOutput(output) {
952
- const result = {};
953
- const lines = output.split("\n");
954
- for (const line of lines) {
955
- const colonIndex = line.indexOf(":");
956
- if (colonIndex > 0) {
957
- const key = line.substring(0, colonIndex).trim();
958
- const value = line.substring(colonIndex + 1).trim();
959
- result[key] = value;
960
- }
961
- }
962
- return result;
963
- }
964
- function parseAppList(output) {
965
- const apps = [];
966
- const lines = output.trim().split("\n");
967
- for (const line of lines) {
968
- const match = line.match(/^([^,]+),\s*([^,]+),\s*"?([^"]+)"?/);
969
- if (match) {
970
- apps.push({
971
- bundleId: match[1].trim(),
972
- version: match[2].trim(),
973
- displayName: match[3].trim(),
974
- bundleVersion: ""
975
- });
976
- }
977
- }
978
- return apps;
979
- }
980
-
981
- // src/logic/actions/device.ts
982
- var execAsync = promisify(execCallback);
952
+ // src/logic/utils/resolvePath.ts
953
+ import { existsSync } from "node:fs";
954
+ import { dirname, isAbsolute, join } from "node:path";
983
955
  function getModuleDir() {
984
956
  if (typeof import.meta !== "undefined" && import.meta.url) {
985
957
  const { fileURLToPath } = __require("node:url");
@@ -987,56 +959,6 @@ function getModuleDir() {
987
959
  }
988
960
  return __dirname;
989
961
  }
990
- async function getDeviceInfo(udid) {
991
- logTask(`Getting device info for ${udid}`);
992
- const result = await runIDeviceTool("ideviceinfo", ["-u", udid]);
993
- if (!result) {
994
- throw new Error("Failed to get device info");
995
- }
996
- const props = parsePlistOutput(result.stdout);
997
- return {
998
- deviceName: props.DeviceName || "",
999
- productType: props.ProductType || "",
1000
- productVersion: props.ProductVersion || "",
1001
- buildVersion: props.BuildVersion || "",
1002
- serialNumber: props.SerialNumber || "",
1003
- udid: props.UniqueDeviceID || udid,
1004
- wifiAddress: props.WiFiAddress || "",
1005
- bluetoothAddress: props.BluetoothAddress || "",
1006
- phoneNumber: props.PhoneNumber || "",
1007
- cpuArchitecture: props.CPUArchitecture || "",
1008
- hardwareModel: props.HardwareModel || "",
1009
- modelNumber: props.ModelNumber || "",
1010
- regionInfo: props.RegionInfo || "",
1011
- timeZone: props.TimeZone || "",
1012
- uniqueChipID: props.UniqueChipID || "",
1013
- isPaired: true
1014
- // If we can get info, device is paired
1015
- };
1016
- }
1017
- async function runIDeviceTool(toolName, args = [], options = {}) {
1018
- const binPath = getIDeviceBinPath();
1019
- const ext = process.platform === "win32" ? ".exe" : "";
1020
- const toolPath = binPath ? join(binPath, `${toolName}${ext}`) : `${toolName}${ext}`;
1021
- const command = `"${toolPath}" ${args.map((a) => `"${a}"`).join(" ")}`;
1022
- return execIDevice(command, options);
1023
- }
1024
- async function execIDevice(command, options = {}) {
1025
- const binPath = getIDeviceBinPath();
1026
- if (binPath) {
1027
- options.cwd = binPath;
1028
- }
1029
- const result = await execAsync(command, {
1030
- ...options,
1031
- env: process.env,
1032
- windowsHide: true,
1033
- encoding: "utf8"
1034
- });
1035
- return {
1036
- stdout: result.stdout.toString(),
1037
- stderr: result.stderr.toString()
1038
- };
1039
- }
1040
962
  function getPlatformDir() {
1041
963
  const platform = process.platform;
1042
964
  if (platform === "win32") {
@@ -1050,29 +972,19 @@ function getPlatformDir() {
1050
972
  }
1051
973
  return platform;
1052
974
  }
1053
- function getBundledResourcesPath() {
1054
- const moduleDir = getModuleDir();
1055
- let packageRoot;
1056
- if (moduleDir.includes("dist")) {
1057
- packageRoot = join(moduleDir, "..", "..");
1058
- } else {
1059
- packageRoot = join(moduleDir, "..", "..", "..", "..");
1060
- }
1061
- const platformDir = getPlatformDir();
1062
- const distPath = join(packageRoot, "dist", "resources", "bin", platformDir);
1063
- if (existsSync(join(distPath, "idevice_id")) || existsSync(join(distPath, "idevice_id.exe"))) {
1064
- return distPath;
1065
- }
1066
- const devPath = join(packageRoot, "resources", "bin", platformDir);
1067
- if (existsSync(join(devPath, "idevice_id")) || existsSync(join(devPath, "idevice_id.exe"))) {
1068
- return devPath;
1069
- }
1070
- return null;
1071
- }
1072
975
  function getResourcesBinPath() {
1073
976
  const envBinPath = process.env.IDeviceBinPath;
1074
977
  if (envBinPath) {
1075
- return envBinPath;
978
+ if (isAbsolute(envBinPath)) {
979
+ return envBinPath;
980
+ }
981
+ const absolutePath = join(process.cwd(), envBinPath);
982
+ logInfo(`Using absolute path: ${absolutePath}`);
983
+ if (existsSync(absolutePath)) {
984
+ return absolutePath;
985
+ }
986
+ logError(`Absolute path does not exist: ${absolutePath}`);
987
+ return "";
1076
988
  }
1077
989
  const bundledPath = getBundledResourcesPath();
1078
990
  if (bundledPath) {
@@ -1098,8 +1010,50 @@ function getResourcesBinPath() {
1098
1010
  }
1099
1011
  return "";
1100
1012
  }
1101
- function getIDeviceBinPath() {
1102
- return getResourcesBinPath();
1013
+ function getBundledResourcesPath() {
1014
+ const moduleDir = getModuleDir();
1015
+ let packageRoot;
1016
+ if (moduleDir.includes("dist")) {
1017
+ packageRoot = join(moduleDir, "..", "..");
1018
+ } else {
1019
+ packageRoot = join(moduleDir, "..", "..", "..", "..");
1020
+ }
1021
+ const platformDir = getPlatformDir();
1022
+ const distPath = join(packageRoot, "dist", "resources", "bin", platformDir);
1023
+ if (existsSync(join(distPath, "idevice_id")) || existsSync(join(distPath, "idevice_id.exe"))) {
1024
+ return distPath;
1025
+ }
1026
+ const devPath = join(packageRoot, "resources", "bin", platformDir);
1027
+ if (existsSync(join(devPath, "idevice_id")) || existsSync(join(devPath, "idevice_id.exe"))) {
1028
+ return devPath;
1029
+ }
1030
+ return null;
1031
+ }
1032
+
1033
+ // src/logic/actions/tool.ts
1034
+ var execAsync = promisify(execCallback);
1035
+ async function runIDeviceTool(toolName, args = [], options = {}) {
1036
+ const binPath = getResourcesBinPath();
1037
+ const ext = process.platform === "win32" ? ".exe" : "";
1038
+ const toolPath = binPath ? join2(binPath, `${toolName}${ext}`) : `${toolName}${ext}`;
1039
+ const command = `"${toolPath}" ${args.map((a) => `"${a}"`).join(" ")}`;
1040
+ return execIDevice(command, options);
1041
+ }
1042
+ async function execIDevice(command, options = {}) {
1043
+ const binPath = getResourcesBinPath();
1044
+ if (binPath) {
1045
+ options.cwd = binPath;
1046
+ }
1047
+ const result = await execAsync(command, {
1048
+ ...options,
1049
+ env: process.env,
1050
+ windowsHide: true,
1051
+ encoding: "utf8"
1052
+ });
1053
+ return {
1054
+ stdout: result.stdout.toString(),
1055
+ stderr: result.stderr.toString()
1056
+ };
1103
1057
  }
1104
1058
 
1105
1059
  // src/logic/actions/activation.ts
@@ -1140,6 +1094,70 @@ async function activate(udid) {
1140
1094
  }
1141
1095
  }
1142
1096
 
1097
+ // src/logic/actions/device.ts
1098
+ import { existsSync as existsSync2 } from "node:fs";
1099
+ import { join as join3 } from "node:path";
1100
+
1101
+ // src/logic/dataParser.ts
1102
+ function parsePlistOutput(output) {
1103
+ const result = {};
1104
+ const lines = output.split("\n");
1105
+ for (const line of lines) {
1106
+ const colonIndex = line.indexOf(":");
1107
+ if (colonIndex > 0) {
1108
+ const key = line.substring(0, colonIndex).trim();
1109
+ const value = line.substring(colonIndex + 1).trim();
1110
+ result[key] = value;
1111
+ }
1112
+ }
1113
+ return result;
1114
+ }
1115
+ function parseAppList(output) {
1116
+ const apps = [];
1117
+ const lines = output.trim().split("\n");
1118
+ for (const line of lines) {
1119
+ const match = line.match(/^([^,]+),\s*([^,]+),\s*"?([^"]+)"?/);
1120
+ if (match) {
1121
+ apps.push({
1122
+ bundleId: match[1].trim(),
1123
+ version: match[2].trim(),
1124
+ displayName: match[3].trim(),
1125
+ bundleVersion: ""
1126
+ });
1127
+ }
1128
+ }
1129
+ return apps;
1130
+ }
1131
+
1132
+ // src/logic/actions/device.ts
1133
+ async function getDeviceInfo(udid) {
1134
+ logTask(`Getting device info for ${udid}`);
1135
+ const result = await runIDeviceTool("ideviceinfo", ["-u", udid]);
1136
+ if (!result) {
1137
+ throw new Error("Failed to get device info");
1138
+ }
1139
+ const props = parsePlistOutput(result.stdout);
1140
+ return {
1141
+ deviceName: props.DeviceName || "",
1142
+ productType: props.ProductType || "",
1143
+ productVersion: props.ProductVersion || "",
1144
+ buildVersion: props.BuildVersion || "",
1145
+ serialNumber: props.SerialNumber || "",
1146
+ udid: props.UniqueDeviceID || udid,
1147
+ wifiAddress: props.WiFiAddress || "",
1148
+ bluetoothAddress: props.BluetoothAddress || "",
1149
+ phoneNumber: props.PhoneNumber || "",
1150
+ cpuArchitecture: props.CPUArchitecture || "",
1151
+ hardwareModel: props.HardwareModel || "",
1152
+ modelNumber: props.ModelNumber || "",
1153
+ regionInfo: props.RegionInfo || "",
1154
+ timeZone: props.TimeZone || "",
1155
+ uniqueChipID: props.UniqueChipID || "",
1156
+ isPaired: true
1157
+ // If we can get info, device is paired
1158
+ };
1159
+ }
1160
+
1143
1161
  // src/logic/actions/pair.ts
1144
1162
  async function isPaired(udid) {
1145
1163
  logTask(`Checking pairing status for ${udid}`);
@@ -1160,10 +1178,14 @@ async function trustDevice(udid, timeout2 = 6e4, onWaitingForTrust) {
1160
1178
  return true;
1161
1179
  }
1162
1180
  logInfo(`Initiating pairing for device ${udid}`);
1163
- const pairResult = await pair(udid);
1164
- if (pairResult) {
1165
- logInfo(`Device ${udid} paired successfully`);
1166
- return true;
1181
+ try {
1182
+ const pairResult = await pair(udid);
1183
+ if (pairResult) {
1184
+ logInfo(`Device ${udid} paired successfully`);
1185
+ return true;
1186
+ }
1187
+ } catch (error) {
1188
+ logError(`Pairing failed with ${udid}: ${error}`);
1167
1189
  }
1168
1190
  logInfo("Please accept the trust dialog on the device...");
1169
1191
  onWaitingForTrust?.();
@@ -1278,6 +1300,12 @@ async function launchApp(bundleId, args, udid) {
1278
1300
  if (!await isPaired(udid)) {
1279
1301
  await waitForPairing(udid, 1e4);
1280
1302
  }
1303
+ const installed = await isAppInstalled(bundleId, udid);
1304
+ if (!installed) {
1305
+ throw new Error(
1306
+ `App "${bundleId}" is not installed on the device. Install the app first or verify the bundle identifier is correct.`
1307
+ );
1308
+ }
1281
1309
  await wakeDevice(udid);
1282
1310
  try {
1283
1311
  logInfo(`Attempting to launch ${bundleId} using idevicedebug...`);
@@ -1405,82 +1433,13 @@ async function launchAppWithPymobiledevice3(bundleId, args, udid) {
1405
1433
 
1406
1434
  // src/logic/actions/proxy.ts
1407
1435
  import { spawn } from "node:child_process";
1408
- import { existsSync as existsSync2 } from "node:fs";
1409
- import { dirname as dirname2, join as join2 } from "node:path";
1410
- function getModuleDir2() {
1411
- if (typeof import.meta !== "undefined" && import.meta.url) {
1412
- const { fileURLToPath } = __require("node:url");
1413
- return dirname2(fileURLToPath(import.meta.url));
1414
- }
1415
- return __dirname;
1416
- }
1417
- function getPlatformDir2() {
1418
- const platform = process.platform;
1419
- if (platform === "win32") {
1420
- return "windows";
1421
- }
1422
- if (platform === "darwin") {
1423
- return "darwin";
1424
- }
1425
- if (platform === "linux") {
1426
- return "linux";
1427
- }
1428
- return platform;
1429
- }
1430
- function getBundledResourcesPath2() {
1431
- const moduleDir = getModuleDir2();
1432
- let packageRoot;
1433
- if (moduleDir.includes("dist")) {
1434
- packageRoot = join2(moduleDir, "..", "..");
1435
- } else {
1436
- packageRoot = join2(moduleDir, "..", "..", "..", "..");
1437
- }
1438
- const platformDir = getPlatformDir2();
1439
- const distPath = join2(packageRoot, "dist", "resources", "bin", platformDir);
1440
- if (existsSync2(join2(distPath, "iproxy")) || existsSync2(join2(distPath, "iproxy.exe"))) {
1441
- return distPath;
1442
- }
1443
- const devPath = join2(packageRoot, "resources", "bin", platformDir);
1444
- if (existsSync2(join2(devPath, "iproxy")) || existsSync2(join2(devPath, "iproxy.exe"))) {
1445
- return devPath;
1446
- }
1447
- return null;
1448
- }
1449
- function getResourcesBinPath2() {
1450
- const envBinPath = process.env.IDeviceBinPath;
1451
- if (envBinPath) {
1452
- return envBinPath;
1453
- }
1454
- const bundledPath = getBundledResourcesPath2();
1455
- if (bundledPath) {
1456
- return bundledPath;
1457
- }
1458
- if (process.platform === "darwin") {
1459
- const homebrewArmPath = "/opt/homebrew/bin";
1460
- if (existsSync2(join2(homebrewArmPath, "iproxy"))) {
1461
- return homebrewArmPath;
1462
- }
1463
- const homebrewIntelPath = "/usr/local/bin";
1464
- if (existsSync2(join2(homebrewIntelPath, "iproxy"))) {
1465
- return homebrewIntelPath;
1466
- }
1467
- }
1468
- if (process.platform === "linux") {
1469
- const linuxPaths = ["/usr/bin", "/usr/local/bin"];
1470
- for (const linuxPath of linuxPaths) {
1471
- if (existsSync2(join2(linuxPath, "iproxy"))) {
1472
- return linuxPath;
1473
- }
1474
- }
1475
- }
1476
- return "";
1477
- }
1436
+ import { join as join4 } from "node:path";
1478
1437
  function startPortForward(localPort, devicePort, udid, startupTimeout = 500) {
1479
1438
  return new Promise((resolve, reject) => {
1480
1439
  logTask(`Starting port forward ${localPort} -> ${devicePort} for device ${udid}`);
1481
- const binPath = getResourcesBinPath2();
1440
+ const binPath = getResourcesBinPath();
1482
1441
  const ext = process.platform === "win32" ? ".exe" : "";
1483
- const toolPath = binPath ? join2(binPath, `iproxy${ext}`) : `iproxy${ext}`;
1442
+ const toolPath = binPath ? join4(binPath, `iproxy${ext}`) : `iproxy${ext}`;
1484
1443
  const spawnOptions = {
1485
1444
  windowsHide: true,
1486
1445
  stdio: ["ignore", "pipe", "pipe"]
@@ -1488,6 +1447,9 @@ function startPortForward(localPort, devicePort, udid, startupTimeout = 500) {
1488
1447
  if (binPath) {
1489
1448
  spawnOptions.cwd = binPath;
1490
1449
  }
1450
+ logInfo(`Spawning iproxy with path: ${toolPath}`);
1451
+ logInfo(`Arguments: ${[localPort.toString(), devicePort.toString(), "-u", udid].join(" ")}`);
1452
+ logInfo(`Options: ${JSON.stringify(spawnOptions)}`);
1491
1453
  const child = spawn(
1492
1454
  toolPath,
1493
1455
  [localPort.toString(), devicePort.toString(), "-u", udid],
@@ -1495,7 +1457,11 @@ function startPortForward(localPort, devicePort, udid, startupTimeout = 500) {
1495
1457
  );
1496
1458
  let hasResolved = false;
1497
1459
  let stderrOutput = "";
1460
+ child.stdout?.on("data", (data) => {
1461
+ logTask(`${data.toString()}`);
1462
+ });
1498
1463
  child.stderr?.on("data", (data) => {
1464
+ logError(`${data.toString()}`);
1499
1465
  const msg = data.toString();
1500
1466
  stderrOutput += msg;
1501
1467
  if (msg.toLowerCase().includes("error") && !hasResolved) {