@mcesystems/apple-kit 1.0.95 → 1.0.97

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 (78) hide show
  1. package/README.md +258 -258
  2. package/dist/index.js +97 -67
  3. package/dist/index.js.map +2 -2
  4. package/dist/index.mjs +97 -67
  5. package/dist/index.mjs.map +3 -3
  6. package/dist/resources/plist/certificate-trust.xml +43 -43
  7. package/dist/resources/plist/wifi-enterprise.xml +59 -59
  8. package/dist/resources/plist/wifi-standard.xml +50 -50
  9. package/dist/types/index.d.ts +13 -34
  10. package/package.json +3 -3
  11. package/resources/ios.exe +0 -0
  12. package/resources/wintun-LICENSE.txt +84 -0
  13. package/resources/wintun.dll +0 -0
  14. package/scripts/README.md +209 -209
  15. package/scripts/build-windows.sh.template +222 -222
  16. package/dist/resources/bin/darwin/idevice_id +0 -0
  17. package/dist/resources/bin/darwin/idevicedebug +0 -0
  18. package/dist/resources/bin/darwin/idevicediagnostics +0 -0
  19. package/dist/resources/bin/darwin/ideviceinfo +0 -0
  20. package/dist/resources/bin/darwin/ideviceinstaller +0 -0
  21. package/dist/resources/bin/darwin/idevicename +0 -0
  22. package/dist/resources/bin/darwin/idevicepair +0 -0
  23. package/dist/resources/bin/darwin/idevicescreenshot +0 -0
  24. package/dist/resources/bin/darwin/idevicesyslog +0 -0
  25. package/dist/resources/bin/darwin/iproxy +0 -0
  26. package/dist/resources/bin/darwin/libcrypto.3.dylib +0 -0
  27. package/dist/resources/bin/darwin/libimobiledevice-1.0.6.dylib +0 -0
  28. package/dist/resources/bin/darwin/libimobiledevice-glue-1.0.0.dylib +0 -0
  29. package/dist/resources/bin/darwin/liblzma.5.dylib +0 -0
  30. package/dist/resources/bin/darwin/libplist-2.0.4.dylib +0 -0
  31. package/dist/resources/bin/darwin/libssl.3.dylib +0 -0
  32. package/dist/resources/bin/darwin/libusbmuxd-2.0.7.dylib +0 -0
  33. package/dist/resources/bin/darwin/libzip.5.dylib +0 -0
  34. package/dist/resources/bin/darwin/libzstd.1.dylib +0 -0
  35. package/dist/resources/licenses/LGPL-2.1.txt +0 -33
  36. package/dist/types/index.d.ts.map +0 -1
  37. package/dist/types/logic/actions/activation.d.ts +0 -12
  38. package/dist/types/logic/actions/activation.d.ts.map +0 -1
  39. package/dist/types/logic/actions/device.d.ts +0 -15
  40. package/dist/types/logic/actions/device.d.ts.map +0 -1
  41. package/dist/types/logic/actions/install.d.ts +0 -10
  42. package/dist/types/logic/actions/install.d.ts.map +0 -1
  43. package/dist/types/logic/actions/pair.d.ts +0 -6
  44. package/dist/types/logic/actions/pair.d.ts.map +0 -1
  45. package/dist/types/logic/actions/proxy.d.ts +0 -23
  46. package/dist/types/logic/actions/proxy.d.ts.map +0 -1
  47. package/dist/types/logic/actions/restore.d.ts +0 -36
  48. package/dist/types/logic/actions/restore.d.ts.map +0 -1
  49. package/dist/types/logic/actions/tool.d.ts +0 -8
  50. package/dist/types/logic/actions/tool.d.ts.map +0 -1
  51. package/dist/types/logic/activationFlow.d.ts +0 -15
  52. package/dist/types/logic/activationFlow.d.ts.map +0 -1
  53. package/dist/types/logic/appleDeviceKit.d.ts +0 -164
  54. package/dist/types/logic/appleDeviceKit.d.ts.map +0 -1
  55. package/dist/types/logic/dataParser.d.ts +0 -23
  56. package/dist/types/logic/dataParser.d.ts.map +0 -1
  57. package/dist/types/logic/iosCli.d.ts +0 -6
  58. package/dist/types/logic/iosCli.d.ts.map +0 -1
  59. package/dist/types/logic/utils/resolvePath.d.ts +0 -13
  60. package/dist/types/logic/utils/resolvePath.d.ts.map +0 -1
  61. package/dist/types/types/activation.d.ts +0 -28
  62. package/dist/types/types/activation.d.ts.map +0 -1
  63. package/dist/types/types/ios.d.ts +0 -152
  64. package/dist/types/types/ios.d.ts.map +0 -1
  65. package/dist/types/types/trust.d.ts +0 -10
  66. package/dist/types/types/trust.d.ts.map +0 -1
  67. package/dist/types/types/types.d.ts +0 -47
  68. package/dist/types/types/types.d.ts.map +0 -1
  69. package/dist/types/types/wifi.d.ts +0 -19
  70. package/dist/types/types/wifi.d.ts.map +0 -1
  71. package/dist/types/types.d.ts +0 -140
  72. package/dist/types/types.d.ts.map +0 -1
  73. package/dist/types/utils/debug.d.ts +0 -17
  74. package/dist/types/utils/debug.d.ts.map +0 -1
  75. package/dist/types/utils/templateLoader.d.ts +0 -8
  76. package/dist/types/utils/templateLoader.d.ts.map +0 -1
  77. package/dist/types/utils/wifiProfile.d.ts +0 -14
  78. package/dist/types/utils/wifiProfile.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -390,7 +390,6 @@ module.exports = __toCommonJS(index_exports);
