@mcesystems/apple-kit 1.0.96 → 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.
- package/dist/index.js +90 -64
- package/dist/index.js.map +2 -2
- package/dist/index.mjs +90 -64
- package/dist/index.mjs.map +2 -2
- package/dist/types/index.d.ts +13 -35
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -38606,31 +38606,34 @@ function escapeXml(str) {
|
|
|
38606
38606
|
var { logInfo: logInfo5 } = createLoggers("apple-kit:wifi-profile");
|
|
38607
38607
|
async function generateWifiProfile(config, options) {
|
|
38608
38608
|
const {
|
|
38609
|
-
ssid,
|
|
38610
38609
|
encryptionType,
|
|
38611
38610
|
password,
|
|
38612
38611
|
autoJoin = true,
|
|
38613
38612
|
organizationName = "MCE Systems",
|
|
38614
|
-
displayName = `WiFi - ${ssid}`,
|
|
38615
38613
|
enterprise = false,
|
|
38616
38614
|
username,
|
|
38617
38615
|
acceptAnyCertificate = true
|
|
38618
38616
|
} = config;
|
|
38617
|
+
const resolvedSsid = config.ssid ?? process.env.WIFI_SSID ?? "";
|
|
38618
|
+
if (!resolvedSsid) {
|
|
38619
|
+
throw new Error("WiFi SSID is required. Set config.ssid or WIFI_SSID environment variable.");
|
|
38620
|
+
}
|
|
38619
38621
|
const profileUuid = randomUUID().toUpperCase();
|
|
38620
38622
|
const payloadUuid = randomUUID().toUpperCase();
|
|
38621
|
-
const profileId = `com.mce.wifi.${
|
|
38623
|
+
const profileId = `com.mce.wifi.${resolvedSsid.replace(/[^a-zA-Z0-9]/g, "")}.${Date.now()}`;
|
|
38622
38624
|
const payloadId = `${profileId}.payload`;
|
|
38623
|
-
|
|
38625
|
+
const displayNameToUse = config.displayName ?? `WiFi - ${resolvedSsid}`;
|
|
38626
|
+
logInfo5(`Generating WiFi profile for SSID: ${resolvedSsid}, encryption: ${encryptionType}`);
|
|
38624
38627
|
const templateName = enterprise ? "wifi-enterprise.xml" : "wifi-standard.xml";
|
|
38625
38628
|
const template = await loadTemplate(templateName, options?.plistDir);
|
|
38626
38629
|
const variables = {
|
|
38627
|
-
ssid:
|
|
38630
|
+
ssid: resolvedSsid,
|
|
38628
38631
|
password: config.password ?? process.env.WIFI_PASSWORD,
|
|
38629
38632
|
encryptionType: parseWifiEncryptionType(config.encryptionType ?? process.env.WIFI_ENCRYPTION),
|
|
38630
38633
|
autoJoin: autoJoin ? "true" : "false",
|
|
38631
38634
|
hiddenNetwork: config.hiddenNetwork ?? process.env.WIFI_HIDDEN === "true",
|
|
38632
38635
|
organizationName,
|
|
38633
|
-
displayName,
|
|
38636
|
+
displayName: displayNameToUse,
|
|
38634
38637
|
profileId,
|
|
38635
38638
|
profileUuid,
|
|
38636
38639
|
payloadId,
|
|
@@ -38725,10 +38728,9 @@ function isAbortError(error) {
|
|
|
38725
38728
|
return error instanceof DOMException && error.name === "AbortError";
|
|
38726
38729
|
}
|
|
38727
38730
|
var ActivationFlow = class {
|
|
38728
|
-
constructor(udid, iosClient
|
|
38731
|
+
constructor(udid, iosClient) {
|
|
38729
38732
|
this.udid = udid;
|
|
38730
38733
|
this.iosClient = iosClient;
|
|
38731
|
-
this.deviceActions = deviceActions;
|
|
38732
38734
|
setNamespace4(`${udid}`);
|
|
38733
38735
|
}
|
|
38734
38736
|
mdmClient;
|
|
@@ -38764,14 +38766,6 @@ var ActivationFlow = class {
|
|
|
38764
38766
|
signal
|
|
38765
38767
|
);
|
|
38766
38768
|
throwIfAborted2(signal);
|
|
38767
|
-
const expectedSsid = config.wifiProfileConfig?.ssid;
|
|
38768
|
-
if (expectedSsid) {
|
|
38769
|
-
if (await this.deviceActions.isWifiConnected(15e3) !== expectedSsid) {
|
|
38770
|
-
throw new Error(
|
|
38771
|
-
`WiFi profile not installed correctly, expected ${expectedSsid} but got ${await this.deviceActions.isWifiConnected(15e3)}`
|
|
38772
|
-
);
|
|
38773
|
-
}
|
|
38774
|
-
}
|
|
38775
38769
|
await this.installMdmProfile(events, signal);
|
|
38776
38770
|
throwIfAborted2(signal);
|
|
38777
38771
|
}
|
|
@@ -39175,45 +39169,59 @@ var IosClient = class {
|
|
|
39175
39169
|
return this.runIosCommand(["devmode", "enable", "--udid", this.udid]);
|
|
39176
39170
|
}
|
|
39177
39171
|
async tunnelStart(userspace = false, pairRecordPath) {
|
|
39178
|
-
|
|
39179
|
-
|
|
39180
|
-
|
|
39181
|
-
|
|
39182
|
-
|
|
39183
|
-
|
|
39184
|
-
|
|
39185
|
-
|
|
39186
|
-
|
|
39172
|
+
return new Promise((resolve2, reject) => {
|
|
39173
|
+
const args = [
|
|
39174
|
+
"tunnel",
|
|
39175
|
+
"start",
|
|
39176
|
+
`--pair-record-path=${pairRecordPath ?? "default"}`,
|
|
39177
|
+
"--udid",
|
|
39178
|
+
this.udid,
|
|
39179
|
+
...userspace ? ["--userspace"] : []
|
|
39180
|
+
];
|
|
39181
|
+
logDetail(`Spawning tunnel: ${this.iosPath} ${args.join(" ")}`);
|
|
39182
|
+
const child = spawn(this.iosPath, args, {
|
|
39183
|
+
windowsHide: true,
|
|
39184
|
+
env: {
|
|
39185
|
+
...process.env,
|
|
39186
|
+
USBMUXD_SOCKET_ADDRESS: this.usbmuxdAddress
|
|
39187
|
+
},
|
|
39188
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
39189
|
+
});
|
|
39190
|
+
let settled = false;
|
|
39191
|
+
const cleanup = () => {
|
|
39192
|
+
child.off("error", onError);
|
|
39193
|
+
child.off("exit", onExit);
|
|
39194
|
+
child.stdout?.off("data", onReadyCheck);
|
|
39195
|
+
child.stderr?.off("data", onReadyCheck);
|
|
39196
|
+
clearTimeout(readyTimeout);
|
|
39197
|
+
};
|
|
39198
|
+
const finish = (result) => {
|
|
39199
|
+
if (settled) {
|
|
39200
|
+
return;
|
|
39201
|
+
}
|
|
39202
|
+
settled = true;
|
|
39203
|
+
cleanup();
|
|
39204
|
+
if (result.reject) {
|
|
39205
|
+
reject(result.reject);
|
|
39206
|
+
return;
|
|
39207
|
+
}
|
|
39208
|
+
if (result.resolve !== void 0) {
|
|
39209
|
+
resolve2(result.resolve);
|
|
39210
|
+
}
|
|
39211
|
+
};
|
|
39212
|
+
const onError = (err) => finish({ reject: err });
|
|
39213
|
+
const onExit = (code) => finish({ reject: new Error(`Tunnel exited early (code=${code})`) });
|
|
39214
|
+
const onReadyCheck = (data) => {
|
|
39215
|
+
const line = data.toString();
|
|
39216
|
+
const isReady = line.includes("Tunnel server started") || line.includes("tunnel") && (line.includes("listening") || line.includes("connected"));
|
|
39217
|
+
if (isReady) finish({ resolve: child });
|
|
39218
|
+
};
|
|
39219
|
+
const readyTimeout = setTimeout(() => finish({ resolve: child }), 1e4);
|
|
39220
|
+
child.once("error", onError);
|
|
39221
|
+
child.once("exit", onExit);
|
|
39222
|
+
child.stdout?.on("data", onReadyCheck);
|
|
39223
|
+
child.stderr?.on("data", onReadyCheck);
|
|
39187
39224
|
});
|
|
39188
|
-
let settled = false;
|
|
39189
|
-
const cleanup = () => {
|
|
39190
|
-
child.off("error", onError);
|
|
39191
|
-
child.off("exit", onExit);
|
|
39192
|
-
child.stdout?.off("data", onReadyCheck);
|
|
39193
|
-
child.stderr?.off("data", onReadyCheck);
|
|
39194
|
-
clearTimeout(readyTimeout);
|
|
39195
|
-
};
|
|
39196
|
-
const finish = (result) => {
|
|
39197
|
-
if (settled) return;
|
|
39198
|
-
settled = true;
|
|
39199
|
-
cleanup();
|
|
39200
|
-
if (result.reject) throw result.reject;
|
|
39201
|
-
if (result.resolve !== void 0) return result.resolve;
|
|
39202
|
-
throw new Error("Tunnel process not found");
|
|
39203
|
-
};
|
|
39204
|
-
const onError = (err) => finish({ reject: err });
|
|
39205
|
-
const onExit = (code) => finish({ reject: new Error(`Tunnel exited early (code=${code})`) });
|
|
39206
|
-
const onReadyCheck = (data) => {
|
|
39207
|
-
const line = data.toString();
|
|
39208
|
-
const isReady = line.includes("Tunnel server started") || line.includes("tunnel") && (line.includes("listening") || line.includes("connected"));
|
|
39209
|
-
if (isReady) finish({ resolve: child });
|
|
39210
|
-
};
|
|
39211
|
-
const readyTimeout = setTimeout(() => finish({ resolve: child }), 1e4);
|
|
39212
|
-
child.once("error", onError);
|
|
39213
|
-
child.once("exit", onExit);
|
|
39214
|
-
child.stdout?.on("data", onReadyCheck);
|
|
39215
|
-
child.stderr?.on("data", onReadyCheck);
|
|
39216
|
-
return child;
|
|
39217
39225
|
}
|
|
39218
39226
|
async fsyncPull({
|
|
39219
39227
|
app,
|
|
@@ -39335,9 +39343,9 @@ var AppleDeviceKit = class _AppleDeviceKit {
|
|
|
39335
39343
|
this.iosClient = new IosClient(iosBinaryPath, udid, usbmuxdAddress);
|
|
39336
39344
|
this.deviceActions = new DeviceActions(this.deviceId, this.iosClient);
|
|
39337
39345
|
this.installActions = new InstallActions(this.deviceId, this.iosClient);
|
|
39338
|
-
this.activationFlow = new ActivationFlow(this.deviceId, this.iosClient
|
|
39346
|
+
this.activationFlow = new ActivationFlow(this.deviceId, this.iosClient);
|
|
39339
39347
|
this.proxyActions = new ProxyActions(this.deviceId, this.iosClient);
|
|
39340
|
-
this.
|
|
39348
|
+
this.getTunnelReady();
|
|
39341
39349
|
}
|
|
39342
39350
|
deviceId;
|
|
39343
39351
|
proxyProcess = null;
|
|
@@ -39349,7 +39357,18 @@ var AppleDeviceKit = class _AppleDeviceKit {
|
|
|
39349
39357
|
activationFlow;
|
|
39350
39358
|
proxyActions;
|
|
39351
39359
|
tunnelProcess = null;
|
|
39360
|
+
tunnelReadyPromise = null;
|
|
39352
39361
|
static IOS_17_VERSION = 17;
|
|
39362
|
+
/**
|
|
39363
|
+
* Returns a promise that resolves when the tunnel is ready (or immediately if not needed).
|
|
39364
|
+
* Reuses the same in-flight promise so constructor and methods don't race.
|
|
39365
|
+
*/
|
|
39366
|
+
getTunnelReady() {
|
|
39367
|
+
if (!this.tunnelReadyPromise) {
|
|
39368
|
+
this.tunnelReadyPromise = this.runEnsureTunnel();
|
|
39369
|
+
}
|
|
39370
|
+
return this.tunnelReadyPromise;
|
|
39371
|
+
}
|
|
39353
39372
|
/**
|
|
39354
39373
|
* Check if iOS version requires tunneling (iOS 17+)
|
|
39355
39374
|
*/
|
|
@@ -39367,9 +39386,15 @@ var AppleDeviceKit = class _AppleDeviceKit {
|
|
|
39367
39386
|
}
|
|
39368
39387
|
}
|
|
39369
39388
|
/**
|
|
39370
|
-
* Ensure tunnel is started for iOS 17+ devices
|
|
39389
|
+
* Ensure tunnel is started for iOS 17+ devices. Safe to call multiple times; reuses in-flight setup.
|
|
39371
39390
|
*/
|
|
39372
39391
|
async ensureTunnel() {
|
|
39392
|
+
await this.getTunnelReady();
|
|
39393
|
+
}
|
|
39394
|
+
/**
|
|
39395
|
+
* Internal tunnel startup. Called once per tunnel lifecycle; getTunnelReady() caches this promise.
|
|
39396
|
+
*/
|
|
39397
|
+
async runEnsureTunnel() {
|
|
39373
39398
|
const requiresTunnel = await this.requiresTunneling();
|
|
39374
39399
|
if (!requiresTunnel) {
|
|
39375
39400
|
logDetail2(`Device ${this.deviceId} does not require tunneling (iOS < 17)`);
|
|
@@ -39382,21 +39407,28 @@ var AppleDeviceKit = class _AppleDeviceKit {
|
|
|
39382
39407
|
}
|
|
39383
39408
|
logInfo7(`Starting tunnel for device ${this.deviceId} (iOS 17+)`);
|
|
39384
39409
|
try {
|
|
39385
|
-
const pairRecordPath = join5(
|
|
39410
|
+
const pairRecordPath = join5(
|
|
39411
|
+
this.deviceActions.getLockdownPath() ?? "",
|
|
39412
|
+
"RemotePairing",
|
|
39413
|
+
`${this.deviceId}`
|
|
39414
|
+
);
|
|
39386
39415
|
await mkdir(pairRecordPath, { recursive: true });
|
|
39387
39416
|
const tunnelProcess = await this.iosClient.tunnelStart(true, pairRecordPath);
|
|
39388
39417
|
this.tunnelProcess = tunnelProcess;
|
|
39389
39418
|
tunnelProcess.on("exit", (code) => {
|
|
39390
39419
|
logError3(`Tunnel process for device ${this.deviceId} exited with code ${code}`);
|
|
39391
39420
|
this.tunnelProcess = null;
|
|
39421
|
+
this.tunnelReadyPromise = null;
|
|
39392
39422
|
});
|
|
39393
39423
|
tunnelProcess.on("error", (error) => {
|
|
39394
39424
|
logError3(`Tunnel process error for device ${this.deviceId}: ${error.message}`);
|
|
39395
39425
|
this.tunnelProcess = null;
|
|
39426
|
+
this.tunnelReadyPromise = null;
|
|
39396
39427
|
});
|
|
39397
39428
|
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
39398
39429
|
logInfo7(`Tunnel started successfully for device ${this.deviceId}`);
|
|
39399
39430
|
} catch (error) {
|
|
39431
|
+
this.tunnelReadyPromise = null;
|
|
39400
39432
|
logError3(
|
|
39401
39433
|
`Failed to start tunnel for device ${this.deviceId}: ${error instanceof Error ? error.message : String(error)}`
|
|
39402
39434
|
);
|
|
@@ -39634,9 +39666,6 @@ var AppleDeviceKit = class _AppleDeviceKit {
|
|
|
39634
39666
|
}
|
|
39635
39667
|
logInfo7(`File ${fileName} pushed to device ${this.deviceId}`);
|
|
39636
39668
|
} finally {
|
|
39637
|
-
if (requiresTunnel) {
|
|
39638
|
-
this.stopTunnel();
|
|
39639
|
-
}
|
|
39640
39669
|
try {
|
|
39641
39670
|
unlinkSync(tmpFilePath);
|
|
39642
39671
|
} catch (_error) {
|
|
@@ -39673,9 +39702,6 @@ var AppleDeviceKit = class _AppleDeviceKit {
|
|
|
39673
39702
|
logInfo7(`File ${fileName} pulled from device ${this.deviceId}`);
|
|
39674
39703
|
return fileData;
|
|
39675
39704
|
} finally {
|
|
39676
|
-
if (requiresTunnel) {
|
|
39677
|
-
this.stopTunnel();
|
|
39678
|
-
}
|
|
39679
39705
|
try {
|
|
39680
39706
|
unlinkSync(tmpFilePath);
|
|
39681
39707
|
} catch (_error) {
|