@vforsh/argus 0.1.12 → 0.1.13
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/dist/.tsbuildinfo +1 -1
- package/dist/argus.js +6266 -1284
- package/dist/cdp/sendCdpCommand.d.ts +6 -2
- package/dist/cdp/sendCdpCommand.d.ts.map +1 -1
- package/dist/cdp/sendCdpCommand.js +18 -12
- package/dist/cdp/sendCdpCommand.js.map +1 -1
- package/dist/cli/plugins/registerPlugins.d.ts.map +1 -1
- package/dist/cli/plugins/registerPlugins.js +1 -1
- package/dist/cli/plugins/registerPlugins.js.map +1 -1
- package/dist/cli/register/domCommandBuilder.d.ts +1 -0
- package/dist/cli/register/domCommandBuilder.d.ts.map +1 -1
- package/dist/cli/register/domCommandBuilder.js +3 -0
- package/dist/cli/register/domCommandBuilder.js.map +1 -1
- package/dist/cli/register/index.d.ts.map +1 -1
- package/dist/cli/register/index.js +4 -0
- package/dist/cli/register/index.js.map +1 -1
- package/dist/cli/register/registerAuth.d.ts.map +1 -1
- package/dist/cli/register/registerAuth.js +103 -4
- package/dist/cli/register/registerAuth.js.map +1 -1
- package/dist/cli/register/registerChrome.d.ts.map +1 -1
- package/dist/cli/register/registerChrome.js +53 -14
- package/dist/cli/register/registerChrome.js.map +1 -1
- package/dist/cli/register/registerClick.d.ts.map +1 -1
- package/dist/cli/register/registerClick.js +2 -1
- package/dist/cli/register/registerClick.js.map +1 -1
- package/dist/cli/register/registerDialog.d.ts +3 -0
- package/dist/cli/register/registerDialog.d.ts.map +1 -0
- package/dist/cli/register/registerDialog.js +45 -0
- package/dist/cli/register/registerDialog.js.map +1 -0
- package/dist/cli/register/registerDom.d.ts.map +1 -1
- package/dist/cli/register/registerDom.js +4 -0
- package/dist/cli/register/registerDom.js.map +1 -1
- package/dist/cli/register/registerEval.js +1 -1
- package/dist/cli/register/registerEval.js.map +1 -1
- package/dist/cli/register/registerFill.d.ts.map +1 -1
- package/dist/cli/register/registerFill.js +4 -3
- package/dist/cli/register/registerFill.js.map +1 -1
- package/dist/cli/register/registerHover.d.ts.map +1 -1
- package/dist/cli/register/registerHover.js +2 -1
- package/dist/cli/register/registerHover.js.map +1 -1
- package/dist/cli/register/registerLocate.d.ts +3 -0
- package/dist/cli/register/registerLocate.d.ts.map +1 -0
- package/dist/cli/register/registerLocate.js +48 -0
- package/dist/cli/register/registerLocate.js.map +1 -0
- package/dist/cli/register/registerNet.d.ts.map +1 -1
- package/dist/cli/register/registerNet.js +234 -13
- package/dist/cli/register/registerNet.js.map +1 -1
- package/dist/cli/register/registerQuickAccess.d.ts.map +1 -1
- package/dist/cli/register/registerQuickAccess.js +33 -3
- package/dist/cli/register/registerQuickAccess.js.map +1 -1
- package/dist/cli/register/registerStorage.d.ts.map +1 -1
- package/dist/cli/register/registerStorage.js +26 -21
- package/dist/cli/register/registerStorage.js.map +1 -1
- package/dist/cli/validation.d.ts +1 -0
- package/dist/cli/validation.d.ts.map +1 -1
- package/dist/cli/validation.js +1 -0
- package/dist/cli/validation.js.map +1 -1
- package/dist/commands/auth.d.ts +39 -18
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +104 -122
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/authCookieSupport.d.ts +54 -0
- package/dist/commands/authCookieSupport.d.ts.map +1 -0
- package/dist/commands/authCookieSupport.js +206 -0
- package/dist/commands/authCookieSupport.js.map +1 -0
- package/dist/commands/authCookies.d.ts +60 -0
- package/dist/commands/authCookies.d.ts.map +1 -0
- package/dist/commands/authCookies.js +149 -0
- package/dist/commands/authCookies.js.map +1 -0
- package/dist/commands/chrome/authState.d.ts +23 -0
- package/dist/commands/chrome/authState.d.ts.map +1 -0
- package/dist/commands/chrome/authState.js +97 -0
- package/dist/commands/chrome/authState.js.map +1 -0
- package/dist/commands/chromeStart.d.ts +1 -0
- package/dist/commands/chromeStart.d.ts.map +1 -1
- package/dist/commands/chromeStart.js +28 -3
- package/dist/commands/chromeStart.js.map +1 -1
- package/dist/commands/code.d.ts.map +1 -1
- package/dist/commands/code.js +9 -1
- package/dist/commands/code.js.map +1 -1
- package/dist/commands/dialog.d.ts +13 -0
- package/dist/commands/dialog.d.ts.map +1 -0
- package/dist/commands/dialog.js +71 -0
- package/dist/commands/dialog.js.map +1 -0
- package/dist/commands/dom/shared.d.ts +5 -1
- package/dist/commands/dom/shared.d.ts.map +1 -1
- package/dist/commands/dom/shared.js +27 -0
- package/dist/commands/dom/shared.js.map +1 -1
- package/dist/commands/domClick.d.ts +1 -0
- package/dist/commands/domClick.d.ts.map +1 -1
- package/dist/commands/domClick.js +20 -10
- package/dist/commands/domClick.js.map +1 -1
- package/dist/commands/domFill.d.ts +1 -0
- package/dist/commands/domFill.d.ts.map +1 -1
- package/dist/commands/domFill.js +13 -9
- package/dist/commands/domFill.js.map +1 -1
- package/dist/commands/domFocus.d.ts +2 -1
- package/dist/commands/domFocus.d.ts.map +1 -1
- package/dist/commands/domFocus.js +7 -6
- package/dist/commands/domFocus.js.map +1 -1
- package/dist/commands/domHover.d.ts +2 -1
- package/dist/commands/domHover.d.ts.map +1 -1
- package/dist/commands/domHover.js +7 -6
- package/dist/commands/domHover.js.map +1 -1
- package/dist/commands/domInfo.d.ts +2 -1
- package/dist/commands/domInfo.d.ts.map +1 -1
- package/dist/commands/domInfo.js +6 -5
- package/dist/commands/domInfo.js.map +1 -1
- package/dist/commands/domTree.js +2 -2
- package/dist/commands/domTree.js.map +1 -1
- package/dist/commands/locate.d.ts +17 -0
- package/dist/commands/locate.d.ts.map +1 -0
- package/dist/commands/locate.js +117 -0
- package/dist/commands/locate.js.map +1 -0
- package/dist/commands/net.d.ts +2 -5
- package/dist/commands/net.d.ts.map +1 -1
- package/dist/commands/net.js +5 -7
- package/dist/commands/net.js.map +1 -1
- package/dist/commands/netBody.d.ts +6 -0
- package/dist/commands/netBody.d.ts.map +1 -0
- package/dist/commands/netBody.js +32 -0
- package/dist/commands/netBody.js.map +1 -0
- package/dist/commands/netCapture.d.ts +36 -0
- package/dist/commands/netCapture.d.ts.map +1 -0
- package/dist/commands/netCapture.js +105 -0
- package/dist/commands/netCapture.js.map +1 -0
- package/dist/commands/netClear.d.ts +5 -0
- package/dist/commands/netClear.d.ts.map +1 -0
- package/dist/commands/netClear.js +20 -0
- package/dist/commands/netClear.js.map +1 -0
- package/dist/commands/netExport.d.ts +13 -0
- package/dist/commands/netExport.d.ts.map +1 -0
- package/dist/commands/netExport.js +124 -0
- package/dist/commands/netExport.js.map +1 -0
- package/dist/commands/netInspect.d.ts +12 -0
- package/dist/commands/netInspect.d.ts.map +1 -0
- package/dist/commands/netInspect.js +205 -0
- package/dist/commands/netInspect.js.map +1 -0
- package/dist/commands/netRequestClient.d.ts +17 -0
- package/dist/commands/netRequestClient.d.ts.map +1 -0
- package/dist/commands/netRequestClient.js +54 -0
- package/dist/commands/netRequestClient.js.map +1 -0
- package/dist/commands/netRequestTarget.d.ts +14 -0
- package/dist/commands/netRequestTarget.d.ts.map +1 -0
- package/dist/commands/netRequestTarget.js +36 -0
- package/dist/commands/netRequestTarget.js.map +1 -0
- package/dist/commands/netShared.d.ts +40 -0
- package/dist/commands/netShared.d.ts.map +1 -0
- package/dist/commands/netShared.js +108 -0
- package/dist/commands/netShared.js.map +1 -0
- package/dist/commands/netShow.d.ts +5 -0
- package/dist/commands/netShow.d.ts.map +1 -0
- package/dist/commands/netShow.js +28 -0
- package/dist/commands/netShow.js.map +1 -0
- package/dist/commands/netSummary.d.ts +6 -0
- package/dist/commands/netSummary.d.ts.map +1 -0
- package/dist/commands/netSummary.js +99 -0
- package/dist/commands/netSummary.js.map +1 -0
- package/dist/commands/netTail.d.ts +2 -5
- package/dist/commands/netTail.d.ts.map +1 -1
- package/dist/commands/netTail.js +7 -15
- package/dist/commands/netTail.js.map +1 -1
- package/dist/commands/netWatch.d.ts +11 -0
- package/dist/commands/netWatch.d.ts.map +1 -0
- package/dist/commands/netWatch.js +55 -0
- package/dist/commands/netWatch.js.map +1 -0
- package/dist/commands/resolveTestId.d.ts +2 -1
- package/dist/commands/resolveTestId.d.ts.map +1 -1
- package/dist/commands/resolveTestId.js +3 -3
- package/dist/commands/resolveTestId.js.map +1 -1
- package/dist/commands/start.d.ts +1 -0
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +62 -7
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/storage.d.ts +17 -0
- package/dist/commands/storage.d.ts.map +1 -0
- package/dist/commands/storage.js +67 -0
- package/dist/commands/storage.js.map +1 -0
- package/dist/commands/watcherNativeHost.d.ts.map +1 -1
- package/dist/commands/watcherNativeHost.js +13 -2
- package/dist/commands/watcherNativeHost.js.map +1 -1
- package/dist/net/har.d.ts +86 -0
- package/dist/net/har.d.ts.map +1 -0
- package/dist/net/har.js +125 -0
- package/dist/net/har.js.map +1 -0
- package/dist/net/summary.d.ts +33 -0
- package/dist/net/summary.d.ts.map +1 -0
- package/dist/net/summary.js +128 -0
- package/dist/net/summary.js.map +1 -0
- package/dist/output/accessibility.js +16 -12
- package/dist/output/accessibility.js.map +1 -1
- package/dist/output/code.d.ts +2 -1
- package/dist/output/code.d.ts.map +1 -1
- package/dist/output/code.js +10 -0
- package/dist/output/code.js.map +1 -1
- package/dist/output/dom.d.ts.map +1 -1
- package/dist/output/dom.js +2 -1
- package/dist/output/dom.js.map +1 -1
- package/dist/output/format.d.ts +1 -3
- package/dist/output/format.d.ts.map +1 -1
- package/dist/output/format.js +0 -8
- package/dist/output/format.js.map +1 -1
- package/dist/output/locate.d.ts +3 -0
- package/dist/output/locate.d.ts.map +1 -0
- package/dist/output/locate.js +25 -0
- package/dist/output/locate.js.map +1 -0
- package/dist/output/net.d.ts +13 -0
- package/dist/output/net.d.ts.map +1 -0
- package/dist/output/net.js +239 -0
- package/dist/output/net.js.map +1 -0
- package/dist/watchers/queryParams.d.ts +17 -0
- package/dist/watchers/queryParams.d.ts.map +1 -1
- package/dist/watchers/queryParams.js +61 -0
- package/dist/watchers/queryParams.js.map +1 -1
- package/package.json +2 -5
- package/dist/commands/storageLocal.d.ts +0 -18
- package/dist/commands/storageLocal.d.ts.map +0 -1
- package/dist/commands/storageLocal.js +0 -92
- package/dist/commands/storageLocal.js.map +0 -1
- package/dist/plugin.d.ts +0 -29
- package/dist/plugin.d.ts.map +0 -1
- package/dist/plugin.js +0 -2
- package/dist/plugin.js.map +0 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { appendNetCommandParams, parseNetDurationMs, parseSettleDurationMs, validateNetCommandOptions } from './netShared.js';
|
|
2
|
+
import { fetchWatcherJson } from '../watchers/requestWatcher.js';
|
|
3
|
+
const WATCH_BATCH_LIMIT = 5_000;
|
|
4
|
+
const RELOAD_SELECTED_SCOPE_ERROR = 'Cannot combine --reload with selected-frame scope. Use tab/page scope, or capture the current buffer without --reload.';
|
|
5
|
+
/**
|
|
6
|
+
* Parse capture options shared by `net watch` and `net export`.
|
|
7
|
+
* `defaultClear` lets each command keep its own sane default without forking validation logic.
|
|
8
|
+
*/
|
|
9
|
+
export const parseNetCaptureOptions = (options, config) => {
|
|
10
|
+
const reloadScope = validateReloadScope(options);
|
|
11
|
+
if (reloadScope.error) {
|
|
12
|
+
return reloadScope;
|
|
13
|
+
}
|
|
14
|
+
const settle = parseSettleDurationMs(options.settle);
|
|
15
|
+
if (settle.error || settle.value == null) {
|
|
16
|
+
return { error: settle.error ?? 'Invalid --settle value.' };
|
|
17
|
+
}
|
|
18
|
+
const maxTimeout = parseNetDurationMs(options.maxTimeout, '--max-timeout');
|
|
19
|
+
if (maxTimeout.error) {
|
|
20
|
+
return { error: maxTimeout.error };
|
|
21
|
+
}
|
|
22
|
+
const validation = validateNetCommandOptions(options);
|
|
23
|
+
if (validation.error) {
|
|
24
|
+
return { error: validation.error };
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
value: {
|
|
28
|
+
settleMs: settle.value,
|
|
29
|
+
maxTimeoutMs: maxTimeout.value,
|
|
30
|
+
clearBeforeCapture: options.clear ?? config.defaultClear,
|
|
31
|
+
shouldReload: options.reload === true,
|
|
32
|
+
ignoreCache: options.ignoreCache === true,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Reload capture is only supported for stable page/tab scopes.
|
|
38
|
+
* Selected-frame scope is intentionally rejected because iframe rematch across reload
|
|
39
|
+
* is not reliable enough to promise correct watch/export output.
|
|
40
|
+
*/
|
|
41
|
+
const validateReloadScope = (options) => {
|
|
42
|
+
if (!options.reload) {
|
|
43
|
+
return {};
|
|
44
|
+
}
|
|
45
|
+
if (options.scope === 'selected' || options.frame === 'selected') {
|
|
46
|
+
return { error: RELOAD_SELECTED_SCOPE_ERROR };
|
|
47
|
+
}
|
|
48
|
+
return {};
|
|
49
|
+
};
|
|
50
|
+
/** Clear/reload if requested, then tail matching requests until the quiet window is reached. */
|
|
51
|
+
export const captureNetWindow = async (watcher, options, capture) => {
|
|
52
|
+
let cleared = 0;
|
|
53
|
+
if (capture.clearBeforeCapture) {
|
|
54
|
+
const response = await fetchWatcherJson(watcher, {
|
|
55
|
+
path: '/net/clear',
|
|
56
|
+
method: 'POST',
|
|
57
|
+
timeoutMs: 5_000,
|
|
58
|
+
});
|
|
59
|
+
cleared = response.cleared;
|
|
60
|
+
}
|
|
61
|
+
if (capture.shouldReload) {
|
|
62
|
+
await fetchWatcherJson(watcher, {
|
|
63
|
+
path: '/reload',
|
|
64
|
+
method: 'POST',
|
|
65
|
+
body: { ignoreCache: capture.ignoreCache },
|
|
66
|
+
timeoutMs: 10_000,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const settled = await waitForNetworkToSettle(watcher, options, capture.settleMs, capture.maxTimeoutMs);
|
|
70
|
+
return { cleared, requests: settled.requests, timedOut: settled.timedOut };
|
|
71
|
+
};
|
|
72
|
+
const waitForNetworkToSettle = async (watcher, options, settleMs, maxTimeoutMs) => {
|
|
73
|
+
const requests = [];
|
|
74
|
+
let after = 0;
|
|
75
|
+
const startedAt = Date.now();
|
|
76
|
+
while (true) {
|
|
77
|
+
const remaining = maxTimeoutMs != null ? maxTimeoutMs - (Date.now() - startedAt) : null;
|
|
78
|
+
if (remaining != null && remaining <= 0) {
|
|
79
|
+
return { requests, timedOut: true };
|
|
80
|
+
}
|
|
81
|
+
const timeoutMs = remaining != null ? Math.min(settleMs, remaining) : settleMs;
|
|
82
|
+
const response = await fetchWatcherJson(watcher, {
|
|
83
|
+
path: '/net/tail',
|
|
84
|
+
query: createNetTailParams(options, after, timeoutMs),
|
|
85
|
+
timeoutMs: timeoutMs + 5_000,
|
|
86
|
+
});
|
|
87
|
+
if (response.requests.length === 0) {
|
|
88
|
+
return { requests, timedOut: maxTimeoutMs != null && timeoutMs < settleMs };
|
|
89
|
+
}
|
|
90
|
+
requests.push(...response.requests);
|
|
91
|
+
after = response.nextAfter;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const createNetTailParams = (options, after, timeoutMs) => {
|
|
95
|
+
const params = new URLSearchParams();
|
|
96
|
+
params.set('after', String(after));
|
|
97
|
+
params.set('limit', String(WATCH_BATCH_LIMIT));
|
|
98
|
+
params.set('timeoutMs', String(timeoutMs));
|
|
99
|
+
const query = appendNetCommandParams(params, { ...options, after: String(after), limit: String(WATCH_BATCH_LIMIT) }, { includeAfter: false });
|
|
100
|
+
if (query.error) {
|
|
101
|
+
throw new Error(query.error);
|
|
102
|
+
}
|
|
103
|
+
return params;
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=netCapture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netCapture.js","sourceRoot":"","sources":["../../src/commands/netCapture.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netClear.d.ts","sourceRoot":"","sources":["../../src/commands/netClear.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,eAAe,GAAG;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAA;CACd,CAAA;AAED,eAAO,MAAM,WAAW,GAAU,IAAI,MAAM,GAAG,SAAS,EAAE,SAAS,eAAe,KAAG,OAAO,CAAC,IAAI,CAqBhG,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createOutput } from '../output/io.js';
|
|
2
|
+
import { requestWatcherAction } from '../watchers/requestWatcher.js';
|
|
3
|
+
export const runNetClear = async (id, options) => {
|
|
4
|
+
const output = createOutput(options);
|
|
5
|
+
const result = await requestWatcherAction({
|
|
6
|
+
id,
|
|
7
|
+
path: '/net/clear',
|
|
8
|
+
method: 'POST',
|
|
9
|
+
timeoutMs: 5_000,
|
|
10
|
+
}, output);
|
|
11
|
+
if (!result) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (options.json) {
|
|
15
|
+
output.writeJson(result.data);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
output.writeHuman(`cleared ${result.data.cleared} requests from ${result.watcher.id}`);
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=netClear.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netClear.js","sourceRoot":"","sources":["../../src/commands/netClear.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AAMpE,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,EAAsB,EAAE,OAAwB,EAAiB,EAAE;IACpG,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;IACpC,MAAM,MAAM,GAAG,MAAM,oBAAoB,CACxC;QACC,EAAE;QACF,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,MAAM;QACd,SAAS,EAAE,KAAK;KAChB,EACD,MAAM,CACN,CAAA;IACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,OAAM;IACP,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAC7B,OAAM;IACP,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,WAAW,MAAM,CAAC,IAAI,CAAC,OAAO,kBAAkB,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;AACvF,CAAC,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { NetCliFilterOptions } from './netShared.js';
|
|
2
|
+
export type NetExportOptions = NetCliFilterOptions & {
|
|
3
|
+
json?: boolean;
|
|
4
|
+
out?: string;
|
|
5
|
+
format?: string;
|
|
6
|
+
reload?: boolean;
|
|
7
|
+
clear?: boolean;
|
|
8
|
+
settle?: string;
|
|
9
|
+
ignoreCache?: boolean;
|
|
10
|
+
maxTimeout?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare const runNetExport: (id: string | undefined, options: NetExportOptions) => Promise<void>;
|
|
13
|
+
//# sourceMappingURL=netExport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netExport.d.ts","sourceRoot":"","sources":["../../src/commands/netExport.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAgBzD,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,GAAG;IACpD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,eAAO,MAAM,YAAY,GAAU,IAAI,MAAM,GAAG,SAAS,EAAE,SAAS,gBAAgB,KAAG,OAAO,CAAC,IAAI,CA2DlG,CAAA"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { captureNetWindow, parseNetCaptureOptions } from './netCapture.js';
|
|
4
|
+
import { appendNetCommandParams, validateNetCommandOptions } from './netShared.js';
|
|
5
|
+
import { buildHarFromNetworkRequests } from '../net/har.js';
|
|
6
|
+
import { createOutput } from '../output/io.js';
|
|
7
|
+
import { resolvePath } from '../utils/paths.js';
|
|
8
|
+
import { fetchWatcherJson, formatWatcherTransportError, resolveWatcherOrExit } from '../watchers/requestWatcher.js';
|
|
9
|
+
const NET_EXPORT_PAGE_LIMIT = 5_000;
|
|
10
|
+
export const runNetExport = async (id, options) => {
|
|
11
|
+
const output = createOutput(options);
|
|
12
|
+
const validated = validateNetExportOptions(options);
|
|
13
|
+
if (validated.error || !validated.value) {
|
|
14
|
+
output.writeWarn(validated.error ?? 'Invalid net export options.');
|
|
15
|
+
process.exitCode = 2;
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const resolved = await resolveWatcherOrExit({ id }, output);
|
|
19
|
+
if (!resolved) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const { watcher } = resolved;
|
|
23
|
+
const exportOptions = validated.value;
|
|
24
|
+
let cleared = 0;
|
|
25
|
+
let timedOut = false;
|
|
26
|
+
let requests;
|
|
27
|
+
try {
|
|
28
|
+
if (exportOptions.capture) {
|
|
29
|
+
const captured = await captureNetWindow(watcher, options, exportOptions.capture);
|
|
30
|
+
cleared = captured.cleared;
|
|
31
|
+
timedOut = captured.timedOut;
|
|
32
|
+
}
|
|
33
|
+
requests = await fetchAllNetworkRequestDetails(watcher, options);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
output.writeWarn(formatWatcherTransportError(watcher, error));
|
|
37
|
+
process.exitCode = 1;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const har = buildHarFromNetworkRequests(requests);
|
|
41
|
+
const outPath = resolvePath(exportOptions.out);
|
|
42
|
+
try {
|
|
43
|
+
await writeHarFile(outPath, har);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
output.writeWarn(`Failed to write HAR file: ${error instanceof Error ? error.message : String(error)}`);
|
|
47
|
+
process.exitCode = 1;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (options.json) {
|
|
51
|
+
output.writeJson({
|
|
52
|
+
ok: true,
|
|
53
|
+
format: exportOptions.format,
|
|
54
|
+
out: outPath,
|
|
55
|
+
requestCount: requests.length,
|
|
56
|
+
reloaded: exportOptions.capture?.shouldReload ?? false,
|
|
57
|
+
cleared,
|
|
58
|
+
timedOut,
|
|
59
|
+
});
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
output.writeHuman(formatHarSavedMessage(outPath, requests.length, timedOut));
|
|
63
|
+
};
|
|
64
|
+
const validateNetExportOptions = (options) => {
|
|
65
|
+
const out = options.out?.trim();
|
|
66
|
+
if (!out) {
|
|
67
|
+
return { error: 'Missing --out value.' };
|
|
68
|
+
}
|
|
69
|
+
const format = (options.format?.trim().toLowerCase() ?? 'har');
|
|
70
|
+
if (format !== 'har') {
|
|
71
|
+
return { error: `Unsupported --format value: ${options.format}. Only "har" is supported right now.` };
|
|
72
|
+
}
|
|
73
|
+
if (options.reload) {
|
|
74
|
+
const capture = parseNetCaptureOptions(options, { defaultClear: true });
|
|
75
|
+
if (capture.error || !capture.value) {
|
|
76
|
+
return { error: capture.error ?? 'Invalid capture options.' };
|
|
77
|
+
}
|
|
78
|
+
return { value: { out, format: 'har', capture: capture.value } };
|
|
79
|
+
}
|
|
80
|
+
const validation = validateNetCommandOptions(options);
|
|
81
|
+
if (validation.error) {
|
|
82
|
+
return { error: validation.error };
|
|
83
|
+
}
|
|
84
|
+
return { value: { out, format: 'har' } };
|
|
85
|
+
};
|
|
86
|
+
const writeHarFile = async (outPath, har) => {
|
|
87
|
+
await fs.mkdir(path.dirname(outPath), { recursive: true });
|
|
88
|
+
await fs.writeFile(outPath, `${JSON.stringify(har, null, 2)}\n`, 'utf8');
|
|
89
|
+
};
|
|
90
|
+
const formatHarSavedMessage = (outPath, requestCount, timedOut) => {
|
|
91
|
+
if (timedOut) {
|
|
92
|
+
return `HAR saved: ${outPath} (${requestCount} requests, max timeout reached before quiet window)`;
|
|
93
|
+
}
|
|
94
|
+
return `HAR saved: ${outPath} (${requestCount} requests)`;
|
|
95
|
+
};
|
|
96
|
+
const fetchAllNetworkRequestDetails = async (watcher, options) => {
|
|
97
|
+
const requests = [];
|
|
98
|
+
let after = 0;
|
|
99
|
+
const baseParams = createNetRequestsBaseParams(options);
|
|
100
|
+
while (true) {
|
|
101
|
+
const params = new URLSearchParams(baseParams);
|
|
102
|
+
params.set('after', String(after));
|
|
103
|
+
params.set('limit', String(NET_EXPORT_PAGE_LIMIT));
|
|
104
|
+
const response = await fetchWatcherJson(watcher, {
|
|
105
|
+
path: '/net/requests',
|
|
106
|
+
query: params,
|
|
107
|
+
timeoutMs: 5_000,
|
|
108
|
+
});
|
|
109
|
+
if (response.requests.length === 0) {
|
|
110
|
+
return requests;
|
|
111
|
+
}
|
|
112
|
+
requests.push(...response.requests);
|
|
113
|
+
after = response.nextAfter;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const createNetRequestsBaseParams = (options) => {
|
|
117
|
+
const params = new URLSearchParams();
|
|
118
|
+
const query = appendNetCommandParams(params, options, { includeAfter: false, includeLimit: false });
|
|
119
|
+
if (query.error) {
|
|
120
|
+
throw new Error(query.error);
|
|
121
|
+
}
|
|
122
|
+
return params;
|
|
123
|
+
};
|
|
124
|
+
//# sourceMappingURL=netExport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netExport.js","sourceRoot":"","sources":["../../src/commands/netExport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type NetCaptureOptions } from './netCapture.js';
|
|
2
|
+
export type NetInspectOptions = NetCaptureOptions & {
|
|
3
|
+
request?: boolean;
|
|
4
|
+
response?: boolean;
|
|
5
|
+
json?: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Happy-path network inspection:
|
|
9
|
+
* capture a fresh request window, pick the newest URL match, then fetch detail + bodies in one go.
|
|
10
|
+
*/
|
|
11
|
+
export declare const runNetInspect: (id: string | undefined, pattern: string, options: NetInspectOptions) => Promise<void>;
|
|
12
|
+
//# sourceMappingURL=netInspect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netInspect.d.ts","sourceRoot":"","sources":["../../src/commands/netInspect.ts"],"names":[],"mappings":"AAMA,OAAO,EAA4C,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAGlG,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,GAAG;IACnD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,OAAO,CAAA;CACd,CAAA;AAoBD;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAU,IAAI,MAAM,GAAG,SAAS,EAAE,SAAS,MAAM,EAAE,SAAS,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAgGrH,CAAA"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { createOutput } from '../output/io.js';
|
|
2
|
+
import { formatNetworkRequestInspect, renderNetworkBodyText } from '../output/net.js';
|
|
3
|
+
import { resolveWatcherOrExit, writeErrorResponse } from '../watchers/requestWatcher.js';
|
|
4
|
+
import { appendNetCommandParams } from './netShared.js';
|
|
5
|
+
import { captureNetWindow, parseNetCaptureOptions } from './netCapture.js';
|
|
6
|
+
import { fetchNetRequestBody, fetchNetRequestDetail, fetchNetRequestSummaries } from './netRequestClient.js';
|
|
7
|
+
/**
|
|
8
|
+
* Happy-path network inspection:
|
|
9
|
+
* capture a fresh request window, pick the newest URL match, then fetch detail + bodies in one go.
|
|
10
|
+
*/
|
|
11
|
+
export const runNetInspect = async (id, pattern, options) => {
|
|
12
|
+
const output = createOutput(options);
|
|
13
|
+
const normalizedPattern = pattern.trim();
|
|
14
|
+
if (!normalizedPattern) {
|
|
15
|
+
writeInspectError(output, 'invalid_request', 'pattern is required', 2);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const resolved = await resolveWatcherOrExit({ id }, output);
|
|
19
|
+
if (!resolved) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const captureOptions = parseNetCaptureOptions({
|
|
23
|
+
...options,
|
|
24
|
+
grep: normalizedPattern,
|
|
25
|
+
reload: options.reload ?? true,
|
|
26
|
+
}, { defaultClear: true });
|
|
27
|
+
if (captureOptions.error || !captureOptions.value) {
|
|
28
|
+
writeInspectError(output, 'invalid_request', captureOptions.error ?? 'Invalid net inspect options.', 2);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const captureStartedAt = Date.now();
|
|
32
|
+
const captured = await captureNetWindow(resolved.watcher, buildInspectSettleFilters(options), captureOptions.value).catch((error) => {
|
|
33
|
+
output.writeWarn(`${resolved.watcher.id}: failed to inspect network (${error instanceof Error ? error.message : String(error)})`);
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
return null;
|
|
36
|
+
});
|
|
37
|
+
if (!captured) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const matchedRequests = await fetchInspectedRequests(resolved.watcher, options, normalizedPattern, captureStartedAt, output);
|
|
41
|
+
if (!matchedRequests) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const selected = matchedRequests[matchedRequests.length - 1];
|
|
45
|
+
if (!selected) {
|
|
46
|
+
writeInspectNoMatch(output, normalizedPattern, captureOptions.value.settleMs, captured.timedOut);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const query = createNetRequestIdQuery(selected.id);
|
|
50
|
+
const detail = await fetchNetRequestDetail(resolved.watcher, query, output);
|
|
51
|
+
if (!detail) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const parts = resolveInspectBodyParts(options);
|
|
55
|
+
const requestBody = parts.includes('request')
|
|
56
|
+
? await fetchInspectableBody(resolved.watcher, query, detail, 'request', output)
|
|
57
|
+
: { body: null, abort: false };
|
|
58
|
+
if (requestBody.abort) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const responseBody = parts.includes('response')
|
|
62
|
+
? await fetchInspectableBody(resolved.watcher, query, detail, 'response', output)
|
|
63
|
+
: { body: null, abort: false };
|
|
64
|
+
if (responseBody.abort) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const result = {
|
|
68
|
+
ok: true,
|
|
69
|
+
pattern: normalizedPattern,
|
|
70
|
+
cleared: captured.cleared,
|
|
71
|
+
reloaded: captureOptions.value.shouldReload,
|
|
72
|
+
settleMs: captureOptions.value.settleMs,
|
|
73
|
+
timedOut: captured.timedOut,
|
|
74
|
+
matchedCount: matchedRequests.length,
|
|
75
|
+
request: detail,
|
|
76
|
+
requestBody: requestBody.body,
|
|
77
|
+
responseBody: responseBody.body,
|
|
78
|
+
};
|
|
79
|
+
if (options.json) {
|
|
80
|
+
output.writeJson(result);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
for (const line of formatNetworkRequestInspect(detail, { matchedCount: matchedRequests.length, pattern: normalizedPattern })) {
|
|
84
|
+
output.writeHuman(line);
|
|
85
|
+
}
|
|
86
|
+
if (parts.includes('request')) {
|
|
87
|
+
writeBodySection(output, 'Request body', requestBody.body, detail.body.request);
|
|
88
|
+
}
|
|
89
|
+
if (parts.includes('response')) {
|
|
90
|
+
writeBodySection(output, 'Response body', responseBody.body, detail.body.response);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const fetchInspectableBody = async (watcher, query, detail, part, output) => {
|
|
94
|
+
if (!detail.body[part]) {
|
|
95
|
+
return { body: null, abort: false };
|
|
96
|
+
}
|
|
97
|
+
const response = await fetchNetRequestBody(watcher, query, part, output, { writeApiErrors: false });
|
|
98
|
+
if (!response) {
|
|
99
|
+
return { body: null, abort: true };
|
|
100
|
+
}
|
|
101
|
+
if (!response.ok) {
|
|
102
|
+
if (response.error.code === 'body_not_available') {
|
|
103
|
+
return { body: null, abort: false };
|
|
104
|
+
}
|
|
105
|
+
writeErrorResponse(response, output);
|
|
106
|
+
return { body: null, abort: true };
|
|
107
|
+
}
|
|
108
|
+
return { body: response, abort: false };
|
|
109
|
+
};
|
|
110
|
+
const resolveInspectBodyParts = (options) => {
|
|
111
|
+
const parts = [];
|
|
112
|
+
if (options.request) {
|
|
113
|
+
parts.push('request');
|
|
114
|
+
}
|
|
115
|
+
if (options.response) {
|
|
116
|
+
parts.push('response');
|
|
117
|
+
}
|
|
118
|
+
return parts.length > 0 ? parts : ['request', 'response'];
|
|
119
|
+
};
|
|
120
|
+
const buildInspectFilters = (options, pattern) => ({
|
|
121
|
+
grep: pattern,
|
|
122
|
+
host: options.host,
|
|
123
|
+
method: options.method,
|
|
124
|
+
status: options.status,
|
|
125
|
+
resourceType: options.resourceType,
|
|
126
|
+
mime: options.mime,
|
|
127
|
+
scope: options.scope,
|
|
128
|
+
frame: options.frame,
|
|
129
|
+
firstParty: options.firstParty,
|
|
130
|
+
thirdParty: options.thirdParty,
|
|
131
|
+
failedOnly: options.failedOnly,
|
|
132
|
+
slowOver: options.slowOver,
|
|
133
|
+
largeOver: options.largeOver,
|
|
134
|
+
ignoreHost: options.ignoreHost,
|
|
135
|
+
ignorePattern: options.ignorePattern,
|
|
136
|
+
});
|
|
137
|
+
const createNetRequestIdQuery = (id) => new URLSearchParams({ id: String(id) });
|
|
138
|
+
/**
|
|
139
|
+
* `net inspect` waits for the page to go quiet, not just for matching requests to stop.
|
|
140
|
+
* That keeps late boot requests observable even when the app spends its first few seconds
|
|
141
|
+
* on unrelated assets or setup calls before hitting the endpoint we care about.
|
|
142
|
+
*/
|
|
143
|
+
const buildInspectSettleFilters = (options) => ({
|
|
144
|
+
scope: options.scope,
|
|
145
|
+
frame: options.frame,
|
|
146
|
+
firstParty: options.firstParty,
|
|
147
|
+
thirdParty: options.thirdParty,
|
|
148
|
+
ignoreHost: options.ignoreHost,
|
|
149
|
+
ignorePattern: options.ignorePattern,
|
|
150
|
+
});
|
|
151
|
+
const fetchInspectedRequests = async (watcher, options, pattern, captureStartedAt, output) => {
|
|
152
|
+
const query = new URLSearchParams();
|
|
153
|
+
const appended = appendNetCommandParams(query, {
|
|
154
|
+
...buildInspectFilters(options, pattern),
|
|
155
|
+
limit: '5000',
|
|
156
|
+
}, { includeAfter: false });
|
|
157
|
+
if (appended.error) {
|
|
158
|
+
writeInspectError(output, 'invalid_request', appended.error, 2);
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
query.set('sinceTs', String(captureStartedAt));
|
|
162
|
+
return await fetchNetRequestSummaries(watcher, query, output);
|
|
163
|
+
};
|
|
164
|
+
const writeBodySection = (output, title, body, available) => {
|
|
165
|
+
output.writeHuman('');
|
|
166
|
+
if (!available || !body) {
|
|
167
|
+
output.writeHuman(`${title}: not available`);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
output.writeHuman(`${title}${body.mimeType ? ` (${body.mimeType})` : ''}:`);
|
|
171
|
+
const rendered = renderNetworkBodyText(body);
|
|
172
|
+
if (rendered == null) {
|
|
173
|
+
output.writeHuman('[base64-encoded binary data; re-run with --json for the raw payload]');
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
process.stdout.write(prettifyJsonLikeBody(rendered));
|
|
177
|
+
};
|
|
178
|
+
const prettifyJsonLikeBody = (value) => {
|
|
179
|
+
const trimmed = value.trim();
|
|
180
|
+
if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {
|
|
181
|
+
return value.endsWith('\n') ? value : `${value}\n`;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
return `${JSON.stringify(JSON.parse(trimmed), null, 2)}\n`;
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return value.endsWith('\n') ? value : `${value}\n`;
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
const writeInspectError = (output, code, message, exitCode) => {
|
|
191
|
+
if (output.json) {
|
|
192
|
+
output.writeJson({ ok: false, error: { code, message } });
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
output.writeWarn(message);
|
|
196
|
+
}
|
|
197
|
+
process.exitCode = exitCode;
|
|
198
|
+
};
|
|
199
|
+
const writeInspectNoMatch = (output, pattern, settleMs, timedOut) => {
|
|
200
|
+
const message = timedOut
|
|
201
|
+
? `No requests matched "${pattern}" before the max timeout expired (quiet window ${settleMs}ms).`
|
|
202
|
+
: `No requests matched "${pattern}" after the ${settleMs}ms quiet window.`;
|
|
203
|
+
writeInspectError(output, 'not_found', message, 1);
|
|
204
|
+
};
|
|
205
|
+
//# sourceMappingURL=netInspect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netInspect.js","sourceRoot":"","sources":["../../src/commands/netInspect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ErrorResponse, NetRequestBodyPart, NetRequestBodyResponse, NetworkRequestSummary, NetworkRequestDetail, WatcherRecord } from '@vforsh/argus-core';
|
|
2
|
+
import type { Output } from '../output/io.js';
|
|
3
|
+
/**
|
|
4
|
+
* Fetch one buffered network request detail record from a resolved watcher.
|
|
5
|
+
* API errors are written to output and normalized to `null` so commands stay linear.
|
|
6
|
+
*/
|
|
7
|
+
export declare const fetchNetRequestDetail: (watcher: Pick<WatcherRecord, "id" | "host" | "port">, query: URLSearchParams, output: Output) => Promise<NetworkRequestDetail | null>;
|
|
8
|
+
/** Fetch buffered request summaries for follow-up selection after a reload capture settles. */
|
|
9
|
+
export declare const fetchNetRequestSummaries: (watcher: Pick<WatcherRecord, "id" | "host" | "port">, query: URLSearchParams, output: Output) => Promise<NetworkRequestSummary[] | null>;
|
|
10
|
+
/**
|
|
11
|
+
* Fetch one lazy request/response body from a resolved watcher.
|
|
12
|
+
* Returns `null` for fatal output-handled failures and the raw error payload for recoverable callers.
|
|
13
|
+
*/
|
|
14
|
+
export declare const fetchNetRequestBody: (watcher: Pick<WatcherRecord, "id" | "host" | "port">, query: URLSearchParams, part: NetRequestBodyPart, output: Output, config?: {
|
|
15
|
+
writeApiErrors?: boolean;
|
|
16
|
+
}) => Promise<NetRequestBodyResponse | ErrorResponse | null>;
|
|
17
|
+
//# sourceMappingURL=netRequestClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netRequestClient.d.ts","sourceRoot":"","sources":["../../src/commands/netRequestClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,aAAa,EAEb,kBAAkB,EAClB,sBAAsB,EAEtB,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,EACb,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAM7C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GACjC,SAAS,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,EACpD,OAAO,eAAe,EACtB,QAAQ,MAAM,KACZ,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAOrC,CAAA;AAED,+FAA+F;AAC/F,eAAO,MAAM,wBAAwB,GACpC,SAAS,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,EACpD,OAAO,eAAe,EACtB,QAAQ,MAAM,KACZ,OAAO,CAAC,qBAAqB,EAAE,GAAG,IAAI,CAOxC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC/B,SAAS,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,EACpD,OAAO,eAAe,EACtB,MAAM,kBAAkB,EACxB,QAAQ,MAAM,EACd,SAAQ;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,KACvC,OAAO,CAAC,sBAAsB,GAAG,aAAa,GAAG,IAAI,CAIvD,CAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { fetchWatcherJson, formatWatcherTransportError, writeErrorResponse } from '../watchers/requestWatcher.js';
|
|
2
|
+
const NET_REQUEST_TIMEOUT_MS = 5_000;
|
|
3
|
+
const NET_REQUEST_BODY_TIMEOUT_MS = 10_000;
|
|
4
|
+
/**
|
|
5
|
+
* Fetch one buffered network request detail record from a resolved watcher.
|
|
6
|
+
* API errors are written to output and normalized to `null` so commands stay linear.
|
|
7
|
+
*/
|
|
8
|
+
export const fetchNetRequestDetail = async (watcher, query, output) => {
|
|
9
|
+
const response = await fetchNetRequestRoute(watcher, '/net/request', query, NET_REQUEST_TIMEOUT_MS, output);
|
|
10
|
+
if (!response || !response.ok) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
return response.request;
|
|
14
|
+
};
|
|
15
|
+
/** Fetch buffered request summaries for follow-up selection after a reload capture settles. */
|
|
16
|
+
export const fetchNetRequestSummaries = async (watcher, query, output) => {
|
|
17
|
+
const response = await fetchNetRequestRoute(watcher, '/net', query, NET_REQUEST_TIMEOUT_MS, output);
|
|
18
|
+
if (!response || !response.ok) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return response.requests;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Fetch one lazy request/response body from a resolved watcher.
|
|
25
|
+
* Returns `null` for fatal output-handled failures and the raw error payload for recoverable callers.
|
|
26
|
+
*/
|
|
27
|
+
export const fetchNetRequestBody = async (watcher, query, part, output, config = {}) => {
|
|
28
|
+
const bodyQuery = new URLSearchParams(query);
|
|
29
|
+
bodyQuery.set('part', part);
|
|
30
|
+
return await fetchNetRequestRoute(watcher, '/net/request/body', bodyQuery, NET_REQUEST_BODY_TIMEOUT_MS, output, config);
|
|
31
|
+
};
|
|
32
|
+
const fetchNetRequestRoute = async (watcher, path, query, timeoutMs, output, config = {}) => {
|
|
33
|
+
try {
|
|
34
|
+
const response = await fetchWatcherJson(watcher, {
|
|
35
|
+
path,
|
|
36
|
+
query,
|
|
37
|
+
timeoutMs,
|
|
38
|
+
returnErrorResponse: true,
|
|
39
|
+
});
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
if (config.writeApiErrors !== false) {
|
|
42
|
+
writeErrorResponse(response, output);
|
|
43
|
+
}
|
|
44
|
+
return response;
|
|
45
|
+
}
|
|
46
|
+
return response;
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
output.writeWarn(formatWatcherTransportError(watcher, error));
|
|
50
|
+
process.exitCode = 1;
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=netRequestClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netRequestClient.js","sourceRoot":"","sources":["../../src/commands/netRequestClient.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAEjH,MAAM,sBAAsB,GAAG,KAAK,CAAA;AACpC,MAAM,2BAA2B,GAAG,MAAM,CAAA;AAE1C;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACzC,OAAoD,EACpD,KAAsB,EACtB,MAAc,EACyB,EAAE;IACzC,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAqB,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAA;IAC/H,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAA;IACZ,CAAC;IAED,OAAO,QAAQ,CAAC,OAAO,CAAA;AACxB,CAAC,CAAA;AAED,+FAA+F;AAC/F,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,EAC5C,OAAoD,EACpD,KAAsB,EACtB,MAAc,EAC4B,EAAE;IAC5C,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAc,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAA;IAChH,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAA;IACZ,CAAC;IAED,OAAO,QAAQ,CAAC,QAAQ,CAAA;AACzB,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EACvC,OAAoD,EACpD,KAAsB,EACtB,IAAwB,EACxB,MAAc,EACd,SAAuC,EAAE,EACgB,EAAE;IAC3D,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,CAAA;IAC5C,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IAC3B,OAAO,MAAM,oBAAoB,CAAyB,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,2BAA2B,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAChJ,CAAC,CAAA;AAED,MAAM,oBAAoB,GAAG,KAAK,EACjC,OAAoD,EACpD,IAAY,EACZ,KAAsB,EACtB,SAAiB,EACjB,MAAc,EACd,SAAuC,EAAE,EACL,EAAE;IACtC,IAAI,CAAC;QACJ,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAoB,OAAO,EAAE;YACnE,IAAI;YACJ,KAAK;YACL,SAAS;YACT,mBAAmB,EAAE,IAAI;SACzB,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YAClB,IAAI,MAAM,CAAC,cAAc,KAAK,KAAK,EAAE,CAAC;gBACrC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;YACrC,CAAC;YACD,OAAO,QAAQ,CAAA;QAChB,CAAC;QAED,OAAO,QAAQ,CAAA;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,CAAC,SAAS,CAAC,2BAA2B,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAA;QAC7D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAO,IAAI,CAAA;IACZ,CAAC;AACF,CAAC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Output } from '../output/io.js';
|
|
2
|
+
/**
|
|
3
|
+
* Accept either an Argus numeric buffer id or a raw CDP request id and turn it into watcher query params.
|
|
4
|
+
*/
|
|
5
|
+
export declare const buildNetRequestLookupQuery: (request: string, output: Output) => URLSearchParams | null;
|
|
6
|
+
/** Parse a CLI request selector into watcher query params. */
|
|
7
|
+
export declare const resolveNetRequestLookupQuery: (request: string) => {
|
|
8
|
+
query: URLSearchParams;
|
|
9
|
+
error?: never;
|
|
10
|
+
} | {
|
|
11
|
+
error: string;
|
|
12
|
+
query?: never;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=netRequestTarget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netRequestTarget.d.ts","sourceRoot":"","sources":["../../src/commands/netRequestTarget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAE7C;;GAEG;AACH,eAAO,MAAM,0BAA0B,GAAI,SAAS,MAAM,EAAE,QAAQ,MAAM,KAAG,eAAe,GAAG,IAS9F,CAAA;AAED,8DAA8D;AAC9D,eAAO,MAAM,4BAA4B,GAAI,SAAS,MAAM,KAAG;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAexI,CAAA"}
|