390
390
  // src/logic/appleDeviceKit.ts
391
391
  var import_node_fs5 = require("node:fs");
392
392
  var import_promises3 = require("node:fs/promises");
393
- var import_promises4 = require("node:fs/promises");
394
393
  var import_node_path5 = require("node:path");
395
394
 
396
395
  // ../tool-debug/dist/index.mjs
@@ -1699,6 +1698,9 @@ ${out.stderr}`;
1699
1698
  (0, import_node_fs2.rmSync)(lockdownFile, { force: true });
1700
1699
  return true;
1701
1700
  }
1701
+ getLockdownPath() {
1702
+ return getLockdownPath();
1703
+ }
1702
1704
  };
1703
1705
 
1704
1706
  // ../mdm-client/dist/index.mjs
@@ -38618,31 +38620,34 @@ function escapeXml(str) {
38618
38620
  var { logInfo: logInfo5 } = createLoggers("apple-kit:wifi-profile");
38619
38621
  async function generateWifiProfile(config, options) {
38620
38622
  const {
38621
- ssid,
38622
38623
  encryptionType,
38623
38624
  password,
38624
38625
  autoJoin = true,
38625
38626
  organizationName = "MCE Systems",
38626
- displayName = `WiFi - ${ssid}`,
38627
38627
  enterprise = false,
38628
38628
  username,
38629
38629
  acceptAnyCertificate = true
38630
38630
  } = config;
38631
+ const resolvedSsid = config.ssid ?? process.env.WIFI_SSID ?? "";
38632
+ if (!resolvedSsid) {
38633
+ throw new Error("WiFi SSID is required. Set config.ssid or WIFI_SSID environment variable.");
38634
+ }
38631
38635
  const profileUuid = (0, import_node_crypto2.randomUUID)().toUpperCase();
38632
38636
  const payloadUuid = (0, import_node_crypto2.randomUUID)().toUpperCase();
38633
- const profileId = `com.mce.wifi.${ssid.replace(/[^a-zA-Z0-9]/g, "")}.${Date.now()}`;
38637
+ const profileId = `com.mce.wifi.${resolvedSsid.replace(/[^a-zA-Z0-9]/g, "")}.${Date.now()}`;
38634
38638
  const payloadId = `${profileId}.payload`;
38635
- logInfo5(`Generating WiFi profile for SSID: ${ssid}, encryption: ${encryptionType}`);
38639
+ const displayNameToUse = config.displayName ?? `WiFi - ${resolvedSsid}`;
38640
+ logInfo5(`Generating WiFi profile for SSID: ${resolvedSsid}, encryption: ${encryptionType}`);
38636
38641
  const templateName = enterprise ? "wifi-enterprise.xml" : "wifi-standard.xml";
38637
38642
  const template = await loadTemplate(templateName, options?.plistDir);
38638
38643
  const variables = {
38639
- ssid: config.ssid ?? process.env.WIFI_SSID,
38644
+ ssid: resolvedSsid,
38640
38645
  password: config.password ?? process.env.WIFI_PASSWORD,
38641
38646
  encryptionType: parseWifiEncryptionType(config.encryptionType ?? process.env.WIFI_ENCRYPTION),
38642
38647
  autoJoin: autoJoin ? "true" : "false",
38643
38648
  hiddenNetwork: config.hiddenNetwork ?? process.env.WIFI_HIDDEN === "true",
38644
38649
  organizationName,
38645
- displayName,
38650
+ displayName: displayNameToUse,
38646
38651
  profileId,
38647
38652
  profileUuid,
38648
38653
  payloadId,
@@ -38737,10 +38742,9 @@ function isAbortError(error) {
38737
38742
  return error instanceof DOMException && error.name === "AbortError";
38738
38743
  }
38739
38744
  var ActivationFlow = class {
38740
- constructor(udid, iosClient, deviceActions) {
38745
+ constructor(udid, iosClient) {
38741
38746
  this.udid = udid;
38742
38747
  this.iosClient = iosClient;
38743
- this.deviceActions = deviceActions;
38744
38748
  setNamespace4(`${udid}`);
38745
38749
  }
38746
38750
  mdmClient;
@@ -38776,14 +38780,6 @@ var ActivationFlow = class {
38776
38780
  signal
38777
38781
  );
38778
38782
  throwIfAborted2(signal);
38779
- const expectedSsid = config.wifiProfileConfig?.ssid;
38780
- if (expectedSsid) {
38781
- if (await this.deviceActions.isWifiConnected(15e3) !== expectedSsid) {
38782
- throw new Error(
38783
- `WiFi profile not installed correctly, expected ${expectedSsid} but got ${await this.deviceActions.isWifiConnected(15e3)}`
38784
- );
38785
- }
38786
- }
38787
38783
  await this.installMdmProfile(events, signal);
38788
38784
  throwIfAborted2(signal);
38789
38785
  }
@@ -39186,46 +39182,60 @@ var IosClient = class {
39186
39182
  async devMode() {
39187
39183
  return this.runIosCommand(["devmode", "enable", "--udid", this.udid]);
39188
39184
  }
39189
- async tunnelStart(userspace = false) {
39190
- const args = ["tunnel", "start", "--udid", this.udid, ...userspace ? ["--userspace"] : []];
39191
- logDetail(`Spawning tunnel: ${this.iosPath} ${args.join(" ")}`);
39192
- const child = (0, import_node_child_process.spawn)(this.iosPath, args, {
39193
- windowsHide: true,
39194
- env: {
39195
- ...process.env,
39196
- USBMUXD_SOCKET_ADDRESS: this.usbmuxdAddress
39197
- },
39198
- stdio: ["ignore", "pipe", "pipe"]
39185
+ async tunnelStart(userspace = false, pairRecordPath) {
39186
+ return new Promise((resolve2, reject) => {
39187
+ const args = [
39188
+ "tunnel",
39189
+ "start",
39190
+ `--pair-record-path=${pairRecordPath ?? "default"}`,
39191
+ "--udid",
39192
+ this.udid,
39193
+ ...userspace ? ["--userspace"] : []
39194
+ ];
39195
+ logDetail(`Spawning tunnel: ${this.iosPath} ${args.join(" ")}`);
39196
+ const child = (0, import_node_child_process.spawn)(this.iosPath, args, {
39197
+ windowsHide: true,
39198
+ env: {
39199
+ ...process.env,
39200
+ USBMUXD_SOCKET_ADDRESS: this.usbmuxdAddress
39201
+ },
39202
+ stdio: ["ignore", "pipe", "pipe"]
39203
+ });
39204
+ let settled = false;
39205
+ const cleanup = () => {
39206
+ child.off("error", onError);
39207
+ child.off("exit", onExit);
39208
+ child.stdout?.off("data", onReadyCheck);
39209
+ child.stderr?.off("data", onReadyCheck);
39210
+ clearTimeout(readyTimeout);
39211
+ };
39212
+ const finish = (result) => {
39213
+ if (settled) {
39214
+ return;
39215
+ }
39216
+ settled = true;
39217
+ cleanup();
39218
+ if (result.reject) {
39219
+ reject(result.reject);
39220
+ return;
39221
+ }
39222
+ if (result.resolve !== void 0) {
39223
+ resolve2(result.resolve);
39224
+ }
39225
+ };
39226
+ const onError = (err) => finish({ reject: err });
39227
+ const onExit = (code) => finish({ reject: new Error(`Tunnel exited early (code=${code})`) });
39228
+ const onReadyCheck = (data) => {
39229
+ const line = data.toString();
39230
+ const isReady = line.includes("Tunnel server started") || line.includes("tunnel") && (line.includes("listening") || line.includes("connected"));
39231
+ if (isReady) finish({ resolve: child });
39232
+ };
39233
+ const readyTimeout = setTimeout(() => finish({ resolve: child }), 1e4);
39234
+ child.once("error", onError);
39235
+ child.once("exit", onExit);
39236
+ child.stdout?.on("data", onReadyCheck);
39237
+ child.stderr?.on("data", onReadyCheck);
39199
39238
  });
39200
- let settled = false;
39201
- const cleanup = () => {
39202
- child.off("error", onError);
39203
- child.off("exit", onExit);
39204
- child.stdout?.off("data", onReadyCheck);
39205
- child.stderr?.off("data", onReadyCheck);
39206
- clearTimeout(readyTimeout);
39207
- };
39208
- const finish = (result) => {
39209
- if (settled) return;
39210
- settled = true;
39211
- cleanup();
39212
- if (result.reject) throw result.reject;
39213
- if (result.resolve !== void 0) return result.resolve;
39214
- throw new Error("Tunnel process not found");
39215
- };
39216
- const onError = (err) => finish({ reject: err });
39217
- const onExit = (code) => finish({ reject: new Error(`Tunnel exited early (code=${code})`) });
39218
- const onReadyCheck = (data) => {
39219
- const line = data.toString();
39220
- const isReady = line.includes("Tunnel server started") || line.includes("tunnel") && (line.includes("listening") || line.includes("connected"));
39221
- if (isReady) finish({ resolve: child });
39222
- };
39223
- const readyTimeout = setTimeout(() => finish({ resolve: child }), 1e4);
39224
- child.once("error", onError);
39225
- child.once("exit", onExit);
39226
- child.stdout?.on("data", onReadyCheck);
39227
- child.stderr?.on("data", onReadyCheck);
39228
- return child;
39229
39239
  }
39230
39240
  async fsyncPull({
39231
39241
  app,
@@ -39347,9 +39357,9 @@ var AppleDeviceKit = class _AppleDeviceKit {
39347
39357
  this.iosClient = new IosClient(iosBinaryPath, udid, usbmuxdAddress);
39348
39358
  this.deviceActions = new DeviceActions(this.deviceId, this.iosClient);
39349
39359
  this.installActions = new InstallActions(this.deviceId, this.iosClient);
39350
- this.activationFlow = new ActivationFlow(this.deviceId, this.iosClient, this.deviceActions);
39360
+ this.activationFlow = new ActivationFlow(this.deviceId, this.iosClient);
39351
39361
  this.proxyActions = new ProxyActions(this.deviceId, this.iosClient);
39352
- this.ensureTunnel();
39362
+ this.getTunnelReady();
39353
39363
  }
39354
39364
  deviceId;
39355
39365
  proxyProcess = null;
@@ -39361,7 +39371,18 @@ var AppleDeviceKit = class _AppleDeviceKit {
39361
39371
  activationFlow;
39362
39372
  proxyActions;
39363
39373
  tunnelProcess = null;
39374
+ tunnelReadyPromise = null;
39364
39375
  static IOS_17_VERSION = 17;
39376
+ /**
39377
+ * Returns a promise that resolves when the tunnel is ready (or immediately if not needed).
39378
+ * Reuses the same in-flight promise so constructor and methods don't race.
39379
+ */
39380
+ getTunnelReady() {
39381
+ if (!this.tunnelReadyPromise) {
39382
+ this.tunnelReadyPromise = this.runEnsureTunnel();
39383
+ }
39384
+ return this.tunnelReadyPromise;
39385
+ }
39365
39386
  /**
39366
39387
  * Check if iOS version requires tunneling (iOS 17+)
39367
39388
  */
@@ -39379,9 +39400,15 @@ var AppleDeviceKit = class _AppleDeviceKit {
39379
39400
  }
39380
39401
  }
39381
39402
  /**
39382
- * Ensure tunnel is started for iOS 17+ devices
39403
+ * Ensure tunnel is started for iOS 17+ devices. Safe to call multiple times; reuses in-flight setup.
39383
39404
  */
39384
39405
  async ensureTunnel() {
39406
+ await this.getTunnelReady();
39407
+ }
39408
+ /**
39409
+ * Internal tunnel startup. Called once per tunnel lifecycle; getTunnelReady() caches this promise.
39410
+ */
39411
+ async runEnsureTunnel() {
39385
39412
  const requiresTunnel = await this.requiresTunneling();
39386
39413
  if (!requiresTunnel) {
39387
39414
  logDetail2(`Device ${this.deviceId} does not require tunneling (iOS < 17)`);
@@ -39394,19 +39421,28 @@ var AppleDeviceKit = class _AppleDeviceKit {
39394
39421
  }
39395
39422
  logInfo7(`Starting tunnel for device ${this.deviceId} (iOS 17+)`);
39396
39423
  try {
39397
- const tunnelProcess = await this.iosClient.tunnelStart(true);
39424
+ const pairRecordPath = (0, import_node_path5.join)(
39425
+ this.deviceActions.getLockdownPath() ?? "",
39426
+ "RemotePairing",
39427
+ `${this.deviceId}`
39428
+ );
39429
+ await (0, import_promises3.mkdir)(pairRecordPath, { recursive: true });
39430
+ const tunnelProcess = await this.iosClient.tunnelStart(true, pairRecordPath);
39398
39431
  this.tunnelProcess = tunnelProcess;
39399
39432
  tunnelProcess.on("exit", (code) => {
39400
39433
  logError3(`Tunnel process for device ${this.deviceId} exited with code ${code}`);
39401
39434
  this.tunnelProcess = null;
39435
+ this.tunnelReadyPromise = null;
39402
39436
  });
39403
39437
  tunnelProcess.on("error", (error) => {
39404
39438
  logError3(`Tunnel process error for device ${this.deviceId}: ${error.message}`);
39405
39439
  this.tunnelProcess = null;
39440
+ this.tunnelReadyPromise = null;
39406
39441
  });
39407
39442
  await new Promise((resolve2) => setTimeout(resolve2, 1e3));
39408
39443
  logInfo7(`Tunnel started successfully for device ${this.deviceId}`);
39409
39444
  } catch (error) {
39445
+ this.tunnelReadyPromise = null;
39410
39446
  logError3(
39411
39447
  `Failed to start tunnel for device ${this.deviceId}: ${error instanceof Error ? error.message : String(error)}`
39412
39448
  );
@@ -39620,7 +39656,7 @@ var AppleDeviceKit = class _AppleDeviceKit {
39620
39656
  const tmpFilePath = (0, import_node_path5.join)(tmpDir, fileName);
39621
39657
  try {
39622
39658
  await (0, import_promises3.mkdir)(tmpDir, { recursive: true });
39623
- await (0, import_promises4.writeFile)(tmpFilePath, fileData);
39659
+ await (0, import_promises3.writeFile)(tmpFilePath, fileData);
39624
39660
  const stats = await (0, import_promises3.stat)(tmpFilePath);
39625
39661
  logDetail2(`Temp file written: ${tmpFilePath}, size: ${stats.size} bytes`);
39626
39662
  if (stats.size !== fileData.length) {
@@ -39644,9 +39680,6 @@ var AppleDeviceKit = class _AppleDeviceKit {
39644
39680
  }
39645
39681
  logInfo7(`File ${fileName} pushed to device ${this.deviceId}`);
39646
39682
  } finally {
39647
- if (requiresTunnel) {
39648
- this.stopTunnel();
39649
- }
39650
39683
  try {
39651
39684
  (0, import_node_fs5.unlinkSync)(tmpFilePath);
39652
39685
  } catch (_error) {
@@ -39683,9 +39716,6 @@ var AppleDeviceKit = class _AppleDeviceKit {
39683
39716
  logInfo7(`File ${fileName} pulled from device ${this.deviceId}`);
39684
39717
  return fileData;
39685
39718
  } finally {
39686
- if (requiresTunnel) {
39687
- this.stopTunnel();
39688
- }
39689
39719
  try {
39690
39720
  (0, import_node_fs5.unlinkSync)(tmpFilePath);
39691
39721
  } catch (_error) {