@mcesystems/apple-kit 1.0.55 → 1.0.56
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 +268 -82
- package/dist/index.js.map +4 -4
- package/dist/index.mjs +268 -82
- package/dist/index.mjs.map +4 -4
- package/dist/types/logic/actions/appState.d.ts +2 -0
- package/dist/types/logic/actions/appState.d.ts.map +1 -0
- package/dist/types/logic/activationFlow.d.ts +2 -0
- package/dist/types/logic/activationFlow.d.ts.map +1 -1
- package/dist/types/logic/appleDeviceKit.d.ts +6 -0
- package/dist/types/logic/appleDeviceKit.d.ts.map +1 -1
- package/dist/types/logic/iosCli.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -32411,6 +32411,131 @@ async function getActivationState(udid) {
|
|
|
32411
32411
|
}
|
|
32412
32412
|
}
|
|
32413
32413
|
|
|
32414
|
+
// src/logic/actions/pair.ts
|
|
32415
|
+
async function isPaired(udid) {
|
|
32416
|
+
logTask(`Checking pairing status for ${udid}`);
|
|
32417
|
+
try {
|
|
32418
|
+
const result = await runIDeviceTool("idevicepair", ["-u", udid, "validate"]);
|
|
32419
|
+
if (!result) {
|
|
32420
|
+
return false;
|
|
32421
|
+
}
|
|
32422
|
+
return result.stdout.toLowerCase().includes("success");
|
|
32423
|
+
} catch {
|
|
32424
|
+
return false;
|
|
32425
|
+
}
|
|
32426
|
+
}
|
|
32427
|
+
async function trustDevice(udid, timeout2 = 6e4, onWaitingForTrust) {
|
|
32428
|
+
logTask(`Trusting device ${udid}`);
|
|
32429
|
+
if (await isPaired(udid)) {
|
|
32430
|
+
logInfo(`Device ${udid} is already trusted`);
|
|
32431
|
+
return true;
|
|
32432
|
+
}
|
|
32433
|
+
logInfo(`Initiating pairing for device ${udid}`);
|
|
32434
|
+
try {
|
|
32435
|
+
const pairResult = await pair(udid);
|
|
32436
|
+
if (pairResult) {
|
|
32437
|
+
logInfo(`Device ${udid} paired successfully`);
|
|
32438
|
+
return true;
|
|
32439
|
+
}
|
|
32440
|
+
} catch (error) {
|
|
32441
|
+
logError(`Pairing failed with ${udid}: ${error}`);
|
|
32442
|
+
}
|
|
32443
|
+
logInfo("Please accept the trust dialog on the device...");
|
|
32444
|
+
onWaitingForTrust?.();
|
|
32445
|
+
try {
|
|
32446
|
+
await waitForPairing(udid, timeout2, 1e3);
|
|
32447
|
+
logInfo(`Device ${udid} is now trusted`);
|
|
32448
|
+
return true;
|
|
32449
|
+
} catch {
|
|
32450
|
+
logInfo(`Timeout waiting for trust acceptance on device ${udid}`);
|
|
32451
|
+
return false;
|
|
32452
|
+
}
|
|
32453
|
+
}
|
|
32454
|
+
async function waitForPairing(udid, timeout2 = 12e4, pollInterval = 1e3) {
|
|
32455
|
+
logTask(`Waiting for pairing on device ${udid}`);
|
|
32456
|
+
const startTime = Date.now();
|
|
32457
|
+
while (Date.now() - startTime < timeout2) {
|
|
32458
|
+
if (await isPaired(udid)) {
|
|
32459
|
+
logInfo(`Device ${udid} is now paired`);
|
|
32460
|
+
return true;
|
|
32461
|
+
}
|
|
32462
|
+
await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
|
|
32463
|
+
}
|
|
32464
|
+
throw new Error(`Timeout waiting for device pairing after ${timeout2}ms`);
|
|
32465
|
+
}
|
|
32466
|
+
async function pair(udid) {
|
|
32467
|
+
logTask(`Initiating pairing for device ${udid}`);
|
|
32468
|
+
try {
|
|
32469
|
+
const result = await runIDeviceTool("idevicepair", ["-u", udid, "pair"]);
|
|
32470
|
+
if (!result) {
|
|
32471
|
+
return false;
|
|
32472
|
+
}
|
|
32473
|
+
return result.stdout.toLowerCase().includes("success");
|
|
32474
|
+
} catch (error) {
|
|
32475
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
32476
|
+
if (errorMsg.includes("Please accept the trust dialog")) {
|
|
32477
|
+
return false;
|
|
32478
|
+
}
|
|
32479
|
+
throw error;
|
|
32480
|
+
}
|
|
32481
|
+
}
|
|
32482
|
+
async function unpair(udid) {
|
|
32483
|
+
logTask(`Un-pairing device ${udid}`);
|
|
32484
|
+
try {
|
|
32485
|
+
const result = await runIDeviceTool("idevicepair", ["-u", udid, "unpair"]);
|
|
32486
|
+
if (!result) {
|
|
32487
|
+
return false;
|
|
32488
|
+
}
|
|
32489
|
+
return result.stdout.toLowerCase().includes("success");
|
|
32490
|
+
} catch {
|
|
32491
|
+
return false;
|
|
32492
|
+
}
|
|
32493
|
+
}
|
|
32494
|
+
|
|
32495
|
+
// src/logic/actions/appState.ts
|
|
32496
|
+
var FRONTMOST_KEYS = [
|
|
32497
|
+
"FrontmostApplicationBundleID",
|
|
32498
|
+
"FrontmostApplicationBundleId",
|
|
32499
|
+
"FrontmostAppBundleIdentifier",
|
|
32500
|
+
"ForegroundApplicationBundleID",
|
|
32501
|
+
"ForegroundApplicationBundleId",
|
|
32502
|
+
"ForegroundAppBundleId",
|
|
32503
|
+
"ApplicationBundleIdentifier",
|
|
32504
|
+
"BundleIdentifier",
|
|
32505
|
+
"bundleIdentifier",
|
|
32506
|
+
"bundleId"
|
|
32507
|
+
];
|
|
32508
|
+
async function isAppOpened(bundleId, udid) {
|
|
32509
|
+
logTask(`Checking if app ${bundleId} is opened on device ${udid}`);
|
|
32510
|
+
if (!await isPaired(udid)) {
|
|
32511
|
+
await waitForPairing(udid, 1e4);
|
|
32512
|
+
}
|
|
32513
|
+
try {
|
|
32514
|
+
for (const key of FRONTMOST_KEYS) {
|
|
32515
|
+
const result = await runIDeviceTool("ideviceinfo", ["-u", udid, "-k", key]);
|
|
32516
|
+
const output = result?.stdout?.trim() ?? "";
|
|
32517
|
+
if (!output) {
|
|
32518
|
+
continue;
|
|
32519
|
+
}
|
|
32520
|
+
if (isBundleIdMatch(output, bundleId)) {
|
|
32521
|
+
return true;
|
|
32522
|
+
}
|
|
32523
|
+
}
|
|
32524
|
+
} catch (error) {
|
|
32525
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
32526
|
+
logInfo(`isAppOpened failed: ${errorMsg}`);
|
|
32527
|
+
}
|
|
32528
|
+
return false;
|
|
32529
|
+
}
|
|
32530
|
+
function isBundleIdMatch(value, bundleId) {
|
|
32531
|
+
if (value === bundleId) {
|
|
32532
|
+
return true;
|
|
32533
|
+
}
|
|
32534
|
+
const escaped = bundleId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
32535
|
+
const matcher = new RegExp(`(^|[^A-Za-z0-9_.-])${escaped}($|[^A-Za-z0-9_.-])`);
|
|
32536
|
+
return matcher.test(value);
|
|
32537
|
+
}
|
|
32538
|
+
|
|
32414
32539
|
// src/logic/actions/device.ts
|
|
32415
32540
|
import { existsSync as existsSync2 } from "node:fs";
|
|
32416
32541
|
import { join as join3 } from "node:path";
|
|
@@ -33273,87 +33398,6 @@ function resolveCredentialsPath(options) {
|
|
|
33273
33398
|
return process.env.MDM_CRED_PATH ?? process.env.APP_CRED_PATH;
|
|
33274
33399
|
}
|
|
33275
33400
|
|
|
33276
|
-
// src/logic/actions/pair.ts
|
|
33277
|
-
async function isPaired(udid) {
|
|
33278
|
-
logTask(`Checking pairing status for ${udid}`);
|
|
33279
|
-
try {
|
|
33280
|
-
const result = await runIDeviceTool("idevicepair", ["-u", udid, "validate"]);
|
|
33281
|
-
if (!result) {
|
|
33282
|
-
return false;
|
|
33283
|
-
}
|
|
33284
|
-
return result.stdout.toLowerCase().includes("success");
|
|
33285
|
-
} catch {
|
|
33286
|
-
return false;
|
|
33287
|
-
}
|
|
33288
|
-
}
|
|
33289
|
-
async function trustDevice(udid, timeout2 = 6e4, onWaitingForTrust) {
|
|
33290
|
-
logTask(`Trusting device ${udid}`);
|
|
33291
|
-
if (await isPaired(udid)) {
|
|
33292
|
-
logInfo(`Device ${udid} is already trusted`);
|
|
33293
|
-
return true;
|
|
33294
|
-
}
|
|
33295
|
-
logInfo(`Initiating pairing for device ${udid}`);
|
|
33296
|
-
try {
|
|
33297
|
-
const pairResult = await pair(udid);
|
|
33298
|
-
if (pairResult) {
|
|
33299
|
-
logInfo(`Device ${udid} paired successfully`);
|
|
33300
|
-
return true;
|
|
33301
|
-
}
|
|
33302
|
-
} catch (error) {
|
|
33303
|
-
logError(`Pairing failed with ${udid}: ${error}`);
|
|
33304
|
-
}
|
|
33305
|
-
logInfo("Please accept the trust dialog on the device...");
|
|
33306
|
-
onWaitingForTrust?.();
|
|
33307
|
-
try {
|
|
33308
|
-
await waitForPairing(udid, timeout2, 1e3);
|
|
33309
|
-
logInfo(`Device ${udid} is now trusted`);
|
|
33310
|
-
return true;
|
|
33311
|
-
} catch {
|
|
33312
|
-
logInfo(`Timeout waiting for trust acceptance on device ${udid}`);
|
|
33313
|
-
return false;
|
|
33314
|
-
}
|
|
33315
|
-
}
|
|
33316
|
-
async function waitForPairing(udid, timeout2 = 12e4, pollInterval = 1e3) {
|
|
33317
|
-
logTask(`Waiting for pairing on device ${udid}`);
|
|
33318
|
-
const startTime = Date.now();
|
|
33319
|
-
while (Date.now() - startTime < timeout2) {
|
|
33320
|
-
if (await isPaired(udid)) {
|
|
33321
|
-
logInfo(`Device ${udid} is now paired`);
|
|
33322
|
-
return true;
|
|
33323
|
-
}
|
|
33324
|
-
await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
|
|
33325
|
-
}
|
|
33326
|
-
throw new Error(`Timeout waiting for device pairing after ${timeout2}ms`);
|
|
33327
|
-
}
|
|
33328
|
-
async function pair(udid) {
|
|
33329
|
-
logTask(`Initiating pairing for device ${udid}`);
|
|
33330
|
-
try {
|
|
33331
|
-
const result = await runIDeviceTool("idevicepair", ["-u", udid, "pair"]);
|
|
33332
|
-
if (!result) {
|
|
33333
|
-
return false;
|
|
33334
|
-
}
|
|
33335
|
-
return result.stdout.toLowerCase().includes("success");
|
|
33336
|
-
} catch (error) {
|
|
33337
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
33338
|
-
if (errorMsg.includes("Please accept the trust dialog")) {
|
|
33339
|
-
return false;
|
|
33340
|
-
}
|
|
33341
|
-
throw error;
|
|
33342
|
-
}
|
|
33343
|
-
}
|
|
33344
|
-
async function unpair(udid) {
|
|
33345
|
-
logTask(`Un-pairing device ${udid}`);
|
|
33346
|
-
try {
|
|
33347
|
-
const result = await runIDeviceTool("idevicepair", ["-u", udid, "unpair"]);
|
|
33348
|
-
if (!result) {
|
|
33349
|
-
return false;
|
|
33350
|
-
}
|
|
33351
|
-
return result.stdout.toLowerCase().includes("success");
|
|
33352
|
-
} catch {
|
|
33353
|
-
return false;
|
|
33354
|
-
}
|
|
33355
|
-
}
|
|
33356
|
-
|
|
33357
33401
|
// src/logic/actions/install.ts
|
|
33358
33402
|
async function installLocalApp(ipaPath, udid) {
|
|
33359
33403
|
logTask(`Installing app ${ipaPath} on device ${udid}`);
|
|
@@ -33921,6 +33965,99 @@ function safeParseJson(line) {
|
|
|
33921
33965
|
return void 0;
|
|
33922
33966
|
}
|
|
33923
33967
|
}
|
|
33968
|
+
function isRecord(value) {
|
|
33969
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
33970
|
+
}
|
|
33971
|
+
function getStringField(record, key) {
|
|
33972
|
+
const value = record[key];
|
|
33973
|
+
return typeof value === "string" ? value : void 0;
|
|
33974
|
+
}
|
|
33975
|
+
function getBooleanField(record, key) {
|
|
33976
|
+
const value = record[key];
|
|
33977
|
+
return typeof value === "boolean" ? value : void 0;
|
|
33978
|
+
}
|
|
33979
|
+
function getNumberField(record, key) {
|
|
33980
|
+
const value = record[key];
|
|
33981
|
+
return typeof value === "number" ? value : void 0;
|
|
33982
|
+
}
|
|
33983
|
+
function getRecordField(record, key) {
|
|
33984
|
+
const value = record[key];
|
|
33985
|
+
return isRecord(value) ? value : void 0;
|
|
33986
|
+
}
|
|
33987
|
+
function toProfileManifest(record) {
|
|
33988
|
+
if (!record) {
|
|
33989
|
+
return void 0;
|
|
33990
|
+
}
|
|
33991
|
+
const description = getStringField(record, "Description");
|
|
33992
|
+
const isActive = getBooleanField(record, "IsActive");
|
|
33993
|
+
if (description === void 0 && isActive === void 0) {
|
|
33994
|
+
return void 0;
|
|
33995
|
+
}
|
|
33996
|
+
return {
|
|
33997
|
+
Description: description,
|
|
33998
|
+
IsActive: isActive
|
|
33999
|
+
};
|
|
34000
|
+
}
|
|
34001
|
+
function toProfileMetadata(record) {
|
|
34002
|
+
if (!record) {
|
|
34003
|
+
return void 0;
|
|
34004
|
+
}
|
|
34005
|
+
const payloadDescription = getStringField(record, "PayloadDescription");
|
|
34006
|
+
const payloadDisplayName = getStringField(record, "PayloadDisplayName");
|
|
34007
|
+
const payloadRemovalDisallowed = getBooleanField(record, "PayloadRemovalDisallowed");
|
|
34008
|
+
const payloadUuid = getStringField(record, "PayloadUUID");
|
|
34009
|
+
const payloadVersion = getNumberField(record, "PayloadVersion");
|
|
34010
|
+
if (payloadDescription === void 0 && payloadDisplayName === void 0 && payloadRemovalDisallowed === void 0 && payloadUuid === void 0 && payloadVersion === void 0) {
|
|
34011
|
+
return void 0;
|
|
34012
|
+
}
|
|
34013
|
+
return {
|
|
34014
|
+
PayloadDescription: payloadDescription,
|
|
34015
|
+
PayloadDisplayName: payloadDisplayName,
|
|
34016
|
+
PayloadRemovalDisallowed: payloadRemovalDisallowed,
|
|
34017
|
+
PayloadUUID: payloadUuid,
|
|
34018
|
+
PayloadVersion: payloadVersion
|
|
34019
|
+
};
|
|
34020
|
+
}
|
|
34021
|
+
function toProfileListEntry(item) {
|
|
34022
|
+
const identifier = getStringField(item, "Identifier");
|
|
34023
|
+
const manifest = toProfileManifest(getRecordField(item, "Manifest"));
|
|
34024
|
+
const metadata = toProfileMetadata(getRecordField(item, "Metadata"));
|
|
34025
|
+
const status = getStringField(item, "Status");
|
|
34026
|
+
if (!identifier && !manifest && !metadata && !status) {
|
|
34027
|
+
return void 0;
|
|
34028
|
+
}
|
|
34029
|
+
return {
|
|
34030
|
+
Identifier: identifier,
|
|
34031
|
+
Manifest: manifest,
|
|
34032
|
+
Metadata: metadata,
|
|
34033
|
+
Status: status
|
|
34034
|
+
};
|
|
34035
|
+
}
|
|
34036
|
+
function parseProfileListOutput(output) {
|
|
34037
|
+
const profiles = [];
|
|
34038
|
+
for (const item of output) {
|
|
34039
|
+
if (Array.isArray(item)) {
|
|
34040
|
+
for (const entry2 of item) {
|
|
34041
|
+
if (!isRecord(entry2)) {
|
|
34042
|
+
continue;
|
|
34043
|
+
}
|
|
34044
|
+
const profileEntry = toProfileListEntry(entry2);
|
|
34045
|
+
if (profileEntry) {
|
|
34046
|
+
profiles.push(profileEntry);
|
|
34047
|
+
}
|
|
34048
|
+
}
|
|
34049
|
+
continue;
|
|
34050
|
+
}
|
|
34051
|
+
if (!isRecord(item)) {
|
|
34052
|
+
continue;
|
|
34053
|
+
}
|
|
34054
|
+
const entry = toProfileListEntry(item);
|
|
34055
|
+
if (entry) {
|
|
34056
|
+
profiles.push(entry);
|
|
34057
|
+
}
|
|
34058
|
+
}
|
|
34059
|
+
return profiles;
|
|
34060
|
+
}
|
|
33924
34061
|
function createIosCli(iosBinaryPath) {
|
|
33925
34062
|
return {
|
|
33926
34063
|
async listDevices() {
|
|
@@ -33959,6 +34096,13 @@ function createIosCli(iosBinaryPath) {
|
|
|
33959
34096
|
},
|
|
33960
34097
|
async info(deviceId) {
|
|
33961
34098
|
return runIosCommand(iosBinaryPath, ["info", "--udid", deviceId]);
|
|
34099
|
+
},
|
|
34100
|
+
async listProfiles(deviceId) {
|
|
34101
|
+
const raw = await runIosCommand(iosBinaryPath, ["profile", "list", "--udid", deviceId]);
|
|
34102
|
+
return {
|
|
34103
|
+
profiles: parseProfileListOutput(raw.output),
|
|
34104
|
+
raw
|
|
34105
|
+
};
|
|
33962
34106
|
}
|
|
33963
34107
|
};
|
|
33964
34108
|
}
|
|
@@ -33966,6 +34110,7 @@ function createIosCli(iosBinaryPath) {
|
|
|
33966
34110
|
// src/logic/activationFlow.ts
|
|
33967
34111
|
var DEFAULT_RETRIES = 150;
|
|
33968
34112
|
var DEFAULT_RETRY_DELAY_MS = 1e3;
|
|
34113
|
+
var MCE_MDM_PROFILE_PREFIX = "com.mce.mdm";
|
|
33969
34114
|
var ActivationFlow = class {
|
|
33970
34115
|
iosCli;
|
|
33971
34116
|
mdmClientPromise;
|
|
@@ -33980,7 +34125,14 @@ var ActivationFlow = class {
|
|
|
33980
34125
|
async run(udid) {
|
|
33981
34126
|
logTask(`Starting activation flow for device ${udid}`);
|
|
33982
34127
|
const activationState = await this.getActivationState(udid);
|
|
33983
|
-
if (activationState
|
|
34128
|
+
if (activationState === "Activated") {
|
|
34129
|
+
const isEnrolled = await this.isEnrolledToMceMdm(udid);
|
|
34130
|
+
if (isEnrolled) {
|
|
34131
|
+
logInfo("Device already activated and enrolled to MCE MDM. Skipping activation flow.");
|
|
34132
|
+
return async () => {
|
|
34133
|
+
};
|
|
34134
|
+
}
|
|
34135
|
+
} else if (activationState) {
|
|
33984
34136
|
logInfo(`Activation state is ${activationState}, activating device`);
|
|
33985
34137
|
await this.retryActivateCommand("activate device", () => this.iosCli.activate(udid));
|
|
33986
34138
|
} else {
|
|
@@ -33992,6 +34144,18 @@ var ActivationFlow = class {
|
|
|
33992
34144
|
await this.retryIosCommand("skip steps", () => this.iosCli.skipSteps(udid));
|
|
33993
34145
|
return () => this.removeWifiProfile(udid, wifiProfileIdentifier);
|
|
33994
34146
|
}
|
|
34147
|
+
async isEnrolledToMceMdm(udid) {
|
|
34148
|
+
const profiles = await this.listProfiles(udid);
|
|
34149
|
+
return profiles.some((profile) => isMceMdmProfile(profile));
|
|
34150
|
+
}
|
|
34151
|
+
async listProfiles(udid) {
|
|
34152
|
+
const result = await this.retry(
|
|
34153
|
+
"list profiles",
|
|
34154
|
+
() => this.iosCli.listProfiles(udid),
|
|
34155
|
+
(response) => response.raw.exitCode === 0
|
|
34156
|
+
);
|
|
34157
|
+
return result.profiles;
|
|
34158
|
+
}
|
|
33995
34159
|
async installWifiProfile(udid) {
|
|
33996
34160
|
const wifiProfile = await generateWifiProfileFromEnv();
|
|
33997
34161
|
if (!wifiProfile) {
|
|
@@ -34149,6 +34313,19 @@ function isActivationSuccess(result) {
|
|
|
34149
34313
|
const hasFatal = result.logMessages.some((log) => log.level === "error");
|
|
34150
34314
|
return !hasFatal;
|
|
34151
34315
|
}
|
|
34316
|
+
function isMceMdmProfile(profile) {
|
|
34317
|
+
const identifier = profile.Identifier;
|
|
34318
|
+
if (!identifier) {
|
|
34319
|
+
return false;
|
|
34320
|
+
}
|
|
34321
|
+
if (!identifier.startsWith(MCE_MDM_PROFILE_PREFIX)) {
|
|
34322
|
+
return false;
|
|
34323
|
+
}
|
|
34324
|
+
if (profile.Manifest?.IsActive === false) {
|
|
34325
|
+
return false;
|
|
34326
|
+
}
|
|
34327
|
+
return true;
|
|
34328
|
+
}
|
|
34152
34329
|
|
|
34153
34330
|
// src/logic/appleDeviceKit.ts
|
|
34154
34331
|
var AppleDeviceKit = class {
|
|
@@ -34255,6 +34432,15 @@ var AppleDeviceKit = class {
|
|
|
34255
34432
|
this.ensureNotDisposed();
|
|
34256
34433
|
return isAppInstalled(bundleId, this.deviceId);
|
|
34257
34434
|
}
|
|
34435
|
+
/**
|
|
34436
|
+
* Check if an app is currently opened on the device
|
|
34437
|
+
*
|
|
34438
|
+
* @param bundleId Application bundle identifier
|
|
34439
|
+
*/
|
|
34440
|
+
async isAppOpened(bundleId) {
|
|
34441
|
+
this.ensureNotDisposed();
|
|
34442
|
+
return isAppOpened(bundleId, this.deviceId);
|
|
34443
|
+
}
|
|
34258
34444
|
/**
|
|
34259
34445
|
* List all installed user applications
|
|
34260
34446
|
*/
|