@dimina-kit/devtools 0.4.0-dev.20260907055341 → 0.5.0-dev.20260908120530
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/README.md +1 -1
- package/dist/main/app/window-runtime-services.d.ts +12 -12
- package/dist/main/app/window-runtime-services.js +34 -15
- package/dist/main/index.bundle.js +6307 -6050
- package/dist/main/services/elements-forward/index.d.ts +2 -2
- package/dist/main/services/elements-forward/index.js +6 -6
- package/dist/main/services/network-forward/body-cache.d.ts +2 -0
- package/dist/main/services/network-forward/body-cache.js +4 -0
- package/dist/main/services/network-forward/global-body-gate.d.ts +1 -1
- package/dist/main/services/network-forward/global-body-gate.js +4 -4
- package/dist/main/services/network-forward/http.d.ts +47 -0
- package/dist/main/services/network-forward/http.js +162 -0
- package/dist/main/services/network-forward/index.d.ts +19 -13
- package/dist/main/services/network-forward/index.js +220 -134
- package/dist/main/services/network-forward/request-ids.d.ts +5 -0
- package/dist/main/services/network-forward/request-ids.js +5 -0
- package/dist/main/services/safe-area/index.d.ts +7 -9
- package/dist/main/services/safe-area/index.js +7 -14
- package/dist/main/services/views/native-simulator-view.js +7 -8
- package/dist/main/services/workbench-context.d.ts +3 -3
- package/dist/main/services/workbench-context.js +7 -1
- package/dist/native-host/render/render.js +525 -482
- package/dist/native-host/service/service.js +2 -2
- package/dist/preload/shared/api-compat.js +63 -41
- package/dist/preload/windows/main.cjs +15 -1
- package/dist/preload/windows/main.cjs.map +2 -2
- package/dist/preload/windows/simulator.cjs +55 -134
- package/dist/preload/windows/simulator.cjs.map +4 -4
- package/dist/preload/windows/simulator.js +55 -134
- package/dist/renderer/assets/workbench-C0Jkdlps.js +5 -0
- package/dist/renderer/entries/workbench/index.html +1 -1
- package/dist/shared/types.d.ts +2 -0
- package/dist/simulator/assets/device-shell-DucLepkm.js +431 -0
- package/dist/simulator/assets/simulator-B4rbcOVt.js +10 -0
- package/dist/simulator/assets/simulator-ui-i3GCc7YJ.js +2 -0
- package/dist/simulator/simulator.html +2 -2
- package/package.json +12 -12
- package/dist/renderer/assets/workbench-BLJ0wKsg.js +0 -5
- package/dist/shared/request-core.d.ts +0 -2
- package/dist/shared/request-core.js +0 -2
- package/dist/simulator/assets/device-shell-pxnZZp10.js +0 -431
- package/dist/simulator/assets/simulator-Dwp7lnvu.js +0 -10
- package/dist/simulator/assets/simulator-ui-B2ddJB1R.js +0 -2
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
import type { WebContents } from 'electron';
|
|
61
61
|
import type { ConnectionRegistry } from '@dimina-kit/electron-deck/main';
|
|
62
62
|
import type { BridgeRouterHandle } from '../../ipc/bridge-router.js';
|
|
63
|
-
import {
|
|
63
|
+
import type { NetworkBodyProvider } from '../network-forward/index.js';
|
|
64
64
|
import { type CdpSessionBroker } from '../cdp-session/index.js';
|
|
65
65
|
/**
|
|
66
66
|
* Which target a front-end CDP command is routed to.
|
|
@@ -108,7 +108,7 @@ export declare const NETWORK_BODY_METHODS: readonly string[];
|
|
|
108
108
|
* equivalent test driven by the same literals, so the two cannot drift.
|
|
109
109
|
*
|
|
110
110
|
* A non-string / missing requestId routes to 'service': only the
|
|
111
|
-
*
|
|
111
|
+
* simulator and native HTTP namespaces is ours to answer, and the real backend is the
|
|
112
112
|
* correct authority for its own ids.
|
|
113
113
|
*/
|
|
114
114
|
export declare function routeOutboundCommand(method: string, params: unknown): CdpRoute;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isFrontendSettled } from '../views/inject-when-ready.js';
|
|
2
|
-
import {
|
|
2
|
+
import { BODY_REQUEST_ID_PREFIXES } from '../network-forward/request-ids.js';
|
|
3
3
|
import { buildSingleDispatchScript, createFrontendReplyChannel, answerNetworkBodyCommand, drainOutboundBatch } from '../network-forward/frontend-dispatch.js';
|
|
4
4
|
import { createCdpSessionBroker } from '../cdp-session/index.js';
|
|
5
5
|
/**
|
|
@@ -56,7 +56,7 @@ export const NETWORK_BODY_METHODS = [
|
|
|
56
56
|
* equivalent test driven by the same literals, so the two cannot drift.
|
|
57
57
|
*
|
|
58
58
|
* A non-string / missing requestId routes to 'service': only the
|
|
59
|
-
*
|
|
59
|
+
* simulator and native HTTP namespaces is ours to answer, and the real backend is the
|
|
60
60
|
* correct authority for its own ids.
|
|
61
61
|
*/
|
|
62
62
|
export function routeOutboundCommand(method, params) {
|
|
@@ -64,7 +64,7 @@ export function routeOutboundCommand(method, params) {
|
|
|
64
64
|
return 'render';
|
|
65
65
|
if (NETWORK_BODY_METHODS.includes(method)) {
|
|
66
66
|
const requestId = params?.requestId;
|
|
67
|
-
if (typeof requestId === 'string' && requestId.startsWith(
|
|
67
|
+
if (typeof requestId === 'string' && BODY_REQUEST_ID_PREFIXES.some((prefix) => requestId.startsWith(prefix))) {
|
|
68
68
|
return 'network';
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -87,13 +87,13 @@ export function routeOutboundCommand(method, params) {
|
|
|
87
87
|
export function buildElementsHookScript() {
|
|
88
88
|
const prefixes = JSON.stringify(RENDER_DOMAIN_PREFIXES);
|
|
89
89
|
const netMethods = JSON.stringify(NETWORK_BODY_METHODS);
|
|
90
|
-
const vprefix = JSON.stringify(
|
|
90
|
+
const vprefix = JSON.stringify(BODY_REQUEST_ID_PREFIXES);
|
|
91
91
|
return `(function(){try{
|
|
92
92
|
if (globalThis.__diminaElementsHookInstalled) return 'already';
|
|
93
93
|
var OUT = (globalThis.__diminaElementsOutbound = globalThis.__diminaElementsOutbound || []);
|
|
94
94
|
var PREFIXES = ${prefixes};
|
|
95
95
|
var NET_METHODS = ${netMethods};
|
|
96
|
-
var
|
|
96
|
+
var VPREFIXES = ${vprefix};
|
|
97
97
|
function isRender(method){
|
|
98
98
|
if (!method) return false;
|
|
99
99
|
for (var i=0;i<PREFIXES.length;i++){ if (method.indexOf(PREFIXES[i])===0) return true; }
|
|
@@ -104,7 +104,7 @@ export function buildElementsHookScript() {
|
|
|
104
104
|
if (isRender(m.method)) return 'render';
|
|
105
105
|
if (NET_METHODS.indexOf(m.method) >= 0 && m.params
|
|
106
106
|
&& typeof m.params.requestId === 'string'
|
|
107
|
-
&& m.params.requestId.indexOf(
|
|
107
|
+
&& VPREFIXES.some(function(prefix){ return m.params.requestId.indexOf(prefix) === 0; })) return 'network';
|
|
108
108
|
return 'service';
|
|
109
109
|
}
|
|
110
110
|
var IFH = globalThis.InspectorFrontendHost;
|
|
@@ -60,6 +60,8 @@ export declare class PrefetchCache<V> {
|
|
|
60
60
|
*/
|
|
61
61
|
prime(id: string, fetch: () => Promise<V>): boolean;
|
|
62
62
|
lookup(id: string): Promise<V>;
|
|
63
|
+
/** Retire a previous redirect hop without disturbing unrelated cached requests. */
|
|
64
|
+
delete(id: string): void;
|
|
63
65
|
clear(): void;
|
|
64
66
|
get size(): number;
|
|
65
67
|
private isExpired;
|
|
@@ -134,6 +134,10 @@ export class PrefetchCache {
|
|
|
134
134
|
this.map.set(id, e);
|
|
135
135
|
return Promise.resolve(v);
|
|
136
136
|
}
|
|
137
|
+
/** Retire a previous redirect hop without disturbing unrelated cached requests. */
|
|
138
|
+
delete(id) {
|
|
139
|
+
this.map.delete(id);
|
|
140
|
+
}
|
|
137
141
|
clear() {
|
|
138
142
|
this.map.clear();
|
|
139
143
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Installing the full elements-forward gate here would silently reroute the
|
|
13
13
|
* global window's Elements panel to the wrong target. This module intercepts
|
|
14
14
|
* ONLY `Network.getResponseBody` / `Network.getRequestPostData` for
|
|
15
|
-
* `dimina:sim:` virtual requestIds; every other command (including all
|
|
15
|
+
* `dimina:sim:` and `dimina:http:` virtual requestIds; every other command (including all
|
|
16
16
|
* DOM/CSS/Overlay/Runtime/Debugger/…) passes straight through untouched.
|
|
17
17
|
*
|
|
18
18
|
* ── Mechanism (same two-way poll bridge as elements-forward) ───────────────
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isFrontendSettled } from '../views/inject-when-ready.js';
|
|
2
|
-
import {
|
|
2
|
+
import { BODY_REQUEST_ID_PREFIXES } from './request-ids.js';
|
|
3
3
|
import { createFrontendReplyChannel, answerNetworkBodyCommand, drainOutboundBatch } from './frontend-dispatch.js';
|
|
4
4
|
/** The only two Network.* commands this gate ever intercepts. */
|
|
5
5
|
const NETWORK_BODY_METHODS = ['Network.getResponseBody', 'Network.getRequestPostData'];
|
|
@@ -12,16 +12,16 @@ const DRAIN_INTERVAL_MS = 150;
|
|
|
12
12
|
*/
|
|
13
13
|
export function buildNetworkOnlyHookScript() {
|
|
14
14
|
const netMethods = JSON.stringify(NETWORK_BODY_METHODS);
|
|
15
|
-
const vprefix = JSON.stringify(
|
|
15
|
+
const vprefix = JSON.stringify(BODY_REQUEST_ID_PREFIXES);
|
|
16
16
|
return `(function(){try{
|
|
17
17
|
if (globalThis.__diminaGlobalNetworkHookInstalled) return 'already';
|
|
18
18
|
var OUT = (globalThis.__diminaGlobalNetworkOutbound = globalThis.__diminaGlobalNetworkOutbound || []);
|
|
19
19
|
var NET_METHODS = ${netMethods};
|
|
20
|
-
var
|
|
20
|
+
var VPREFIXES = ${vprefix};
|
|
21
21
|
function isNetworkBody(m){
|
|
22
22
|
if (!m || !m.method) return false;
|
|
23
23
|
if (NET_METHODS.indexOf(m.method) < 0) return false;
|
|
24
|
-
return !!(m.params && typeof m.params.requestId === 'string' && m.params.requestId.indexOf(
|
|
24
|
+
return !!(m.params && typeof m.params.requestId === 'string' && VPREFIXES.some(function(prefix){ return m.params.requestId.indexOf(prefix) === 0; }));
|
|
25
25
|
}
|
|
26
26
|
var IFH = globalThis.InspectorFrontendHost;
|
|
27
27
|
if (IFH && typeof IFH.sendMessageToBackend === 'function' && !IFH.__diminaGlobalNetworkWrapped){
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { NativeRequestTrace } from "../../ipc/bridge-router.js";
|
|
2
|
+
/** One CDP message ready for `DevToolsAPI.dispatchMessage` injection. */
|
|
3
|
+
export interface SynthesizedRequestMessage {
|
|
4
|
+
method: string;
|
|
5
|
+
params: unknown;
|
|
6
|
+
/**
|
|
7
|
+
* The verdict `isUserFacingRequest` produced for this request's url at
|
|
8
|
+
* `sent` time, cached for the request's whole lifetime — every later event
|
|
9
|
+
* reuses it (they carry no url of their own). The user-facing sink gates
|
|
10
|
+
* on this; the global mirror ignores it.
|
|
11
|
+
*/
|
|
12
|
+
userFacing: boolean;
|
|
13
|
+
/** Response body ready to prime the forwarder's body-cache, present only
|
|
14
|
+
* on the message synthesized from a `finished` trace event. */
|
|
15
|
+
body?: {
|
|
16
|
+
base64Encoded: boolean;
|
|
17
|
+
body: string;
|
|
18
|
+
};
|
|
19
|
+
/** Request post data ready to prime the forwarder's post-data cache,
|
|
20
|
+
* present only on the message synthesized from the `sent` trace event when
|
|
21
|
+
* the request carried a body. */
|
|
22
|
+
postData?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface RequestTraceSynthesizerOptions {
|
|
25
|
+
/** Per-forwarder instance tag keeping virtual ids collision-free. */
|
|
26
|
+
epoch: string;
|
|
27
|
+
/**
|
|
28
|
+
* Origins the app itself serves (resource server / simulator shell), the
|
|
29
|
+
* same inputs `resolveUserFacing` feeds `isUserFacingRequest` for
|
|
30
|
+
* simulator-captured HTTP traffic. Re-read at each initial `sent`; redirects retain that verdict.
|
|
31
|
+
*/
|
|
32
|
+
internalOrigins?: () => ReadonlyArray<string | null | undefined>;
|
|
33
|
+
}
|
|
34
|
+
export declare class RequestTraceSynthesizer {
|
|
35
|
+
private readonly options;
|
|
36
|
+
private readonly requests;
|
|
37
|
+
private seq;
|
|
38
|
+
constructor(options: RequestTraceSynthesizerOptions);
|
|
39
|
+
/**
|
|
40
|
+
* Map one trace event to its CDP message, or null when the event must be
|
|
41
|
+
* dropped (a non-`sent` event for a requestId this synthesizer never saw
|
|
42
|
+
* sent — defensive against out-of-order delivery).
|
|
43
|
+
*/
|
|
44
|
+
synthesize(sessionId: string, event: NativeRequestTrace): SynthesizedRequestMessage | null;
|
|
45
|
+
private synthesizeRequest;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Synthesize Chrome DevTools Protocol `Network.request*`/`Network.loading*`
|
|
3
|
+
* messages from the main-process HTTP request trace stream (see
|
|
4
|
+
* electron-runtime `native-request/trace.ts`).
|
|
5
|
+
*
|
|
6
|
+
* Why this exists: `wx.request` runs on Node http/https in the MAIN process
|
|
7
|
+
* (see native-request's design notes — this replaced a renderer `fetch()`
|
|
8
|
+
* specifically to stop Chromium's Fetch/CORS algorithm from attaching a
|
|
9
|
+
* spurious OPTIONS preflight to it) — no `webContents.debugger` can observe
|
|
10
|
+
* it, so the embedded DevTools Network tab would otherwise show nothing for
|
|
11
|
+
* every wx.request call. The trace stream gives one ordered fact per
|
|
12
|
+
* lifecycle moment; this module re-shapes each fact into the CDP events the
|
|
13
|
+
* front-end already renders natively for an XHR-classified resource
|
|
14
|
+
* (`requestWillBeSent` creates the row, `responseReceived` fills in
|
|
15
|
+
* status/headers, `loadingFinished`/`loadingFailed` settles it).
|
|
16
|
+
*
|
|
17
|
+
* Ordering contract this module relies on (guaranteed by the trace layer):
|
|
18
|
+
* `sent` strictly precedes every other event for its requestId, and exactly
|
|
19
|
+
* one of `loadingFinished`/`loadingFailed` terminates each sent request. The
|
|
20
|
+
* front-end silently drops loading events for an unknown requestId, so this
|
|
21
|
+
* module mirrors that discipline defensively: any non-`sent` event for an
|
|
22
|
+
* unknown requestId is dropped rather than synthesized.
|
|
23
|
+
*
|
|
24
|
+
* Pure and self-contained (no Electron imports) so it is unit-testable.
|
|
25
|
+
*/
|
|
26
|
+
import { NATIVE_HTTP_REQUEST_ID_PREFIX } from "./request-ids.js";
|
|
27
|
+
import { isUserFacingRequest } from "./user-facing.js";
|
|
28
|
+
/** CDP `Network.ResourceType` this forwarder classifies every wx.request
|
|
29
|
+
* call as — the same bucket the real front-end uses for `XMLHttpRequest`/
|
|
30
|
+
* `fetch()` business calls, so it renders with the matching icon/filter. */
|
|
31
|
+
const RESOURCE_TYPE = "XHR";
|
|
32
|
+
export class RequestTraceSynthesizer {
|
|
33
|
+
options;
|
|
34
|
+
requests = new Map();
|
|
35
|
+
seq = 0;
|
|
36
|
+
constructor(options) {
|
|
37
|
+
this.options = options;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Map one trace event to its CDP message, or null when the event must be
|
|
41
|
+
* dropped (a non-`sent` event for a requestId this synthesizer never saw
|
|
42
|
+
* sent — defensive against out-of-order delivery).
|
|
43
|
+
*/
|
|
44
|
+
synthesize(sessionId, event) {
|
|
45
|
+
const key = `${sessionId} ${event.requestId}`;
|
|
46
|
+
if (event.type === "sent" || event.type === "redirect") {
|
|
47
|
+
return this.synthesizeRequest(key, event);
|
|
48
|
+
}
|
|
49
|
+
const state = this.requests.get(key);
|
|
50
|
+
if (!state)
|
|
51
|
+
return null;
|
|
52
|
+
const { requestId, userFacing } = state;
|
|
53
|
+
const timestamp = event.time / 1000;
|
|
54
|
+
switch (event.type) {
|
|
55
|
+
case "response":
|
|
56
|
+
return {
|
|
57
|
+
method: "Network.responseReceived",
|
|
58
|
+
params: {
|
|
59
|
+
requestId,
|
|
60
|
+
loaderId: requestId,
|
|
61
|
+
timestamp,
|
|
62
|
+
type: RESOURCE_TYPE,
|
|
63
|
+
response: {
|
|
64
|
+
url: state.url,
|
|
65
|
+
status: event.status,
|
|
66
|
+
statusText: event.statusText,
|
|
67
|
+
headers: event.headers,
|
|
68
|
+
// Chromium uses these together to replace provisional headers
|
|
69
|
+
// and expose the verbatim source. ExtraInfo has no raw request
|
|
70
|
+
// text and would override this response snapshot in the frontend.
|
|
71
|
+
...(event.requestHeaders && event.requestHeadersText ? {
|
|
72
|
+
requestHeaders: event.requestHeaders,
|
|
73
|
+
requestHeadersText: event.requestHeadersText,
|
|
74
|
+
} : {}),
|
|
75
|
+
mimeType: mimeTypeOf(event.headers),
|
|
76
|
+
connectionReused: false,
|
|
77
|
+
connectionId: 0,
|
|
78
|
+
encodedDataLength: 0,
|
|
79
|
+
fromDiskCache: false,
|
|
80
|
+
fromServiceWorker: false,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
userFacing,
|
|
84
|
+
};
|
|
85
|
+
case "finished":
|
|
86
|
+
// Terminal: release the id mapping so a long-lived owner can't grow it.
|
|
87
|
+
this.requests.delete(key);
|
|
88
|
+
return {
|
|
89
|
+
method: "Network.loadingFinished",
|
|
90
|
+
params: {
|
|
91
|
+
requestId,
|
|
92
|
+
timestamp,
|
|
93
|
+
encodedDataLength: event.encodedDataLength,
|
|
94
|
+
},
|
|
95
|
+
userFacing,
|
|
96
|
+
...(event.body !== undefined ? { body: { base64Encoded: event.bodyBase64Encoded, body: event.body } } : {}),
|
|
97
|
+
};
|
|
98
|
+
case "failed":
|
|
99
|
+
this.requests.delete(key);
|
|
100
|
+
return {
|
|
101
|
+
method: "Network.loadingFailed",
|
|
102
|
+
params: {
|
|
103
|
+
requestId,
|
|
104
|
+
timestamp,
|
|
105
|
+
type: RESOURCE_TYPE,
|
|
106
|
+
errorText: event.errorText,
|
|
107
|
+
},
|
|
108
|
+
userFacing,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
synthesizeRequest(key, event) {
|
|
113
|
+
const previous = this.requests.get(key);
|
|
114
|
+
if (event.type === "redirect" && !previous)
|
|
115
|
+
return null;
|
|
116
|
+
const requestId = event.type === "redirect" ? previous.requestId
|
|
117
|
+
: `${NATIVE_HTTP_REQUEST_ID_PREFIX}${this.options.epoch}:${this.seq++}`;
|
|
118
|
+
const userFacing = event.type === "redirect" ? previous.userFacing : isUserFacingRequest(event.url, this.options.internalOrigins?.());
|
|
119
|
+
this.requests.set(key, { requestId, url: event.url, userFacing });
|
|
120
|
+
const timestamp = event.time / 1000;
|
|
121
|
+
const hasPostData = event.hasPostData ?? event.postData !== undefined;
|
|
122
|
+
const message = {
|
|
123
|
+
method: "Network.requestWillBeSent",
|
|
124
|
+
params: {
|
|
125
|
+
requestId,
|
|
126
|
+
loaderId: requestId,
|
|
127
|
+
documentURL: event.url,
|
|
128
|
+
request: {
|
|
129
|
+
url: event.url,
|
|
130
|
+
method: event.method,
|
|
131
|
+
headers: event.headers,
|
|
132
|
+
hasPostData,
|
|
133
|
+
...(hasPostData ? { postData: event.postData } : {}),
|
|
134
|
+
},
|
|
135
|
+
timestamp,
|
|
136
|
+
wallTime: timestamp,
|
|
137
|
+
initiator: { type: "script" },
|
|
138
|
+
type: RESOURCE_TYPE,
|
|
139
|
+
...(event.type === "redirect" ? { redirectResponse: {
|
|
140
|
+
...event.redirectResponse,
|
|
141
|
+
mimeType: mimeTypeOf(event.redirectResponse.headers),
|
|
142
|
+
connectionReused: false, connectionId: 0, encodedDataLength: 0,
|
|
143
|
+
} } : {}),
|
|
144
|
+
},
|
|
145
|
+
userFacing,
|
|
146
|
+
};
|
|
147
|
+
if (hasPostData)
|
|
148
|
+
message.postData = event.postData;
|
|
149
|
+
return message;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** `Content-Type: application/json; charset=utf-8` → `application/json`. Case
|
|
153
|
+
* -insensitive header lookup, matching HTTP semantics. */
|
|
154
|
+
function mimeTypeOf(headers) {
|
|
155
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
156
|
+
if (name.toLowerCase() !== "content-type")
|
|
157
|
+
continue;
|
|
158
|
+
return value.split(";")[0]?.trim() ?? "";
|
|
159
|
+
}
|
|
160
|
+
return "";
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -74,18 +74,11 @@
|
|
|
74
74
|
* transport) arrive as trace events via `reportWebSocketTrace` and are
|
|
75
75
|
* synthesized into `Network.webSocket*` CDP messages (see websocket.ts).
|
|
76
76
|
*/
|
|
77
|
-
import type { WebContents } from
|
|
78
|
-
import { type ConnectionRegistry, type Disposable } from
|
|
79
|
-
import { type CdpSessionBroker } from
|
|
80
|
-
import type { NativeWebSocketTrace } from
|
|
81
|
-
|
|
82
|
-
* Namespace prefix of every virtual requestId this forwarder injects into the
|
|
83
|
-
* DevTools front-end. SINGLE SOURCE for the literal: the front-end outbound
|
|
84
|
-
* gate (elements-forward) keys its `Network.getResponseBody` /
|
|
85
|
-
* `Network.getRequestPostData` interception on this exact prefix, so the two
|
|
86
|
-
* modules can never drift apart on what counts as "one of ours".
|
|
87
|
-
*/
|
|
88
|
-
export declare const VIRTUAL_REQUEST_ID_PREFIX = "dimina:sim:";
|
|
77
|
+
import type { WebContents } from "electron";
|
|
78
|
+
import { type ConnectionRegistry, type Disposable } from "@dimina-kit/electron-deck/main";
|
|
79
|
+
import { type CdpSessionBroker } from "../cdp-session/index.js";
|
|
80
|
+
import type { NativeRequestTrace, NativeWebSocketTrace } from "../../ipc/bridge-router.js";
|
|
81
|
+
export { VIRTUAL_REQUEST_ID_PREFIX } from "./request-ids.js";
|
|
89
82
|
/** CDP `Network.getResponseBody` result shape (served from the prefetch cache). */
|
|
90
83
|
export interface CdpResponseBody {
|
|
91
84
|
body: string;
|
|
@@ -106,7 +99,7 @@ export interface NetworkBodyProvider {
|
|
|
106
99
|
}>;
|
|
107
100
|
}
|
|
108
101
|
/** Which layer a captured request came from (tags the fallback log line). */
|
|
109
|
-
export type NetworkSource =
|
|
102
|
+
export type NetworkSource = "service" | "render";
|
|
110
103
|
/** A normalized completed network request, used only by the console fallback. */
|
|
111
104
|
export interface NetworkRequestRecord {
|
|
112
105
|
source: NetworkSource;
|
|
@@ -227,6 +220,19 @@ export interface NetworkForwarder extends Disposable {
|
|
|
227
220
|
* user-facing. Best-effort like every injection point — never throws.
|
|
228
221
|
*/
|
|
229
222
|
reportWebSocketTrace(sessionId: string, event: NativeWebSocketTrace): void;
|
|
223
|
+
/**
|
|
224
|
+
* Surface one main-process HTTP request trace event (wx.request traffic
|
|
225
|
+
* runs on Node http/https, invisible to any debugger, precisely so it
|
|
226
|
+
* skips Chromium's Fetch/CORS algorithm and its OPTIONS preflight) as a
|
|
227
|
+
* synthesized `Network.request*`/`Network.loading*` CDP event, through the
|
|
228
|
+
* SAME channels as forwarded simulator traffic: the global mirror
|
|
229
|
+
* unfiltered, plus the user-facing native sink when the request's url
|
|
230
|
+
* classified user-facing. `finished` primes the body cache (the response is
|
|
231
|
+
* already fully buffered in-process, no CDP round-trip needed); `sent`
|
|
232
|
+
* primes the post-data cache when the request carried a body. Best-effort
|
|
233
|
+
* like every injection point — never throws.
|
|
234
|
+
*/
|
|
235
|
+
reportNativeRequestTrace(sessionId: string, event: NativeRequestTrace): void;
|
|
230
236
|
/**
|
|
231
237
|
* Body/post-data lookups for the virtual requestIds this forwarder injected,
|
|
232
238
|
* backed by the loadingFinished-time prefetch cache. Keyed by virtual id, so
|