lim 0.30.2 → 0.31.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.
Files changed (127) hide show
  1. package/dist/base-command.d.ts +3 -0
  2. package/dist/base-command.d.ts.map +1 -1
  3. package/dist/base-command.js +10 -0
  4. package/dist/base-command.js.map +1 -1
  5. package/dist/commands/android/app-logs.d.ts +17 -0
  6. package/dist/commands/android/app-logs.d.ts.map +1 -0
  7. package/dist/commands/android/app-logs.js +35 -0
  8. package/dist/commands/android/app-logs.js.map +1 -0
  9. package/dist/commands/android/create.d.ts +4 -0
  10. package/dist/commands/android/create.d.ts.map +1 -1
  11. package/dist/commands/android/create.js +45 -0
  12. package/dist/commands/android/create.js.map +1 -1
  13. package/dist/commands/android/events.d.ts +17 -0
  14. package/dist/commands/android/events.d.ts.map +1 -0
  15. package/dist/commands/android/events.js +35 -0
  16. package/dist/commands/android/events.js.map +1 -0
  17. package/dist/commands/android/record.d.ts +2 -0
  18. package/dist/commands/android/record.d.ts.map +1 -1
  19. package/dist/commands/android/record.js +27 -3
  20. package/dist/commands/android/record.js.map +1 -1
  21. package/dist/commands/android/recordings.d.ts +17 -0
  22. package/dist/commands/android/recordings.d.ts.map +1 -0
  23. package/dist/commands/android/recordings.js +35 -0
  24. package/dist/commands/android/recordings.js.map +1 -0
  25. package/dist/commands/android/tunnel/index.d.ts +29 -0
  26. package/dist/commands/android/tunnel/index.d.ts.map +1 -0
  27. package/dist/commands/android/tunnel/index.js +170 -0
  28. package/dist/commands/android/tunnel/index.js.map +1 -0
  29. package/dist/commands/android/tunnel/index.test.d.ts +2 -0
  30. package/dist/commands/android/tunnel/index.test.d.ts.map +1 -0
  31. package/dist/commands/android/tunnel/index.test.js +66 -0
  32. package/dist/commands/android/tunnel/index.test.js.map +1 -0
  33. package/dist/commands/android/tunnel/status.d.ts +17 -0
  34. package/dist/commands/android/tunnel/status.d.ts.map +1 -0
  35. package/dist/commands/android/tunnel/status.js +61 -0
  36. package/dist/commands/android/tunnel/status.js.map +1 -0
  37. package/dist/commands/android/tunnel/stop.d.ts +17 -0
  38. package/dist/commands/android/tunnel/stop.d.ts.map +1 -0
  39. package/dist/commands/android/tunnel/stop.js +50 -0
  40. package/dist/commands/android/tunnel/stop.js.map +1 -0
  41. package/dist/commands/ios/app-logs.d.ts +17 -0
  42. package/dist/commands/ios/app-logs.d.ts.map +1 -0
  43. package/dist/commands/ios/app-logs.js +35 -0
  44. package/dist/commands/ios/app-logs.js.map +1 -0
  45. package/dist/commands/ios/create.d.ts +4 -0
  46. package/dist/commands/ios/create.d.ts.map +1 -1
  47. package/dist/commands/ios/create.js +45 -0
  48. package/dist/commands/ios/create.js.map +1 -1
  49. package/dist/commands/ios/events.d.ts +17 -0
  50. package/dist/commands/ios/events.d.ts.map +1 -0
  51. package/dist/commands/ios/events.js +35 -0
  52. package/dist/commands/ios/events.js.map +1 -0
  53. package/dist/commands/ios/launch-app.js +1 -1
  54. package/dist/commands/ios/launch-app.js.map +1 -1
  55. package/dist/commands/ios/record.d.ts +2 -0
  56. package/dist/commands/ios/record.d.ts.map +1 -1
  57. package/dist/commands/ios/record.js +27 -3
  58. package/dist/commands/ios/record.js.map +1 -1
  59. package/dist/commands/ios/recordings.d.ts +17 -0
  60. package/dist/commands/ios/recordings.d.ts.map +1 -0
  61. package/dist/commands/ios/recordings.js +35 -0
  62. package/dist/commands/ios/recordings.js.map +1 -0
  63. package/dist/commands/ios/tunnel/index.d.ts +3 -9
  64. package/dist/commands/ios/tunnel/index.d.ts.map +1 -1
  65. package/dist/commands/ios/tunnel/index.js +33 -239
  66. package/dist/commands/ios/tunnel/index.js.map +1 -1
  67. package/dist/commands/ios/tunnel/status.d.ts.map +1 -1
  68. package/dist/commands/ios/tunnel/status.js +17 -41
  69. package/dist/commands/ios/tunnel/status.js.map +1 -1
  70. package/dist/commands/ios/tunnel/stop.d.ts +0 -4
  71. package/dist/commands/ios/tunnel/stop.d.ts.map +1 -1
  72. package/dist/commands/ios/tunnel/stop.js +13 -111
  73. package/dist/commands/ios/tunnel/stop.js.map +1 -1
  74. package/dist/commands/xcode/build.d.ts +1 -0
  75. package/dist/commands/xcode/build.d.ts.map +1 -1
  76. package/dist/commands/xcode/build.js +16 -0
  77. package/dist/commands/xcode/build.js.map +1 -1
  78. package/dist/lib/duration.d.ts +5 -0
  79. package/dist/lib/duration.d.ts.map +1 -1
  80. package/dist/lib/duration.js +21 -0
  81. package/dist/lib/duration.js.map +1 -1
  82. package/dist/lib/session-artifacts.d.ts +11 -0
  83. package/dist/lib/session-artifacts.d.ts.map +1 -0
  84. package/dist/lib/session-artifacts.js +30 -0
  85. package/dist/lib/session-artifacts.js.map +1 -0
  86. package/dist/lib/session-captures.d.ts +41 -0
  87. package/dist/lib/session-captures.d.ts.map +1 -0
  88. package/dist/lib/session-captures.js +55 -0
  89. package/dist/lib/session-captures.js.map +1 -0
  90. package/dist/lib/tunnel-command.d.ts +98 -0
  91. package/dist/lib/tunnel-command.d.ts.map +1 -0
  92. package/dist/lib/tunnel-command.js +542 -0
  93. package/dist/lib/tunnel-command.js.map +1 -0
  94. package/dist/lib/tunnel-command.test.d.ts +2 -0
  95. package/dist/lib/tunnel-command.test.d.ts.map +1 -0
  96. package/dist/lib/tunnel-command.test.js +91 -0
  97. package/dist/lib/tunnel-command.test.js.map +1 -0
  98. package/dist/lib/tunnel-har.d.ts +14 -0
  99. package/dist/lib/tunnel-har.d.ts.map +1 -0
  100. package/dist/lib/tunnel-har.js +150 -0
  101. package/dist/lib/tunnel-har.js.map +1 -0
  102. package/dist/lib/tunnel-har.test.d.ts +2 -0
  103. package/dist/lib/tunnel-har.test.d.ts.map +1 -0
  104. package/dist/lib/tunnel-har.test.js +164 -0
  105. package/dist/lib/tunnel-har.test.js.map +1 -0
  106. package/dist/lib/tunnel-process.d.ts +98 -0
  107. package/dist/lib/tunnel-process.d.ts.map +1 -0
  108. package/dist/lib/{ios-tunnel-process.js → tunnel-process.js} +87 -97
  109. package/dist/lib/tunnel-process.js.map +1 -0
  110. package/dist/lib/tunnel-process.test.d.ts +2 -0
  111. package/dist/lib/tunnel-process.test.d.ts.map +1 -0
  112. package/dist/lib/tunnel-process.test.js +428 -0
  113. package/dist/lib/tunnel-process.test.js.map +1 -0
  114. package/dist/lib/xcode-signing-options.d.ts +10 -0
  115. package/dist/lib/xcode-signing-options.d.ts.map +1 -1
  116. package/dist/lib/xcode-signing-options.js +42 -0
  117. package/dist/lib/xcode-signing-options.js.map +1 -1
  118. package/dist/lib/xcode-signing-options.test.js +32 -0
  119. package/dist/lib/xcode-signing-options.test.js.map +1 -1
  120. package/package.json +2 -2
  121. package/dist/lib/ios-tunnel-process.d.ts +0 -70
  122. package/dist/lib/ios-tunnel-process.d.ts.map +0 -1
  123. package/dist/lib/ios-tunnel-process.js.map +0 -1
  124. package/dist/lib/ios-tunnel-process.test.d.ts +0 -2
  125. package/dist/lib/ios-tunnel-process.test.d.ts.map +0 -1
  126. package/dist/lib/ios-tunnel-process.test.js +0 -339
  127. package/dist/lib/ios-tunnel-process.test.js.map +0 -1
