appium-ios-remotexpc 5.2.1 → 5.2.2
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/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [5.2.2](https://github.com/appium/appium-ios-remotexpc/compare/v5.2.1...v5.2.2) (2026-06-24)
|
|
2
|
+
|
|
3
|
+
### Miscellaneous Chores
|
|
4
|
+
|
|
5
|
+
* Add scripts to typescript checks ([#253](https://github.com/appium/appium-ios-remotexpc/issues/253)) ([f06a206](https://github.com/appium/appium-ios-remotexpc/commit/f06a2060a41f834ca049cb31d9f453c12d9fc013))
|
|
6
|
+
|
|
1
7
|
## [5.2.1](https://github.com/appium/appium-ios-remotexpc/compare/v5.2.0...v5.2.1) (2026-06-24)
|
|
2
8
|
|
|
3
9
|
### Miscellaneous Chores
|
package/package.json
CHANGED
package/scripts/lib/progress.mjs
CHANGED
|
@@ -16,6 +16,10 @@ export function startTimeoutProgressLogger({
|
|
|
16
16
|
let timer = null;
|
|
17
17
|
let isStopped = false;
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} status
|
|
21
|
+
* @param {boolean} isComplete
|
|
22
|
+
*/
|
|
19
23
|
const logProgress = (status, isComplete = false) => {
|
|
20
24
|
const elapsedMs = performance.now() - startedAt;
|
|
21
25
|
const boundedElapsedMs = Math.min(elapsedMs, timeoutMs);
|
|
@@ -28,6 +32,10 @@ export function startTimeoutProgressLogger({
|
|
|
28
32
|
);
|
|
29
33
|
};
|
|
30
34
|
|
|
35
|
+
/**
|
|
36
|
+
* @param {string} status
|
|
37
|
+
* @param {boolean} isComplete
|
|
38
|
+
*/
|
|
31
39
|
const stop = (status, isComplete = false) => {
|
|
32
40
|
if (isStopped) {
|
|
33
41
|
return;
|
|
@@ -35,7 +35,7 @@ export async function refreshServiceCatalog(udid, entry, log) {
|
|
|
35
35
|
* @template T
|
|
36
36
|
* @param {object} opts
|
|
37
37
|
* @param {import('appium-ios-remotexpc').TunnelRegistryServer | null} opts.registryServer
|
|
38
|
-
* @param {T} opts.result
|
|
38
|
+
* @param {T & { tunnel: { Address: string, RsdPort?: number } }} opts.result
|
|
39
39
|
* @param {(result: T) => string} opts.getUdid
|
|
40
40
|
* @param {(result: T, existing: import('appium-ios-remotexpc').TunnelRegistryEntry | undefined, now: number) => import('appium-ios-remotexpc').TunnelRegistryEntry} opts.buildEntry
|
|
41
41
|
* @param {{info: (message: string) => void, warn: (message: string) => void}} opts.log
|
package/scripts/pair-appletv.mjs
CHANGED
|
@@ -20,12 +20,23 @@ const log = logger.getLogger('AppleTVPairing');
|
|
|
20
20
|
const APPLETV_PAIRING_DISCOVERY_PROGRESS_INTERVAL_MS = 1000;
|
|
21
21
|
const APPLETV_PAIRING_DISCOVERY_PROGRESS_BAR_WIDTH = 24;
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* @param {import('appium-ios-remotexpc').AppleTVPairingService} pairingService
|
|
25
|
+
* @param {number} timeoutMs
|
|
26
|
+
* @returns {{ startedAt: number, promise: Promise<AppleTVDevice[]> }}
|
|
27
|
+
*/
|
|
23
28
|
function discoverAppleTVPairingDevices(pairingService, timeoutMs) {
|
|
24
29
|
const startedAt = performance.now();
|
|
25
30
|
const promise = pairingService.discoverDevices({ timeoutMs });
|
|
26
31
|
return { startedAt, promise };
|
|
27
32
|
}
|
|
28
33
|
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @param {{ startedAt: number, promise: Promise<AppleTVDevice[]> }} discovery
|
|
37
|
+
* @param {number} timeoutMs
|
|
38
|
+
* @returns {Promise<AppleTVDevice[]>}
|
|
39
|
+
*/
|
|
29
40
|
async function waitForAppleTVPairingDiscovery(discovery, timeoutMs) {
|
|
30
41
|
const progress = startTimeoutProgressLogger({
|
|
31
42
|
log,
|
|
@@ -48,6 +59,12 @@ async function waitForAppleTVPairingDiscovery(discovery, timeoutMs) {
|
|
|
48
59
|
}
|
|
49
60
|
}
|
|
50
61
|
|
|
62
|
+
/**
|
|
63
|
+
* @param {import('appium-ios-remotexpc').AppleTVPairingService} pairingService
|
|
64
|
+
* @param {string} deviceSelector
|
|
65
|
+
* @param {number} discoveryTimeoutMs
|
|
66
|
+
* @returns {Promise<{ success: boolean, deviceId: string, pairingFile?: string, error?: Error | null }>}
|
|
67
|
+
*/
|
|
51
68
|
async function discoverAndPairWithProgress(
|
|
52
69
|
pairingService,
|
|
53
70
|
deviceSelector,
|
|
@@ -124,3 +141,7 @@ async function main() {
|
|
|
124
141
|
}
|
|
125
142
|
|
|
126
143
|
await main();
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @typedef {import('appium-ios-remotexpc').AppleTVDevice} AppleTVDevice
|
|
147
|
+
*/
|
|
@@ -39,6 +39,7 @@ const APPLETV_TUNNEL_DISCOVERY_PROGRESS_BAR_WIDTH = 24;
|
|
|
39
39
|
/** @type {import('appium-ios-remotexpc').TunnelRegistryServer | null} */
|
|
40
40
|
let registryServer = null;
|
|
41
41
|
|
|
42
|
+
/** @type {(() => void)[]} */
|
|
42
43
|
const registryWatcherStops = [];
|
|
43
44
|
/** @type {Map<string, Promise<void>>} */
|
|
44
45
|
const reconnectingByUdid = new Map();
|
|
@@ -48,6 +49,10 @@ const establishedTunnelsByUdid = new Map();
|
|
|
48
49
|
/** @type {Map<string, () => void>} */
|
|
49
50
|
const lifecycleWatchStopByUdid = new Map();
|
|
50
51
|
|
|
52
|
+
/**
|
|
53
|
+
* @param {import('appium-ios-tuntap').TunnelConnection} tunnelConnection
|
|
54
|
+
* @returns {Promise<void>}
|
|
55
|
+
*/
|
|
51
56
|
async function closeTunnelQuietly(tunnelConnection) {
|
|
52
57
|
try {
|
|
53
58
|
await tunnelConnection.closer();
|
|
@@ -56,6 +61,10 @@ async function closeTunnelQuietly(tunnelConnection) {
|
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
63
|
|
|
64
|
+
/**
|
|
65
|
+
* @param {string} udid
|
|
66
|
+
* @returns {void}
|
|
67
|
+
*/
|
|
59
68
|
function stopLifecycleWatch(udid) {
|
|
60
69
|
const stop = lifecycleWatchStopByUdid.get(udid);
|
|
61
70
|
if (stop) {
|
|
@@ -68,7 +77,7 @@ function stopLifecycleWatch(udid) {
|
|
|
68
77
|
*
|
|
69
78
|
* @param {import('appium-ios-remotexpc').AppleTVTunnelService} tunnelService
|
|
70
79
|
* @param {number} timeoutMs
|
|
71
|
-
* @returns {
|
|
80
|
+
* @returns {{ startedAt: number, promise: Promise<AppleTVDevice[]> }}
|
|
72
81
|
*/
|
|
73
82
|
function startDevicesDiscovery(tunnelService, timeoutMs) {
|
|
74
83
|
const startedAt = performance.now();
|
|
@@ -78,7 +87,7 @@ function startDevicesDiscovery(tunnelService, timeoutMs) {
|
|
|
78
87
|
|
|
79
88
|
/**
|
|
80
89
|
*
|
|
81
|
-
* @param {Promise<AppleTVDevice[]>} discovery
|
|
90
|
+
* @param {{ startedAt: number, promise: Promise<AppleTVDevice[]> }} discovery
|
|
82
91
|
* @param {number} timeoutMs
|
|
83
92
|
* @returns {Promise<AppleTVDevice[]>}
|
|
84
93
|
*/
|
|
@@ -109,9 +118,13 @@ async function waitForDevicesDiscovery(discovery, timeoutMs) {
|
|
|
109
118
|
* @returns {boolean}
|
|
110
119
|
*/
|
|
111
120
|
function isNoDevicesFoundError(err) {
|
|
112
|
-
return err instanceof Error && ('code' in err && err.code === 'NO_DEVICES') || err.message?.includes('No devices found');
|
|
121
|
+
return err instanceof Error && ('code' in err && err.code === 'NO_DEVICES') || /** @type {Error} */ (err).message?.includes('No devices found');
|
|
113
122
|
}
|
|
114
123
|
|
|
124
|
+
/**
|
|
125
|
+
* @param {AppleTvEstablishedTunnel} result
|
|
126
|
+
* @returns {void}
|
|
127
|
+
*/
|
|
115
128
|
function registerEstablishedTunnel(result) {
|
|
116
129
|
const udid = result.device.identifier;
|
|
117
130
|
stopLifecycleWatch(udid);
|
|
@@ -125,11 +138,15 @@ function registerEstablishedTunnel(result) {
|
|
|
125
138
|
}
|
|
126
139
|
establishedTunnelsByUdid.set(udid, result);
|
|
127
140
|
}
|
|
141
|
+
|
|
142
|
+
/** @type {import('appium-ios-remotexpc').AppleTVTunnelService | null} */
|
|
128
143
|
let tunnelService = null;
|
|
129
144
|
|
|
130
145
|
/**
|
|
131
|
-
* @param {
|
|
146
|
+
* @param {import('appium-ios-remotexpc').TunnelRegistry} registry
|
|
132
147
|
* @param {AppleTvEstablishedTunnel[]} successfulResults
|
|
148
|
+
* @param {object} callbacks
|
|
149
|
+
* @param {function({ udid: string, address: string }): Promise<void>} [callbacks.onTunnelDead]
|
|
133
150
|
*/
|
|
134
151
|
function attachAppleTvTunnelRegistryLifecycleWatch(registry, successfulResults, callbacks = {}) {
|
|
135
152
|
for (const result of successfulResults) {
|
|
@@ -163,7 +180,14 @@ function attachAppleTvTunnelRegistryLifecycleWatch(registry, successfulResults,
|
|
|
163
180
|
);
|
|
164
181
|
}
|
|
165
182
|
|
|
183
|
+
/**
|
|
184
|
+
* @returns {void}
|
|
185
|
+
*/
|
|
166
186
|
function setupCleanupHandlers() {
|
|
187
|
+
/**
|
|
188
|
+
* @param {string} signal
|
|
189
|
+
* @returns {Promise<void>}
|
|
190
|
+
*/
|
|
167
191
|
const cleanup = async (signal) => {
|
|
168
192
|
log.warn(`\nCleaning up (${signal})...`);
|
|
169
193
|
|
|
@@ -230,6 +254,7 @@ function setupCleanupHandlers() {
|
|
|
230
254
|
*/
|
|
231
255
|
async function establishOneTunnel(startResult) {
|
|
232
256
|
const { tcpSocket, psk, device } = startResult;
|
|
257
|
+
/** @type {{ notify: ((reason: string) => void) | null }} */
|
|
233
258
|
const lifecycle = { notify: null };
|
|
234
259
|
|
|
235
260
|
const tunnelConnection = await TunnelManager.getTunnelPsk(
|
|
@@ -247,6 +272,10 @@ async function establishOneTunnel(startResult) {
|
|
|
247
272
|
RsdPort: tunnelConnection.RsdPort,
|
|
248
273
|
},
|
|
249
274
|
tunnelConnection,
|
|
275
|
+
/**
|
|
276
|
+
* @param {(reason: string) => void} handler
|
|
277
|
+
* @returns {void}
|
|
278
|
+
*/
|
|
250
279
|
registerOnDead: (handler) => {
|
|
251
280
|
lifecycle.notify = handler;
|
|
252
281
|
},
|
|
@@ -256,6 +285,12 @@ async function establishOneTunnel(startResult) {
|
|
|
256
285
|
return result;
|
|
257
286
|
}
|
|
258
287
|
|
|
288
|
+
/**
|
|
289
|
+
* @param {AppleTvEstablishedTunnel} result
|
|
290
|
+
* @param {import('appium-ios-remotexpc').TunnelRegistryEntry | undefined} existing
|
|
291
|
+
* @param {number} now
|
|
292
|
+
* @returns {import('appium-ios-remotexpc').TunnelRegistryEntry}
|
|
293
|
+
*/
|
|
259
294
|
function buildAppleTvTunnelEntry(result, existing, now) {
|
|
260
295
|
const udid = result.device.identifier;
|
|
261
296
|
const entry = {
|
|
@@ -272,6 +307,11 @@ function buildAppleTvTunnelEntry(result, existing, now) {
|
|
|
272
307
|
return entry;
|
|
273
308
|
}
|
|
274
309
|
|
|
310
|
+
/**
|
|
311
|
+
*
|
|
312
|
+
* @param {AppleTvEstablishedTunnel} result
|
|
313
|
+
* @returns {Promise<boolean>}
|
|
314
|
+
*/
|
|
275
315
|
async function publishDiscoveredTunnelEntry(result) {
|
|
276
316
|
return await publishTunnelRegistryEntry({
|
|
277
317
|
registryServer,
|
|
@@ -282,6 +322,16 @@ async function publishDiscoveredTunnelEntry(result) {
|
|
|
282
322
|
});
|
|
283
323
|
}
|
|
284
324
|
|
|
325
|
+
/**
|
|
326
|
+
*
|
|
327
|
+
* @param {object} opts
|
|
328
|
+
* @param {string} opts.udid
|
|
329
|
+
* @param {number} opts.maxRetries
|
|
330
|
+
* @param {import('appium-ios-remotexpc').AppleTVTunnelService} opts.tunnelService
|
|
331
|
+
* @param {function(string): Promise<void>} opts.reconnectTunnelByUdid
|
|
332
|
+
* @param {number} opts.discoveryTimeoutMs
|
|
333
|
+
* @returns {Promise<void>}
|
|
334
|
+
*/
|
|
285
335
|
async function runAppleTvReconnectAttempts({
|
|
286
336
|
udid,
|
|
287
337
|
maxRetries,
|
|
@@ -327,6 +377,14 @@ async function runAppleTvReconnectAttempts({
|
|
|
327
377
|
log.error(`Reconnect retries exhausted for ${udid}`);
|
|
328
378
|
}
|
|
329
379
|
|
|
380
|
+
/**
|
|
381
|
+
*
|
|
382
|
+
* @param {object} opts
|
|
383
|
+
* @param {number} opts.reconnectRetries
|
|
384
|
+
* @param {import('appium-ios-remotexpc').AppleTVTunnelService} opts.tunnelService
|
|
385
|
+
* @param {number} opts.discoveryTimeoutMs
|
|
386
|
+
* @returns {function(string): Promise<void>}
|
|
387
|
+
*/
|
|
330
388
|
function createAppleTvReconnectTunnelByUdid({
|
|
331
389
|
reconnectRetries,
|
|
332
390
|
tunnelService,
|
|
@@ -565,3 +623,7 @@ await main();
|
|
|
565
623
|
* @property {import('appium-ios-tuntap').TunnelConnection} tunnelConnection
|
|
566
624
|
* @property {(handler: (reason: string) => void) => void} registerOnDead
|
|
567
625
|
*/
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* @typedef {import('appium-ios-remotexpc').AppleTVDevice} AppleTVDevice
|
|
629
|
+
*/
|
|
@@ -40,6 +40,10 @@ const establishedTunnelsByUdid = new Map();
|
|
|
40
40
|
/** @type {Map<string, () => void>} */
|
|
41
41
|
const lifecycleWatchStopByUdid = new Map();
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* @param {import('appium-ios-tuntap').TunnelConnection} tunnelConnection
|
|
45
|
+
* @returns {Promise<void>}
|
|
46
|
+
*/
|
|
43
47
|
async function closeTunnelQuietly(tunnelConnection) {
|
|
44
48
|
try {
|
|
45
49
|
await tunnelConnection.closer();
|
|
@@ -48,6 +52,10 @@ async function closeTunnelQuietly(tunnelConnection) {
|
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
54
|
|
|
55
|
+
/**
|
|
56
|
+
* @param {string} udid
|
|
57
|
+
* @returns {void}
|
|
58
|
+
*/
|
|
51
59
|
function stopLifecycleWatch(udid) {
|
|
52
60
|
const stop = lifecycleWatchStopByUdid.get(udid);
|
|
53
61
|
if (stop) {
|
|
@@ -56,6 +64,10 @@ function stopLifecycleWatch(udid) {
|
|
|
56
64
|
}
|
|
57
65
|
}
|
|
58
66
|
|
|
67
|
+
/**
|
|
68
|
+
* @param {TunnelCreationSuccessResult} result
|
|
69
|
+
* @returns {void}
|
|
70
|
+
*/
|
|
59
71
|
function registerEstablishedTunnel(result) {
|
|
60
72
|
const udid = result.device.Properties.SerialNumber;
|
|
61
73
|
stopLifecycleWatch(udid);
|
|
@@ -70,6 +82,11 @@ function registerEstablishedTunnel(result) {
|
|
|
70
82
|
establishedTunnelsByUdid.set(udid, result);
|
|
71
83
|
}
|
|
72
84
|
|
|
85
|
+
/**
|
|
86
|
+
*
|
|
87
|
+
* @param {string} connectionType
|
|
88
|
+
* @returns {number}
|
|
89
|
+
*/
|
|
73
90
|
function connectionTypeRank(connectionType) {
|
|
74
91
|
if (connectionType === 'USB') {
|
|
75
92
|
return 0;
|
|
@@ -104,15 +121,25 @@ function dedupeDevicesByUdid(devices) {
|
|
|
104
121
|
return [...byUdid.values()];
|
|
105
122
|
}
|
|
106
123
|
|
|
124
|
+
/**
|
|
125
|
+
*
|
|
126
|
+
* @param {TunnelCreationSuccessResult} result
|
|
127
|
+
* @param {import('appium-ios-remotexpc').TunnelRegistryEntry | undefined} existing
|
|
128
|
+
* @param {number} now
|
|
129
|
+
* @returns {import('appium-ios-remotexpc').TunnelRegistryEntry}
|
|
130
|
+
*/
|
|
107
131
|
function buildTunnelEntry(result, existing, now) {
|
|
108
132
|
const udid = result.device.Properties.SerialNumber;
|
|
133
|
+
/** @type {import('appium-ios-remotexpc').TunnelRegistryEntry} */
|
|
109
134
|
const entry = {
|
|
110
135
|
udid,
|
|
111
136
|
deviceId: result.device.DeviceID,
|
|
112
137
|
address: result.tunnel.Address,
|
|
113
138
|
rsdPort: result.tunnel.RsdPort,
|
|
114
139
|
services: {},
|
|
140
|
+
// @ts-expect-error - connectionType is not typed
|
|
115
141
|
connectionType: result.device.Properties.ConnectionType,
|
|
142
|
+
// @ts-expect-error - productId is not typed
|
|
116
143
|
productId: result.device.Properties.ProductID,
|
|
117
144
|
createdAt: existing?.createdAt ?? now,
|
|
118
145
|
lastUpdated: now,
|
|
@@ -120,6 +147,10 @@ function buildTunnelEntry(result, existing, now) {
|
|
|
120
147
|
return entry;
|
|
121
148
|
}
|
|
122
149
|
|
|
150
|
+
/**
|
|
151
|
+
* @param {TunnelCreationSuccessResult} result
|
|
152
|
+
* @returns {Promise<boolean>}
|
|
153
|
+
*/
|
|
123
154
|
async function publishDiscoveredTunnelEntry(result) {
|
|
124
155
|
return await publishTunnelRegistryEntry({
|
|
125
156
|
registryServer,
|
|
@@ -130,6 +161,7 @@ async function publishDiscoveredTunnelEntry(result) {
|
|
|
130
161
|
});
|
|
131
162
|
}
|
|
132
163
|
|
|
164
|
+
/** @type {(() => void)[]} */
|
|
133
165
|
const registryWatcherStops = [];
|
|
134
166
|
/** @type {Map<string, Promise<void>>} */
|
|
135
167
|
const reconnectingByUdid = new Map();
|
|
@@ -137,8 +169,11 @@ const reconnectingByUdid = new Map();
|
|
|
137
169
|
/**
|
|
138
170
|
* When the native forwarder exits, drop the UDID from the HTTP registry and tear down state.
|
|
139
171
|
*
|
|
140
|
-
* @param {
|
|
172
|
+
* @param {import('appium-ios-remotexpc').TunnelRegistry} registry
|
|
141
173
|
* @param {TunnelCreationSuccessResult[]} successful
|
|
174
|
+
* @param {object} callbacks
|
|
175
|
+
* @param {function({ udid: string, address: string }): Promise<void>} [callbacks.onTunnelDead]
|
|
176
|
+
* @returns {void}
|
|
142
177
|
*/
|
|
143
178
|
function attachTunnelRegistryLifecycleWatch(registry, successful, callbacks = {}) {
|
|
144
179
|
for (const result of successful) {
|
|
@@ -172,6 +207,15 @@ function attachTunnelRegistryLifecycleWatch(registry, successful, callbacks = {}
|
|
|
172
207
|
);
|
|
173
208
|
}
|
|
174
209
|
|
|
210
|
+
/**
|
|
211
|
+
*
|
|
212
|
+
* @param {object} opts
|
|
213
|
+
* @param {string} opts.udid
|
|
214
|
+
* @param {number} opts.maxRetries
|
|
215
|
+
* @param {import('appium-ios-remotexpc').UsbmuxDevice} opts.device
|
|
216
|
+
* @param {function(string): Promise<void>} opts.reconnectTunnelByUdid
|
|
217
|
+
* @returns {Promise<void>}
|
|
218
|
+
*/
|
|
175
219
|
async function runReconnectAttempts({
|
|
176
220
|
udid,
|
|
177
221
|
maxRetries,
|
|
@@ -193,6 +237,7 @@ async function runReconnectAttempts({
|
|
|
193
237
|
registryServer.getRegistry(),
|
|
194
238
|
[result],
|
|
195
239
|
{
|
|
240
|
+
|
|
196
241
|
onTunnelDead: async ({ udid: droppedUdid }) => {
|
|
197
242
|
await reconnectTunnelByUdid(droppedUdid);
|
|
198
243
|
},
|
|
@@ -211,6 +256,12 @@ async function runReconnectAttempts({
|
|
|
211
256
|
log.error(`Reconnect retries exhausted for ${udid}`);
|
|
212
257
|
}
|
|
213
258
|
|
|
259
|
+
/**
|
|
260
|
+
* @param {object} opts
|
|
261
|
+
* @param {number} opts.reconnectRetries
|
|
262
|
+
* @param {Map<string, import('appium-ios-remotexpc').UsbmuxDevice>} opts.devicesByUdid
|
|
263
|
+
* @returns {function(string): Promise<void>}
|
|
264
|
+
*/
|
|
214
265
|
function createReconnectTunnelByUdid({
|
|
215
266
|
reconnectRetries,
|
|
216
267
|
devicesByUdid,
|
|
@@ -245,7 +296,14 @@ function createReconnectTunnelByUdid({
|
|
|
245
296
|
};
|
|
246
297
|
}
|
|
247
298
|
|
|
299
|
+
/**
|
|
300
|
+
* @returns {void}
|
|
301
|
+
*/
|
|
248
302
|
function setupCleanupHandlers() {
|
|
303
|
+
/**
|
|
304
|
+
* @param {string} signal
|
|
305
|
+
* @returns {Promise<void>}
|
|
306
|
+
*/
|
|
249
307
|
const cleanup = async (signal) => {
|
|
250
308
|
log.warn(`\nCleaning up (${signal})...`);
|
|
251
309
|
|
|
@@ -298,6 +356,10 @@ function setupCleanupHandlers() {
|
|
|
298
356
|
});
|
|
299
357
|
}
|
|
300
358
|
|
|
359
|
+
/**
|
|
360
|
+
* @param {import('appium-ios-remotexpc').UsbmuxDevice} device
|
|
361
|
+
* @returns {Promise<TunnelCreationSuccessResult>}
|
|
362
|
+
*/
|
|
301
363
|
async function createTunnelForDevice(device) {
|
|
302
364
|
const udid = device.Properties.SerialNumber;
|
|
303
365
|
|
|
@@ -323,6 +385,7 @@ async function createTunnelForDevice(device) {
|
|
|
323
385
|
log.info('CoreDeviceProxy started successfully');
|
|
324
386
|
|
|
325
387
|
log.info(`Creating tunnel...`);
|
|
388
|
+
/** @type {{ notify: ((reason: string) => void) | null }} */
|
|
326
389
|
const lifecycle = { notify: null };
|
|
327
390
|
const tunnelConnection = await TunnelManager.getTunnel(
|
|
328
391
|
socket,
|
|
@@ -339,7 +402,9 @@ async function createTunnelForDevice(device) {
|
|
|
339
402
|
log.info(` Tunnel Address: ${tunnelConnection.Address}`);
|
|
340
403
|
log.info(` Tunnel RsdPort: ${tunnelConnection.RsdPort}`);
|
|
341
404
|
|
|
405
|
+
/** @type {TunnelCreationSuccessResult} */
|
|
342
406
|
const result = {
|
|
407
|
+
// @ts-expect-error - device is not typed
|
|
343
408
|
device,
|
|
344
409
|
tunnel: {
|
|
345
410
|
Address: tunnelConnection.Address,
|
|
@@ -347,6 +412,10 @@ async function createTunnelForDevice(device) {
|
|
|
347
412
|
},
|
|
348
413
|
success: true,
|
|
349
414
|
tunnelConnection,
|
|
415
|
+
/**
|
|
416
|
+
* @param {(reason: string) => void} handler
|
|
417
|
+
* @returns {void}
|
|
418
|
+
*/
|
|
350
419
|
registerOnDead: (handler) => {
|
|
351
420
|
lifecycle.notify = handler;
|
|
352
421
|
},
|
|
@@ -358,6 +427,7 @@ async function createTunnelForDevice(device) {
|
|
|
358
427
|
const errorMessage = `Failed to create tunnel for device ${udid}: ${error}`;
|
|
359
428
|
log.error(`❌ ${errorMessage}`);
|
|
360
429
|
return {
|
|
430
|
+
// @ts-expect-error - device is not typed
|
|
361
431
|
device,
|
|
362
432
|
tunnel: { Address: '', RsdPort: 0 },
|
|
363
433
|
success: false,
|
|
@@ -366,6 +436,9 @@ async function createTunnelForDevice(device) {
|
|
|
366
436
|
}
|
|
367
437
|
}
|
|
368
438
|
|
|
439
|
+
/**
|
|
440
|
+
* @returns {Promise<void>}
|
|
441
|
+
*/
|
|
369
442
|
async function main() {
|
|
370
443
|
setupCleanupHandlers();
|
|
371
444
|
|
|
@@ -492,6 +565,10 @@ async function main() {
|
|
|
492
565
|
registryServer.getRegistry(),
|
|
493
566
|
[result],
|
|
494
567
|
{
|
|
568
|
+
/**
|
|
569
|
+
* @param {{ udid: string }} ctx
|
|
570
|
+
* @returns {Promise<void>}
|
|
571
|
+
*/
|
|
495
572
|
onTunnelDead: async ({ udid }) => {
|
|
496
573
|
await reconnectTunnelByUdid(udid);
|
|
497
574
|
},
|
|
@@ -554,8 +631,9 @@ await main();
|
|
|
554
631
|
* Successful tunnel row (USB lockdown + CoreDeviceProxy) used for the registry and lifecycle watch.
|
|
555
632
|
*
|
|
556
633
|
* @typedef {object} TunnelCreationSuccessResult
|
|
557
|
-
* @property {{ Properties: { SerialNumber: string }, DeviceID: number }} device
|
|
634
|
+
* @property {{ Properties: { SerialNumber: string, [key: string]: unknown }, DeviceID: number }} device
|
|
558
635
|
* @property {{ Address: string, RsdPort?: number }} tunnel
|
|
559
636
|
* @property {import('appium-ios-tuntap').TunnelConnection} tunnelConnection
|
|
560
637
|
* @property {(handler: (reason: string) => void) => void} registerOnDead
|
|
638
|
+
* @property {boolean} success
|
|
561
639
|
*/
|