appium-ios-remotexpc 0.0.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 (92) hide show
  1. package/.github/dependabot.yml +38 -0
  2. package/.github/workflows/format-check.yml +43 -0
  3. package/.github/workflows/lint-and-build.yml +40 -0
  4. package/.github/workflows/pr-title.yml +16 -0
  5. package/.github/workflows/publish.js.yml +42 -0
  6. package/.github/workflows/test-validation.yml +40 -0
  7. package/.mocharc.json +8 -0
  8. package/.prettierignore +3 -0
  9. package/.prettierrc +17 -0
  10. package/.releaserc +37 -0
  11. package/CHANGELOG.md +63 -0
  12. package/LICENSE +201 -0
  13. package/README.md +178 -0
  14. package/assets/images/ios-arch.png +0 -0
  15. package/eslint.config.js +45 -0
  16. package/package.json +78 -0
  17. package/scripts/test-tunnel-creation.ts +378 -0
  18. package/src/base-plist-service.ts +83 -0
  19. package/src/base-socket-service.ts +55 -0
  20. package/src/index.ts +34 -0
  21. package/src/lib/apple-tv/constants.ts +83 -0
  22. package/src/lib/apple-tv/errors.ts +31 -0
  23. package/src/lib/apple-tv/tlv/decoder.ts +68 -0
  24. package/src/lib/apple-tv/tlv/encoder.ts +33 -0
  25. package/src/lib/apple-tv/tlv/index.ts +6 -0
  26. package/src/lib/apple-tv/tlv/pairing-tlv.ts +31 -0
  27. package/src/lib/apple-tv/types.ts +58 -0
  28. package/src/lib/apple-tv/utils/buffer-utils.ts +90 -0
  29. package/src/lib/apple-tv/utils/index.ts +2 -0
  30. package/src/lib/apple-tv/utils/uuid-generator.ts +43 -0
  31. package/src/lib/lockdown/index.ts +468 -0
  32. package/src/lib/pair-record/index.ts +8 -0
  33. package/src/lib/pair-record/pair-record.ts +133 -0
  34. package/src/lib/plist/binary-plist-creator.ts +571 -0
  35. package/src/lib/plist/binary-plist-parser.ts +587 -0
  36. package/src/lib/plist/constants.ts +53 -0
  37. package/src/lib/plist/index.ts +54 -0
  38. package/src/lib/plist/length-based-splitter.ts +326 -0
  39. package/src/lib/plist/plist-creator.ts +42 -0
  40. package/src/lib/plist/plist-decoder.ts +135 -0
  41. package/src/lib/plist/plist-encoder.ts +36 -0
  42. package/src/lib/plist/plist-parser.ts +144 -0
  43. package/src/lib/plist/plist-service.ts +231 -0
  44. package/src/lib/plist/unified-plist-creator.ts +19 -0
  45. package/src/lib/plist/unified-plist-parser.ts +25 -0
  46. package/src/lib/plist/utils.ts +376 -0
  47. package/src/lib/remote-xpc/constants.ts +22 -0
  48. package/src/lib/remote-xpc/handshake-frames.ts +377 -0
  49. package/src/lib/remote-xpc/handshake.ts +152 -0
  50. package/src/lib/remote-xpc/remote-xpc-connection.ts +461 -0
  51. package/src/lib/remote-xpc/xpc-protocol.ts +412 -0
  52. package/src/lib/tunnel/index.ts +253 -0
  53. package/src/lib/tunnel/packet-stream-client.ts +185 -0
  54. package/src/lib/tunnel/packet-stream-server.ts +133 -0
  55. package/src/lib/tunnel/tunnel-api-client.ts +234 -0
  56. package/src/lib/tunnel/tunnel-registry-server.ts +410 -0
  57. package/src/lib/types.ts +291 -0
  58. package/src/lib/usbmux/index.ts +630 -0
  59. package/src/lib/usbmux/usbmux-decoder.ts +66 -0
  60. package/src/lib/usbmux/usbmux-encoder.ts +55 -0
  61. package/src/service-connection.ts +79 -0
  62. package/src/services/index.ts +15 -0
  63. package/src/services/ios/base-service.ts +81 -0
  64. package/src/services/ios/diagnostic-service/index.ts +241 -0
  65. package/src/services/ios/diagnostic-service/keys.ts +770 -0
  66. package/src/services/ios/syslog-service/index.ts +387 -0
  67. package/src/services/ios/tunnel-service/index.ts +88 -0
  68. package/src/services.ts +81 -0
  69. package/test/integration/diagnostics-test.ts +44 -0
  70. package/test/integration/read-pair-record-test.ts +39 -0
  71. package/test/integration/tunnel-test.ts +104 -0
  72. package/test/unit/apple-tv/tlv/decoder.spec.ts +144 -0
  73. package/test/unit/apple-tv/tlv/encoder.spec.ts +91 -0
  74. package/test/unit/apple-tv/tlv/pairing-tlv.spec.ts +101 -0
  75. package/test/unit/apple-tv/tlv/tlv-integration.spec.ts +146 -0
  76. package/test/unit/apple-tv/utils/buffer-utils.spec.ts +74 -0
  77. package/test/unit/apple-tv/utils/uuid-generator.spec.ts +39 -0
  78. package/test/unit/fixtures/index.ts +88 -0
  79. package/test/unit/fixtures/usbmuxconnectmessage.bin +0 -0
  80. package/test/unit/fixtures/usbmuxlistdevicemessage.bin +0 -0
  81. package/test/unit/plist/error-handling.spec.ts +101 -0
  82. package/test/unit/plist/fixtures/sample.binary.plist +0 -0
  83. package/test/unit/plist/fixtures/sample.xml.plist +38 -0
  84. package/test/unit/plist/plist-parser.spec.ts +283 -0
  85. package/test/unit/plist/plist.spec.ts +205 -0
  86. package/test/unit/plist/tag-position-handling.spec.ts +90 -0
  87. package/test/unit/plist/unified-plist-parser.spec.ts +227 -0
  88. package/test/unit/plist/utils.spec.ts +249 -0
  89. package/test/unit/plist/xml-cleaning.spec.ts +60 -0
  90. package/test/unit/tunnel/tunnel-registry-server.spec.ts +194 -0
  91. package/test/unit/usbmux/usbmux-specs.ts +71 -0
  92. package/tsconfig.json +36 -0