@@ -0,0 +1,542 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.tunnelClientFacade = tunnelClientFacade;
7
+ exports.runTunnelForeground = runTunnelForeground;
8
+ exports.serveTunnelDetached = serveTunnelDetached;
9
+ exports.startTunnelDetached = startTunnelDetached;
10
+ exports.runTunnelStatus = runTunnelStatus;
11
+ exports.runTunnelStop = runTunnelStop;
12
+ const child_process_1 = require("child_process");
13
+ const fs_1 = __importDefault(require("fs"));
14
+ const api_1 = require("@limrun/api");
15
+ const tunnel_process_1 = require("./tunnel-process");
16
+ const tunnel_har_1 = require("./tunnel-har");
17
+ /**
18
+ * Adapts an SDK instance client to the product-neutral facade. Both clients
19
+ * accept the selectors shape directly, so the adapter only threads the CLI's
20
+ * log level through.
21
+ */
22
+ function tunnelClientFacade(client, disconnect, logLevel) {
23
+ return {
24
+ startTunnel: (options) => client.startTunnel({
25
+ selectors: options.selectors,
26
+ logLevel,
27
+ inspection: options.inspection,
28
+ ...(options.onInspectionEvent ? { onInspectionEvent: options.onInspectionEvent } : {}),
29
+ ...(options.onInspectionError ? { onInspectionError: options.onInspectionError } : {}),
30
+ }),
31
+ getTunnelStatus: () => client.getTunnelStatus(),
32
+ stopTunnel: (tunnelId) => client.stopTunnel(tunnelId),
33
+ disconnect,
34
+ };
35
+ }
36
+ const RECONNECT_INITIAL_BACKOFF_MS = 500;
37
+ const RECONNECT_MAX_BACKOFF_MS = 30000;
38
+ function createInspectionSession(context) {
39
+ const maxBodyBytes = context.harBodyLimit ?? api_1.DESTINATION_TUNNEL_DEFAULT_MAX_BODY_BYTES;
40
+ const config = {
41
+ enabled: context.inspect,
42
+ captureBodies: context.inspect && (context.harPath !== undefined || context.persist === true),
43
+ maxBodyBytes,
44
+ persist: context.persist ?? false,
45
+ ttlSeconds: context.ttlSeconds ?? api_1.DESTINATION_TUNNEL_DEFAULT_TTL_SECONDS,
46
+ };
47
+ if (!context.inspect) {
48
+ return { config, resetPending: () => { }, finalize: async () => { }, close: () => { } };
49
+ }
50
+ let recorder = context.harPath ? (0, tunnel_har_1.createTunnelHarRecorder)(context.harPath, maxBodyBytes) : undefined;
51
+ const reportError = (error) => {
52
+ context.io.info(`Inspection stream warning: ${error.message}`);
53
+ try {
54
+ context.onInspectionError?.(error);
55
+ }
56
+ catch {
57
+ // User callbacks cannot affect tunnel ownership or reconnect behavior.
58
+ }
59
+ };
60
+ const invoke = (callback) => {
61
+ try {
62
+ callback?.();
63
+ }
64
+ catch (error) {
65
+ reportError(error instanceof Error ? error : new Error(String(error)));
66
+ }
67
+ };
68
+ const onEvent = (event) => {
69
+ invoke(() => recorder?.onEvent(event));
70
+ if (event.type === 'gap') {
71
+ context.io.info(event.data.message);
72
+ }
73
+ else if (event.type === 'complete') {
74
+ context.io.info((0, tunnel_har_1.formatInspectionSummary)(event.data));
75
+ }
76
+ invoke(() => context.onInspectionEvent?.(event));
77
+ };
78
+ return {
79
+ config,
80
+ onEvent,
81
+ onError: reportError,
82
+ resetPending: () => recorder?.resetPending(),
83
+ finalize: async () => {
84
+ const current = recorder;
85
+ recorder = undefined;
86
+ await current?.finalize();
87
+ },
88
+ close: () => {
89
+ recorder?.close();
90
+ recorder = undefined;
91
+ },
92
+ };
93
+ }
94
+ /**
95
+ * The shared start -> await-end -> backoff cycle behind both the foreground
96
+ * and detached serve flows. `beforeStart` may veto a (re)start (e.g. the
97
+ * detached owner was cancelled); a throw from `onReady` tears the fresh
98
+ * tunnel down before propagating so no unowned server-side session is left.
99
+ */
100
+ async function runTunnelLoop(context, client, inspection, hooks) {
101
+ const sleep = context.sleep ?? api_1.defaultSleep;
102
+ let tunnel;
103
+ let reconnected = false;
104
+ try {
105
+ let backoffMs = RECONNECT_INITIAL_BACKOFF_MS;
106
+ for (;;) {
107
+ if (hooks.beforeStart && !hooks.beforeStart())
108
+ return 'cancelled';
109
+ tunnel = await client.startTunnel({
110
+ selectors: context.selectors,
111
+ inspection: inspection.config,
112
+ ...(inspection.onEvent ? { onInspectionEvent: inspection.onEvent } : {}),
113
+ ...(inspection.onError ? { onInspectionError: inspection.onError } : {}),
114
+ });
115
+ backoffMs = RECONNECT_INITIAL_BACKOFF_MS;
116
+ hooks.onReady(tunnel, reconnected);
117
+ reconnected = true;
118
+ const outcome = await awaitTunnelEnd(tunnel);
119
+ tunnel.close();
120
+ tunnel = undefined;
121
+ inspection.resetPending();
122
+ if (outcome === 'shutdown')
123
+ return 'shutdown';
124
+ if (!context.reconnect)
125
+ return 'disconnected';
126
+ context.io.info(`Tunnel disconnected; reconnecting in ${backoffMs}ms...`);
127
+ await sleep(jittered(backoffMs));
128
+ backoffMs = Math.min(backoffMs * 2, RECONNECT_MAX_BACKOFF_MS);
129
+ }
130
+ }
131
+ finally {
132
+ tunnel?.close();
133
+ }
134
+ }
135
+ async function runTunnelForeground(context) {
136
+ const client = await context.connect();
137
+ let inspection;
138
+ try {
139
+ inspection = createInspectionSession(context);
140
+ const end = await runTunnelLoop(context, client, inspection, {
141
+ onReady: (tunnel, reconnected) => {
142
+ if (reconnected) {
143
+ context.io.info(`Tunnel reconnected with new ID ${tunnel.tunnelId}.`);
144
+ }
145
+ else {
146
+ printTunnelReady(context, tunnel.tunnelId, false);
147
+ }
148
+ },
149
+ });
150
+ if (end === 'disconnected') {
151
+ throw new Error('Destination tunnel disconnected unexpectedly');
152
+ }
153
+ await inspection.finalize();
154
+ }
155
+ finally {
156
+ inspection?.close();
157
+ client.disconnect();
158
+ }
159
+ }
160
+ async function serveTunnelDetached(context, owner) {
161
+ const sleep = context.sleep ?? api_1.defaultSleep;
162
+ const ownershipDeadline = Date.now() + 2000;
163
+ let starting = (0, tunnel_process_1.loadTunnelProcess)(context.instanceId, owner);
164
+ while (starting?.pid !== process.pid && Date.now() < ownershipDeadline) {
165
+ await sleep(25);
166
+ starting = (0, tunnel_process_1.loadTunnelProcess)(context.instanceId, owner);
167
+ }
168
+ if (!starting || starting.pid !== process.pid) {
169
+ context.io.error('Detached tunnel ownership handshake failed.');
170
+ }
171
+ const client = await context.connect();
172
+ let inspection;
173
+ let capLogs;
174
+ try {
175
+ inspection = createInspectionSession(context);
176
+ capLogs = setInterval(() => (0, tunnel_process_1.capTunnelLog)(starting.logPath), 30000);
177
+ await runTunnelLoop(context, client, inspection, {
178
+ // A stop may have cancelled this owner while it was starting or in
179
+ // backoff; never (re)create the tunnel for a cancelled owner.
180
+ beforeStart: () => !(0, tunnel_process_1.isTunnelProcessCancelled)(context.instanceId, owner) &&
181
+ (0, tunnel_process_1.loadTunnelProcess)(context.instanceId, owner) !== undefined,
182
+ // A throw here (ownership cancelled between connect and ready) makes
183
+ // the loop close the fresh tunnel before propagating.
184
+ onReady: (tunnel) => {
185
+ (0, tunnel_process_1.updateTunnelProcess)({ ...starting, status: 'ready', tunnelId: tunnel.tunnelId }, owner);
186
+ },
187
+ });
188
+ await inspection.finalize();
189
+ }
190
+ finally {
191
+ if (capLogs)
192
+ clearInterval(capLogs);
193
+ (0, tunnel_process_1.capTunnelLog)(starting.logPath);
194
+ inspection?.close();
195
+ client.disconnect();
196
+ (0, tunnel_process_1.clearTunnelProcess)(context.instanceId, owner);
197
+ }
198
+ }
199
+ async function startTunnelDetached(context) {
200
+ await assertNoActiveTunnel(context);
201
+ clearDeadOwners(context);
202
+ const liveOwner = (0, tunnel_process_1.listTunnelProcesses)(context.instanceId).find((state) => {
203
+ if (state.status === 'starting' && !(0, tunnel_process_1.tunnelProcessStartingLeaseExpired)(state)) {
204
+ return true;
205
+ }
206
+ const identity = (0, tunnel_process_1.tunnelOwnerProcessIdentity)(state);
207
+ return identity === 'match' || identity === 'unknown';
208
+ });
209
+ if (liveOwner) {
210
+ context.io.error(`A local tunnel process is already ${liveOwner.status} for ${context.instanceId} (PID ${liveOwner.pid}). ` +
211
+ `Run \`lim ${context.product} tunnel status --id ${context.instanceId}\` or stop it first.`);
212
+ }
213
+ const owner = (0, tunnel_process_1.newTunnelOwner)();
214
+ const paths = (0, tunnel_process_1.tunnelProcessPaths)(context.instanceId, owner);
215
+ const starting = {
216
+ owner,
217
+ pid: 0,
218
+ instanceId: context.instanceId,
219
+ product: context.product,
220
+ status: 'starting',
221
+ selectors: context.selectors,
222
+ ...(context.product === 'android' ?
223
+ {
224
+ inspect: context.inspect,
225
+ ...(context.persist ? { persist: true } : {}),
226
+ ...(context.ttlSeconds ? { ttlSeconds: context.ttlSeconds } : {}),
227
+ ...(context.harPath ? { harPath: context.harPath } : {}),
228
+ ...(context.harBodyLimit ? { harBodyLimit: context.harBodyLimit } : {}),
229
+ }
230
+ : {}),
231
+ startedAt: new Date().toISOString(),
232
+ logPath: paths.log,
233
+ };
234
+ if (!(0, tunnel_process_1.claimTunnelProcess)(starting)) {
235
+ context.io.error('Failed to claim detached tunnel process state.');
236
+ }
237
+ const scriptPath = process.argv[1];
238
+ if (!scriptPath) {
239
+ (0, tunnel_process_1.clearTunnelProcess)(context.instanceId, owner);
240
+ context.io.error('Cannot locate the lim CLI entrypoint for detached startup.');
241
+ }
242
+ const logDescriptor = (0, tunnel_process_1.prepareTunnelLog)(paths.log);
243
+ let child;
244
+ try {
245
+ child = (0, child_process_1.spawn)(process.execPath, (0, tunnel_process_1.buildTunnelServeArgs)({
246
+ scriptPath,
247
+ product: context.product,
248
+ instanceId: context.instanceId,
249
+ owner,
250
+ selectors: context.selectors,
251
+ inspect: context.inspect,
252
+ ...(context.persist ? { persist: true } : {}),
253
+ ...(context.ttlSeconds ? { ttlSeconds: context.ttlSeconds } : {}),
254
+ ...(context.harPath ? { harPath: context.harPath } : {}),
255
+ ...(context.harBodyLimit ? { harBodyLimit: context.harBodyLimit } : {}),
256
+ ...(context.verbose ? { verbose: true } : {}),
257
+ }), {
258
+ detached: true,
259
+ windowsHide: true,
260
+ stdio: ['ignore', logDescriptor, logDescriptor],
261
+ env: (0, tunnel_process_1.tunnelChildEnvironment)(context.apiKey),
262
+ });
263
+ }
264
+ catch (error) {
265
+ fs_1.default.closeSync(logDescriptor);
266
+ (0, tunnel_process_1.clearTunnelProcess)(context.instanceId, owner);
267
+ throw error;
268
+ }
269
+ fs_1.default.closeSync(logDescriptor);
270
+ child.unref();
271
+ const pid = child.pid;
272
+ if (!pid) {
273
+ (0, tunnel_process_1.clearTunnelProcess)(context.instanceId, owner);
274
+ context.io.error('Failed to spawn the detached tunnel process.');
275
+ }
276
+ (0, tunnel_process_1.updateTunnelProcess)({ ...starting, pid }, owner);
277
+ const readiness = await (0, tunnel_process_1.waitForTunnelProcessReady)({
278
+ load: () => (0, tunnel_process_1.loadTunnelProcess)(context.instanceId, owner),
279
+ isAlive: () => (0, tunnel_process_1.isSpawnedTunnelProcessAlive)(child, pid),
280
+ sleep: context.sleep ?? api_1.defaultSleep,
281
+ });
282
+ if (readiness.outcome === 'ready') {
283
+ const state = readiness.state;
284
+ printTunnelReady(context, state.tunnelId, true, { pid, logPath: paths.log });
285
+ return;
286
+ }
287
+ if (readiness.outcome === 'exited') {
288
+ (0, tunnel_process_1.clearTunnelProcess)(context.instanceId, owner);
289
+ context.io.error(`Detached tunnel exited during startup.\n${(0, tunnel_process_1.readTunnelLogTail)(paths.log)}\nLogs: ${paths.log}`);
290
+ }
291
+ // Cancel before killing so the child cannot finish becoming ready (or
292
+ // reconnect) between our signal and its exit.
293
+ (0, tunnel_process_1.markTunnelProcessCancelled)(context.instanceId, owner);
294
+ child.kill('SIGTERM');
295
+ let exited = await waitForProcessExit(child, pid, 20, context.sleep ?? api_1.defaultSleep);
296
+ if (!exited) {
297
+ child.kill('SIGKILL');
298
+ exited = await waitForProcessExit(child, pid, 20, context.sleep ?? api_1.defaultSleep);
299
+ }
300
+ if (exited) {
301
+ (0, tunnel_process_1.clearTunnelProcess)(context.instanceId, owner);
302
+ }
303
+ const retainedOwnership = exited ? '' : ` and PID ${pid} did not exit; its ownership record was retained`;
304
+ context.io.error(`Detached tunnel did not become ready within 30s${retainedOwnership}.\n` +
305
+ `${(0, tunnel_process_1.readTunnelLogTail)(paths.log)}\nLogs: ${paths.log}`);
306
+ }
307
+ /**
308
+ * Shared status flow: owner listing, JSON assembly, and failure lines are
309
+ * identical across products; only how the active tunnel's targets are
310
+ * rendered differs (iOS shows routes, Android shows selectors and binds).
311
+ */
312
+ async function runTunnelStatus(context) {
313
+ const client = await context.connect();
314
+ try {
315
+ const status = await client.getTunnelStatus();
316
+ const owners = (0, tunnel_process_1.listTunnelProcesses)(context.instanceId).map((state) => ({
317
+ owner: state.owner,
318
+ pid: state.pid,
319
+ status: state.status,
320
+ tunnelId: state.tunnelId,
321
+ logPath: state.logPath,
322
+ process: (0, tunnel_process_1.tunnelOwnerProcessIdentity)(state),
323
+ }));
324
+ if (context.io.isJsonEnabled()) {
325
+ context.io.outputJson({
326
+ instanceId: context.instanceId,
327
+ ...status,
328
+ localOwners: owners,
329
+ });
330
+ return;
331
+ }
332
+ if (status.active) {
333
+ context.io.output(`Tunnel ${status.active.tunnelId}: ${status.active.state}`);
334
+ context.renderActive(status.active, context.io);
335
+ }
336
+ else {
337
+ context.io.output('No active destination tunnel.');
338
+ }
339
+ if (status.lastFailure) {
340
+ context.io.output(`Last failure: ${status.lastFailure.tunnelId} (${status.lastFailure.code})`);
341
+ }
342
+ if (status.lastDialFailure) {
343
+ context.io.output((0, tunnel_process_1.formatTunnelDialFailure)(status.lastDialFailure));
344
+ }
345
+ for (const owner of owners) {
346
+ context.io.output(`Local owner: PID ${owner.pid} (${owner.process}, ${owner.status})${owner.logPath ? `, logs: ${owner.logPath}` : ''}`);
347
+ }
348
+ }
349
+ finally {
350
+ client.disconnect();
351
+ }
352
+ }
353
+ async function runTunnelStop(context) {
354
+ const ownerSnapshot = (0, tunnel_process_1.listTunnelProcesses)(context.instanceId);
355
+ const remote = await stopRemoteTunnel(context);
356
+ const expectedTunnelId = remote.outcome === 'none' ? undefined : remote.tunnelId;
357
+ const owners = (0, tunnel_process_1.selectTunnelOwnersForStop)(ownerSnapshot, expectedTunnelId);
358
+ const local = await stopLocalOwners(context, owners, remote);
359
+ if (context.io.isJsonEnabled()) {
360
+ context.io.outputJson({
361
+ instanceId: context.instanceId,
362
+ ...(remote.outcome === 'none' ? {} : { tunnelId: remote.tunnelId }),
363
+ outcome: remote.outcome,
364
+ localProcessesStopped: local.processesStopped,
365
+ localRecordsCleaned: local.recordsCleaned,
366
+ });
367
+ }
368
+ else if (remote.outcome === 'stopped') {
369
+ context.io.output(`Stopped destination tunnel ${remote.tunnelId}.`);
370
+ }
371
+ else if (remote.outcome === 'gone') {
372
+ context.io.output(`Destination tunnel ${remote.tunnelId} was already gone.`);
373
+ }
374
+ else if (local.processesStopped > 0 || local.recordsCleaned > 0) {
375
+ context.io.output('Cleaned local destination tunnel ownership.');
376
+ }
377
+ else {
378
+ context.io.output('No active destination tunnel.');
379
+ }
380
+ }
381
+ async function stopRemoteTunnel(context) {
382
+ const client = await context.connect();
383
+ try {
384
+ const status = await client.getTunnelStatus();
385
+ if (!status.active)
386
+ return { outcome: 'none' };
387
+ const tunnelId = status.active.tunnelId;
388
+ try {
389
+ await client.stopTunnel(tunnelId);
390
+ }
391
+ catch (error) {
392
+ if ((0, tunnel_process_1.stopTunnelErrorIsNotFound)(error)) {
393
+ return { outcome: 'gone', tunnelId };
394
+ }
395
+ throw error;
396
+ }
397
+ return { outcome: 'stopped', tunnelId };
398
+ }
399
+ finally {
400
+ client.disconnect();
401
+ }
402
+ }
403
+ async function stopLocalOwners(context, owners, remote) {
404
+ const sleep = context.sleep ?? api_1.defaultSleep;
405
+ let processesStopped = 0;
406
+ let recordsCleaned = 0;
407
+ const retainedOwners = [];
408
+ for (const snapshot of owners) {
409
+ // Cancel every selected owner up front: a starting or reconnecting child
410
+ // observes the marker and can never recreate the tunnel from here on.
411
+ (0, tunnel_process_1.markTunnelProcessCancelled)(context.instanceId, snapshot.owner);
412
+ let state = (0, tunnel_process_1.loadTunnelProcess)(context.instanceId, snapshot.owner) ?? snapshot;
413
+ let identity = (0, tunnel_process_1.tunnelOwnerProcessIdentity)(state);
414
+ const wasRunning = identity === 'match';
415
+ if (identity === 'match' && remote.outcome === 'stopped') {
416
+ await waitForPIDExit(state.pid, 50, sleep);
417
+ }
418
+ state = (0, tunnel_process_1.loadTunnelProcess)(context.instanceId, state.owner) ?? state;
419
+ identity = (0, tunnel_process_1.tunnelOwnerProcessIdentity)(state);
420
+ // Cancelled owners are always stopped, even when a reconnect gave the
421
+ // same owner a new tunnel generation ID meanwhile.
422
+ if (identity === 'match') {
423
+ identity = await signalOwnerAndRefreshIdentity(state, 'SIGTERM', 20, sleep);
424
+ }
425
+ if (identity === 'match') {
426
+ identity = await signalOwnerAndRefreshIdentity(state, 'SIGKILL', 20, sleep);
427
+ }
428
+ if (identity === 'match' || identity === 'unknown') {
429
+ retainedOwners.push(state);
430
+ continue;
431
+ }
432
+ if (!(0, tunnel_process_1.clearTunnelProcess)(context.instanceId, state.owner)) {
433
+ retainedOwners.push(state);
434
+ continue;
435
+ }
436
+ recordsCleaned++;
437
+ if (wasRunning)
438
+ processesStopped++;
439
+ }
440
+ if (retainedOwners.length > 0) {
441
+ context.io.error(`Could not verify that ${retainedOwners.length} local tunnel process(es) exited. ` +
442
+ `Ownership records were retained: ${retainedOwners.map((state) => state.logPath).join(', ')}`);
443
+ }
444
+ return { processesStopped, recordsCleaned };
445
+ }
446
+ async function assertNoActiveTunnel(context) {
447
+ const client = await context.connect();
448
+ try {
449
+ const status = await client.getTunnelStatus();
450
+ if (status.active) {
451
+ context.io.error(`Tunnel ${status.active.tunnelId} is already ${status.active.state}. ` +
452
+ `Run \`lim ${context.product} tunnel status --id ${context.instanceId}\` or stop it first.`);
453
+ }
454
+ }
455
+ finally {
456
+ client.disconnect();
457
+ }
458
+ }
459
+ function clearDeadOwners(context) {
460
+ for (const state of (0, tunnel_process_1.listTunnelProcesses)(context.instanceId)) {
461
+ const identity = (0, tunnel_process_1.tunnelOwnerProcessIdentity)(state);
462
+ if (identity === 'unknown') {
463
+ context.io.error(`Cannot verify local tunnel owner PID ${state.pid}; ownership state was retained at ${state.logPath}.`);
464
+ }
465
+ if (identity === 'match')
466
+ continue;
467
+ if (state.status === 'starting' && !(0, tunnel_process_1.tunnelProcessStartingLeaseExpired)(state))
468
+ continue;
469
+ if (!(0, tunnel_process_1.clearTunnelProcess)(context.instanceId, state.owner)) {
470
+ context.io.error(`Cannot clean local tunnel owner PID ${state.pid}; stop it before starting another tunnel.`);
471
+ }
472
+ }
473
+ }
474
+ /** Resolves 'shutdown' on SIGINT/SIGTERM and 'disconnected' on tunnel loss. */
475
+ function awaitTunnelEnd(tunnel) {
476
+ return new Promise((resolve) => {
477
+ const keepAlive = setInterval(() => { }, 1 << 30);
478
+ let unsubscribe = () => { };
479
+ const cleanup = () => {
480
+ clearInterval(keepAlive);
481
+ unsubscribe();
482
+ process.off('SIGINT', shutdown);
483
+ process.off('SIGTERM', shutdown);
484
+ };
485
+ const shutdown = () => {
486
+ cleanup();
487
+ resolve('shutdown');
488
+ };
489
+ process.once('SIGINT', shutdown);
490
+ process.once('SIGTERM', shutdown);
491
+ unsubscribe = (0, tunnel_process_1.subscribeTunnelDisconnect)(tunnel, () => {
492
+ cleanup();
493
+ resolve('disconnected');
494
+ });
495
+ });
496
+ }
497
+ async function signalOwnerAndRefreshIdentity(state, signal, attempts, sleep) {
498
+ const result = (0, tunnel_process_1.signalTunnelOwner)(state, signal);
499
+ if (result !== 'signaled')
500
+ return result;
501
+ await waitForPIDExit(state.pid, attempts, sleep);
502
+ return (0, tunnel_process_1.tunnelOwnerProcessIdentity)(state);
503
+ }
504
+ async function waitForPIDExit(pid, attempts, sleep) {
505
+ for (let attempt = 0; attempt < attempts && (0, tunnel_process_1.isProcessAlive)(pid); attempt++) {
506
+ await sleep(100);
507
+ }
508
+ }
509
+ async function waitForProcessExit(child, pid, attempts, sleep) {
510
+ for (let attempt = 0; attempt < attempts; attempt++) {
511
+ if (child.exitCode !== null || child.signalCode !== null || !(0, tunnel_process_1.isProcessAlive)(pid)) {
512
+ return true;
513
+ }
514
+ await sleep(100);
515
+ }
516
+ return !(0, tunnel_process_1.isProcessAlive)(pid);
517
+ }
518
+ function jittered(delayMs) {
519
+ return Math.round(delayMs * (0.75 + Math.random() * 0.5));
520
+ }
521
+ function printTunnelReady(context, tunnelId, detached, processInfo) {
522
+ const ready = {
523
+ instanceId: context.instanceId,
524
+ tunnelId,
525
+ state: 'ready',
526
+ detached,
527
+ ...processInfo,
528
+ };
529
+ if (context.io.isJsonEnabled()) {
530
+ context.io.outputJson(ready);
531
+ return;
532
+ }
533
+ context.io.output(`Tunnel ID: ${ready.tunnelId}`);
534
+ if (detached) {
535
+ context.io.output(`Logs: ${processInfo?.logPath}`);
536
+ context.io.output(`Stop: lim ${context.product} tunnel stop --id ${context.instanceId}`);
537
+ }
538
+ else {
539
+ context.io.info('Tunnel started. Press Ctrl+C to stop.');
540
+ }
541
+ }
542
+ //# sourceMappingURL=tunnel-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-command.js","sourceRoot":"","sources":["../../src/lib/tunnel-command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tunnel-command.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-command.test.d.ts","sourceRoot":"","sources":["../../src/lib/tunnel-command.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const fs_1 = __importDefault(require("fs"));
7
+ const os_1 = __importDefault(require("os"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const tunnel_command_1 = require("./tunnel-command");
10
+ describe('tunnel client facade inspection wiring', () => {
11
+ test('propagates negotiated inspection settings and callbacks', async () => {
12
+ const startTunnel = jest.fn(async () => ({
13
+ tunnelId: 'tunnel-1',
14
+ close: () => { },
15
+ getConnectionState: () => 'connected',
16
+ onConnectionStateChange: () => () => { },
17
+ }));
18
+ const facade = (0, tunnel_command_1.tunnelClientFacade)({
19
+ startTunnel,
20
+ getTunnelStatus: async () => ({}),
21
+ stopTunnel: async () => { },
22
+ }, () => { }, 'info');
23
+ const onInspectionEvent = (_event) => { };
24
+ const onInspectionError = () => { };
25
+ await facade.startTunnel({
26
+ selectors: ['api.example.test'],
27
+ inspection: {
28
+ enabled: true,
29
+ captureBodies: true,
30
+ maxBodyBytes: 1024,
31
+ persist: true,
32
+ ttlSeconds: 3600,
33
+ },
34
+ onInspectionEvent,
35
+ onInspectionError,
36
+ });
37
+ expect(startTunnel).toHaveBeenCalledWith({
38
+ selectors: ['api.example.test'],
39
+ logLevel: 'info',
40
+ inspection: {
41
+ enabled: true,
42
+ captureBodies: true,
43
+ maxBodyBytes: 1024,
44
+ persist: true,
45
+ ttlSeconds: 3600,
46
+ },
47
+ onInspectionEvent,
48
+ onInspectionError,
49
+ });
50
+ });
51
+ test('disconnects the client when HAR setup fails', async () => {
52
+ const temporary = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'lim-tunnel-command-'));
53
+ const occupiedPath = path_1.default.join(temporary, 'file');
54
+ fs_1.default.writeFileSync(occupiedPath, 'not a directory');
55
+ const disconnect = jest.fn();
56
+ const client = {
57
+ startTunnel: jest.fn(async () => {
58
+ throw new Error('must not start');
59
+ }),
60
+ getTunnelStatus: async () => ({}),
61
+ stopTunnel: async () => { },
62
+ disconnect,
63
+ };
64
+ try {
65
+ await expect((0, tunnel_command_1.runTunnelForeground)({
66
+ product: 'android',
67
+ instanceId: 'instance-1',
68
+ selectors: ['api.example.test'],
69
+ reconnect: true,
70
+ inspect: true,
71
+ harPath: path_1.default.join(occupiedPath, 'capture.har'),
72
+ connect: async () => client,
73
+ io: {
74
+ error: (message) => {
75
+ throw new Error(message);
76
+ },
77
+ output: () => { },
78
+ info: () => { },
79
+ outputJson: () => { },
80
+ isJsonEnabled: () => false,
81
+ },
82
+ })).rejects.toThrow();
83
+ expect(disconnect).toHaveBeenCalledTimes(1);
84
+ expect(client.startTunnel).not.toHaveBeenCalled();
85
+ }
86
+ finally {
87
+ fs_1.default.rmSync(temporary, { recursive: true, force: true });
88
+ }
89
+ });
90
+ });
91
+ //# sourceMappingURL=tunnel-command.test.js.map