@mcesystems/apple-kit 1.0.87 → 1.0.91

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.
@@ -3,6 +3,84 @@
3
3
  import { ChildProcess } from 'node:child_process';
4
4
  import { EventEmitter } from 'node:events';
5
5
 
6
+ export interface MdmClientOptions {
7
+ endpoint?: string;
8
+ authApiUrl?: string;
9
+ credentialsPath?: string;
10
+ timeoutMs?: number;
11
+ }
12
+ export interface InstallAppMdmOptions {
13
+ appId?: string;
14
+ url?: string;
15
+ waitForInstalled?: boolean;
16
+ clientConfig?: MdmClientOptions$1;
17
+ }
18
+ export interface MdmClientOptions$1 {
19
+ endpoint?: string;
20
+ authApiUrl?: string;
21
+ credentialsPath?: string;
22
+ timeoutMs?: number;
23
+ }
24
+ /**
25
+ * WiFi Profile Types
26
+ */
27
+ export type WifiEncryptionType = "WEP" | "WPA" | "WPA2" | "WPA3" | "Any" | "None";
28
+ export type WifiEapType = "TLS" | "TTLS" | "LEAP" | "PEAP" | "EAP-FAST" | "EAP-SIM" | "EAP-AKA";
29
+ export interface WifiProfileConfig {
30
+ ssid: string;
31
+ password?: string;
32
+ encryptionType?: WifiEncryptionType;
33
+ autoJoin?: boolean;
34
+ hiddenNetwork?: boolean;
35
+ organizationName?: string;
36
+ displayName?: string;
37
+ enterprise?: boolean;
38
+ username?: string;
39
+ eapType?: WifiEapType;
40
+ acceptAnyCertificate?: boolean;
41
+ }
42
+ export interface ActivationFlowConfig {
43
+ /**
44
+ * Whether to install MDM profile.
45
+ * If not set, defaults to true.
46
+ */
47
+ withMdm?: boolean;
48
+ /**
49
+ * Path to the ios CLI binary (go-ios wrapper).
50
+ * If not set, defaults to resourcesDir/ios/bin/{platform}/ios(.exe).
51
+ */
52
+ iosBinaryPath?: string;
53
+ /**
54
+ * Path to the certificate file (optional).
55
+ * If not set, defaults to CERT_FILE from env.
56
+ */
57
+ certFile?: string;
58
+ /**
59
+ * MDM client options.
60
+ * If not set, defaults to MDM_CLIENT_OPTIONS from env.
61
+ */
62
+ mdmClientOptions?: MdmClientOptions;
63
+ /**
64
+ * Organization name used for trust profile display (optional).
65
+ * If not set, uses ORGANIZATION_NAME from env.
66
+ */
67
+ organizationName?: string;
68
+ /**
69
+ * Folder to read/write trust_profile.mobileconfig (optional).
70
+ * If not set, defaults to the package resources folder.
71
+ */
72
+ resourcesDir?: string;
73
+ /**
74
+ * WiFi profile configuration.
75
+ * If not set, defaults to WIFI_PROFILE_CONFIG from env.
76
+ */
77
+ wifiProfileConfig?: WifiProfileConfig;
78
+ /**
79
+ * Folder to read/write plist files (optional).
80
+ * If not set, defaults to the package resources folder.
81
+ */
82
+ plistDir?: string;
83
+ }
6
84
  export interface DeviceListOutput {
7
85
  deviceList: string[];
8
86
  }
@@ -182,11 +260,6 @@ export interface PortForwardResult {
182
260
  /** The device port being forwarded to */
183
261
  devicePort: number;
184
262
  }
185
- export interface InstallAppMdmOptions {
186
- appId?: string;
187
- url?: string;
188
- waitForInstalled?: boolean;
189
- }
190
263
  /**
191
264
  * AppleDeviceKit - iOS device operations wrapper
192
265
  *
@@ -300,6 +373,14 @@ export declare class AppleDeviceKit {
300
373
  */
301
374
  wipe(): Promise<void>;
302
375
  removeProfile(profileIdentifier: string): Promise<void>;
376
+ /**
377
+ * Check if the device is connected to WiFi.
378
+ * Returns the connected SSID when connected, undefined when not.
379
+ * Uses ios syslog capture and parses for the CurrentBSS pattern.
380
+ *
381
+ * @param timeoutMs Duration to capture syslog before parsing (default 5000)
382
+ */
383
+ isWifiConnected(timeoutMs?: number): Promise<string | undefined>;
303
384
  listProfiles(): Promise<IosProfileListResult>;
304
385
  /**
305
386
  * Activate the device using the activation flow.
@@ -312,7 +393,7 @@ export declare class AppleDeviceKit {
312
393
  *
313
394
  * Precondition: the device must be paired and trusted.
314
395
  */
