appium-ios-remotexpc 0.17.0 → 0.18.1

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/src/index.d.ts +1 -1
  3. package/build/src/index.d.ts.map +1 -1
  4. package/build/src/lib/apple-tv/encryption/ed25519.d.ts.map +1 -1
  5. package/build/src/lib/apple-tv/encryption/ed25519.js +1 -1
  6. package/build/src/lib/tunnel/packet-stream-client.js +1 -1
  7. package/build/src/lib/types.d.ts +205 -0
  8. package/build/src/lib/types.d.ts.map +1 -1
  9. package/build/src/services/ios/dvt/instruments/application-listing.d.ts +2 -9
  10. package/build/src/services/ios/dvt/instruments/application-listing.d.ts.map +1 -1
  11. package/build/src/services/ios/dvt/instruments/application-listing.js +2 -15
  12. package/build/src/services/ios/dvt/instruments/base-instrument.d.ts +19 -0
  13. package/build/src/services/ios/dvt/instruments/base-instrument.d.ts.map +1 -0
  14. package/build/src/services/ios/dvt/instruments/base-instrument.js +24 -0
  15. package/build/src/services/ios/dvt/instruments/condition-inducer.d.ts +2 -9
  16. package/build/src/services/ios/dvt/instruments/condition-inducer.d.ts.map +1 -1
  17. package/build/src/services/ios/dvt/instruments/condition-inducer.js +2 -15
  18. package/build/src/services/ios/dvt/instruments/device-info.d.ts +98 -0
  19. package/build/src/services/ios/dvt/instruments/device-info.d.ts.map +1 -0
  20. package/build/src/services/ios/dvt/instruments/device-info.js +167 -0
  21. package/build/src/services/ios/dvt/instruments/graphics.d.ts +2 -6
  22. package/build/src/services/ios/dvt/instruments/graphics.d.ts.map +1 -1
  23. package/build/src/services/ios/dvt/instruments/graphics.js +2 -11
  24. package/build/src/services/ios/dvt/instruments/location-simulation.d.ts +2 -9
  25. package/build/src/services/ios/dvt/instruments/location-simulation.d.ts.map +1 -1
  26. package/build/src/services/ios/dvt/instruments/location-simulation.js +2 -15
  27. package/build/src/services/ios/dvt/instruments/screenshot.d.ts +2 -6
  28. package/build/src/services/ios/dvt/instruments/screenshot.d.ts.map +1 -1
  29. package/build/src/services/ios/dvt/instruments/screenshot.js +2 -11
  30. package/build/src/services.d.ts.map +1 -1
  31. package/build/src/services.js +3 -0
  32. package/package.json +3 -2
  33. package/src/index.ts +2 -0
  34. package/src/lib/apple-tv/encryption/ed25519.ts +2 -6
  35. package/src/lib/tunnel/packet-stream-client.ts +1 -1
  36. package/src/lib/types.ts +224 -0
  37. package/src/services/ios/dvt/instruments/application-listing.ts +2 -17
  38. package/src/services/ios/dvt/instruments/base-instrument.ts +27 -0
  39. package/src/services/ios/dvt/instruments/condition-inducer.ts +2 -17
  40. package/src/services/ios/dvt/instruments/device-info.ts +204 -0
  41. package/src/services/ios/dvt/instruments/graphics.ts +2 -13
  42. package/src/services/ios/dvt/instruments/location-simulation.ts +2 -18
  43. package/src/services/ios/dvt/instruments/screenshot.ts +2 -13
  44. package/src/services.ts +3 -0
@@ -1,7 +1,6 @@
1
1
  import { getLogger } from '../../../../lib/logger.js';
2
- import type { Channel } from '../channel.js';
3
2
  import { MessageAux } from '../dtx-message.js';
4
- import type { DVTSecureSocketProxyService } from '../index.js';
3
+ import { BaseInstrument } from './base-instrument.js';
5
4
 
6
5
  const log = getLogger('ApplicationListing');
