@mcesystems/apple-kit 1.0.96 → 1.0.98

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.
Files changed (79) hide show
  1. package/README.md +258 -258
  2. package/dist/index.js +140 -64
  3. package/dist/index.js.map +2 -2
  4. package/dist/index.mjs +140 -64
  5. package/dist/index.mjs.map +2 -2
  6. package/dist/resources/bin/darwin/idevice_id +0 -0
  7. package/dist/resources/bin/darwin/idevicedebug +0 -0
  8. package/dist/resources/bin/darwin/idevicediagnostics +0 -0
  9. package/dist/resources/bin/darwin/ideviceinfo +0 -0
  10. package/dist/resources/bin/darwin/ideviceinstaller +0 -0
  11. package/dist/resources/bin/darwin/idevicename +0 -0
  12. package/dist/resources/bin/darwin/idevicepair +0 -0
  13. package/dist/resources/bin/darwin/idevicescreenshot +0 -0
  14. package/dist/resources/bin/darwin/idevicesyslog +0 -0
  15. package/dist/resources/bin/darwin/iproxy +0 -0
  16. package/dist/resources/bin/darwin/libcrypto.3.dylib +0 -0
  17. package/dist/resources/bin/darwin/libimobiledevice-1.0.6.dylib +0 -0
  18. package/dist/resources/bin/darwin/libimobiledevice-glue-1.0.0.dylib +0 -0
  19. package/dist/resources/bin/darwin/liblzma.5.dylib +0 -0
  20. package/dist/resources/bin/darwin/libplist-2.0.4.dylib +0 -0
  21. package/dist/resources/bin/darwin/libssl.3.dylib +0 -0
  22. package/dist/resources/bin/darwin/libusbmuxd-2.0.7.dylib +0 -0
  23. package/dist/resources/bin/darwin/libzip.5.dylib +0 -0
  24. package/dist/resources/bin/darwin/libzstd.1.dylib +0 -0
  25. package/dist/resources/licenses/LGPL-2.1.txt +33 -0
  26. package/dist/resources/plist/certificate-trust.xml +43 -43
  27. package/dist/resources/plist/wifi-enterprise.xml +59 -59
  28. package/dist/resources/plist/wifi-standard.xml +50 -50
  29. package/dist/types/index.d.ts +111 -35
  30. package/dist/types/index.d.ts.map +1 -0
  31. package/dist/types/logic/actions/activation.d.ts +12 -0
  32. package/dist/types/logic/actions/activation.d.ts.map +1 -0
  33. package/dist/types/logic/actions/device.d.ts +15 -0
  34. package/dist/types/logic/actions/device.d.ts.map +1 -0
  35. package/dist/types/logic/actions/install.d.ts +10 -0
  36. package/dist/types/logic/actions/install.d.ts.map +1 -0
  37. package/dist/types/logic/actions/pair.d.ts +6 -0
  38. package/dist/types/logic/actions/pair.d.ts.map +1 -0
  39. package/dist/types/logic/actions/proxy.d.ts +23 -0
  40. package/dist/types/logic/actions/proxy.d.ts.map +1 -0
  41. package/dist/types/logic/actions/restore.d.ts +36 -0
  42. package/dist/types/logic/actions/restore.d.ts.map +1 -0
  43. package/dist/types/logic/actions/tool.d.ts +8 -0
  44. package/dist/types/logic/actions/tool.d.ts.map +1 -0
  45. package/dist/types/logic/activationFlow.d.ts +15 -0
  46. package/dist/types/logic/activationFlow.d.ts.map +1 -0
  47. package/dist/types/logic/appleDeviceKit.d.ts +164 -0
  48. package/dist/types/logic/appleDeviceKit.d.ts.map +1 -0
  49. package/dist/types/logic/dataParser.d.ts +23 -0
  50. package/dist/types/logic/dataParser.d.ts.map +1 -0
  51. package/dist/types/logic/iosCli.d.ts +6 -0
  52. package/dist/types/logic/iosCli.d.ts.map +1 -0
  53. package/dist/types/logic/utils/resolvePath.d.ts +13 -0
  54. package/dist/types/logic/utils/resolvePath.d.ts.map +1 -0
  55. package/dist/types/types/activation.d.ts +28 -0
  56. package/dist/types/types/activation.d.ts.map +1 -0
  57. package/dist/types/types/ios.d.ts +152 -0
  58. package/dist/types/types/ios.d.ts.map +1 -0
  59. package/dist/types/types/trust.d.ts +10 -0
  60. package/dist/types/types/trust.d.ts.map +1 -0
  61. package/dist/types/types/types.d.ts +47 -0
  62. package/dist/types/types/types.d.ts.map +1 -0
  63. package/dist/types/types/wifi.d.ts +19 -0
  64. package/dist/types/types/wifi.d.ts.map +1 -0
  65. package/dist/types/types.d.ts +140 -0
  66. package/dist/types/types.d.ts.map +1 -0
  67. package/dist/types/utils/debug.d.ts +17 -0
  68. package/dist/types/utils/debug.d.ts.map +1 -0
  69. package/dist/types/utils/templateLoader.d.ts +8 -0
  70. package/dist/types/utils/templateLoader.d.ts.map +1 -0
  71. package/dist/types/utils/wifiProfile.d.ts +14 -0
  72. package/dist/types/utils/wifiProfile.d.ts.map +1 -0
  73. package/package.json +3 -3
  74. package/scripts/README.md +209 -209
  75. package/scripts/build-windows.sh.template +222 -222
  76. package/scripts/prepare-ios.ts +9 -1
  77. package/resources/ios.exe +0 -0
  78. package/resources/wintun-LICENSE.txt +0 -84
  79. package/resources/wintun.dll +0 -0
