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 @@
1
+ {"version":3,"file":"tunnel-command.test.js","sourceRoot":"","sources":["../../src/lib/tunnel-command.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type DestinationTunnelInspectionComplete, type DestinationTunnelInspectionEvent } from '@limrun/api';
2
+ export interface TunnelHarRecorder {
3
+ onEvent: (event: DestinationTunnelInspectionEvent) => void;
4
+ resetPending: () => void;
5
+ finalize: () => Promise<void>;
6
+ close: () => void;
7
+ }
8
+ /**
9
+ * Append-only NDJSON capture spool. Completed exchanges are durable
10
+ * independently, while finalization streams them into HAR 1.2.
11
+ */
12
+ export declare function createTunnelHarRecorder(harPath: string, bodyLimit: number): TunnelHarRecorder;
13
+ export declare function formatInspectionSummary(event: DestinationTunnelInspectionComplete): string;
14
+ //# sourceMappingURL=tunnel-har.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-har.d.ts","sourceRoot":"","sources":["../../src/lib/tunnel-har.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,mCAAmC,EACxC,KAAK,gCAAgC,EAEtC,MAAM,aAAa,CAAC;AAMrB,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,IAAI,CAAC;IAC3D,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAkE7F;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,mCAAmC,GAAG,MAAM,CAG1F"}
@@ -0,0 +1,150 @@
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.createTunnelHarRecorder = createTunnelHarRecorder;
7
+ exports.formatInspectionSummary = formatInspectionSummary;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const readline_1 = __importDefault(require("readline"));
11
+ const api_1 = require("@limrun/api");
12
+ /**
13
+ * Append-only NDJSON capture spool. Completed exchanges are durable
14
+ * independently, while finalization streams them into HAR 1.2.
15
+ */
16
+ function createTunnelHarRecorder(harPath, bodyLimit) {
17
+ if (!Number.isInteger(bodyLimit) || bodyLimit < 1) {
18
+ throw new Error('HAR body limit must be a positive integer');
19
+ }
20
+ const finalPath = path_1.default.resolve(harPath);
21
+ const partialPath = `${finalPath}.partial`;
22
+ fs_1.default.mkdirSync(path_1.default.dirname(finalPath), { recursive: true });
23
+ ensureAppendBoundary(partialPath);
24
+ const descriptor = fs_1.default.openSync(partialPath, 'a', 0o600);
25
+ fs_1.default.fchmodSync(descriptor, 0o600);
26
+ const assembler = new api_1.DestinationTunnelHARAssembler(bodyLimit);
27
+ let closed = false;
28
+ const appendRecord = (record) => {
29
+ if (closed)
30
+ return;
31
+ fs_1.default.writeSync(descriptor, `${JSON.stringify(record)}\n`, undefined, 'utf8');
32
+ };
33
+ const onEvent = (event) => {
34
+ if (closed)
35
+ return;
36
+ if (event.type === 'gap') {
37
+ appendRecord({ type: 'gap', gap: event.data });
38
+ return;
39
+ }
40
+ const entry = assembler.add(event);
41
+ if (entry)
42
+ appendRecord({ type: 'entry', entry });
43
+ };
44
+ const resetPending = () => {
45
+ assembler.reset();
46
+ };
47
+ const close = () => {
48
+ if (closed)
49
+ return;
50
+ closed = true;
51
+ assembler.reset();
52
+ fs_1.default.fsyncSync(descriptor);
53
+ fs_1.default.closeSync(descriptor);
54
+ };
55
+ const finalize = async () => {
56
+ close();
57
+ const temporaryPath = `${finalPath}.${process.pid}.${Date.now()}.tmp`;
58
+ const output = fs_1.default.openSync(temporaryPath, 'wx', 0o600);
59
+ try {
60
+ fs_1.default.writeSync(output, '{"log":{"version":"1.2","creator":{"name":"Limrun CLI","version":"1"},"entries":[');
61
+ const gaps = await copySpoolRecords(partialPath, output);
62
+ fs_1.default.writeSync(output, '],"_limrun":{"gaps":[');
63
+ fs_1.default.writeSync(output, gaps.map((gap) => JSON.stringify(gap)).join(','));
64
+ fs_1.default.writeSync(output, ']}}}\n');
65
+ fs_1.default.fsyncSync(output);
66
+ }
67
+ catch (error) {
68
+ fs_1.default.closeSync(output);
69
+ fs_1.default.rmSync(temporaryPath, { force: true });
70
+ throw error;
71
+ }
72
+ fs_1.default.closeSync(output);
73
+ fs_1.default.chmodSync(temporaryPath, 0o600);
74
+ fs_1.default.renameSync(temporaryPath, finalPath);
75
+ fs_1.default.rmSync(partialPath, { force: true });
76
+ };
77
+ return { onEvent, resetPending, finalize, close };
78
+ }
79
+ function formatInspectionSummary(event) {
80
+ const outcome = event._limrun.error ? `ERROR ${event._limrun.error}` : String(event.response.status);
81
+ return `${event.request.method} ${event.request.url} ${outcome} ${event.time}ms ${event.response.bodySize} B`;
82
+ }
83
+ async function copySpoolRecords(partialPath, output) {
84
+ const lines = readline_1.default.createInterface({
85
+ input: fs_1.default.createReadStream(partialPath, { encoding: 'utf8' }),
86
+ crlfDelay: Infinity,
87
+ });
88
+ let first = true;
89
+ const gaps = [];
90
+ for await (const line of lines) {
91
+ const record = parseSpoolRecord(line);
92
+ if (!record)
93
+ continue;
94
+ if (record.type === 'gap') {
95
+ gaps.push(record.gap);
96
+ continue;
97
+ }
98
+ if (!first)
99
+ fs_1.default.writeSync(output, ',');
100
+ fs_1.default.writeSync(output, JSON.stringify(record.entry));
101
+ first = false;
102
+ }
103
+ return gaps;
104
+ }
105
+ function parseSpoolRecord(line) {
106
+ if (!line.trim())
107
+ return undefined;
108
+ try {
109
+ const value = JSON.parse(line);
110
+ if (value.type === 'entry' && typeof value.entry === 'object' && value.entry !== null) {
111
+ return { type: 'entry', entry: value.entry };
112
+ }
113
+ if (value.type === 'gap' && typeof value.gap === 'object' && value.gap !== null) {
114
+ const gap = value.gap;
115
+ if (Number.isSafeInteger(gap.fromSequence) &&
116
+ Number.isSafeInteger(gap.toSequence) &&
117
+ typeof gap.message === 'string') {
118
+ return { type: 'gap', gap };
119
+ }
120
+ }
121
+ }
122
+ catch {
123
+ // A crash may leave one torn final record; earlier newline-delimited
124
+ // records remain recoverable and are still finalized.
125
+ }
126
+ return undefined;
127
+ }
128
+ function ensureAppendBoundary(partialPath) {
129
+ try {
130
+ const descriptor = fs_1.default.openSync(partialPath, 'r+');
131
+ try {
132
+ fs_1.default.fchmodSync(descriptor, 0o600);
133
+ const size = fs_1.default.fstatSync(descriptor).size;
134
+ if (size === 0)
135
+ return;
136
+ const byte = Buffer.alloc(1);
137
+ fs_1.default.readSync(descriptor, byte, 0, 1, size - 1);
138
+ if (byte[0] !== 0x0a)
139
+ fs_1.default.writeSync(descriptor, '\n', size, 'utf8');
140
+ }
141
+ finally {
142
+ fs_1.default.closeSync(descriptor);
143
+ }
144
+ }
145
+ catch (error) {
146
+ if (error.code !== 'ENOENT')
147
+ throw error;
148
+ }
149
+ }
150
+ //# sourceMappingURL=tunnel-har.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-har.js","sourceRoot":"","sources":["../../src/lib/tunnel-har.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tunnel-har.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-har.test.d.ts","sourceRoot":"","sources":["../../src/lib/tunnel-har.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,164 @@
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_har_1 = require("./tunnel-har");
10
+ describe('tunnel HAR capture', () => {
11
+ let directory;
12
+ beforeEach(() => {
13
+ directory = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'lim-har-'));
14
+ });
15
+ afterEach(() => {
16
+ fs_1.default.rmSync(directory, { recursive: true, force: true });
17
+ });
18
+ test('spools bounded bodies and atomically finalizes HAR 1.2', async () => {
19
+ const harPath = path_1.default.join(directory, 'traffic.har');
20
+ const recorder = (0, tunnel_har_1.createTunnelHarRecorder)(harPath, 4);
21
+ recorder.onEvent(bodyEvent(1, 'request', Buffer.from('hello')));
22
+ recorder.onEvent(bodyEvent(2, 'response', Buffer.from([0, 1, 2])));
23
+ recorder.onEvent({
24
+ type: 'gap',
25
+ sequence: 4,
26
+ data: {
27
+ fromSequence: 3,
28
+ toSequence: 4,
29
+ message: 'Inspection stream gap: missing sequences 3-4',
30
+ },
31
+ });
32
+ recorder.onEvent({
33
+ type: 'complete',
34
+ sequence: 5,
35
+ requestId: 'request-1',
36
+ data: completeEvent(),
37
+ });
38
+ recorder.onEvent({
39
+ type: 'complete',
40
+ sequence: 6,
41
+ requestId: 'request-2',
42
+ data: {
43
+ ...completeEvent(),
44
+ _limrun: {
45
+ ...completeEvent()._limrun,
46
+ tunnelId: 'tunnel-2',
47
+ },
48
+ },
49
+ });
50
+ expect(fs_1.default.statSync(`${harPath}.partial`).mode & 0o777).toBe(0o600);
51
+ await recorder.finalize();
52
+ expect(fs_1.default.existsSync(`${harPath}.partial`)).toBe(false);
53
+ expect(fs_1.default.statSync(harPath).mode & 0o777).toBe(0o600);
54
+ const har = JSON.parse(fs_1.default.readFileSync(harPath, 'utf8'));
55
+ expect(har.log.version).toBe('1.2');
56
+ expect(har.log.entries).toHaveLength(2);
57
+ expect(har.log.entries[0].request.postData).toEqual({
58
+ mimeType: 'application/octet-stream',
59
+ text: 'aGVsbA==',
60
+ });
61
+ expect(har.log.entries[0].request.postData).not.toHaveProperty('_encoding');
62
+ expect(har.log.entries[0].response.content).toEqual({
63
+ size: 3,
64
+ mimeType: 'application/octet-stream',
65
+ text: 'AAEC',
66
+ encoding: 'base64',
67
+ });
68
+ expect(har.log.entries[0].response).not.toHaveProperty('trailers');
69
+ expect(har.log.entries[0].response).not.toHaveProperty('_trailers');
70
+ expect(har.log.entries[0].response.cookies[0]).not.toHaveProperty('sameSite');
71
+ expect(har.log.entries[0]._limrun).toEqual({
72
+ tunnelId: 'tunnel-1',
73
+ selectorId: 'selector-1',
74
+ responseTrailers: [{ name: 'grpc-status', value: '0' }],
75
+ responseCookieSameSite: [{ index: 0, value: 'Strict' }],
76
+ requestBodyEncoding: 'base64',
77
+ requestBodyTruncated: true,
78
+ responseBodyTruncated: false,
79
+ });
80
+ expect(har.log._limrun.gaps).toEqual([
81
+ {
82
+ fromSequence: 3,
83
+ toSequence: 4,
84
+ message: 'Inspection stream gap: missing sequences 3-4',
85
+ },
86
+ ]);
87
+ expect(har.log.entries[1]._limrun).toMatchObject({
88
+ tunnelId: 'tunnel-2',
89
+ });
90
+ });
91
+ test('drops incomplete body state between tunnel generations', async () => {
92
+ const harPath = path_1.default.join(directory, 'reconnected.har');
93
+ const recorder = (0, tunnel_har_1.createTunnelHarRecorder)(harPath, 1024);
94
+ recorder.onEvent(bodyEvent(1, 'request', Buffer.from('old generation')));
95
+ recorder.resetPending();
96
+ recorder.onEvent({
97
+ type: 'complete',
98
+ sequence: 2,
99
+ requestId: 'request-1',
100
+ data: completeEvent(),
101
+ });
102
+ await recorder.finalize();
103
+ const har = JSON.parse(fs_1.default.readFileSync(harPath, 'utf8'));
104
+ expect(har.log.entries[0].request.postData.text).toBe('original body');
105
+ });
106
+ test('recovers complete records before a torn final partial record', async () => {
107
+ const harPath = path_1.default.join(directory, 'recovered.har');
108
+ fs_1.default.writeFileSync(`${harPath}.partial`, '{"type":"entry","entry":{"startedDateTime":"2026-01-01T00:00:00Z"}}\n{"type":"entry"', { mode: 0o644 });
109
+ const recorder = (0, tunnel_har_1.createTunnelHarRecorder)(harPath, 1);
110
+ await recorder.finalize();
111
+ const har = JSON.parse(fs_1.default.readFileSync(harPath, 'utf8'));
112
+ expect(har.log.entries).toEqual([{ startedDateTime: '2026-01-01T00:00:00Z' }]);
113
+ expect(fs_1.default.statSync(harPath).mode & 0o777).toBe(0o600);
114
+ });
115
+ test('formats only the one-line completion summary', () => {
116
+ expect((0, tunnel_har_1.formatInspectionSummary)(completeEvent())).toBe('POST https://example.test/full?q=secret 201 25ms 3 B');
117
+ const failed = completeEvent();
118
+ failed._limrun.error = 'connection reset';
119
+ expect((0, tunnel_har_1.formatInspectionSummary)(failed)).toBe('POST https://example.test/full?q=secret ERROR connection reset 25ms 3 B');
120
+ });
121
+ });
122
+ function bodyEvent(sequence, direction, body) {
123
+ return { type: 'body', sequence, requestId: 'request-1', direction, body };
124
+ }
125
+ function completeEvent() {
126
+ return {
127
+ startedDateTime: '2026-08-29T09:00:00.000Z',
128
+ time: 25,
129
+ request: {
130
+ method: 'POST',
131
+ url: 'https://example.test/full?q=secret',
132
+ httpVersion: 'HTTP/1.1',
133
+ headers: [
134
+ { name: 'Content-Type', value: 'application/octet-stream' },
135
+ { name: 'Cookie', value: 'private=1' },
136
+ ],
137
+ queryString: [{ name: 'q', value: 'secret' }],
138
+ cookies: [{ name: 'private', value: '1' }],
139
+ headersSize: 50,
140
+ bodySize: 5,
141
+ postData: { mimeType: 'application/octet-stream', text: 'original body' },
142
+ },
143
+ response: {
144
+ status: 201,
145
+ statusText: 'Created',
146
+ httpVersion: 'HTTP/1.1',
147
+ headers: [{ name: 'Set-Cookie', value: 'private=2' }],
148
+ cookies: [{ name: 'private', value: '2' }],
149
+ content: { size: 3, mimeType: 'application/octet-stream' },
150
+ redirectURL: '',
151
+ headersSize: 20,
152
+ bodySize: 3,
153
+ },
154
+ cache: {},
155
+ timings: { blocked: 0, dns: 1, connect: 2, ssl: 3, send: 4, wait: 10, receive: 5 },
156
+ _limrun: {
157
+ tunnelId: 'tunnel-1',
158
+ selectorId: 'selector-1',
159
+ responseTrailers: [{ name: 'grpc-status', value: '0' }],
160
+ responseCookieSameSite: [{ index: 0, value: 'Strict' }],
161
+ },
162
+ };
163
+ }
164
+ //# sourceMappingURL=tunnel-har.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-har.test.js","sourceRoot":"","sources":["../../src/lib/tunnel-har.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ import { type ChildProcess } from 'child_process';
2
+ import { type DestinationTunnelSelectors, type DestinationTunnelStatus } from '@limrun/api';
3
+ export declare const TUNNELS_ROOT: string;
4
+ export type TunnelProduct = 'ios' | 'android';
5
+ export interface TunnelProcessState {
6
+ owner: string;
7
+ pid: number;
8
+ instanceId: string;
9
+ product: TunnelProduct;
10
+ status: 'starting' | 'ready';
11
+ selectors: DestinationTunnelSelectors;
12
+ inspect?: boolean;
13
+ persist?: boolean;
14
+ ttlSeconds?: number;
15
+ harPath?: string;
16
+ harBodyLimit?: number;
17
+ startedAt: string;
18
+ logPath: string;
19
+ tunnelId?: string;
20
+ }
21
+ export type ReadyTunnelProcessState = TunnelProcessState & {
22
+ status: 'ready';
23
+ tunnelId: string;
24
+ };
25
+ export type TunnelOwnerProcessIdentity = 'match' | 'mismatch' | 'missing' | 'unknown';
26
+ export interface TunnelProcessPaths {
27
+ directory: string;
28
+ state: string;
29
+ log: string;
30
+ cancelled: string;
31
+ }
32
+ export declare function parseTunnelSelectors(values: readonly string[], options?: {
33
+ minPort?: number;
34
+ allowDomains?: boolean;
35
+ }): DestinationTunnelSelectors;
36
+ export declare function newTunnelOwner(): string;
37
+ export declare function formatTunnelSelectors(selectors: DestinationTunnelSelectors): string[];
38
+ export declare function formatTunnelDialFailure(failure: NonNullable<DestinationTunnelStatus['lastDialFailure']>): string;
39
+ export declare function buildTunnelServeArgs(options: {
40
+ scriptPath: string;
41
+ product: TunnelProduct;
42
+ instanceId: string;
43
+ owner: string;
44
+ selectors: DestinationTunnelSelectors;
45
+ inspect?: boolean;
46
+ persist?: boolean;
47
+ ttlSeconds?: number;
48
+ harPath?: string;
49
+ harBodyLimit?: number;
50
+ verbose?: boolean;
51
+ }): string[];
52
+ export declare function tunnelChildEnvironment(apiKey: string | undefined, environment?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
53
+ export declare function waitForTunnelProcessReady(options: {
54
+ load: () => TunnelProcessState | undefined;
55
+ isAlive: () => boolean;
56
+ sleep: (milliseconds: number) => Promise<void>;
57
+ now?: () => number;
58
+ timeoutMs?: number;
59
+ pollMs?: number;
60
+ }): Promise<{
61
+ outcome: 'ready';
62
+ state: ReadyTunnelProcessState;
63
+ } | {
64
+ outcome: 'exited';
65
+ } | {
66
+ outcome: 'timeout';
67
+ }>;
68
+ export declare function tunnelProcessPaths(instanceId: string, owner: string, root?: string): TunnelProcessPaths;
69
+ export declare function claimTunnelProcess(state: TunnelProcessState, root?: string): boolean;
70
+ export declare function updateTunnelProcess(state: TunnelProcessState, expectedOwner: string, root?: string): void;
71
+ export declare function loadTunnelProcess(instanceId: string, owner: string, root?: string): TunnelProcessState | undefined;
72
+ export declare function listTunnelProcesses(instanceId: string, root?: string): TunnelProcessState[];
73
+ export declare function selectTunnelOwnersForStop(owners: TunnelProcessState[], tunnelId: string | undefined): TunnelProcessState[];
74
+ export interface TunnelLike {
75
+ getConnectionState: () => 'connecting' | 'connected' | 'disconnected' | 'reconnecting';
76
+ onConnectionStateChange: (callback: (state: 'connecting' | 'connected' | 'disconnected' | 'reconnecting') => void) => () => void;
77
+ }
78
+ export declare function subscribeTunnelDisconnect(tunnel: TunnelLike, onDisconnect: () => void): () => void;
79
+ export declare function stopTunnelErrorIsNotFound(error: unknown): boolean;
80
+ /**
81
+ * Mark an owner as cancelled without removing its state. Cancellation is
82
+ * observed by the serving child before every reconnect attempt and by every
83
+ * state update, so a cancelled starting owner can never recreate the tunnel
84
+ * between our stop signal and its exit.
85
+ */
86
+ export declare function markTunnelProcessCancelled(instanceId: string, owner: string, root?: string): void;
87
+ export declare function isTunnelProcessCancelled(instanceId: string, owner: string, root?: string): boolean;
88
+ export declare function clearTunnelProcess(instanceId: string, owner: string, root?: string): boolean;
89
+ export declare function pruneTunnelLogs(instanceId: string, root?: string, retain?: number): void;
90
+ export declare function isProcessAlive(pid: number): boolean;
91
+ export declare function isSpawnedTunnelProcessAlive(child: Pick<ChildProcess, 'exitCode' | 'signalCode'>, pid: number): boolean;
92
+ export declare function tunnelProcessStartingLeaseExpired(state: TunnelProcessState, now?: number): boolean;
93
+ export declare function tunnelOwnerProcessIdentity(state: TunnelProcessState): TunnelOwnerProcessIdentity;
94
+ export declare function signalTunnelOwner(state: TunnelProcessState, signal: NodeJS.Signals): 'signaled' | TunnelOwnerProcessIdentity;
95
+ export declare function prepareTunnelLog(logPath: string, maxBytes?: number): number;
96
+ export declare function readTunnelLogTail(logPath: string, lines?: number, maxBytes?: number): string;
97
+ export declare function capTunnelLog(logPath: string, maxBytes?: number): boolean;
98
+ //# sourceMappingURL=tunnel-process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel-process.d.ts","sourceRoot":"","sources":["../../src/lib/tunnel-process.ts"],"names":[],"mappings":"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"}