7
6
 
@@ -46,24 +45,10 @@ export interface iOSApplication {
46
45
  /**
47
46
  * Application Listing service for retrieving installed applications
48
47
  */
49
- export class ApplicationListing {
48
+ export class ApplicationListing extends BaseInstrument {
50
49
  static readonly IDENTIFIER =
51
50
  'com.apple.instruments.server.services.device.applictionListing';
52
51
 
53
- private channel: Channel | null = null;
54
-
55
- constructor(private readonly dvt: DVTSecureSocketProxyService) {}
56
-
57
- /**
58
- * Initialize the application listing channel
59
- */
60
- async initialize(): Promise<void> {
61
- if (this.channel) {
62
- return;
63
- }
64
- this.channel = await this.dvt.makeChannel(ApplicationListing.IDENTIFIER);
65
- }
66
-
67
52
  /**
68
53
  * Get the list of installed applications from the device
69
54
  * @returns {Promise<iOSApplication[]>}
@@ -0,0 +1,27 @@
1
+ import type { Channel } from '../channel.js';
2
+ import type { DVTSecureSocketProxyService } from '../index.js';
3
+
4
+ /**
5
+ * Base class for DVT instrument services.
6
+ *
7
+ * Subclasses must define a static `IDENTIFIER` property.
8
+ */
9
+ export abstract class BaseInstrument {
10
+ static readonly IDENTIFIER: string;
11
+
12
+ protected channel: Channel | null = null;
13
+ constructor(protected readonly dvt: DVTSecureSocketProxyService) {}
14
+
15
+ protected get identifier(): string {
16
+ return (this.constructor as typeof BaseInstrument).IDENTIFIER;
17
+ }
18
+
19
+ /**
20
+ * Initialize the instrument channel.
21
+ */
22
+ async initialize(): Promise<void> {
23
+ if (!this.channel) {
24
+ this.channel = await this.dvt.makeChannel(this.identifier);
25
+ }
26
+ }
27
+ }
@@ -1,8 +1,7 @@
1
1
  import { getLogger } from '../../../../lib/logger.js';
2
2
  import type { ConditionGroup } from '../../../../lib/types.js';
3
- import type { Channel } from '../channel.js';
4
3
  import { MessageAux } from '../dtx-message.js';
5
- import type { DVTSecureSocketProxyService } from '../index.js';
4
+ import { BaseInstrument } from './base-instrument.js';
6
5
 
7
6
  const log = getLogger('ConditionInducer');
8
7
 
@@ -10,24 +9,10 @@ const log = getLogger('ConditionInducer');
10
9
  * Condition Inducer service for simulating various device conditions
11
10
  * such as network conditions, thermal states, etc.
12
11
  */
13
- export class ConditionInducer {
12
+ export class ConditionInducer extends BaseInstrument {
14
13
  static readonly IDENTIFIER =
15
14
  'com.apple.instruments.server.services.ConditionInducer';
16
15
 
17
- private channel: Channel | null = null;
18
-
19
- constructor(private readonly dvt: DVTSecureSocketProxyService) {}
20
-
21
- /**
22
- * Initialize the condition inducer channel
23
- */
24
- async initialize(): Promise<void> {
25
- if (this.channel) {
26
- return;
27
- }
28
- this.channel = await this.dvt.makeChannel(ConditionInducer.IDENTIFIER);
29
- }
30
-
31
16
  /**
32
17
  * List all available condition inducers and their profiles
33
18
  * @returns Array of condition groups with their available profiles
@@ -0,0 +1,204 @@
1
+ import { getLogger } from '../../../../lib/logger.js';
2
+ import { parseBinaryPlist } from '../../../../lib/plist/index.js';
3
+ import type { ProcessInfo } from '../../../../lib/types.js';
4
+ import { MessageAux } from '../dtx-message.js';
5
+ import { BaseInstrument } from './base-instrument.js';
6
+
7
+ const log = getLogger('DeviceInfo');
8
+
9
+ /**
10
+ * DeviceInfo service provides access to device information, file system,
11
+ * and process management through the DTX protocol.
12
+ *
13
+ * Available methods:
14
+ * - ls(path): List directory contents
15
+ * - execnameForPid(pid): Get executable path for a process ID
16
+ * - proclist(): Get list of running processes
17
+ * - isRunningPid(pid): Check if a process is running
18
+ * - hardwareInformation(): Get hardware details
19
+ * - networkInformation(): Get network configuration
20
+ * - machTimeInfo(): Get mach time information
21
+ * - machKernelName(): Get kernel name
22
+ * - kpepDatabase(): Get kernel performance event database
23
+ * - traceCodes(): Get trace code mappings
24
+ * - nameForUid(uid): Get username for UID
25
+ * - nameForGid(gid): Get group name for GID
26
+ */
27
+ export class DeviceInfo extends BaseInstrument {
28
+ static readonly IDENTIFIER =
29
+ 'com.apple.instruments.server.services.deviceinfo';
30
+
31
+ /**
32
+ * List directory contents at the specified path.
33
+ * @param path - The directory path to list
34
+ * @returns Array of filenames
35
+ * @throws {Error} If the directory doesn't exist or cannot be accessed
36
+ */
37
+ async ls(path: string): Promise<string[]> {
38
+ const result = await this.requestInformation(
39
+ 'directoryListingForPath_',
40
+ path,
41
+ );
42
+
43
+ if (result === null || result === undefined) {
44
+ throw new Error(`Failed to list directory: ${path}`);
45
+ }
46
+
47
+ log.debug(`Listed directory ${path}: ${result.length} entries`);
48
+ return result;
49
+ }
50
+
51
+ /**
52
+ * Get the full executable path for a given process ID.
53
+ * @param pid - The process identifier
54
+ * @returns The full path to the executable
55
+ */
56
+ async execnameForPid(pid: number): Promise<string> {
57
+ return this.requestInformation('execnameForPid_', pid);
58
+ }
59
+
60
+ /**
61
+ * Get the list of all running processes on the device.
62
+ * @returns Array of process information objects
63
+ */
64
+ async proclist(): Promise<ProcessInfo[]> {
65
+ const result = await this.requestInformation('runningProcesses');
66
+
67
+ if (!Array.isArray(result)) {
68
+ throw new Error(
69
+ `proclist returned invalid data: expected an array, got ${typeof result} (${JSON.stringify(result)})`,
70
+ );
71
+ }
72
+
73
+ log.debug(`Retrieved ${result.length} running processes`);
74
+ return result;
75
+ }
76
+
77
+ /**
78
+ * Check if a process with the given PID is currently running.
79
+ * @param pid - The process identifier to check
80
+ * @returns true if the process is running, false otherwise
81
+ */
82
+ async isRunningPid(pid: number): Promise<boolean> {
83
+ return this.requestInformation('isRunningPid_', pid);
84
+ }
85
+
86
+ /**
87
+ * Get hardware information about the device.
88
+ * @returns Object containing hardware information
89
+ */
90
+ async hardwareInformation(): Promise<any> {
91
+ return this.requestInformation('hardwareInformation');
92
+ }
93
+
94
+ /**
95
+ * Get network configuration information.
96
+ * @returns Object containing network information
97
+ */
98
+ async networkInformation(): Promise<any> {
99
+ return this.requestInformation('networkInformation');
100
+ }
101
+
102
+ /**
103
+ * Get mach kernel time information.
104
+ * @returns Object containing mach time info
105
+ */
106
+ async machTimeInfo(): Promise<any> {
107
+ return this.requestInformation('machTimeInfo');
108
+ }
109
+
110
+ /**
111
+ * Get the mach kernel name.
112
+ * @returns The kernel name string
113
+ */
114
+ async machKernelName(): Promise<string> {
115
+ return this.requestInformation('machKernelName');
116
+ }
117
+
118
+ /**
119
+ * Get the kernel performance event (kpep) database.
120
+ * @returns Object containing kpep database or null if not available
121
+ */
122
+ async kpepDatabase(): Promise<any | null> {
123
+ const kpepData = await this.requestInformation('kpepDatabase');
124
+
125
+ if (kpepData === null || kpepData === undefined) {
126
+ return null;
127
+ }
128
+
129
+ // The kpepDatabase is returned as binary plist data
130
+ if (Buffer.isBuffer(kpepData)) {
131
+ try {
132
+ return parseBinaryPlist(kpepData);
133
+ } catch (error) {
134
+ log.warn('Failed to parse kpep database:', error);
135
+ return null;
136
+ }
137
+ }
138
+
139
+ return kpepData;
140
+ }
141
+
142
+ /**
143
+ * Get trace code mappings.
144
+ * @returns Object mapping trace codes (as hex strings) to descriptions
145
+ */
146
+ async traceCodes(): Promise<Record<string, string>> {
147
+ const codesFile = await this.requestInformation('traceCodesFile');
148
+ if (typeof codesFile !== 'string') {
149
+ return {};
150
+ }
151
+
152
+ const codes: Record<string, string> = {};
153
+
154
+ for (const line of codesFile.split('\n')) {
155
+ const match = line.trim().match(/^(\S+)\s+(.+)$/);
156
+ if (match) {
157
+ const [, hex, description] = match;
158
+ codes[hex] = description;
159
+ }
160
+ }
161
+
162
+ log.debug(`Retrieved ${Object.keys(codes).length} trace codes`);
163
+ return codes;
164
+ }
165
+
166
+ /**
167
+ * Get the username for a given user ID (UID).
168
+ * @param uid - The user identifier
169
+ * @returns The username string
170
+ */
171
+ async nameForUid(uid: number): Promise<string> {
172
+ return this.requestInformation('nameForUID_', uid);
173
+ }
174
+
175
+ /**
176
+ * Get the group name for a given group ID (GID).
177
+ * @param gid - The group identifier
178
+ * @returns The group name string
179
+ */
180
+ async nameForGid(gid: number): Promise<string> {
181
+ return this.requestInformation('nameForGID_', gid);
182
+ }
183
+
184
+ /**
185
+ * Generic method to request information from the device.
186
+ * @param selectorName - The selector name to call
187
+ * @param arg - Optional argument to pass to the selector
188
+ * @returns The information object or value returned by the selector
189
+ * @private
190
+ */
191
+ private async requestInformation(
192
+ selectorName: string,
193
+ arg?: any,
194
+ ): Promise<any> {
195
+ await this.initialize();
196
+
197
+ const call = this.channel!.call(selectorName);
198
+ const args =
199
+ arg !== undefined ? new MessageAux().appendObj(arg) : undefined;
200
+
201
+ await call(args);
202
+ return this.channel!.receivePlist();
203
+ }
204
+ }
@@ -1,24 +1,13 @@
1
1
  import { getLogger } from '../../../../lib/logger.js';
2
- import type { Channel } from '../channel.js';
3
2
  import { MessageAux } from '../dtx-message.js';
4
- import type { DVTSecureSocketProxyService } from '../index.js';
3
+ import { BaseInstrument } from './base-instrument.js';
5
4
 
6
5
  const log = getLogger('Graphics');
7
6
 
8
- export class Graphics {
7
+ export class Graphics extends BaseInstrument {
9
8
  static readonly IDENTIFIER =
10
9
  'com.apple.instruments.server.services.graphics.opengl';
11
10
 
12
- private channel: Channel | null = null;
13
-
14
- constructor(private readonly dvt: DVTSecureSocketProxyService) {}
15
-
16
- async initialize(): Promise<void> {
17
- if (!this.channel) {
18
- this.channel = await this.dvt.makeChannel(Graphics.IDENTIFIER);
19
- }
20
- }
21
-
22
11
  async start(): Promise<void> {
23
12
  await this.initialize();
24
13
 
@@ -1,7 +1,6 @@
1
1
  import { getLogger } from '../../../../lib/logger.js';
2
- import type { Channel } from '../channel.js';
3
2
  import { MessageAux } from '../dtx-message.js';
4
- import type { DVTSecureSocketProxyService } from '../index.js';
3
+ import { BaseInstrument } from './base-instrument.js';
5
4
 
6
5
  const log = getLogger('LocationSimulation');
7
6
 
@@ -16,25 +15,10 @@ export interface LocationCoordinates {
16
15
  /**
17
16
  * Location simulation service for simulating device GPS location
18
17
  */
19
- export class LocationSimulation {
18
+ export class LocationSimulation extends BaseInstrument {
20
19
  static readonly IDENTIFIER =
21
20
  'com.apple.instruments.server.services.LocationSimulation';
22
21
 
23
- private channel: Channel | null = null;
24
-
25
- constructor(private readonly dvt: DVTSecureSocketProxyService) {}
26
-
27
- /**
28
- * Initialize the location simulation channel
29
- */
30
- async initialize(): Promise<void> {
31
- if (this.channel) {
32
- return;
33
- }
34
-
35
- this.channel = await this.dvt.makeChannel(LocationSimulation.IDENTIFIER);
36
- }
37
-
38
22
  /**
39
23
  * Set the simulated GPS location
40
24
  * @param coordinates The location coordinates
@@ -1,26 +1,15 @@
1
1
  import { getLogger } from '../../../../lib/logger.js';
2
- import type { Channel } from '../channel.js';
3
- import type { DVTSecureSocketProxyService } from '../index.js';
2
+ import { BaseInstrument } from './base-instrument.js';
4
3
 
5
4
  const log = getLogger('Screenshot');
6
5
 
7
6
  /**
8
7
  * Screenshot service for capturing device screenshots
9
8
  */
10
- export class Screenshot {
9
+ export class Screenshot extends BaseInstrument {
11
10
  static readonly IDENTIFIER =
12
11
  'com.apple.instruments.server.services.screenshot';
13
12
 
14
- private channel: Channel | null = null;
15
-
16
- constructor(private readonly dvt: DVTSecureSocketProxyService) {}
17
-
18
- async initialize(): Promise<void> {
19
- if (!this.channel) {
20
- this.channel = await this.dvt.makeChannel(Screenshot.IDENTIFIER);
21
- }
22
- }
23
-
24
13
  /**
25
14
  * Capture a screenshot from the device
26
15
  * @returns The screenshot data as a Buffer
package/src/services.ts CHANGED
@@ -20,6 +20,7 @@ import DiagnosticsService from './services/ios/diagnostic-service/index.js';
20
20
  import { DVTSecureSocketProxyService } from './services/ios/dvt/index.js';
21
21
  import { ApplicationListing } from './services/ios/dvt/instruments/application-listing.js';
22
22
  import { ConditionInducer } from './services/ios/dvt/instruments/condition-inducer.js';
23
+ import { DeviceInfo } from './services/ios/dvt/instruments/device-info.js';
23
24
  import { Graphics } from './services/ios/dvt/instruments/graphics.js';
24
25
  import { LocationSimulation } from './services/ios/dvt/instruments/location-simulation.js';
25
26
  import { Screenshot } from './services/ios/dvt/instruments/screenshot.js';
@@ -206,6 +207,7 @@ export async function startDVTService(
206
207
  const screenshot = new Screenshot(dvtService);
207
208
  const appListing = new ApplicationListing(dvtService);
208
209
  const graphics = new Graphics(dvtService);
210
+ const deviceInfo = new DeviceInfo(dvtService);
209
211
 
210
212
  return {
211
213
  remoteXPC: remoteXPC as RemoteXpcConnection,
@@ -215,6 +217,7 @@ export async function startDVTService(
215
217
  screenshot,
216
218
  appListing,
217
219
  graphics,
220
+ deviceInfo,
218
221
  };
219
222
  }
220
223