@mcesystems/apple-kit 1.0.58 → 1.0.60

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/README.md CHANGED
@@ -1,306 +1,306 @@
1
- # @mcesystems/apple-kit
2
-
3
- iOS device management toolkit using libimobiledevice command-line tools. Provides device detection, app installation/uninstallation, port forwarding, activation, and device property access.
4
-
5
- ## Features
6
-
7
- - **Device Detection**: Monitor iOS device connections via USB plug-and-play
8
- - **App Management**: Install and uninstall iOS applications (.ipa files)
9
- - **Launch Apps**: Start applications on the device
10
- - **Port Forwarding**: Forward local ports to device ports (for debugging, etc.)
11
- - **Device Activation**: Check and manage device activation state
12
- - **Trust/Pairing**: Handle device trust and pairing
13
- - **Device Info**: Access device properties (name, model, iOS version, UDID, etc.)
14
- - **Cross-platform**: Works on Windows, macOS, and Linux
15
-
16
- ## Installation
17
-
18
- ```bash
19
- npm install @mcesystems/apple-kit
20
- ```
21
-
22
- ## Requirements
23
-
24
- - Node.js 18+
25
- - iOS device connected via USB
26
- - Device must be trusted/paired with the computer
27
-
28
- ### Platform-specific Requirements
29
-
30
- #### Windows
31
- - libimobiledevice binaries - use the export script (see below)
32
- - iTunes installed OR Apple Mobile Device Support
33
-
34
- #### macOS
35
- **Option 1: Use bundled binaries (recommended for distribution)**
36
-
37
- Use the export script to bundle binaries for your application:
38
- ```bash
39
- # Using npx (after installing the package)
40
- npx export-apple-resources /path/to/your-app/resources/apple-kit
41
-
42
- # Or run the script directly
43
- npx tsx node_modules/@mcesystems/apple-kit/scripts/export-resources.ts /path/to/your-app/resources
44
- ```
45
-
46
- See [scripts/README.md](./scripts/README.md) for detailed prerequisites and instructions.
47
-
48
- **Option 2: Use Homebrew installation (for development)**
49
- - Install via Homebrew: `brew install libimobiledevice ideviceinstaller`
50
- - Tools are auto-detected from `/opt/homebrew/bin` (Apple Silicon) or `/usr/local/bin` (Intel)
51
-
52
- #### Linux
53
- - libimobiledevice-utils: `sudo apt install libimobiledevice-utils`
54
- - Tools are auto-detected from `/usr/bin` or `/usr/local/bin`
55
-
56
- ### Binary Resolution Order
57
-
58
- The package looks for idevice tools in this order:
59
- 1. `IDeviceBinPath` environment variable (for custom paths)
60
- 2. Bundled resources in your app's `resources/bin/{platform}/` directory
61
- 3. Homebrew paths on macOS (`/opt/homebrew/bin`, `/usr/local/bin`)
62
- 4. System PATH (for global installations)
63
-
64
- ## Usage
65
-
66
- ### Device Monitoring
67
-
68
- ```typescript
69
- import { DevicesMonitor } from '@mcesystems/apple-kit';
70
-
71
- const monitor = new DevicesMonitor({
72
- logicalPortMap: {
73
- "Port_#0005.Hub_#0002": 1,
74
- "Port_#0006.Hub_#0002": 2
75
- }
76
- });
77
-
78
- const events = await monitor.startTracking();
79
-
80
- events.on('added', async (deviceKit) => {
81
- console.log(`iOS device connected: ${deviceKit.getDeviceId()}`);
82
- const info = await deviceKit.getDeviceInfo();
83
- console.log(` ${info.deviceName} - iOS ${info.productVersion}`);
84
- });
85
-
86
- events.on('removed', (deviceId, port) => {
87
- console.log(`iOS device disconnected: ${deviceId}`);
88
- });
89
-
90
- // Later: stop monitoring
91
- await monitor.stopTracking();
92
- ```
93
-
94
- ### Install/Uninstall Agent
95
-
96
- ```typescript
97
- import { AppleDeviceKit } from '@mcesystems/apple-kit';
98
-
99
- const device = new AppleDeviceKit('device-udid', 1);
100
-
101
- // Install an agent/app locally
102
- await device.installApp('/path/to/agent.ipa');
103
-
104
- // Install via MDM (ignores ipaPath, uses appId or url)
105
- await device.installApp('/path/to/agent.ipa', {
106
- installViaMdm: true,
107
- mdm: {
108
- appId: 'com.example.agent',
109
- url: 'https://example.com/agent.ipa',
110
- waitForInstalled: true
111
- }
112
- });
113
-
114
- // Check if installed
115
- const isInstalled = await device.isAppInstalled('com.example.agent');
116
-
117
- // List all installed apps
118
- const apps = await device.listApps();
119
-
120
- // Uninstall an agent/app
121
- await device.uninstallApp('com.example.agent');
122
- ```
123
-
124
- ### Device Info
125
-
126
- ```typescript
127
- const device = new AppleDeviceKit('device-udid', 1);
128
-
129
- const info = await device.getDeviceInfo();
130
- console.log(`Device: ${info.deviceName}`);
131
- console.log(`Model: ${info.productType}`);
132
- console.log(`iOS: ${info.productVersion} (${info.buildVersion})`);
133
- console.log(`Serial: ${info.serialNumber}`);
134
- console.log(`UDID: ${info.udid}`);
135
- ```
136
-
137
- ### Trust/Pairing
138
-
139
- ```typescript
140
- const device = new AppleDeviceKit('device-udid', 1);
141
-
142
- // Check if device is trusted
143
- const isPaired = await device.isPaired();
144
-
145
- // Initiate pairing (user must accept on device)
146
- await device.pair();
147
-
148
- // Wait for user to accept trust dialog
149
- await device.waitForPairing(60000); // 60 second timeout
150
-
151
- // Unpair device
152
- await device.unpair();
153
- ```
154
-
155
- ### Launch Application
156
-
157
- ```typescript
158
- const device = new AppleDeviceKit('device-udid', 1);
159
-
160
- // Launch an app
161
- await device.launchApp('com.example.myapp');
162
-
163
- // Launch with arguments
164
- await device.launchApp('com.example.myapp', ['--debug', '--port=8080']);
165
- ```
166
-
167
- ### Port Forwarding
168
-
169
- ```typescript
170
- const device = new AppleDeviceKit('device-udid', 1);
171
-
172
- // Forward local port 8080 to device port 8080
173
- const forward = device.startPortForward(8080, 8080);
174
-
175
- // Use the forwarded connection...
176
- // connect to localhost:8080 to reach device:8080
177
-
178
- // Stop forwarding when done
179
- forward.stop();
180
-
181
- // Or use async version that waits for ready
182
- const forwardAsync = await device.startPortForwardAsync(8080, 8080);
183
- ```
184
-
185
- ### Activation
186
-
187
- ```typescript
188
- const device = new AppleDeviceKit('device-udid', 1);
189
-
190
- // Get activation state
191
- const state = await device.getActivationState();
192
- console.log(`Activated: ${state.isActivated}`);
193
- console.log(`State: ${state.activationState}`);
194
-
195
- // Activate device (requires valid activation record)
196
- await device.activate({
197
- resourcesDir: process.env.APPLE_KIT_RESOURCES_DIR,
198
- });
199
-
200
- // Deactivate device
201
- await device.deactivate();
202
- ```
203
-
204
- When `resourcesDir` is set, the activation flow reads MDM credentials from
205
- `@clientLocal.json` inside that folder, plist templates from `resourcesDir/plist`,
206
- and the iOS CLI binary from `resourcesDir/ios/bin/{platform}`.
207
- If `resourcesDir/mdm/enrollment_{udid}.mobileconfig` or
208
- `resourcesDir/mdm/enrollment.mobileconfig` exists, it is installed instead of
209
- calling the MDM API (offline enrollment).
210
-
211
- ### Running Without iTunes (usbmuxd)
212
-
213
- On Windows, iTunes provides the Apple Mobile Device Service for USB communication. If you don't have iTunes installed, you can run the bundled `usbmuxd`:
214
-
215
- ```typescript
216
- import { startUsbmuxd, stopUsbmuxd, ensureUsbmuxd } from '@mcesystems/apple-kit';
217
-
218
- // Start usbmuxd daemon (required if iTunes is not installed)
219
- const daemon = startUsbmuxd();
220
-
221
- // Or ensure it's running (starts if not already running)
222
- ensureUsbmuxd();
223
-
224
- // Now you can use device operations...
225
- const devices = await AppleDeviceKit.listDevices();
226
-
227
- // When done, stop the daemon
228
- stopUsbmuxd();
229
- // or
230
- daemon.stop();
231
- ```
232
-
233
- **Note:** The usbmuxd daemon must be running before connecting devices. Start it before plugging in your iOS device.
234
-
235
- ## API Reference
236
-
237
- ### AppleDeviceKit
238
-
239
- **Static methods:**
240
- - `listDevices()`: Get all connected iOS devices
241
-
242
- **Device Info:**
243
- - `getDeviceInfo()`: Get device properties
244
- - `getDeviceId()`: Get the device UDID
245
- - `getPort()`: Get the logical port number
246
-
247
- **App Management:**
248
- - `installApp(ipaPath, options?)`: Install an IPA file or via MDM
249
- - `uninstallApp(bundleId)`: Uninstall an app by bundle ID
250
- - `isAppInstalled(bundleId)`: Check if app is installed
251
- - `listApps()`: List all installed user apps
252
- - `launchApp(bundleId, args?)`: Launch an application
253
-
254
- **Trust/Pairing:**
255
- - `isPaired()`: Check if device is paired/trusted
256
- - `pair()`: Initiate pairing (user must accept on device)
257
- - `unpair()`: Remove pairing/trust
258
- - `waitForPairing(timeout?)`: Wait for device to be paired
259
-
260
- **Port Forwarding:**
261
- - `startPortForward(localPort, devicePort)`: Start port forwarding
262
- - `startPortForwardAsync(localPort, devicePort)`: Start and wait for ready
263
-
264
- **Activation:**
265
- - `getActivationState()`: Get activation state
266
- - `activate()`: Activate the device
267
- - `deactivate()`: Deactivate the device
268
-
269
- ### DevicesMonitor
270
-
271
- - `startTracking()`: Start monitoring for iOS device connections
272
- - `stopTracking()`: Stop monitoring
273
- - `getKits()`: Get all currently tracked devices
274
- - `getKit(udid)`: Get a specific device kit by UDID
275
-
276
- ### usbmuxd Functions
277
-
278
- - `startUsbmuxd(foreground?)`: Start the usbmuxd daemon
279
- - `stopUsbmuxd()`: Stop the daemon
280
- - `isUsbmuxdRunning()`: Check if daemon is running
281
- - `ensureUsbmuxd()`: Start if not already running
282
-
283
- To use a custom resources folder, pass it as the second parameter:
284
- `startUsbmuxd(false, { resourcesDir: "..." })`.
285
-
286
- ### Types
287
-
288
- ```typescript
289
- interface PortForwardHandle {
290
- stop: () => void;
291
- localPort: number;
292
- devicePort: number;
293
- process: ChildProcess;
294
- }
295
-
296
- interface ActivationState {
297
- isActivated: boolean;
298
- activationState: string;
299
- }
300
- ```
301
-
302
- ## License
303
-
304
- ISC
305
-
306
- libimobiledevice is licensed under LGPL-2.1.
1
+ # @mcesystems/apple-kit
2
+
3
+ iOS device management toolkit using libimobiledevice command-line tools. Provides device detection, app installation/uninstallation, port forwarding, activation, and device property access.
4
+
5
+ ## Features
6
+
7
+ - **Device Detection**: Monitor iOS device connections via USB plug-and-play
8
+ - **App Management**: Install and uninstall iOS applications (.ipa files)
9
+ - **Launch Apps**: Start applications on the device
10
+ - **Port Forwarding**: Forward local ports to device ports (for debugging, etc.)
11
+ - **Device Activation**: Check and manage device activation state
12
+ - **Trust/Pairing**: Handle device trust and pairing
13
+ - **Device Info**: Access device properties (name, model, iOS version, UDID, etc.)
14
+ - **Cross-platform**: Works on Windows, macOS, and Linux
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @mcesystems/apple-kit
20
+ ```
21
+
22
+ ## Requirements
23
+
24
+ - Node.js 18+
25
+ - iOS device connected via USB
26
+ - Device must be trusted/paired with the computer
27
+
28
+ ### Platform-specific Requirements
29
+
30
+ #### Windows
31
+ - libimobiledevice binaries - use the export script (see below)
32
+ - iTunes installed OR Apple Mobile Device Support
33
+
34
+ #### macOS
35
+ **Option 1: Use bundled binaries (recommended for distribution)**
36
+
37
+ Use the export script to bundle binaries for your application:
38
+ ```bash
39
+ # Using npx (after installing the package)
40
+ npx export-apple-resources /path/to/your-app/resources/apple-kit
41
+
42
+ # Or run the script directly
43
+ npx tsx node_modules/@mcesystems/apple-kit/scripts/export-resources.ts /path/to/your-app/resources
44
+ ```
45
+
46
+ See [scripts/README.md](./scripts/README.md) for detailed prerequisites and instructions.
47
+
48
+ **Option 2: Use Homebrew installation (for development)**
49
+ - Install via Homebrew: `brew install libimobiledevice ideviceinstaller`
50
+ - Tools are auto-detected from `/opt/homebrew/bin` (Apple Silicon) or `/usr/local/bin` (Intel)
51
+
52
+ #### Linux
53
+ - libimobiledevice-utils: `sudo apt install libimobiledevice-utils`
54
+ - Tools are auto-detected from `/usr/bin` or `/usr/local/bin`
55
+
56
+ ### Binary Resolution Order
57
+
58
+ The package looks for idevice tools in this order:
59
+ 1. `IDeviceBinPath` environment variable (for custom paths)
60
+ 2. Bundled resources in your app's `resources/bin/{platform}/` directory
61
+ 3. Homebrew paths on macOS (`/opt/homebrew/bin`, `/usr/local/bin`)
62
+ 4. System PATH (for global installations)
63
+
64
+ ## Usage
65
+
66
+ ### Device Monitoring
67
+
68
+ ```typescript
69
+ import { DevicesMonitor } from '@mcesystems/apple-kit';
70
+
71
+ const monitor = new DevicesMonitor({
72
+ logicalPortMap: {
73
+ "Port_#0005.Hub_#0002": 1,
74
+ "Port_#0006.Hub_#0002": 2
75
+ }
76
+ });
77
+
78
+ const events = await monitor.startTracking();
79
+
80
+ events.on('added', async (deviceKit) => {
81
+ console.log(`iOS device connected: ${deviceKit.getDeviceId()}`);
82
+ const info = await deviceKit.getDeviceInfo();
83
+ console.log(` ${info.deviceName} - iOS ${info.productVersion}`);
84
+ });
85
+
86
+ events.on('removed', (deviceId, port) => {
87
+ console.log(`iOS device disconnected: ${deviceId}`);
88
+ });
89
+
90
+ // Later: stop monitoring
91
+ await monitor.stopTracking();
92
+ ```
93
+
94
+ ### Install/Uninstall Agent
95
+
96
+ ```typescript
97
+ import { AppleDeviceKit } from '@mcesystems/apple-kit';
98
+
99
+ const device = new AppleDeviceKit('device-udid', 1);
100
+
101
+ // Install an agent/app locally
102
+ await device.installApp('/path/to/agent.ipa');
103
+
104
+ // Install via MDM (ignores ipaPath, uses appId or url)
105
+ await device.installApp('/path/to/agent.ipa', {
106
+ installViaMdm: true,
107
+ mdm: {
108
+ appId: 'com.example.agent',
109
+ url: 'https://example.com/agent.ipa',
110
+ waitForInstalled: true
111
+ }
112
+ });
113
+
114
+ // Check if installed
115
+ const isInstalled = await device.isAppInstalled('com.example.agent');
116
+
117
+ // List all installed apps
118
+ const apps = await device.listApps();
119
+
120
+ // Uninstall an agent/app
121
+ await device.uninstallApp('com.example.agent');
122
+ ```
123
+
124
+ ### Device Info
125
+
126
+ ```typescript
127
+ const device = new AppleDeviceKit('device-udid', 1);
128
+
129
+ const info = await device.getDeviceInfo();
130
+ console.log(`Device: ${info.deviceName}`);
131
+ console.log(`Model: ${info.productType}`);
132
+ console.log(`iOS: ${info.productVersion} (${info.buildVersion})`);
133
+ console.log(`Serial: ${info.serialNumber}`);
134
+ console.log(`UDID: ${info.udid}`);
135
+ ```
136
+
137
+ ### Trust/Pairing
138
+
139
+ ```typescript
140
+ const device = new AppleDeviceKit('device-udid', 1);
141
+
142
+ // Check if device is trusted
143
+ const isPaired = await device.isPaired();
144
+
145
+ // Initiate pairing (user must accept on device)
146
+ await device.pair();
147
+
148
+ // Wait for user to accept trust dialog
149
+ await device.waitForPairing(60000); // 60 second timeout
150
+
151
+ // Unpair device
152
+ await device.unpair();
153
+ ```
154
+
155
+ ### Launch Application
156
+
157
+ ```typescript
158
+ const device = new AppleDeviceKit('device-udid', 1);
159
+
160
+ // Launch an app
161
+ await device.launchApp('com.example.myapp');
162
+
163
+ // Launch with arguments
164
+ await device.launchApp('com.example.myapp', ['--debug', '--port=8080']);
165
+ ```
166
+
167
+ ### Port Forwarding
168
+
169
+ ```typescript
170
+ const device = new AppleDeviceKit('device-udid', 1);
171
+
172
+ // Forward local port 8080 to device port 8080
173
+ const forward = device.startPortForward(8080, 8080);
174
+
175
+ // Use the forwarded connection...
176
+ // connect to localhost:8080 to reach device:8080
177
+
178
+ // Stop forwarding when done
179
+ forward.stop();
180
+
181
+ // Or use async version that waits for ready
182
+ const forwardAsync = await device.startPortForwardAsync(8080, 8080);
183
+ ```
184
+
185
+ ### Activation
186
+
187
+ ```typescript
188
+ const device = new AppleDeviceKit('device-udid', 1);
189
+
190
+ // Get activation state
191
+ const state = await device.getActivationState();
192
+ console.log(`Activated: ${state.isActivated}`);
193
+ console.log(`State: ${state.activationState}`);
194
+
195
+ // Activate device (requires valid activation record)
196
+ await device.activate({
197
+ resourcesDir: process.env.APPLE_KIT_RESOURCES_DIR,
198
+ });
199
+
200
+ // Deactivate device
201
+ await device.deactivate();
202
+ ```
203
+
204
+ When `resourcesDir` is set, the activation flow reads MDM credentials from
205
+ `@clientLocal.json` inside that folder, plist templates from `resourcesDir/plist`,
206
+ and the iOS CLI binary from `resourcesDir/ios/bin/{platform}`.
207
+ If `resourcesDir/mdm/enrollment_{udid}.mobileconfig` or
208
+ `resourcesDir/mdm/enrollment.mobileconfig` exists, it is installed instead of
209
+ calling the MDM API (offline enrollment).
210
+
211
+ ### Running Without iTunes (usbmuxd)
212
+
213
+ On Windows, iTunes provides the Apple Mobile Device Service for USB communication. If you don't have iTunes installed, you can run the bundled `usbmuxd`:
214
+
215
+ ```typescript
216
+ import { startUsbmuxd, stopUsbmuxd, ensureUsbmuxd } from '@mcesystems/apple-kit';
217
+
218
+ // Start usbmuxd daemon (required if iTunes is not installed)
219
+ const daemon = startUsbmuxd();
220
+
221
+ // Or ensure it's running (starts if not already running)
222
+ ensureUsbmuxd();
223
+
224
+ // Now you can use device operations...
225
+ const devices = await AppleDeviceKit.listDevices();
226
+
227
+ // When done, stop the daemon
228
+ stopUsbmuxd();
229
+ // or
230
+ daemon.stop();
231
+ ```
232
+
233
+ **Note:** The usbmuxd daemon must be running before connecting devices. Start it before plugging in your iOS device.
234
+
235
+ ## API Reference
236
+
237
+ ### AppleDeviceKit
238
+
239
+ **Static methods:**
240
+ - `listDevices()`: Get all connected iOS devices
241
+
242
+ **Device Info:**
243
+ - `getDeviceInfo()`: Get device properties
244
+ - `getDeviceId()`: Get the device UDID
245
+ - `getPort()`: Get the logical port number
246
+
247
+ **App Management:**
248
+ - `installApp(ipaPath, options?)`: Install an IPA file or via MDM
249
+ - `uninstallApp(bundleId)`: Uninstall an app by bundle ID
250
+ - `isAppInstalled(bundleId)`: Check if app is installed
251
+ - `listApps()`: List all installed user apps
252
+ - `launchApp(bundleId, args?)`: Launch an application
253
+
254
+ **Trust/Pairing:**
255
+ - `isPaired()`: Check if device is paired/trusted
256
+ - `pair()`: Initiate pairing (user must accept on device)
257
+ - `unpair()`: Remove pairing/trust
258
+ - `waitForPairing(timeout?)`: Wait for device to be paired
259
+
260
+ **Port Forwarding:**
261
+ - `startPortForward(localPort, devicePort)`: Start port forwarding
262
+ - `startPortForwardAsync(localPort, devicePort)`: Start and wait for ready
263
+
264
+ **Activation:**
265
+ - `getActivationState()`: Get activation state
266
+ - `activate()`: Activate the device
267
+ - `deactivate()`: Deactivate the device
268
+
269
+ ### DevicesMonitor
270
+
271
+ - `startTracking()`: Start monitoring for iOS device connections
272
+ - `stopTracking()`: Stop monitoring
273
+ - `getKits()`: Get all currently tracked devices
274
+ - `getKit(udid)`: Get a specific device kit by UDID
275
+
276
+ ### usbmuxd Functions
277
+
278
+ - `startUsbmuxd(foreground?)`: Start the usbmuxd daemon
279
+ - `stopUsbmuxd()`: Stop the daemon
280
+ - `isUsbmuxdRunning()`: Check if daemon is running
281
+ - `ensureUsbmuxd()`: Start if not already running
282
+
283
+ To use a custom resources folder, pass it as the second parameter:
284
+ `startUsbmuxd(false, { resourcesDir: "..." })`.
285
+
286
+ ### Types
287
+
288
+ ```typescript
289
+ interface PortForwardHandle {
290
+ stop: () => void;
291
+ localPort: number;
292
+ devicePort: number;
293
+ process: ChildProcess;
294
+ }
295
+
296
+ interface ActivationState {
297
+ isActivated: boolean;
298
+ activationState: string;
299
+ }
300
+ ```
301
+
302
+ ## License
303
+
304
+ ISC
305
+
306
+ libimobiledevice is licensed under LGPL-2.1.