@@ -0,0 +1,410 @@
1
+ import { logger } from '@appium/support';
2
+ import * as http from 'node:http';
3
+ import { URL } from 'node:url';
4
+
5
+ import type { TunnelRegistry, TunnelRegistryEntry } from '../types.js';
6
+
7
+ // Constants
8
+ const DEFAULT_TUNNEL_REGISTRY_PORT = 42314;
9
+ const API_BASE_PATH = '/remotexpc/tunnels';
10
+
11
+ // Logger instance
12
+ const log = logger.getLogger('TunnelRegistryServer');
13
+
14
+ // Helper functions
15
+ /**
16
+ * Parse JSON body from HTTP request
17
+ */
18
+ async function parseJSONBody<T = unknown>(
19
+ req: http.IncomingMessage,
20
+ ): Promise<T> {
21
+ return new Promise((resolve, reject) => {
22
+ let body = '';
23
+ req.on('data', (chunk) => {
24
+ body += chunk.toString();
25
+ });
26
+ req.on('end', () => {
27
+ try {
28
+ resolve(body ? JSON.parse(body) : {});
29
+ } catch (error) {
30
+ reject(error);
31
+ }
32
+ });
33
+ req.on('error', reject);
34
+ });
35
+ }
36
+
37
+ /**
38
+ * Send JSON response
39
+ */
40
+ function sendJSON(
41
+ res: http.ServerResponse,
42
+ statusCode: number,
43
+ data: unknown,
44
+ ): void {
45
+ const statusText = http.STATUS_CODES[statusCode] || '';
46
+ let responseBody;
47
+ if (data && typeof data === 'object' && data !== null) {
48
+ if ('error' in data) {
49
+ responseBody = { status: statusText, ...data };
50
+ } else {
51
+ responseBody = { status: statusText, ...data };
52
+ }
53
+ } else {
54
+ responseBody = { status: statusText, data };
55
+ }
56
+ res.writeHead(statusCode, { 'Content-Type': 'application/json' });
57
+ res.end(JSON.stringify(responseBody));
58
+ }
59
+
60
+ /**
61
+ * Tunnel Registry Server - provides API endpoints for tunnel registry operations
62
+ */
63
+ export class TunnelRegistryServer {
64
+ private server?: http.Server;
65
+ public port: number;
66
+ public tunnelsInfo?: TunnelRegistry;
67
+ private registry: TunnelRegistry = {
68
+ tunnels: {},
69
+ metadata: {
70
+ lastUpdated: new Date().toISOString(),
71
+ totalTunnels: 0,
72
+ activeTunnels: 0,
73
+ },
74
+ };
75
+
76
+ /**
77
+ * Create a new TunnelRegistryServer
78
+ * @param tunnelsInfo - Registry data object
79
+ * @param port - Port to listen on
80
+ */
81
+ constructor(tunnelsInfo: TunnelRegistry | undefined, port: number) {
82
+ this.port = port;
83
+ this.tunnelsInfo = tunnelsInfo;
84
+ }
85
+
86
+ /**
87
+ * Get tunnels from registry
88
+ */
89
+ private get tunnels(): Record<string, TunnelRegistryEntry> {
90
+ return this.registry.tunnels;
91
+ }
92
+
93
+ /**
94
+ * Get auto-calculated metadata
95
+ */
96
+ private get metadata(): TunnelRegistry['metadata'] {
97
+ const tunnelCount = Object.keys(this.tunnels).length;
98
+ return {
99
+ lastUpdated: new Date().toISOString(),
100
+ totalTunnels: tunnelCount,
101
+ activeTunnels: tunnelCount, // Assuming all tunnels are active
102
+ };
103
+ }
104
+
105
+ /**
106
+ * Get a complete registry with tunnels and metadata
107
+ */
108
+ private get fullRegistry(): TunnelRegistry {
109
+ return {
110
+ tunnels: this.tunnels,
111
+ metadata: this.metadata,
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Start the server
117
+ */
118
+ async start(): Promise<void> {
119
+ try {
120
+ // Load the registry first
121
+ await this.loadRegistry();
122
+
123
+ // Create HTTP server with request handler
124
+ this.server = http.createServer(async (req, res) => {
125
+ await this.handleRequest(req, res);
126
+ });
127
+
128
+ // Start listening
129
+ await new Promise<void>((resolve, reject) => {
130
+ this.server?.listen(this.port, () => {
131
+ log.info(`Tunnel Registry Server started on port ${this.port}`);
132
+ log.info(
133
+ `API available at http://localhost:${this.port}${API_BASE_PATH}`,
134
+ );
135
+ resolve();
136
+ });
137
+
138
+ // Handle server errors
139
+ this.server?.on('error', (error) => {
140
+ log.error(`Server error: ${error}`);
141
+ reject(error);
142
+ });
143
+ });
144
+ } catch (error) {
145
+ log.error(`Failed to start server: ${error}`);
146
+ throw error;
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Stop the server
152
+ */
153
+ async stop(): Promise<void> {
154
+ if (!this.server) {
155
+ log.warn('Server not running');
156
+ return;
157
+ }
158
+
159
+ try {
160
+ await new Promise<void>((resolve, reject) => {
161
+ this.server?.close((error?: Error) => {
162
+ if (error) {
163
+ reject(error);
164
+ } else {
165
+ resolve();
166
+ }
167
+ });
168
+ });
169
+ log.info('Tunnel Registry Server stopped');
170
+ } catch (error) {
171
+ log.error(`Error stopping server: ${error}`);
172
+ throw error;
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Main request handler
178
+ */
179
+ private async handleRequest(
180
+ req: http.IncomingMessage,
181
+ res: http.ServerResponse,
182
+ ): Promise<void> {
183
+ const url = new URL(req.url || '', `http://localhost:${this.port}`);
184
+ const method = req.method || 'GET';
185
+ const pathname = url.pathname;
186
+
187
+ // Log the request
188
+ log.debug(`${method} ${pathname}`);
189
+
190
+ // Match routes
191
+ const basePath = API_BASE_PATH;
192
+
193
+ try {
194
+ // GET /remotexpc/tunnels - Get all tunnels
195
+ if (method === 'GET' && pathname === basePath) {
196
+ await this.getAllTunnels(res);
197
+ return;
198
+ }
199
+
200
+ // GET /remotexpc/tunnels/device/:deviceId - Get tunnel by device ID
201
+ const deviceMatch = pathname.match(
202
+ new RegExp(`^${basePath}/device/(.+)$`),
203
+ );
204
+ if (method === 'GET' && deviceMatch) {
205
+ const deviceIdStr = deviceMatch[1];
206
+ const deviceId = parseInt(deviceIdStr, 10);
207
+ await this.getTunnelByDeviceId(res, deviceId);
208
+ return;
209
+ }
210
+
211
+ // GET /remotexpc/tunnels/:udid - Get tunnel by UDID
212
+ const udidMatch = pathname.match(new RegExp(`^${basePath}/([^/]+)$`));
213
+ if (
214
+ method === 'GET' &&
215
+ udidMatch &&
216
+ !udidMatch[1].startsWith('device/')
217
+ ) {
218
+ const udid = udidMatch[1];
219
+ await this.getTunnelByUdid(res, udid);
220
+ return;
221
+ }
222
+
223
+ // PUT /remotexpc/tunnels/:udid - Update tunnel
224
+ if (method === 'PUT' && udidMatch) {
225
+ const udid = udidMatch[1];
226
+ await this.updateTunnel(req, res, udid);
227
+ return;
228
+ }
229
+
230
+ // No route matched
231
+ sendJSON(res, 404, { error: 'Not found' });
232
+ } catch (error) {
233
+ log.error(`Request handling error: ${error}`);
234
+ sendJSON(res, 500, {
235
+ error: 'Internal server error',
236
+ });
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Handler for getting all tunnels
242
+ */
243
+ private async getAllTunnels(res: http.ServerResponse): Promise<void> {
244
+ try {
245
+ await this.loadRegistry();
246
+ sendJSON(res, 200, this.fullRegistry);
247
+ } catch (error) {
248
+ log.error(`Error getting all tunnels: ${error}`);
249
+ sendJSON(res, 500, {
250
+ error: 'Failed to get tunnels',
251
+ });
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Handler for getting a tunnel by UDID
257
+ */
258
+ private async getTunnelByUdid(
259
+ res: http.ServerResponse,
260
+ udid: string,
261
+ ): Promise<void> {
262
+ try {
263
+ await this.loadRegistry();
264
+ const tunnel = this.tunnels[udid];
265
+
266
+ if (!tunnel) {
267
+ sendJSON(res, 404, {
268
+ error: `Tunnel not found for UDID: ${udid}`,
269
+ });
270
+ return;
271
+ }
272
+
273
+ sendJSON(res, 200, tunnel);
274
+ } catch (error) {
275
+ log.error(`Error getting tunnel by UDID: ${error}`);
276
+ sendJSON(res, 500, {
277
+ error: 'Failed to get tunnel',
278
+ });
279
+ }
280
+ }
281
+
282
+ /**
283
+ * Handler for getting a tunnel by device ID
284
+ */
285
+ private async getTunnelByDeviceId(
286
+ res: http.ServerResponse,
287
+ deviceId: number,
288
+ ): Promise<void> {
289
+ try {
290
+ await this.loadRegistry();
291
+
292
+ if (isNaN(deviceId)) {
293
+ sendJSON(res, 400, { error: 'Invalid device ID' });
294
+ return;
295
+ }
296
+
297
+ const tunnel = Object.values(this.tunnels).find(
298
+ (t) => t.deviceId === deviceId,
299
+ );
300
+
301
+ if (!tunnel) {
302
+ sendJSON(res, 404, {
303
+ error: `Tunnel not found for device ID: ${deviceId}`,
304
+ });
305
+ return;
306
+ }
307
+
308
+ sendJSON(res, 200, tunnel);
309
+ } catch (error) {
310
+ log.error(`Error getting tunnel by device ID: ${error}`);
311
+ sendJSON(res, 500, {
312
+ error: 'Failed to get tunnel',
313
+ });
314
+ }
315
+ }
316
+
317
+ /**
318
+ * Handler for updating a tunnel
319
+ */
320
+ private async updateTunnel(
321
+ req: http.IncomingMessage,
322
+ res: http.ServerResponse,
323
+ udid: string,
324
+ ): Promise<void> {
325
+ try {
326
+ await this.loadRegistry();
327
+ let tunnelData: TunnelRegistryEntry | null = null;
328
+ try {
329
+ tunnelData = await parseJSONBody<TunnelRegistryEntry>(req);
330
+ } catch (parseError: unknown) {
331
+ const errorMessage =
332
+ parseError instanceof Error ? parseError.message : String(parseError);
333
+ log.error(`Failed to parse JSON body: ${errorMessage}`);
334
+ sendJSON(res, 400, {
335
+ error: 'Malformed JSON in request body',
336
+ });
337
+ return;
338
+ }
339
+
340
+ if (!tunnelData || typeof tunnelData !== 'object') {
341
+ sendJSON(res, 400, {
342
+ error: 'Invalid tunnel data',
343
+ });
344
+ return;
345
+ }
346
+
347
+ // Ensure the UDID in the path matches the one in the body
348
+ if (tunnelData.udid !== udid) {
349
+ sendJSON(res, 400, {
350
+ error: 'UDID mismatch between path and body',
351
+ });
352
+ return;
353
+ }
354
+
355
+ // Update the tunnel
356
+ this.registry.tunnels[udid] = {
357
+ ...tunnelData,
358
+ lastUpdated: Date.now(),
359
+ };
360
+
361
+ sendJSON(res, 200, {
362
+ success: true,
363
+ tunnel: this.registry.tunnels[udid],
364
+ });
365
+ } catch (error) {
366
+ log.error(`Error updating tunnel: ${error}`);
367
+ sendJSON(res, 500, {
368
+ error: 'Failed to update tunnel',
369
+ });
370
+ }
371
+ }
372
+
373
+ /**
374
+ * Load the registry from provided data
375
+ */
376
+ private async loadRegistry(): Promise<void> {
377
+ try {
378
+ if (this.tunnelsInfo) {
379
+ this.registry = this.tunnelsInfo;
380
+ }
381
+ // Use the provided registry object or default empty registry
382
+ } catch (error) {
383
+ log.warn(`Failed to load registry: ${error}`);
384
+ // If there's an error, use the default empty registry
385
+ this.registry = {
386
+ tunnels: {},
387
+ metadata: {
388
+ lastUpdated: new Date().toISOString(),
389
+ totalTunnels: 0,
390
+ activeTunnels: 0,
391
+ },
392
+ };
393
+ }
394
+ }
395
+ }
396
+
397
+ /**
398
+ * Create and start a TunnelRegistryServer instance
399
+ * @param tunnelInfos - Registry data object
400
+ * @param port - Port to listen on
401
+ * @returns The started TunnelRegistryServer instance
402
+ */
403
+ export async function startTunnelRegistryServer(
404
+ tunnelInfos: TunnelRegistry | undefined,
405
+ port: number = DEFAULT_TUNNEL_REGISTRY_PORT,
406
+ ): Promise<TunnelRegistryServer> {
407
+ const server = new TunnelRegistryServer(tunnelInfos, port);
408
+ await server.start();
409
+ return server;
410
+ }
@@ -0,0 +1,291 @@
1
+ /**
2
+ * Common type definitions for the appium-ios-remotexpc library
3
+ */
4
+ import { EventEmitter } from 'events';
5
+ import type { PacketData } from 'tuntap-bridge';
6
+
7
+ import type { BaseService, Service } from '../services/ios/base-service.js';
8
+ import type { Device } from './usbmux/index.js';
9
+
10
+ /**
11
+ * Represents a value that can be stored in a plist
12
+ */
13
+ export type PlistValue =
14
+ | string
15
+ | number
16
+ | bigint
17
+ | boolean
18
+ | Date
19
+ | Buffer
20
+ | PlistArray
21
+ | PlistDictionary
22
+ | null;
23
+
24
+ /**
25
+ * Represents an array in a plist
26
+ */
27
+ export type PlistArray = Array<PlistValue>;
28
+
29
+ /**
30
+ * Represents a dictionary in a plist
31
+ */
32
+ export interface PlistDictionary {
33
+ [key: string]: PlistValue;
34
+ }
35
+
36
+ /**
37
+ * Represents a message that can be sent or received via plist
38
+ */
39
+ export type PlistMessage = PlistDictionary;
40
+
41
+ /**
42
+ * Represents a value that can be encoded in XPC protocol
43
+ */
44
+ export type XPCValue =
45
+ | string
46
+ | number
47
+ | bigint
48
+ | boolean
49
+ | Date
50
+ | Buffer
51
+ | Uint8Array
52
+ | XPCArray
53
+ | XPCDictionary
54
+ | null;
55
+
56
+ /**
57
+ * Represents an array in XPC protocol
58
+ */
59
+ export type XPCArray = Array<XPCValue>;
60
+
61
+ /**
62
+ * Represents a dictionary in XPC protocol
63
+ */
64
+ export interface XPCDictionary {
65
+ [key: string]: XPCValue;
66
+ }
67
+
68
+ /**
69
+ * Represents a callback function for handling responses
70
+ */
71
+ export type ResponseCallback<T> = (data: T) => void;
72
+
73
+ export interface TunnelRegistryEntry {
74
+ /** Unique device identifier */
75
+ udid: string;
76
+ /** Numeric device ID */
77
+ deviceId: number;
78
+ /** IP address of the tunnel */
79
+ address: string;
80
+ /** Remote Service Discovery (RSD) port number */
81
+ rsdPort: number;
82
+ /** Packet stream port number */
83
+ packetStreamPort: number;
84
+ /** Type of connection (e.g., 'USB', 'Network') */
85
+ connectionType: string;
86
+ /** Product identifier of the device */
87
+ productId: number;
88
+ /** Timestamp when the tunnel was created (milliseconds since epoch) */
89
+ createdAt: number;
90
+ /** Timestamp when the tunnel was last updated (milliseconds since epoch) */
91
+ lastUpdated: number;
92
+ }
93
+
94
+ export interface TunnelRegistry {
95
+ /** Map of UDID to tunnel registry entries */
96
+ tunnels: Record<string, TunnelRegistryEntry>;
97
+ /** Metadata about the registry */
98
+ metadata: {
99
+ /** ISO 8601 timestamp of last registry update */
100
+ lastUpdated: string;
101
+ /** Total number of tunnels in the registry */
102
+ totalTunnels: number;
103
+ /** Number of currently active tunnels */
104
+ activeTunnels: number;
105
+ };
106
+ }
107
+
108
+ export interface SocketInfo {
109
+ /** Device server information */
110
+ server: Device;
111
+ /** Port number for the socket connection */
112
+ port: number;
113
+ /** Device-specific information */
114
+ deviceInfo: {
115
+ /** Unique device identifier */
116
+ udid: string;
117
+ /** IP address of the device */
118
+ address: string;
119
+ /** Optional Remote Service Discovery (RSD) port number */
120
+ rsdPort?: number;
121
+ };
122
+ }
123
+
124
+ export interface TunnelResult {
125
+ /** Device information */
126
+ device: Device;
127
+ /** Tunnel connection details */
128
+ tunnel: {
129
+ /** IP address of the tunnel */
130
+ Address: string;
131
+ /** Optional Remote Service Discovery (RSD) port number */
132
+ RsdPort?: number;
133
+ };
134
+ /** Optional packet stream port number */
135
+ packetStreamPort?: number;
136
+ /** Indicates whether the tunnel creation was successful */
137
+ success: boolean;
138
+ /** Error message if tunnel creation failed */
139
+ error?: string;
140
+ }
141
+
142
+ /**
143
+ * Represents the instance side of DiagnosticsService
144
+ */
145
+ export interface DiagnosticsService extends BaseService {
146
+ /**
147
+ * Restart the device
148
+ * @returns Promise that resolves when the restart request is sent
149
+ */
150
+ restart(): Promise<PlistDictionary>;
151
+
152
+ /**
153
+ * Shutdown the device
154
+ * @returns Promise that resolves when the shutdown request is sent
155
+ */
156
+ shutdown(): Promise<PlistDictionary>;
157
+
158
+ /**
159
+ * Put the device in sleep mode
160
+ * @returns Promise that resolves when the sleep request is sent
161
+ */
162
+ sleep(): Promise<PlistDictionary>;
163
+
164
+ /**
165
+ * Query IORegistry
166
+ * @param options Options for the IORegistry query
167
+ * @returns Object containing the IORegistry information
168
+ */
169
+ ioregistry(options?: {
170
+ plane?: string;
171
+ name?: string;
172
+ ioClass?: string;
173
+ returnRawJson?: boolean;
174
+ timeout?: number;
175
+ }): Promise<PlistDictionary[] | Record<string, any>>;
176
+ }
177
+
178
+ /**
179
+ * Represents the static side of DiagnosticsService
180
+ */
181
+ export interface DiagnosticsServiceConstructor {
182
+ /**
183
+ * Service name for Remote Service Discovery
184
+ */
185
+ readonly RSD_SERVICE_NAME: string;
186
+ /**
187
+ * Creates a new DiagnosticsService instance
188
+ * @param address Tuple containing [host, port]
189
+ */
190
+ new (address: [string, number]): DiagnosticsService;
191
+ }
192
+
193
+ /**
194
+ * Options for configuring syslog capture
195
+ */
196
+ export interface SyslogOptions {
197
+ /** Process ID to filter logs by */
198
+ pid?: number;
199
+ /** Whether to enable verbose logging */
200
+ enableVerboseLogging?: boolean;
201
+ }
202
+
203
+ /**
204
+ * Interface for a packet source that can provide packet data
205
+ */
206
+ export interface PacketSource {
207
+ /** Add a packet consumer to receive packets */
208
+ addPacketConsumer: (consumer: PacketConsumer) => void;
209
+ /** Remove a packet consumer */
210
+ removePacketConsumer: (consumer: PacketConsumer) => void;
211
+ }
212
+
213
+ /**
214
+ * Interface for a packet consumer that can process packets
215
+ */
216
+ export interface PacketConsumer {
217
+ /** Handler for received packets */
218
+ onPacket: (packet: PacketData) => void;
219
+ }
220
+
221
+ /**
222
+ * Represents the instance side of SyslogService
223
+ */
224
+ export interface SyslogService extends EventEmitter {
225
+ /**
226
+ * Starts capturing syslog data from the device
227
+ * @param service Service information
228
+ * @param packetSource Source of packet data (can be PacketConsumer or AsyncIterable)
229
+ * @param options Configuration options for syslog capture
230
+ * @returns Promise resolving to the initial response from the service
231
+ */
232
+ start(
233
+ service: Service,
234
+ packetSource: PacketSource | AsyncIterable<PacketData>,
235
+ options?: SyslogOptions,
236
+ ): Promise<void>;
237
+
238
+ /**
239
+ * Stops capturing syslog data
240
+ * @returns Promise that resolves when capture is stopped
241
+ */
242
+ stop(): Promise<void>;
243
+
244
+ /**
245
+ * Restart the device
246
+ * @param service Service information
247
+ * @returns Promise that resolves when the restart request is sent
248
+ */
249
+ restart(service: Service): Promise<void>;
250
+
251
+ /**
252
+ * Event emitter for 'start' events
253
+ */
254
+ on(event: 'start', listener: (response: any) => void): this;
255
+
256
+ /**
257
+ * Event emitter for 'stop' events
258
+ */
259
+ on(event: 'stop', listener: () => void): this;
260
+
261
+ /**
262
+ * Event emitter for 'message' events
263
+ */
264
+ on(event: 'message', listener: (message: string) => void): this;
265
+
266
+ /**
267
+ * Event emitter for 'plist' events
268
+ */
269
+ on(event: 'plist', listener: (data: any) => void): this;
270
+
271
+ /**
272
+ * Event emitter for 'error' events
273
+ */
274
+ on(event: 'error', listener: (error: Error) => void): this;
275
+
276
+ /**
277
+ * Event emitter for any events
278
+ */
279
+ on(event: string, listener: (...args: any[]) => void): this;
280
+ }
281
+
282
+ /**
283
+ * Represents the static side of SyslogService
284
+ */
285
+ export interface SyslogServiceConstructor {
286
+ /**
287
+ * Creates a new SyslogService instance
288
+ * @param address Tuple containing [host, port]
289
+ */
290
+ new (address: [string, number]): SyslogService;
291
+ }