package/dist/index.js CHANGED
@@ -1590,6 +1590,38 @@ var DeviceActions = class {
1590
1590
  }
1591
1591
  return result.output[0];
1592
1592
  }
1593
+ async batteryInfo() {
1594
+ logInfo(`Getting device info for ${this.udid}`);
1595
+ const result = await this.iosClient.batteryInfo();
1596
+ if (result.exitCode !== 0) {
1597
+ throw new Error("Failed to get battery info");
1598
+ }
1599
+ return result.output[0];
1600
+ }
1601
+ async capacityInfo() {
1602
+ logInfo(`Getting device info for ${this.udid}`);
1603
+ const result = await this.iosClient.capacityInfo();
1604
+ if (result.exitCode !== 0) {
1605
+ throw new Error("Failed to get capacity info");
1606
+ }
1607
+ return result.output[0];
1608
+ }
1609
+ async cloudConfigInfo() {
1610
+ logInfo(`Getting device info for ${this.udid}`);
1611
+ const result = await this.iosClient.cloudConfigInfo();
1612
+ if (result.exitCode !== 0) {
1613
+ throw new Error("Failed to get cloud config info");
1614
+ }
1615
+ return result.output[0];
1616
+ }
1617
+ async regularModelNumber() {
1618
+ logInfo(`Getting device info for ${this.udid}`);
1619
+ const result = await this.iosClient.regularModelNumber();
1620
+ if (result.exitCode !== 0) {
1621
+ throw new Error("Failed to get regular model number");
1622
+ }
1623
+ return result.output[0];
1624
+ }
1593
1625
  async listDevices() {
1594
1626
  logInfo("Listing devices");
1595
1627
  return this.iosClient.listDevices();
@@ -38620,31 +38652,34 @@ function escapeXml(str) {
38620
38652
  var { logInfo: logInfo5 } = createLoggers("apple-kit:wifi-profile");
38621
38653
  async function generateWifiProfile(config, options) {
38622
38654
  const {
38623
- ssid,
38624
38655
  encryptionType,
38625
38656
  password,
38626
38657
  autoJoin = true,
38627
38658
  organizationName = "MCE Systems",
38628
- displayName = `WiFi - ${ssid}`,
38629
38659
  enterprise = false,
38630
38660
  username,
38631
38661
  acceptAnyCertificate = true
38632
38662
  } = config;
38663
+ const resolvedSsid = config.ssid ?? process.env.WIFI_SSID ?? "";
38664
+ if (!resolvedSsid) {
38665
+ throw new Error("WiFi SSID is required. Set config.ssid or WIFI_SSID environment variable.");
38666
+ }
38633
38667
  const profileUuid = (0, import_node_crypto2.randomUUID)().toUpperCase();
38634
38668
  const payloadUuid = (0, import_node_crypto2.randomUUID)().toUpperCase();
38635
- const profileId = `com.mce.wifi.${ssid.replace(/[^a-zA-Z0-9]/g, "")}.${Date.now()}`;
38669
+ const profileId = `com.mce.wifi.${resolvedSsid.replace(/[^a-zA-Z0-9]/g, "")}.${Date.now()}`;
38636
38670
  const payloadId = `${profileId}.payload`;
38637
- logInfo5(`Generating WiFi profile for SSID: ${ssid}, encryption: ${encryptionType}`);
38671
+ const displayNameToUse = config.displayName ?? `WiFi - ${resolvedSsid}`;
38672
+ logInfo5(`Generating WiFi profile for SSID: ${resolvedSsid}, encryption: ${encryptionType}`);
38638
38673
  const templateName = enterprise ? "wifi-enterprise.xml" : "wifi-standard.xml";
38639
38674
  const template = await loadTemplate(templateName, options?.plistDir);
38640
38675
  const variables = {
38641
- ssid: config.ssid ?? process.env.WIFI_SSID,
38676
+ ssid: resolvedSsid,
38642
38677
  password: config.password ?? process.env.WIFI_PASSWORD,
38643
38678
  encryptionType: parseWifiEncryptionType(config.encryptionType ?? process.env.WIFI_ENCRYPTION),
38644
38679
  autoJoin: autoJoin ? "true" : "false",
38645
38680
  hiddenNetwork: config.hiddenNetwork ?? process.env.WIFI_HIDDEN === "true",
38646
38681
  organizationName,
38647
- displayName,
38682
+ displayName: displayNameToUse,
38648
38683
  profileId,
38649
38684
  profileUuid,
38650
38685
  payloadId,
@@ -38739,10 +38774,9 @@ function isAbortError(error) {
38739
38774
  return error instanceof DOMException && error.name === "AbortError";
38740
38775
  }
38741
38776
  var ActivationFlow = class {
38742
- constructor(udid, iosClient, deviceActions) {
38777
+ constructor(udid, iosClient) {
38743
38778
  this.udid = udid;
38744
38779
  this.iosClient = iosClient;
38745
- this.deviceActions = deviceActions;
38746
38780
  setNamespace4(`${udid}`);
38747
38781
  }
38748
38782
  mdmClient;
@@ -38778,14 +38812,6 @@ var ActivationFlow = class {
38778
38812
  signal
38779
38813
  );
38780
38814
  throwIfAborted2(signal);
38781
- const expectedSsid = config.wifiProfileConfig?.ssid;
38782
- if (expectedSsid) {
38783
- if (await this.deviceActions.isWifiConnected(15e3) !== expectedSsid) {
38784
- throw new Error(
38785
- `WiFi profile not installed correctly, expected ${expectedSsid} but got ${await this.deviceActions.isWifiConnected(15e3)}`
38786
- );
38787
- }
38788
- }
38789
38815
  await this.installMdmProfile(events, signal);
38790
38816
  throwIfAborted2(signal);
38791
38817
  }
@@ -39163,6 +39189,24 @@ var IosClient = class {
39163
39189
  async info() {
39164
39190
  return this.runIosCommand(["info", "--udid", this.udid]);
39165
39191
  }
39192
+ async batteryInfo() {
39193
+ return this.runIosCommand(["batteryregistry", "--udid", this.udid]);
39194
+ }
39195
+ async capacityInfo() {
39196
+ return this.runIosCommand([
39197
+ "lockdown",
39198
+ "get",
39199
+ "--domain=com.apple.disk_usage",
39200
+ "--udid",
39201
+ this.udid
39202
+ ]);
39203
+ }
39204
+ async cloudConfigInfo() {
39205
+ return this.runIosCommand(["prepare", "cloudconfig", "--udid", this.udid]);
39206
+ }
39207
+ async regularModelNumber() {
39208
+ return this.runIosCommand(["lockdown", "get", "RegulatoryModelNumber", "--udid", this.udid]);
39209
+ }
39166
39210
  async installApp(ipaPath) {
39167
39211
  return this.runIosCommand(["install", `--path=${ipaPath}`, "--udid", this.udid]);
39168
39212
  }
@@ -39189,45 +39233,59 @@ var IosClient = class {
39189
39233
  return this.runIosCommand(["devmode", "enable", "--udid", this.udid]);
39190
39234
  }
39191
39235
  async tunnelStart(userspace = false, pairRecordPath) {
39192
- const args = ["tunnel", "start", `--pair-record-path=${pairRecordPath ?? "default"}`, "--udid", this.udid, ...userspace ? ["--userspace"] : []];
39193
- logDetail(`Spawning tunnel: ${this.iosPath} ${args.join(" ")}`);
39194
- const child = (0, import_node_child_process.spawn)(this.iosPath, args, {
39195
- windowsHide: true,
39196
- env: {
39197
- ...process.env,
39198
- USBMUXD_SOCKET_ADDRESS: this.usbmuxdAddress
39199
- },
39200
- stdio: ["ignore", "pipe", "pipe"]
39236
+ return new Promise((resolve2, reject) => {
39237
+ const args = [
39238
+ "tunnel",
39239
+ "start",
39240
+ `--pair-record-path=${pairRecordPath ?? "default"}`,
39241
+ "--udid",
39242
+ this.udid,
39243
+ ...userspace ? ["--userspace"] : []
39244
+ ];
39245
+ logDetail(`Spawning tunnel: ${this.iosPath} ${args.join(" ")}`);
39246
+ const child = (0, import_node_child_process.spawn)(this.iosPath, args, {
39247
+ windowsHide: true,
39248
+ env: {
39249
+ ...process.env,
39250
+ USBMUXD_SOCKET_ADDRESS: this.usbmuxdAddress
39251
+ },
39252
+ stdio: ["ignore", "pipe", "pipe"]
39253
+ });
39254
+ let settled = false;
39255
+ const cleanup = () => {
39256
+ child.off("error", onError);
39257
+ child.off("exit", onExit);
39258
+ child.stdout?.off("data", onReadyCheck);
39259
+ child.stderr?.off("data", onReadyCheck);
39260
+ clearTimeout(readyTimeout);
39261
+ };
39262
+ const finish = (result) => {
39263
+ if (settled) {
39264
+ return;
39265
+ }
39266
+ settled = true;
39267
+ cleanup();
39268
+ if (result.reject) {
39269
+ reject(result.reject);
39270
+ return;
39271
+ }
39272
+ if (result.resolve !== void 0) {
39273
+ resolve2(result.resolve);
39274
+ }
39275
+ };
39276
+ const onError = (err) => finish({ reject: err });
39277
+ const onExit = (code) => finish({ reject: new Error(`Tunnel exited early (code=${code})`) });
39278
+ const onReadyCheck = (data) => {
39279
+ const line = data.toString();
39280
+ const isReady = line.includes("Tunnel server started") || line.includes("tunnel") && (line.includes("listening") || line.includes("connected"));
39281
+ if (isReady) finish({ resolve: child });
39282
+ };
39283
+ const readyTimeout = setTimeout(() => finish({ resolve: child }), 1e4);
39284
+ child.once("error", onError);
39285
+ child.once("exit", onExit);
39286
+ child.stdout?.on("data", onReadyCheck);
39287
+ child.stderr?.on("data", onReadyCheck);
39201
39288
  });
39202
- let settled = false;
39203
- const cleanup = () => {
39204
- child.off("error", onError);
39205
- child.off("exit", onExit);
39206
- child.stdout?.off("data", onReadyCheck);
39207
- child.stderr?.off("data", onReadyCheck);
39208
- clearTimeout(readyTimeout);
39209
- };
39210
- const finish = (result) => {
39211
- if (settled) return;
39212
- settled = true;
39213
- cleanup();
39214
- if (result.reject) throw result.reject;
39215
- if (result.resolve !== void 0) return result.resolve;
39216
- throw new Error("Tunnel process not found");
39217
- };
39218
- const onError = (err) => finish({ reject: err });
39219
- const onExit = (code) => finish({ reject: new Error(`Tunnel exited early (code=${code})`) });
39220
- const onReadyCheck = (data) => {
39221
- const line = data.toString();
39222
- const isReady = line.includes("Tunnel server started") || line.includes("tunnel") && (line.includes("listening") || line.includes("connected"));
39223
- if (isReady) finish({ resolve: child });
39224
- };
39225
- const readyTimeout = setTimeout(() => finish({ resolve: child }), 1e4);
39226
- child.once("error", onError);
39227
- child.once("exit", onExit);
39228
- child.stdout?.on("data", onReadyCheck);
39229
- child.stderr?.on("data", onReadyCheck);
39230
- return child;
39231
39289
  }
39232
39290
  async fsyncPull({
39233
39291
  app,
@@ -39349,9 +39407,9 @@ var AppleDeviceKit = class _AppleDeviceKit {
39349
39407
  this.iosClient = new IosClient(iosBinaryPath, udid, usbmuxdAddress);
39350
39408
  this.deviceActions = new DeviceActions(this.deviceId, this.iosClient);
39351
39409
  this.installActions = new InstallActions(this.deviceId, this.iosClient);
39352
- this.activationFlow = new ActivationFlow(this.deviceId, this.iosClient, this.deviceActions);
39410
+ this.activationFlow = new ActivationFlow(this.deviceId, this.iosClient);
39353
39411
  this.proxyActions = new ProxyActions(this.deviceId, this.iosClient);
39354
- this.ensureTunnel();
39412
+ this.getTunnelReady();
39355
39413
  }
39356
39414
  deviceId;
39357
39415
  proxyProcess = null;
@@ -39363,7 +39421,18 @@ var AppleDeviceKit = class _AppleDeviceKit {
39363
39421
  activationFlow;
39364
39422
  proxyActions;
39365
39423
  tunnelProcess = null;
39424
+ tunnelReadyPromise = null;
39366
39425
  static IOS_17_VERSION = 17;
39426
+ /**
39427
+ * Returns a promise that resolves when the tunnel is ready (or immediately if not needed).
39428
+ * Reuses the same in-flight promise so constructor and methods don't race.
39429
+ */
39430
+ getTunnelReady() {
39431
+ if (!this.tunnelReadyPromise) {
39432
+ this.tunnelReadyPromise = this.runEnsureTunnel();
39433
+ }
39434
+ return this.tunnelReadyPromise;
39435
+ }
39367
39436
  /**
39368
39437
  * Check if iOS version requires tunneling (iOS 17+)
39369
39438
  */
@@ -39381,9 +39450,15 @@ var AppleDeviceKit = class _AppleDeviceKit {
39381
39450
  }
39382
39451
  }
39383
39452
  /**
39384
- * Ensure tunnel is started for iOS 17+ devices
39453
+ * Ensure tunnel is started for iOS 17+ devices. Safe to call multiple times; reuses in-flight setup.
39385
39454
  */
39386
39455
  async ensureTunnel() {
39456
+ await this.getTunnelReady();
39457
+ }
39458
+ /**
39459
+ * Internal tunnel startup. Called once per tunnel lifecycle; getTunnelReady() caches this promise.
39460
+ */
39461
+ async runEnsureTunnel() {
39387
39462
  const requiresTunnel = await this.requiresTunneling();
39388
39463
  if (!requiresTunnel) {
39389
39464
  logDetail2(`Device ${this.deviceId} does not require tunneling (iOS < 17)`);
@@ -39396,21 +39471,28 @@ var AppleDeviceKit = class _AppleDeviceKit {
39396
39471
  }
39397
39472
  logInfo7(`Starting tunnel for device ${this.deviceId} (iOS 17+)`);
39398
39473
  try {
39399
- const pairRecordPath = (0, import_node_path5.join)(this.deviceActions.getLockdownPath() ?? "", "RemotePairing", `${this.deviceId}`);
39474
+ const pairRecordPath = (0, import_node_path5.join)(
39475
+ this.deviceActions.getLockdownPath() ?? "",
39476
+ "RemotePairing",
39477
+ `${this.deviceId}`
39478
+ );
39400
39479
  await (0, import_promises3.mkdir)(pairRecordPath, { recursive: true });
39401
39480
  const tunnelProcess = await this.iosClient.tunnelStart(true, pairRecordPath);
39402
39481
  this.tunnelProcess = tunnelProcess;
39403
39482
  tunnelProcess.on("exit", (code) => {
39404
39483
  logError3(`Tunnel process for device ${this.deviceId} exited with code ${code}`);
39405
39484
  this.tunnelProcess = null;
39485
+ this.tunnelReadyPromise = null;
39406
39486
  });
39407
39487
  tunnelProcess.on("error", (error) => {
39408
39488
  logError3(`Tunnel process error for device ${this.deviceId}: ${error.message}`);
39409
39489
  this.tunnelProcess = null;
39490
+ this.tunnelReadyPromise = null;
39410
39491
  });
39411
39492
  await new Promise((resolve2) => setTimeout(resolve2, 1e3));
39412
39493
  logInfo7(`Tunnel started successfully for device ${this.deviceId}`);
39413
39494
  } catch (error) {
39495
+ this.tunnelReadyPromise = null;
39414
39496
  logError3(
39415
39497
  `Failed to start tunnel for device ${this.deviceId}: ${error instanceof Error ? error.message : String(error)}`
39416
39498
  );
@@ -39648,9 +39730,6 @@ var AppleDeviceKit = class _AppleDeviceKit {
39648
39730
  }
39649
39731
  logInfo7(`File ${fileName} pushed to device ${this.deviceId}`);
39650
39732
  } finally {
39651
- if (requiresTunnel) {
39652
- this.stopTunnel();
39653
- }
39654
39733
  try {
39655
39734
  (0, import_node_fs5.unlinkSync)(tmpFilePath);
39656
39735
  } catch (_error) {
@@ -39687,9 +39766,6 @@ var AppleDeviceKit = class _AppleDeviceKit {
39687
39766
  logInfo7(`File ${fileName} pulled from device ${this.deviceId}`);
39688
39767
  return fileData;
39689
39768
  } finally {
39690
- if (requiresTunnel) {
39691
- this.stopTunnel();
39692
- }
39693
39769
  try {
39694
39770
  (0, import_node_fs5.unlinkSync)(tmpFilePath);
39695
39771
  } catch (_error) {