@ebowwa/ios-devices 1.0.0

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.
@@ -0,0 +1,404 @@
1
+ /**
2
+ * LibIMobileDevice - Wrapper for idevice* tools
3
+ * Cross-platform iOS device communication (works with iOS 4+)
4
+ */
5
+
6
+ import { exec, execILDevice, type ExecOptions } from './utils.js';
7
+ import {
8
+ type CommandResult,
9
+ type LogEntry,
10
+ type LogFilter,
11
+ type BackupInfo,
12
+ type ProvisioningProfile,
13
+ type Location,
14
+ type DiagnosticsType,
15
+ } from './types.js';
16
+
17
+ export interface LibIMobileDeviceOptions {
18
+ udid?: string;
19
+ timeout?: number;
20
+ }
21
+
22
+ export class LibIMobileDevice {
23
+ private options: LibIMobileDeviceOptions;
24
+
25
+ constructor(options: LibIMobileDeviceOptions = {}) {
26
+ this.options = options;
27
+ }
28
+
29
+ private buildArgs(extra: string[] = []): string[] {
30
+ const args: string[] = [];
31
+ if (this.options.udid) {
32
+ args.push('--udid', this.options.udid);
33
+ }
34
+ return [...args, ...extra];
35
+ }
36
+
37
+ // ==========================================================================
38
+ // Device Information
39
+ // ==========================================================================
40
+
41
+ /**
42
+ * List connected devices
43
+ */
44
+ async listDevices(): Promise<CommandResult> {
45
+ return execILDevice('idevice_id', ['-l']);
46
+ }
47
+
48
+ /**
49
+ * Get device info
50
+ */
51
+ async getDeviceInfo(): Promise<CommandResult> {
52
+ return execILDevice('ideviceinfo', this.buildArgs());
53
+ }
54
+
55
+ /**
56
+ * Get device name
57
+ */
58
+ async getDeviceName(): Promise<CommandResult> {
59
+ return execILDevice('idevicename', this.buildArgs());
60
+ }
61
+
62
+ /**
63
+ * Set device name
64
+ */
65
+ async setDeviceName(name: string): Promise<CommandResult> {
66
+ return execILDevice('idevicename', this.buildArgs([name]));
67
+ }
68
+
69
+ /**
70
+ * Get device date/time
71
+ */
72
+ async getDeviceDate(): Promise<CommandResult> {
73
+ return execILDevice('idevicedate', this.buildArgs());
74
+ }
75
+
76
+ // ==========================================================================
77
+ // Syslog
78
+ // ==========================================================================
79
+
80
+ /**
81
+ * Stream syslog (returns immediately, use for real-time monitoring)
82
+ */
83
+ async streamSyslog(filter?: LogFilter): Promise<CommandResult> {
84
+ const args = this.buildArgs();
85
+
86
+ if (filter?.match) args.push('--match', filter.match);
87
+ if (filter?.unmatch) args.push('--unmatch', filter.unmatch);
88
+ if (filter?.process) args.push('--process', filter.process);
89
+ if (filter?.exclude) args.push('--exclude', filter.exclude);
90
+ if (filter?.kernel) args.push('--kernel');
91
+ if (filter?.trigger) args.push('--trigger', filter.trigger);
92
+ if (filter?.untrigger) args.push('--untrigger', filter.untrigger);
93
+
94
+ return execILDevice('idevicesyslog', args, { timeout: 0 }); // No timeout for streaming
95
+ }
96
+
97
+ /**
98
+ * Get syslog archive
99
+ */
100
+ async getSyslogArchive(outputPath: string, options?: {
101
+ startTime?: number;
102
+ ageLimit?: string;
103
+ sizeLimit?: string;
104
+ }): Promise<CommandResult> {
105
+ const args = this.buildArgs(['archive', outputPath]);
106
+
107
+ if (options?.startTime) {
108
+ args.push('--start-time', String(options.startTime));
109
+ }
110
+ if (options?.ageLimit) {
111
+ args.push('--age-limit', options.ageLimit);
112
+ }
113
+ if (options?.sizeLimit) {
114
+ args.push('--size-limit', options.sizeLimit);
115
+ }
116
+
117
+ return execILDevice('idevicesyslog', args, { timeout: 120000 });
118
+ }
119
+
120
+ /**
121
+ * Get process list from syslog
122
+ */
123
+ async getProcessList(): Promise<CommandResult> {
124
+ return execILDevice('idevicesyslog', this.buildArgs(['pidlist']));
125
+ }
126
+
127
+ // ==========================================================================
128
+ // Screenshot
129
+ // ==========================================================================
130
+
131
+ /**
132
+ * Take screenshot
133
+ */
134
+ async takeScreenshot(outputPath?: string): Promise<CommandResult> {
135
+ const args = this.buildArgs();
136
+ if (outputPath) {
137
+ args.push('--output', outputPath);
138
+ }
139
+ return execILDevice('idevicescreenshot', args);
140
+ }
141
+
142
+ // ==========================================================================
143
+ // Location
144
+ // ==========================================================================
145
+
146
+ /**
147
+ * Set simulated location
148
+ */
149
+ async setLocation(latitude: number, longitude: number): Promise<CommandResult> {
150
+ return execILDevice('idevicesetlocation', this.buildArgs([String(latitude), String(longitude)]));
151
+ }
152
+
153
+ /**
154
+ * Reset location (stop simulation)
155
+ */
156
+ async resetLocation(): Promise<CommandResult> {
157
+ return execILDevice('idevicesetlocation', this.buildArgs(['reset']));
158
+ }
159
+
160
+ // ==========================================================================
161
+ // Diagnostics
162
+ // ==========================================================================
163
+
164
+ /**
165
+ * Get diagnostics info
166
+ */
167
+ async getDiagnostics(type: DiagnosticsType = 'All'): Promise<CommandResult> {
168
+ return execILDevice('idevicediagnostics', this.buildArgs(['diagnostics', type]));
169
+ }
170
+
171
+ /**
172
+ * Get IO Registry
173
+ */
174
+ async getIORegistry(plane?: 'IODeviceTree' | 'IOPower' | 'IOService'): Promise<CommandResult> {
175
+ const args = this.buildArgs(['ioreg']);
176
+ if (plane) {
177
+ args.push(plane);
178
+ }
179
+ return execILDevice('idevicediagnostics', args);
180
+ }
181
+
182
+ /**
183
+ * Get IO Registry entry
184
+ */
185
+ async getIORegistryEntry(key: string): Promise<CommandResult> {
186
+ return execILDevice('idevicediagnostics', this.buildArgs(['ioregentry', key]));
187
+ }
188
+
189
+ /**
190
+ * Get MobileGestalt values
191
+ */
192
+ async getMobileGestalt(...keys: string[]): Promise<CommandResult> {
193
+ return execILDevice('idevicediagnostics', this.buildArgs(['mobilegestalt', ...keys]));
194
+ }
195
+
196
+ /**
197
+ * Shutdown device
198
+ */
199
+ async shutdown(): Promise<CommandResult> {
200
+ return execILDevice('idevicediagnostics', this.buildArgs(['shutdown']));
201
+ }
202
+
203
+ /**
204
+ * Restart device
205
+ */
206
+ async restart(): Promise<CommandResult> {
207
+ return execILDevice('idevicediagnostics', this.buildArgs(['restart']));
208
+ }
209
+
210
+ /**
211
+ * Sleep device
212
+ */
213
+ async sleep(): Promise<CommandResult> {
214
+ return execILDevice('idevicediagnostics', this.buildArgs(['sleep']));
215
+ }
216
+
217
+ // ==========================================================================
218
+ // Pairing
219
+ // ==========================================================================
220
+
221
+ /**
222
+ * Pair with device
223
+ */
224
+ async pair(): Promise<CommandResult> {
225
+ return execILDevice('idevicepair', this.buildArgs());
226
+ }
227
+
228
+ /**
229
+ * Validate pairing
230
+ */
231
+ async validatePair(): Promise<CommandResult> {
232
+ return execILDevice('idevicepair', this.buildArgs(['validate']));
233
+ }
234
+
235
+ // ==========================================================================
236
+ // Backup
237
+ // ==========================================================================
238
+
239
+ /**
240
+ * Create backup
241
+ */
242
+ async createBackup(directory: string, encrypt?: boolean, password?: string): Promise<CommandResult> {
243
+ const args = this.buildArgs(['backup', directory]);
244
+ if (encrypt) {
245
+ args.push('--encryption');
246
+ if (password) {
247
+ args.push('--password', password);
248
+ }
249
+ }
250
+ return execILDevice('idevicebackup2', args, { timeout: 600000 }); // 10 min
251
+ }
252
+
253
+ /**
254
+ * Restore backup
255
+ */
256
+ async restoreBackup(directory: string, password?: string): Promise<CommandResult> {
257
+ const args = this.buildArgs(['restore', directory]);
258
+ if (password) {
259
+ args.push('--password', password);
260
+ }
261
+ return execILDevice('idevicebackup2', args, { timeout: 600000 });
262
+ }
263
+
264
+ /**
265
+ * Get backup info
266
+ */
267
+ async getBackupInfo(directory: string): Promise<CommandResult> {
268
+ return execILDevice('idevicebackup2', this.buildArgs(['info', directory]));
269
+ }
270
+
271
+ /**
272
+ * List backups
273
+ */
274
+ async listBackups(): Promise<CommandResult> {
275
+ return execILDevice('idevicebackup2', this.buildArgs(['list']));
276
+ }
277
+
278
+ /**
279
+ * Unpack backup
280
+ */
281
+ async unpackBackup(directory: string): Promise<CommandResult> {
282
+ return execILDevice('idevicebackup2', this.buildArgs(['unback', directory]), { timeout: 300000 });
283
+ }
284
+
285
+ // ==========================================================================
286
+ // Provisioning Profiles
287
+ // ==========================================================================
288
+
289
+ /**
290
+ * List provisioning profiles
291
+ */
292
+ async listProfiles(): Promise<CommandResult> {
293
+ return execILDevice('ideviceprovision', this.buildArgs(['list']));
294
+ }
295
+
296
+ /**
297
+ * Install provisioning profile
298
+ */
299
+ async installProfile(profilePath: string): Promise<CommandResult> {
300
+ return execILDevice('ideviceprovision', this.buildArgs(['install', profilePath]));
301
+ }
302
+
303
+ /**
304
+ * Remove provisioning profile
305
+ */
306
+ async removeProfile(uuid: string): Promise<CommandResult> {
307
+ return execILDevice('ideviceprovision', this.buildArgs(['remove', uuid]));
308
+ }
309
+
310
+ // ==========================================================================
311
+ // Crash Reports
312
+ // ==========================================================================
313
+
314
+ /**
315
+ * Download crash reports
316
+ */
317
+ async downloadCrashReports(outputDirectory: string, options?: {
318
+ extract?: boolean;
319
+ keep?: boolean;
320
+ }): Promise<CommandResult> {
321
+ const args = this.buildArgs([outputDirectory]);
322
+ if (options?.extract) {
323
+ args.push('--extract');
324
+ }
325
+ if (options?.keep) {
326
+ args.push('--keep');
327
+ }
328
+ return execILDevice('idevicecrashreport', args);
329
+ }
330
+
331
+ // ==========================================================================
332
+ // Developer Mode
333
+ // ==========================================================================
334
+
335
+ /**
336
+ * List developer mode status
337
+ */
338
+ async listDevMode(): Promise<CommandResult> {
339
+ return execILDevice('idevicedevmodectl', ['list']);
340
+ }
341
+
342
+ // ==========================================================================
343
+ // Image Mounting
344
+ // ==========================================================================
345
+
346
+ /**
347
+ * Mount developer disk image
348
+ */
349
+ async mountImage(imagePath: string, signaturePath?: string): Promise<CommandResult> {
350
+ const args = this.buildArgs([imagePath]);
351
+ if (signaturePath) {
352
+ args.push('--signature', signaturePath);
353
+ }
354
+ return execILDevice('ideviceimagemounter', args);
355
+ }
356
+
357
+ // ==========================================================================
358
+ // Recovery Mode
359
+ // ==========================================================================
360
+
361
+ /**
362
+ * Enter recovery mode
363
+ */
364
+ async enterRecovery(): Promise<CommandResult> {
365
+ return execILDevice('ideviceenterrecovery', this.buildArgs());
366
+ }
367
+
368
+ // ==========================================================================
369
+ // Bluetooth Logging
370
+ // ==========================================================================
371
+
372
+ /**
373
+ * Start Bluetooth packet logging
374
+ */
375
+ async startBluetoothLogging(outputPath?: string): Promise<CommandResult> {
376
+ const args = this.buildArgs();
377
+ if (outputPath) {
378
+ args.push('--output', outputPath);
379
+ }
380
+ return execILDevice('idevicebtlogger', args, { timeout: 0 });
381
+ }
382
+
383
+ // ==========================================================================
384
+ // Debug Server
385
+ // ==========================================================================
386
+
387
+ /**
388
+ * Start debug server proxy
389
+ */
390
+ async startDebugServerProxy(port: number = 6666): Promise<CommandResult> {
391
+ return execILDevice('idevicedebugserverproxy', this.buildArgs([String(port)]), { timeout: 0 });
392
+ }
393
+
394
+ // ==========================================================================
395
+ // AFC Client (File System)
396
+ // ==========================================================================
397
+
398
+ /**
399
+ * Start AFC shell
400
+ */
401
+ async startAFCShell(): Promise<CommandResult> {
402
+ return execILDevice('afcclient', this.buildArgs(), { timeout: 0 });
403
+ }
404
+ }
@@ -0,0 +1,5 @@
1
+ declare module 'shell-quote' {
2
+ export function parse(str: string): Array<string | { op: string }>;
3
+ export function parse(str: string, env?: Record<string, string>): Array<string | { op: string }>;
4
+ export function quote(args: string[]): string;
5
+ }