315
- activate(signal?: AbortSignal): {
396
+ activate(signal?: AbortSignal, config?: ActivationFlowConfig): {
316
397
  promise: Promise<(() => Promise<void>) | undefined>;
317
398
  events: EventEmitter;
318
399
  };
@@ -353,7 +434,7 @@ export declare class IosClient {
353
434
  private iosPath;
354
435
  private udid;
355
436
  private readonly _usbmuxdAddress?;
356
- constructor(iosPath: string, udid: string, _usbmuxdAddress?: string | undefined);
437
+ constructor(iosPath: string, udid: string, _usbmuxdAddress?: string);
357
438
  get usbmuxdAddress(): string | undefined;
358
439
  private safeParseJson;
359
440
  private parseFsyncTreeStdout;
@@ -365,7 +446,7 @@ export declare class IosClient {
365
446
  installProfile(profilePath: string): Promise<IosCommandResult>;
366
447
  removeProfile(profileName: string): Promise<IosCommandResult>;
367
448
  listProfiles(): Promise<IosProfileListResult>;
368
- skipSteps(steps?: string[]): Promise<IosCommandResult>;
449
+ skipSteps(steps?: string[], certFile?: string, organizationName?: string): Promise<IosCommandResult>;
369
450
  listSteps(): Promise<IosCommandResult>;
370
451
  activate(): Promise<IosCommandResult>;
371
452
  pair(): Promise<IosCommandResult>;
@@ -393,27 +474,70 @@ export declare class IosClient {
393
474
  srcPath: string;
394
475
  dstPath: string;
395
476
  }): Promise<IosCommandResult>;
477
+ /**
478
+ * Capture syslog output for a duration. The syslog command streams and does not exit;
479
+ * we run it for timeoutMs then kill the process.
480
+ * If stopWhen returns true, we stop early and return immediately.
481
+ */
482
+ captureSyslog(timeoutMs?: number, stopWhen?: (output: {
483
+ stdout: string;
484
+ stderr: string;
485
+ }) => boolean): Promise<{
486
+ stdout: string;
487
+ stderr: string;
488
+ }>;
396
489
  fsyncTree({ app, path, }: {
397
490
  app: string;
398
491
  path?: string;
399
492
  }): Promise<IosFsyncTreeResult>;
400
493
  }
494
+ declare class DeviceActions {
495
+ private readonly udid;
496
+ private readonly iosClient;
497
+ constructor(udid: string, iosClient: IosClient);
498
+ info(): Promise<LockdownInfo>;
499
+ listDevices(): Promise<IosListResult>;
500
+ wipe(): Promise<void>;
501
+ removeProfile(profileIdentifier: string): Promise<void>;
502
+ listProfiles(): Promise<IosProfileListResult>;
503
+ pair(): Promise<boolean>;
504
+ trustDevice({ timeout, pollInterval, onWaitingForTrust, signal, }: {
505
+ timeout?: number;
506
+ pollInterval?: number;
507
+ onWaitingForTrust?: () => void;
508
+ signal?: AbortSignal;
509
+ }): Promise<boolean>;
510
+ waitForPairing({ timeout, pollInterval, signal, }: {
511
+ timeout?: number;
512
+ pollInterval?: number;
513
+ signal?: AbortSignal;
514
+ }): Promise<boolean>;
515
+ /**
516
+ * Returns true if device is paired and trusted.
517
+ * Uses info() which only succeeds when full pairing is established (user has accepted Trust).
518
+ * Prefer this over lockdown file check since file location/timing can vary by platform.
519
+ */
520
+ private isPairedViaInfo;
521
+ isWifiConnected(timeoutMs?: number): Promise<string | undefined>;
522
+ unpair(): Promise<boolean>;
523
+ }
401
524
  export declare class ActivationFlow {
402
525
  private readonly udid;
403
526
  private readonly iosClient;
527
+ private readonly deviceActions;
404
528
  private mdmClient;
405
- constructor(udid: string, iosClient: IosClient);
406
- run(steps?: string[], signal?: AbortSignal): {
529
+ constructor(udid: string, iosClient: IosClient, deviceActions: DeviceActions);
530
+ run(steps?: string[], signal?: AbortSignal, config?: ActivationFlowConfig): {
407
531
  promise: Promise<(() => Promise<void>) | undefined>;
408
532
  events: EventEmitter;
409
533
  };
410
534
  private runInternal;
411
535
  private installWifiProfile;
412
536
  private installMdmProfile;
537
+ private retryMdmEnrollmentProfile;
413
538
  private removeWifiProfile;
414
539
  private retryIosCommand;
415
540
  private retryActivateCommand;
416
- private retry;
417
541
  }
418
542
  /**
419
543
  * Activation flow event names (use with EventEmitter.on/emit).
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@mcesystems/apple-kit",
3
- "version": "1.0.87",
3
+ "version": "1.0.91",
4
4
  "description": "iOS device management toolkit using libimobiledevice command-line tools",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/types/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
+ "my-internal": "./src/index.ts",
10
11
  "types": "./dist/types/index.d.ts",
11
12
  "import": "./dist/index.mjs",
12
13
  "require": "./dist/index.js"
@@ -37,8 +38,9 @@
37
38
  "graphql-request": "^5.2.0",
38
39
  "tsx": "^4.21.0",
39
40
  "plist": "^3.1.0",
40
- "@mcesystems/tool-debug-g4": "1.0.87",
41
- "@mcesystems/mdm-client-g4": "1.0.87"
41
+ "ts-retry-promise": "^0.8.1",
42
+ "@mcesystems/tool-debug-g4": "1.0.91",
43
+ "@mcesystems/mdm-client-g4": "1.0.91"
42
44
  },
43
45
  "devDependencies": {
44
46
  "@types/node": "^22.10.2",
@@ -52,8 +54,7 @@
52
54
  "rimraf": "^6.0.1",
53
55
  "typescript": "^5.7.2",
54
56
  "vitest": "^2.1.8",
55
- "@types/plist": "^3.0.5",
56
- "@mcesystems/usb-device-listener": "1.0.87"
57
+ "@types/plist": "^3.0.5"
57
58
  },
58
59
  "files": [
59
60
  "dist",
@@ -71,10 +72,10 @@
71
72
  "build": "tsx esbuild.config.mts",
72
73
  "build:all": "pnpm --filter @mcesystems/apple-kit... build",
73
74
  "clean": "rimraf dist",
74
- "check:types": "tsc --noEmit",
75
+ "check:types": "tsc -p tsconfig.build.json --noEmit",
75
76
  "activate:example": "tsx src/examples/activationExample.ts",
76
77
  "ios:example": "tsx src/examples/iosExample.ts",
77
- "usbmuxd:example": "tsx src/examples/usbmuxdIntegrationExample.ts",
78
+ "pairing:example": "tsx src/examples/waitForPairingExample.ts",
78
79
  "pack": "npm pack",
79
80
  "test": "vitest run",
80
81
  "test:watch": "vitest"
@@ -9,15 +9,15 @@ import { fileURLToPath } from "node:url";
9
9
  const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = path.dirname(__filename);
11
11
 
12
- const PACKAGE_ROOT = path.resolve(__dirname, "..");
13
- const RESOURCES_DIR = path.join(PACKAGE_ROOT, "resources");
12
+ const PACKAGE_ROOT = process.env.PACKAGE_ROOT ?? path.resolve(__dirname, "..");
13
+ const DESTINATION_DIR = process.env.DESTINATION_DIR ?? path.join(PACKAGE_ROOT, "resources");
14
14
  const GO_IOS_DIST_DIR = path.join(PACKAGE_ROOT, "node_modules", "go-ios", "dist");
15
15
 
16
16
  const WINTUN_VERSION = "0.14.1";
17
17
  const WINTUN_ZIP_NAME = `wintun-${WINTUN_VERSION}.zip`;
18
18
  const WINTUN_URL = `https://www.wintun.net/builds/${WINTUN_ZIP_NAME}`;
19
- const WINTUN_ZIP_PATH = path.join(RESOURCES_DIR, WINTUN_ZIP_NAME);
20
- const WINTUN_EXTRACT_DIR = path.join(RESOURCES_DIR, ".wintun-extract");
19
+ const WINTUN_ZIP_PATH = path.join(DESTINATION_DIR, WINTUN_ZIP_NAME);
20
+ const WINTUN_EXTRACT_DIR = path.join(DESTINATION_DIR, ".wintun-extract");
21
21
 
22
22
  async function pathExists(targetPath: string): Promise<boolean> {
23
23
  try {
@@ -180,7 +180,7 @@ async function copyGoIosBinary(): Promise<void> {
180
180
  if (!(await pathExists(sourcePath))) {
181
181
  throw new Error(`go-ios binary not found: ${sourcePath}`);
182
182
  }
183
- await copyFile(sourcePath, path.join(RESOURCES_DIR, destinationName));
183
+ await copyFile(sourcePath, path.join(DESTINATION_DIR, destinationName));
184
184
  console.log(`Copied go-ios binary to resources/${destinationName}`);
185
185
  }
186
186
 
@@ -201,17 +201,17 @@ async function copyWintunDll(): Promise<void> {
201
201
  throw new Error(`wintun.dll not found after extraction: ${dllPath}`);
202
202
  }
203
203
 
204
- await copyFile(dllPath, path.join(RESOURCES_DIR, "wintun.dll"));
204
+ await copyFile(dllPath, path.join(DESTINATION_DIR, "wintun.dll"));
205
205
  console.log(`Copied wintun.dll (${archFolder}) to resources/`);
206
206
 
207
207
  if (await pathExists(licensePath)) {
208
- await copyFile(licensePath, path.join(RESOURCES_DIR, "wintun-LICENSE.txt"));
208
+ await copyFile(licensePath, path.join(DESTINATION_DIR, "wintun-LICENSE.txt"));
209
209
  console.log("Copied Wintun license to resources/wintun-LICENSE.txt");
210
210
  }
211
211
  }
212
212
 
213
213
  async function main(): Promise<void> {
214
- await mkdir(RESOURCES_DIR, { recursive: true });
214
+ await mkdir(DESTINATION_DIR, { recursive: true });
215
215
  await copyGoIosBinary();
216
216
  await copyWintunDll();
217
217
  }