@dimina-kit/devtools 0.3.2-dev.20260525152421 → 0.3.2-dev.20260610082053
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 +43 -40
- package/dist/main/api.d.ts +0 -1
- package/dist/main/api.js +5 -1
- package/dist/main/app/app.d.ts +15 -5
- package/dist/main/app/app.js +247 -110
- package/dist/main/app/bootstrap.d.ts +16 -0
- package/dist/main/app/bootstrap.js +20 -0
- package/dist/main/app/launch.d.ts +8 -4
- package/dist/main/app/launch.js +9 -4
- package/dist/main/index.bundle.js +6607 -2102
- package/dist/main/index.js +9 -1
- package/dist/main/ipc/app.d.ts +1 -1
- package/dist/main/ipc/bridge-router.d.ts +61 -0
- package/dist/main/ipc/bridge-router.js +1300 -0
- package/dist/main/ipc/panels.d.ts +1 -1
- package/dist/main/ipc/panels.js +6 -2
- package/dist/main/ipc/popover.d.ts +1 -1
- package/dist/main/ipc/project-fs.d.ts +57 -0
- package/dist/main/ipc/project-fs.js +448 -0
- package/dist/main/ipc/projects.d.ts +1 -1
- package/dist/main/ipc/session.d.ts +1 -1
- package/dist/main/ipc/settings.d.ts +1 -1
- package/dist/main/ipc/simulator-module.d.ts +6 -0
- package/dist/main/ipc/simulator-module.js +11 -1
- package/dist/main/ipc/simulator.d.ts +2 -2
- package/dist/main/ipc/simulator.js +49 -5
- package/dist/main/ipc/toolbar.d.ts +1 -1
- package/dist/main/ipc/views.d.ts +19 -0
- package/dist/main/ipc/views.js +65 -0
- package/dist/main/runtime/devtools-backend.d.ts +17 -0
- package/dist/main/runtime/devtools-backend.js +49 -0
- package/dist/main/runtime/miniapp-runtime.d.ts +39 -0
- package/dist/main/runtime/miniapp-runtime.js +17 -0
- package/dist/main/services/automation/exec.d.ts +27 -2
- package/dist/main/services/automation/exec.js +37 -3
- package/dist/main/services/automation/handlers/app.js +127 -11
- package/dist/main/services/automation/handlers/page.js +36 -19
- package/dist/main/services/automation/index.js +40 -13
- package/dist/main/services/automation/wait-active-page.d.ts +56 -0
- package/dist/main/services/automation/wait-active-page.js +71 -0
- package/dist/main/services/console-forward/index.d.ts +36 -0
- package/dist/main/services/console-forward/index.js +81 -0
- package/dist/main/services/dimina-resource-server.d.ts +7 -0
- package/dist/main/services/dimina-resource-server.js +99 -0
- package/dist/main/services/elements-forward/index.d.ts +66 -0
- package/dist/main/services/elements-forward/index.js +583 -0
- package/dist/main/services/layout/index.d.ts +23 -1
- package/dist/main/services/layout/index.js +28 -3
- package/dist/main/services/mcp/index.d.ts +1 -0
- package/dist/main/services/mcp/index.js +3 -0
- package/dist/main/services/mcp/server.d.ts +1 -1
- package/dist/main/services/mcp/server.js +1 -1
- package/dist/main/services/mcp/target-manager.d.ts +35 -0
- package/dist/main/services/mcp/target-manager.js +63 -1
- package/dist/main/services/mcp/tools/context-tools.js +15 -1
- package/dist/main/services/module.d.ts +1 -1
- package/dist/main/services/network-forward/index.d.ts +190 -0
- package/dist/main/services/network-forward/index.js +765 -0
- package/dist/main/services/notifications/renderer-notifier.d.ts +11 -0
- package/dist/main/services/notifications/renderer-notifier.js +7 -1
- package/dist/main/services/render-inspect/index.d.ts +41 -0
- package/dist/main/services/render-inspect/index.js +88 -0
- package/dist/main/services/safe-area/index.d.ts +17 -0
- package/dist/main/services/safe-area/index.js +59 -0
- package/dist/main/services/service-host-pool/pool.d.ts +197 -0
- package/dist/main/services/service-host-pool/pool.js +364 -0
- package/dist/main/services/simulator/custom-apis.d.ts +34 -0
- package/dist/main/services/simulator/custom-apis.js +22 -0
- package/dist/main/services/simulator-appdata/index.d.ts +35 -0
- package/dist/main/services/simulator-appdata/index.js +71 -0
- package/dist/main/services/simulator-current-page/index.d.ts +24 -0
- package/dist/main/services/simulator-current-page/index.js +19 -0
- package/dist/main/services/simulator-storage/index.d.ts +37 -2
- package/dist/main/services/simulator-storage/index.js +209 -32
- package/dist/main/services/simulator-storage/service-storage-ops.d.ts +40 -0
- package/dist/main/services/simulator-storage/service-storage-ops.js +67 -0
- package/dist/main/services/simulator-temp-files/fs-channels.js +1 -1
- package/dist/main/services/simulator-temp-files/index.d.ts +1 -1
- package/dist/main/services/simulator-temp-files/index.js +1 -1
- package/dist/main/services/simulator-temp-files/request-handler.js +1 -1
- package/dist/main/services/simulator-wxml/index.d.ts +29 -0
- package/dist/main/services/simulator-wxml/index.js +28 -0
- package/dist/main/services/update/update-manager.d.ts +10 -0
- package/dist/main/services/update/update-manager.js +16 -3
- package/dist/main/services/views/devtools-tabs.d.ts +47 -0
- package/dist/main/services/views/devtools-tabs.js +95 -0
- package/dist/main/services/views/view-manager.d.ts +142 -4
- package/dist/main/services/views/view-manager.js +909 -17
- package/dist/main/services/workbench-context.d.ts +66 -1
- package/dist/main/services/workbench-context.js +6 -1
- package/dist/main/services/workspace/workspace-service.d.ts +8 -0
- package/dist/main/services/workspace/workspace-service.js +12 -0
- package/dist/main/utils/ipc-registry.d.ts +11 -2
- package/dist/main/utils/ipc-registry.js +63 -3
- package/dist/main/utils/paths.d.ts +15 -0
- package/dist/main/utils/paths.js +19 -0
- package/dist/main/utils/sender-policy.d.ts +9 -3
- package/dist/main/utils/sender-policy.js +18 -4
- package/dist/main/utils/theme.d.ts +1 -1
- package/dist/main/utils/theme.js +1 -1
- package/dist/main/windows/main-window/create.d.ts +0 -6
- package/dist/main/windows/main-window/create.js +11 -59
- package/dist/main/windows/main-window/events.d.ts +1 -1
- package/dist/main/windows/main-window/events.js +1 -1
- package/dist/main/windows/service-host-window/create.d.ts +52 -0
- package/dist/main/windows/service-host-window/create.js +112 -0
- package/dist/native-host/common/common.js +368 -0
- package/dist/native-host/container/pageFrame.css +1 -0
- package/dist/native-host/render/render.js +9334 -0
- package/dist/native-host/service/service.js +6 -0
- package/dist/preload/index.d.ts +2 -0
- package/dist/preload/index.js +6 -0
- package/dist/preload/instrumentation/app-data.d.ts +18 -20
- package/dist/preload/instrumentation/app-data.js +23 -160
- package/dist/preload/instrumentation/wxml-extract.d.ts +1 -1
- package/dist/preload/instrumentation/wxml-extract.js +1 -1
- package/dist/preload/runtime/bridge.d.ts +3 -8
- package/dist/preload/runtime/bridge.js +2 -32
- package/dist/preload/runtime/custom-apis.js +20 -17
- package/dist/preload/runtime/host-toolbar-advertiser.d.ts +27 -0
- package/dist/preload/runtime/host-toolbar-advertiser.js +55 -0
- package/dist/preload/runtime/main-api-runner.d.ts +9 -0
- package/dist/preload/runtime/main-api-runner.js +85 -0
- package/dist/preload/runtime/native-host.d.ts +43 -0
- package/dist/preload/runtime/native-host.js +83 -0
- package/dist/preload/shared/expose.d.ts +10 -5
- package/dist/preload/shared/expose.js +29 -11
- package/dist/preload/shared/sid-registry.d.ts +11 -0
- package/dist/preload/shared/sid-registry.js +38 -0
- package/dist/preload/windows/host-toolbar.cjs +161 -0
- package/dist/preload/windows/host-toolbar.cjs.map +7 -0
- package/dist/preload/windows/host-toolbar.d.ts +2 -0
- package/dist/preload/windows/host-toolbar.js +12 -0
- package/dist/preload/windows/main.cjs +1939 -0
- package/dist/preload/windows/main.cjs.map +4 -4
- package/dist/preload/windows/simulator.cjs +925 -0
- package/dist/preload/windows/simulator.cjs.map +7 -0
- package/dist/preload/windows/simulator.js +243 -573
- package/dist/render-host/pageFrame.html +29 -0
- package/dist/render-host/preload.cjs +154 -0
- package/dist/render-host/render-inspect.js +295 -0
- package/dist/renderer/assets/abap-DiwvWnMr.js +2 -0
- package/dist/renderer/assets/apex-CmtZjKlf.js +2 -0
- package/dist/renderer/assets/azcli-DL2My_i-.js +2 -0
- package/dist/renderer/assets/bat-B-nC98wG.js +2 -0
- package/dist/renderer/assets/bicep-Ju5MwOgh.js +3 -0
- package/dist/renderer/assets/cameligo-8Eu1TyBr.js +2 -0
- package/dist/renderer/assets/chunk-DPI0Y_ll.js +1 -0
- package/dist/renderer/assets/clojure-u-RpMkH3.js +2 -0
- package/dist/renderer/assets/codicon-ngg6Pgfi.ttf +0 -0
- package/dist/renderer/assets/coffee-CdA7bbTe.js +2 -0
- package/dist/renderer/assets/constants-CLAQX6VZ.js +2 -0
- package/dist/renderer/assets/cpp-CzNFP8ks.js +2 -0
- package/dist/renderer/assets/csharp-j1LThmcE.js +2 -0
- package/dist/renderer/assets/csp-CLRC61y6.js +2 -0
- package/dist/renderer/assets/css-r6rC_7P2.js +4 -0
- package/dist/renderer/assets/css.worker-DyDu5ynT.js +90 -0
- package/dist/renderer/assets/cssMode-BCBgxrnA.js +2 -0
- package/dist/renderer/assets/cypher-CW08XVUh.js +2 -0
- package/dist/renderer/assets/dart-Cs9aL5T_.js +2 -0
- package/dist/renderer/assets/dockerfile-BWM0M184.js +2 -0
- package/dist/renderer/assets/ecl-MJJuer5P.js +2 -0
- package/dist/renderer/assets/editor-CWI9TnMM.css +1 -0
- package/dist/renderer/assets/editor.api2-BTaYmRq7.js +873 -0
- package/dist/renderer/assets/editor.worker-Dpt_xPrs.js +27 -0
- package/dist/renderer/assets/elixir-D2AIuXqn.js +2 -0
- package/dist/renderer/assets/flow9-B2H24giC.js +2 -0
- package/dist/renderer/assets/freemarker2-DGDGzimW.js +4 -0
- package/dist/renderer/assets/fsharp-CMk2OIJN.js +2 -0
- package/dist/renderer/assets/go-BrMkuJg0.js +2 -0
- package/dist/renderer/assets/graphql-PSR1UKGv.js +2 -0
- package/dist/renderer/assets/handlebars-bOHhw3EG.js +2 -0
- package/dist/renderer/assets/hcl-DAQrbDOW.js +2 -0
- package/dist/renderer/assets/html-BMyuX0_c.js +2 -0
- package/dist/renderer/assets/html.worker-IWNXhnIC.js +503 -0
- package/dist/renderer/assets/htmlMode-DR4kXJ7l.js +2 -0
- package/dist/renderer/assets/index-CcJKzatF.js +50 -0
- package/dist/renderer/assets/ini-0TG5BxW0.js +2 -0
- package/dist/renderer/assets/input-QGx6FFX1.js +2 -0
- package/dist/renderer/assets/ipc-transport-BT4QYQqu.css +1 -0
- package/dist/renderer/assets/{ipc-transport-BzPzxPwf.js → ipc-transport-DvZvwK-Z.js} +5 -5
- package/dist/renderer/assets/java-rgorz17v.js +2 -0
- package/dist/renderer/assets/javascript-Bu-tl1P7.js +2 -0
- package/dist/renderer/assets/json.worker-c4h5s80L.js +59 -0
- package/dist/renderer/assets/jsonMode-MQV_ffLR.js +8 -0
- package/dist/renderer/assets/julia-C8VMdHm8.js +2 -0
- package/dist/renderer/assets/kotlin-AhhC4Qhm.js +2 -0
- package/dist/renderer/assets/less-Cgca25AP.js +3 -0
- package/dist/renderer/assets/lexon-D0GHdBaw.js +2 -0
- package/dist/renderer/assets/liquid-ClkfOvhB.js +2 -0
- package/dist/renderer/assets/lspLanguageFeatures-Bke_4Ie9.js +5 -0
- package/dist/renderer/assets/lua-DmRsNG-P.js +2 -0
- package/dist/renderer/assets/m3-BgL5dNKT.js +2 -0
- package/dist/renderer/assets/markdown-BuJfycGS.js +2 -0
- package/dist/renderer/assets/mdx-RZdUskPu.js +2 -0
- package/dist/renderer/assets/mips-C9m_93PR.js +2 -0
- package/dist/renderer/assets/monaco.contribution-B7rUMaEv.js +3 -0
- package/dist/renderer/assets/msdax-CpFHC9OI.js +2 -0
- package/dist/renderer/assets/mysql-qFvltsqN.js +2 -0
- package/dist/renderer/assets/objective-c-Bnmr858J.js +2 -0
- package/dist/renderer/assets/pascal-WP0_D5AO.js +2 -0
- package/dist/renderer/assets/pascaligo-Blom4Rij.js +2 -0
- package/dist/renderer/assets/perl-B-vk8g64.js +2 -0
- package/dist/renderer/assets/pgsql-Cgvz6v67.js +2 -0
- package/dist/renderer/assets/php-8a3Lrw9m.js +2 -0
- package/dist/renderer/assets/pla-DuFqEZ8V.js +2 -0
- package/dist/renderer/assets/popover-BOH1If1J.js +2 -0
- package/dist/renderer/assets/postiats-DkLtSgkp.js +2 -0
- package/dist/renderer/assets/powerquery-BJ1aNepW.js +2 -0
- package/dist/renderer/assets/powershell-rE98k687.js +2 -0
- package/dist/renderer/assets/protobuf-CUheFacr.js +3 -0
- package/dist/renderer/assets/pug-LDcAMD8w.js +2 -0
- package/dist/renderer/assets/python-Cobrm_-8.js +2 -0
- package/dist/renderer/assets/qsharp-DUKSQoR1.js +2 -0
- package/dist/renderer/assets/r-D-QApv87.js +2 -0
- package/dist/renderer/assets/razor-BEUIQFNJ.js +2 -0
- package/dist/renderer/assets/redis-SXdDyWR9.js +2 -0
- package/dist/renderer/assets/redshift-Y6lsCryn.js +2 -0
- package/dist/renderer/assets/restructuredtext-edObr9a8.js +2 -0
- package/dist/renderer/assets/ruby-CNnUfF-8.js +2 -0
- package/dist/renderer/assets/rust-IHUZWzBr.js +2 -0
- package/dist/renderer/assets/sb-DrUvY44N.js +2 -0
- package/dist/renderer/assets/scala-B4hbXGLM.js +2 -0
- package/dist/renderer/assets/scheme-BGrd12j3.js +2 -0
- package/dist/renderer/assets/scss-x5G1ES4U.js +4 -0
- package/dist/renderer/assets/select-C7JQ8G5N.js +2 -0
- package/dist/renderer/assets/settings-DpAbTJyF.js +2 -0
- package/dist/renderer/assets/{settings-api-BXCw9vOZ.js → settings-api-RD2IZF53.js} +2 -2
- package/dist/renderer/assets/shell-DOehe2Y8.js +2 -0
- package/dist/renderer/assets/solidity-BeRvcwWV.js +2 -0
- package/dist/renderer/assets/sophia-DZbkUNjy.js +2 -0
- package/dist/renderer/assets/sparql-B7_oi5-h.js +2 -0
- package/dist/renderer/assets/sql-CTlsFWVE.js +2 -0
- package/dist/renderer/assets/st-DJVEJdPE.js +2 -0
- package/dist/renderer/assets/swift-CwhT3fYa.js +2 -0
- package/dist/renderer/assets/systemverilog-BQN63pkN.js +2 -0
- package/dist/renderer/assets/tcl-DqwfpskA.js +2 -0
- package/dist/renderer/assets/ts.worker-BwM5Ha3L.js +67720 -0
- package/dist/renderer/assets/tsMode-BHa7dl9v.js +12 -0
- package/dist/renderer/assets/twig-BiyenUgc.js +2 -0
- package/dist/renderer/assets/typescript-15aT0Yj8.js +2 -0
- package/dist/renderer/assets/typespec-CWOJribt.js +2 -0
- package/dist/renderer/assets/vb-Cq5F87m3.js +2 -0
- package/dist/renderer/assets/wgsl-BAvW2lVr.js +299 -0
- package/dist/renderer/assets/workbenchSettings-CNJX4Qna.js +8 -0
- package/dist/renderer/assets/workers-CRBS0W-v.js +2 -0
- package/dist/renderer/assets/xml-bR2Zh-HV.js +2 -0
- package/dist/renderer/assets/yaml-Bdk54Qrb.js +2 -0
- package/dist/renderer/entries/main/index.html +29 -6
- package/dist/renderer/entries/popover/index.html +7 -6
- package/dist/renderer/entries/settings/index.html +6 -5
- package/dist/renderer/entries/workbench-settings/index.html +6 -5
- package/dist/service-host/preload.cjs +254 -0
- package/dist/service-host/service.html +10 -0
- package/dist/service-host/sourcemap-rewrite.cjs +58 -0
- package/dist/service-host/sync-api-patch.js +20 -0
- package/dist/service-host/sync-impls/menu-button.js +16 -0
- package/dist/service-host/sync-impls/storage.js +50 -0
- package/dist/service-host/sync-impls/system-info.js +54 -0
- package/dist/shared/appdata-accumulator.d.ts +95 -0
- package/dist/shared/appdata-accumulator.js +213 -0
- package/dist/shared/bridge-channels.d.ts +364 -0
- package/dist/shared/bridge-channels.js +54 -0
- package/dist/shared/constants.d.ts +0 -4
- package/dist/shared/constants.js +0 -4
- package/dist/shared/ipc-channels.d.ts +108 -1
- package/dist/shared/ipc-channels.js +127 -10
- package/dist/shared/ipc-schemas.d.ts +65 -2
- package/dist/shared/ipc-schemas.js +79 -3
- package/dist/shared/open-in-editor.d.ts +71 -0
- package/dist/shared/open-in-editor.js +138 -0
- package/dist/shared/simulator-api-metadata.d.ts +21 -0
- package/dist/shared/simulator-api-metadata.js +23 -0
- package/dist/shared/types.d.ts +2 -2
- package/dist/shared/vpath.d.ts +42 -0
- package/dist/shared/vpath.js +105 -0
- package/dist/simulator/assets/device-shell-DsdcNEkt.css +1 -0
- package/dist/simulator/assets/device-shell-vwYSOVrh.js +2 -0
- package/dist/simulator/assets/jsx-runtime-P6ZegaOf.js +2 -0
- package/dist/simulator/assets/simulator-DddliUL5.js +10 -0
- package/dist/simulator/assets/simulator-mini-app-BDNu5n26.js +2 -0
- package/dist/simulator/device-shell/menu-button-geometry.js +8 -0
- package/dist/simulator/simulator.html +2 -112
- package/package.json +9 -9
- package/dist/main/utils/disposable.d.ts +0 -18
- package/dist/main/utils/disposable.js +0 -67
- package/dist/renderer/assets/constants-DI382mTP.js +0 -2
- package/dist/renderer/assets/index-4lkyF644.js +0 -46
- package/dist/renderer/assets/input-D4byFOLS.js +0 -2
- package/dist/renderer/assets/ipc-transport-DqbRdZNO.css +0 -1
- package/dist/renderer/assets/popover-cxKrg_os.js +0 -2
- package/dist/renderer/assets/select-BgSkkdHW.js +0 -2
- package/dist/renderer/assets/settings-oD2K1jdT.js +0 -2
- package/dist/renderer/assets/workbenchSettings-CTNBpTft.js +0 -8
- package/dist/simulator/assets/simulator-CVOFTpSj.js +0 -9
|
@@ -1,16 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { evalInActivePage, evalInSim } from '../exec.js';
|
|
2
2
|
import { registerElement } from '../registry.js';
|
|
3
3
|
export const pageHandlers = {};
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a dotted/indexed path (`a.b`, `a[0].b`) against an appdata object,
|
|
6
|
+
* or return the whole object when no path is given. Shared by both Page.getData
|
|
7
|
+
* branches so the traversal stays identical.
|
|
8
|
+
*/
|
|
9
|
+
function resolveAppDataPath(appdata, pathKey) {
|
|
10
|
+
if (!pathKey)
|
|
11
|
+
return appdata;
|
|
12
|
+
const keys = pathKey.replace(/\[(\d+)\]/g, '.$1').split('.');
|
|
13
|
+
let val = appdata;
|
|
14
|
+
for (const k of keys) {
|
|
15
|
+
if (val == null || typeof val !== 'object') {
|
|
16
|
+
val = undefined;
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
val = val[k];
|
|
20
|
+
}
|
|
21
|
+
return val;
|
|
22
|
+
}
|
|
4
23
|
// -- Page domain --
|
|
5
24
|
pageHandlers['Page.getElement'] = async (ctx, params) => {
|
|
6
25
|
const selector = params.selector;
|
|
7
26
|
const pageId = params.pageId || 1;
|
|
8
27
|
const escaped = selector.replace(/'/g, "\\'");
|
|
9
|
-
const info = await
|
|
28
|
+
const info = await evalInActivePage(ctx, `
|
|
10
29
|
const el = _doc.querySelector('${escaped}')
|
|
11
30
|
if (!el) return null
|
|
12
31
|
return { tagName: el.tagName.toLowerCase() }
|
|
13
|
-
`)
|
|
32
|
+
`);
|
|
14
33
|
if (!info)
|
|
15
34
|
throw new Error(`Element not found: ${selector}`);
|
|
16
35
|
const elementId = registerElement(selector, 0, pageId);
|
|
@@ -20,11 +39,11 @@ pageHandlers['Page.getElements'] = async (ctx, params) => {
|
|
|
20
39
|
const selector = params.selector;
|
|
21
40
|
const pageId = params.pageId || 1;
|
|
22
41
|
const escaped = selector.replace(/'/g, "\\'");
|
|
23
|
-
const items = await
|
|
42
|
+
const items = await evalInActivePage(ctx, `
|
|
24
43
|
return Array.from(_doc.querySelectorAll('${escaped}')).map(el => ({
|
|
25
44
|
tagName: el.tagName.toLowerCase(),
|
|
26
45
|
}))
|
|
27
|
-
`)
|
|
46
|
+
`);
|
|
28
47
|
return {
|
|
29
48
|
elements: items.map((item, i) => ({
|
|
30
49
|
elementId: registerElement(selector, i, pageId),
|
|
@@ -34,19 +53,17 @@ pageHandlers['Page.getElements'] = async (ctx, params) => {
|
|
|
34
53
|
};
|
|
35
54
|
pageHandlers['Page.getData'] = async (ctx, params) => {
|
|
36
55
|
const pathKey = params.path;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
break;
|
|
46
|
-
}
|
|
47
|
-
val = val[k];
|
|
56
|
+
// NATIVE-HOST: under native-host the page AppData lives in the service window's
|
|
57
|
+
// Worker-less runtime (tracked centrally via ctx.appData), NOT in the render
|
|
58
|
+
// guest's DOM. Source the active bridge's reactive state from the central
|
|
59
|
+
// accumulator, then run the SAME path traversal as the default branch.
|
|
60
|
+
if (ctx.bridge?.isNativeHost()) {
|
|
61
|
+
const bridgeId = ctx.bridge.getActiveBridgeId();
|
|
62
|
+
const appdata = bridgeId ? (ctx.appData?.getPageData(bridgeId) ?? {}) : {};
|
|
63
|
+
return { data: resolveAppDataPath(appdata, pathKey) };
|
|
48
64
|
}
|
|
49
|
-
|
|
65
|
+
const appdata = await evalInSim(ctx, `window.__simulatorData ? window.__simulatorData.getAppdata() : {}`);
|
|
66
|
+
return { data: resolveAppDataPath(appdata, pathKey) };
|
|
50
67
|
};
|
|
51
68
|
pageHandlers['Page.setData'] = async () => {
|
|
52
69
|
throw new Error('Page.setData is not supported (requires AppService layer)');
|
|
@@ -56,11 +73,11 @@ pageHandlers['Page.callMethod'] = async (_ctx, params) => {
|
|
|
56
73
|
};
|
|
57
74
|
pageHandlers['Page.getWindowProperties'] = async (ctx, params) => {
|
|
58
75
|
const names = params.names;
|
|
59
|
-
const properties = await
|
|
76
|
+
const properties = await evalInActivePage(ctx, `
|
|
60
77
|
return ${JSON.stringify(names)}.map(n => {
|
|
61
78
|
try { return eval(n) } catch { return undefined }
|
|
62
79
|
})
|
|
63
|
-
`)
|
|
80
|
+
`);
|
|
64
81
|
return { properties };
|
|
65
82
|
};
|
|
66
83
|
//# sourceMappingURL=page.js.map
|
|
@@ -54,6 +54,23 @@ export async function startAutomationServer(ctx, port = 0) {
|
|
|
54
54
|
ws.send(msg);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
+
// Native-host console forwarding: under native-host the page/service console
|
|
58
|
+
// doesn't flow through the simulator guest's `ipc-message-host` channel (there
|
|
59
|
+
// is no Worker/MiniApp in the guest). Instead the render-host / service-host
|
|
60
|
+
// preloads post each console entry to main, bridge-router routes it to the
|
|
61
|
+
// always-on ConsoleForwarder, and we SUBSCRIBE to rebroadcast every entry
|
|
62
|
+
// (both layers) as an `App.logAdded` event — same shape the default-arch path
|
|
63
|
+
// emits below in `setupConsoleForwarding`. We no longer set `ctx.guestConsole`
|
|
64
|
+
// ourselves (the forwarder owns it); subscribing means render + service both
|
|
65
|
+
// reach automation while the forwarder also mirrors render into the service
|
|
66
|
+
// host's console for the embedded DevTools. Unsubscribed on close().
|
|
67
|
+
const consoleSub = ctx.consoleForwarder?.subscribe((entry) => {
|
|
68
|
+
const e = (entry ?? {});
|
|
69
|
+
broadcast({
|
|
70
|
+
method: 'App.logAdded',
|
|
71
|
+
params: { type: e.level || 'log', args: e.args || [] },
|
|
72
|
+
});
|
|
73
|
+
});
|
|
57
74
|
// Forward simulator console logs as App.logAdded events.
|
|
58
75
|
// Track the polling interval + stop timer + currently-attached sim and
|
|
59
76
|
// the named handler so we can fully detach on close() or sim destruction.
|
|
@@ -64,7 +81,11 @@ export async function startAutomationServer(ctx, port = 0) {
|
|
|
64
81
|
let pollStopTimer = null;
|
|
65
82
|
let attachedSim = null;
|
|
66
83
|
let ipcMessageHostHandler = null;
|
|
67
|
-
|
|
84
|
+
// Handle for the destroyed-teardown owned by the sim's connection (replaces a
|
|
85
|
+
// bespoke `sim.once('destroyed')` + manual removeListener). Disposing it on
|
|
86
|
+
// graceful close()/detach releases the disposer from the connection segment so
|
|
87
|
+
// it can't accumulate across automation create/dispose cycles on the same sim.
|
|
88
|
+
let simDestroyedDisposer = null;
|
|
68
89
|
function detachConsoleForwarding() {
|
|
69
90
|
if (attachedSim) {
|
|
70
91
|
if (ipcMessageHostHandler) {
|
|
@@ -77,18 +98,16 @@ export async function startAutomationServer(ctx, port = 0) {
|
|
|
77
98
|
}
|
|
78
99
|
catch { /* noop */ }
|
|
79
100
|
}
|
|
80
|
-
if (simDestroyedHandler) {
|
|
81
|
-
try {
|
|
82
|
-
if (!attachedSim.isDestroyed()) {
|
|
83
|
-
attachedSim.removeListener('destroyed', simDestroyedHandler);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
catch { /* noop */ }
|
|
87
|
-
}
|
|
88
101
|
}
|
|
102
|
+
// Release the connection-owned destroyed disposer (idempotent; safe even if
|
|
103
|
+
// the sim is already destroyed — the disposer body only nulls local refs).
|
|
104
|
+
try {
|
|
105
|
+
simDestroyedDisposer?.dispose();
|
|
106
|
+
}
|
|
107
|
+
catch { /* noop */ }
|
|
89
108
|
attachedSim = null;
|
|
90
109
|
ipcMessageHostHandler = null;
|
|
91
|
-
|
|
110
|
+
simDestroyedDisposer = null;
|
|
92
111
|
}
|
|
93
112
|
function setupConsoleForwarding() {
|
|
94
113
|
if (consoleForwardingSetup)
|
|
@@ -116,14 +135,17 @@ export async function startAutomationServer(ctx, port = 0) {
|
|
|
116
135
|
// sender would throw) and allow re-attach to a new simulator.
|
|
117
136
|
attachedSim = null;
|
|
118
137
|
ipcMessageHostHandler = null;
|
|
119
|
-
|
|
138
|
+
simDestroyedDisposer = null;
|
|
120
139
|
consoleForwardingSetup = false;
|
|
121
140
|
};
|
|
122
141
|
attachedSim = sim;
|
|
123
142
|
ipcMessageHostHandler = onIpcMessageHost;
|
|
124
|
-
simDestroyedHandler = onSimDestroyed;
|
|
125
143
|
sim.on('ipc-message-host', onIpcMessageHost);
|
|
126
|
-
|
|
144
|
+
// Route the destroyed-teardown through the per-webContents connection
|
|
145
|
+
// registry: the connection arms a single `wc.once('destroyed')` and runs
|
|
146
|
+
// owned disposers on hard-destroy (or soft reset for pool reuse), so we no
|
|
147
|
+
// longer manage a bespoke 'destroyed' listener here.
|
|
148
|
+
simDestroyedDisposer = ctx.connections.acquire(sim).own(onSimDestroyed);
|
|
127
149
|
}, 1000);
|
|
128
150
|
// Stop polling after 30s
|
|
129
151
|
pollStopTimer = setTimeout(() => {
|
|
@@ -176,6 +198,11 @@ export async function startAutomationServer(ctx, port = 0) {
|
|
|
176
198
|
pollStopTimer = null;
|
|
177
199
|
}
|
|
178
200
|
detachConsoleForwarding();
|
|
201
|
+
// Unsubscribe from the always-on ConsoleForwarder so a late guest console
|
|
202
|
+
// entry can't broadcast against a torn-down server. The forwarder keeps
|
|
203
|
+
// owning `ctx.guestConsole` (render→service mirroring continues without an
|
|
204
|
+
// automation client). No-op if the forwarder was absent.
|
|
205
|
+
consoleSub?.dispose();
|
|
179
206
|
for (const ws of clients) {
|
|
180
207
|
try {
|
|
181
208
|
ws.close();
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-process readiness primitive (shared abstraction).
|
|
3
|
+
*
|
|
4
|
+
* Replaces the blind `setTimeout(1500/2000)` navigation waits in automation
|
|
5
|
+
* handlers with "wait for the bridge's `activePage` signal, with a timeout
|
|
6
|
+
* floor". The bridge (`BridgeRouterHandle`) already fan-outs an `activePage`
|
|
7
|
+
* render event whenever the DeviceShell reports a new top-of-stack page, so we
|
|
8
|
+
* wait for that real signal instead of guessing how long a navigation takes.
|
|
9
|
+
*
|
|
10
|
+
* Design contract:
|
|
11
|
+
* - Subscribe to `bridge.onRenderEvent` and resolve on the first matching
|
|
12
|
+
* `activePage` event. "Matching" = `opts.match(bridgeId, pagePath)` when a
|
|
13
|
+
* predicate is supplied, otherwise `bridgeId !== opts.since` (i.e. the
|
|
14
|
+
* active page actually changed away from where navigation started).
|
|
15
|
+
* - Timeout floor: resolve (NEVER reject, never hang) at `opts.timeoutMs` so a
|
|
16
|
+
* caller awaiting this can always make progress even if the signal is lost.
|
|
17
|
+
* - Race close: navigation can land before we subscribe, so read
|
|
18
|
+
* `getActiveBridgeId()` once right after subscribing; when no `match`
|
|
19
|
+
* predicate is given and it is already `!== since`, resolve immediately.
|
|
20
|
+
* (With a `match` predicate we cannot decide from the bridgeId alone — there
|
|
21
|
+
* is no pagePath in the snapshot — so we wait for an event.)
|
|
22
|
+
* - Resolve exactly once; later events are inert and the subscription is torn
|
|
23
|
+
* down on resolve.
|
|
24
|
+
*/
|
|
25
|
+
/** The render-event shape `waitForActivePage` reads (subset of `RenderEvent`). */
|
|
26
|
+
export interface ActivePageEventLike {
|
|
27
|
+
kind: 'domReady' | 'activePage';
|
|
28
|
+
appId: string;
|
|
29
|
+
bridgeId: string;
|
|
30
|
+
pagePath?: string;
|
|
31
|
+
}
|
|
32
|
+
/** Minimal bridge surface this helper is allowed to touch. */
|
|
33
|
+
export interface WaitActivePageBridge {
|
|
34
|
+
onRenderEvent(listener: (event: ActivePageEventLike) => void): () => void;
|
|
35
|
+
getActiveBridgeId(): string | null;
|
|
36
|
+
}
|
|
37
|
+
export interface WaitActivePageOptions {
|
|
38
|
+
/** The active bridgeId before navigation started (or null if unknown). */
|
|
39
|
+
since: string | null;
|
|
40
|
+
/** Timeout floor in ms — resolve unconditionally once this elapses. */
|
|
41
|
+
timeoutMs: number;
|
|
42
|
+
/**
|
|
43
|
+
* Optional predicate deciding which `activePage` event ends the wait. When
|
|
44
|
+
* omitted, any `activePage` whose `bridgeId !== since` ends it.
|
|
45
|
+
*/
|
|
46
|
+
match?: (bridgeId: string, pagePath?: string) => boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Fired exactly once if the wait resolves via the timeout floor rather than a
|
|
49
|
+
* matching signal — i.e. the expected `activePage` was never observed. Lets
|
|
50
|
+
* the caller surface "signal not seen, proceeding on timeout" instead of
|
|
51
|
+
* silently masking a lost signal. Never fired on a signal/race-close resolve.
|
|
52
|
+
*/
|
|
53
|
+
onTimeout?: () => void;
|
|
54
|
+
}
|
|
55
|
+
export declare function waitForActivePage(bridge: WaitActivePageBridge, opts: WaitActivePageOptions): Promise<void>;
|
|
56
|
+
//# sourceMappingURL=wait-active-page.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-process readiness primitive (shared abstraction).
|
|
3
|
+
*
|
|
4
|
+
* Replaces the blind `setTimeout(1500/2000)` navigation waits in automation
|
|
5
|
+
* handlers with "wait for the bridge's `activePage` signal, with a timeout
|
|
6
|
+
* floor". The bridge (`BridgeRouterHandle`) already fan-outs an `activePage`
|
|
7
|
+
* render event whenever the DeviceShell reports a new top-of-stack page, so we
|
|
8
|
+
* wait for that real signal instead of guessing how long a navigation takes.
|
|
9
|
+
*
|
|
10
|
+
* Design contract:
|
|
11
|
+
* - Subscribe to `bridge.onRenderEvent` and resolve on the first matching
|
|
12
|
+
* `activePage` event. "Matching" = `opts.match(bridgeId, pagePath)` when a
|
|
13
|
+
* predicate is supplied, otherwise `bridgeId !== opts.since` (i.e. the
|
|
14
|
+
* active page actually changed away from where navigation started).
|
|
15
|
+
* - Timeout floor: resolve (NEVER reject, never hang) at `opts.timeoutMs` so a
|
|
16
|
+
* caller awaiting this can always make progress even if the signal is lost.
|
|
17
|
+
* - Race close: navigation can land before we subscribe, so read
|
|
18
|
+
* `getActiveBridgeId()` once right after subscribing; when no `match`
|
|
19
|
+
* predicate is given and it is already `!== since`, resolve immediately.
|
|
20
|
+
* (With a `match` predicate we cannot decide from the bridgeId alone — there
|
|
21
|
+
* is no pagePath in the snapshot — so we wait for an event.)
|
|
22
|
+
* - Resolve exactly once; later events are inert and the subscription is torn
|
|
23
|
+
* down on resolve.
|
|
24
|
+
*/
|
|
25
|
+
export function waitForActivePage(bridge, opts) {
|
|
26
|
+
const { since, timeoutMs, match, onTimeout } = opts;
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
let isSettled = false;
|
|
29
|
+
let unsubscribe = null;
|
|
30
|
+
let timer = null;
|
|
31
|
+
const finish = () => {
|
|
32
|
+
if (isSettled)
|
|
33
|
+
return;
|
|
34
|
+
isSettled = true;
|
|
35
|
+
if (timer !== null) {
|
|
36
|
+
clearTimeout(timer);
|
|
37
|
+
timer = null;
|
|
38
|
+
}
|
|
39
|
+
if (unsubscribe) {
|
|
40
|
+
unsubscribe();
|
|
41
|
+
unsubscribe = null;
|
|
42
|
+
}
|
|
43
|
+
resolve();
|
|
44
|
+
};
|
|
45
|
+
const matches = (bridgeId, pagePath) => match ? match(bridgeId, pagePath) : bridgeId !== since;
|
|
46
|
+
unsubscribe = bridge.onRenderEvent((event) => {
|
|
47
|
+
if (isSettled)
|
|
48
|
+
return;
|
|
49
|
+
if (event.kind !== 'activePage')
|
|
50
|
+
return;
|
|
51
|
+
if (matches(event.bridgeId, event.pagePath))
|
|
52
|
+
finish();
|
|
53
|
+
});
|
|
54
|
+
// Timeout floor — resolve (never reject) so awaiters never hang. Fire the
|
|
55
|
+
// optional onTimeout hook first so a lost signal is visible, not masked.
|
|
56
|
+
timer = setTimeout(() => {
|
|
57
|
+
if (isSettled)
|
|
58
|
+
return;
|
|
59
|
+
onTimeout?.();
|
|
60
|
+
finish();
|
|
61
|
+
}, timeoutMs);
|
|
62
|
+
// Race close: the page may already have advanced before we subscribed.
|
|
63
|
+
// Only decidable without a pagePath when no `match` predicate is supplied.
|
|
64
|
+
if (!match) {
|
|
65
|
+
const current = bridge.getActiveBridgeId();
|
|
66
|
+
if (current !== null && current !== since)
|
|
67
|
+
finish();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=wait-active-page.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type Disposable } from '@dimina-kit/electron-deck/main';
|
|
2
|
+
import type { BridgeRouterHandle } from '../../ipc/bridge-router.js';
|
|
3
|
+
/**
|
|
4
|
+
* One console entry posted by a guest preload. Shape mirrors
|
|
5
|
+
* render-host/preload.cjs + service-host/preload.cjs `emitConsoleLog`:
|
|
6
|
+
* - `source` which layer it came from ('render' | 'service'); ONLY 'render'
|
|
7
|
+
* is forwarded into the service host (see loop-safety above).
|
|
8
|
+
* - `bridgeId` present for render entries; identifies the owning page so we
|
|
9
|
+
* can target the matching app's service host (multi-app safe).
|
|
10
|
+
* - `level` console method name ('log' | 'warn' | 'error' | 'info' | 'debug').
|
|
11
|
+
* - `args` already-`safeSerialize`d arguments (structured-cloneable).
|
|
12
|
+
*/
|
|
13
|
+
export interface GuestConsoleEntry {
|
|
14
|
+
source?: string;
|
|
15
|
+
bridgeId?: string;
|
|
16
|
+
level?: string;
|
|
17
|
+
args?: unknown[];
|
|
18
|
+
ts?: number;
|
|
19
|
+
}
|
|
20
|
+
/** A consumer of every guest console entry (render AND service). */
|
|
21
|
+
export type ConsoleSink = (entry: GuestConsoleEntry) => void;
|
|
22
|
+
export interface ConsoleForwarder extends Disposable {
|
|
23
|
+
/**
|
|
24
|
+
* The single sink bridge-router invokes (wired onto `ctx.guestConsole.emit`).
|
|
25
|
+
* Fans every entry out to subscribers, then runs the render→service forward.
|
|
26
|
+
*/
|
|
27
|
+
emit(entry: unknown): void;
|
|
28
|
+
/**
|
|
29
|
+
* Register an external sink (e.g. automation WS broadcast). Returns a
|
|
30
|
+
* Disposable that unregisters it. Sinks see EVERY entry (both layers) — the
|
|
31
|
+
* render→service forward is internal and not exposed as a sink.
|
|
32
|
+
*/
|
|
33
|
+
subscribe(sink: ConsoleSink): Disposable;
|
|
34
|
+
}
|
|
35
|
+
export declare function createConsoleForwarder(bridge: Pick<BridgeRouterHandle, 'getServiceWc' | 'getServiceWcForBridge'>): ConsoleForwarder;
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { DisposableRegistry, toDisposable } from '@dimina-kit/electron-deck/main';
|
|
2
|
+
/** Console levels we re-emit into the service host. Anything else maps to 'log'. */
|
|
3
|
+
const FORWARDABLE_LEVELS = new Set(['log', 'warn', 'error', 'info', 'debug']);
|
|
4
|
+
/**
|
|
5
|
+
* Build the `executeJavaScript` source that re-emits a render entry inside the
|
|
6
|
+
* service host. Args are carried as a JSON string and parsed service-side, so no
|
|
7
|
+
* guest-controlled value is ever interpolated into executable JS — the only
|
|
8
|
+
* thing that reaches the parser is a JSON literal. The `[视图]` prefix lets the
|
|
9
|
+
* DevTools console filter isolate the render layer.
|
|
10
|
+
*/
|
|
11
|
+
function buildForwardScript(level, args) {
|
|
12
|
+
const method = FORWARDABLE_LEVELS.has(level) ? level : 'log';
|
|
13
|
+
// JSON.stringify('…') yields a valid JS string literal; embedding it and
|
|
14
|
+
// re-parsing keeps args as data, never code. JSON.stringify can throw on a
|
|
15
|
+
// value that slipped past safeSerialize (e.g. a BigInt) — caller guards.
|
|
16
|
+
const argsJson = JSON.stringify(args ?? []);
|
|
17
|
+
// `console[method]` (not `console.log`) preserves the original level so the
|
|
18
|
+
// DevTools severity filter still works on the forwarded line.
|
|
19
|
+
return `(()=>{try{const a=JSON.parse(${JSON.stringify(argsJson)});console[${JSON.stringify(method)}]('[视图]',...a)}catch(_){}})()`;
|
|
20
|
+
}
|
|
21
|
+
export function createConsoleForwarder(bridge) {
|
|
22
|
+
const sinks = new Set();
|
|
23
|
+
const registry = new DisposableRegistry();
|
|
24
|
+
/**
|
|
25
|
+
* Render→service forward. Resolves the service host for the entry's owning
|
|
26
|
+
* page (multi-app safe), falling back to the active app's service host when
|
|
27
|
+
* the bridgeId is unknown — that's the host the embedded DevTools inspects.
|
|
28
|
+
* No-op on a destroyed/missing host so we never write to a torn-down wc (pool
|
|
29
|
+
* reuse / session swap can swap the host out under us).
|
|
30
|
+
*/
|
|
31
|
+
function forwardRenderToServiceHost(entry) {
|
|
32
|
+
let wc = null;
|
|
33
|
+
if (entry.bridgeId && bridge.getServiceWcForBridge) {
|
|
34
|
+
wc = bridge.getServiceWcForBridge(entry.bridgeId);
|
|
35
|
+
}
|
|
36
|
+
if (!wc)
|
|
37
|
+
wc = bridge.getServiceWc();
|
|
38
|
+
if (!wc || wc.isDestroyed())
|
|
39
|
+
return;
|
|
40
|
+
let script;
|
|
41
|
+
try {
|
|
42
|
+
script = buildForwardScript(entry.level ?? 'log', entry.args ?? []);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// Args that escaped safeSerialize and aren't JSON-stringifiable — drop
|
|
46
|
+
// rather than break the forward. Console capture must never throw.
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// executeJavaScript rejects if the host navigates/teardowns mid-call; the
|
|
50
|
+
// injected body is itself try/caught. Swallow either — best-effort mirror.
|
|
51
|
+
wc.executeJavaScript(script, true).catch(() => { });
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
// The single sink bridge-router calls (`ctx.guestConsole.emit`). Fans out
|
|
55
|
+
// to external subscribers (both layers) then runs the render→service forward
|
|
56
|
+
// (render only — see loop-safety invariant in the module header).
|
|
57
|
+
emit(raw) {
|
|
58
|
+
const entry = (raw ?? {});
|
|
59
|
+
for (const sink of sinks) {
|
|
60
|
+
try {
|
|
61
|
+
sink(entry);
|
|
62
|
+
}
|
|
63
|
+
catch { /* a sink must never break the others */ }
|
|
64
|
+
}
|
|
65
|
+
// Forward ONLY the render layer. Service entries are already shown
|
|
66
|
+
// natively in the attached DevTools, and forwarding them would loop
|
|
67
|
+
// (see header).
|
|
68
|
+
if (entry.source === 'render')
|
|
69
|
+
forwardRenderToServiceHost(entry);
|
|
70
|
+
},
|
|
71
|
+
subscribe(sink) {
|
|
72
|
+
sinks.add(sink);
|
|
73
|
+
return registry.add(toDisposable(() => { sinks.delete(sink); }));
|
|
74
|
+
},
|
|
75
|
+
dispose() {
|
|
76
|
+
sinks.clear();
|
|
77
|
+
return registry.disposeAll();
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface DiminaResourceServer {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
close(): Promise<void>;
|
|
4
|
+
}
|
|
5
|
+
export declare function startDiminaResourceServer(rootDir: string): Promise<DiminaResourceServer>;
|
|
6
|
+
export declare function toSourceUrl(filePath: string): string;
|
|
7
|
+
//# sourceMappingURL=dimina-resource-server.d.ts.map
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
const MIME_TYPES = {
|
|
6
|
+
'.css': 'text/css; charset=utf-8',
|
|
7
|
+
'.html': 'text/html; charset=utf-8',
|
|
8
|
+
'.js': 'text/javascript; charset=utf-8',
|
|
9
|
+
'.json': 'application/json; charset=utf-8',
|
|
10
|
+
'.map': 'application/json; charset=utf-8',
|
|
11
|
+
'.svg': 'image/svg+xml',
|
|
12
|
+
'.png': 'image/png',
|
|
13
|
+
'.jpg': 'image/jpeg',
|
|
14
|
+
'.jpeg': 'image/jpeg',
|
|
15
|
+
'.gif': 'image/gif',
|
|
16
|
+
'.webp': 'image/webp',
|
|
17
|
+
'.wasm': 'application/wasm',
|
|
18
|
+
};
|
|
19
|
+
export async function startDiminaResourceServer(rootDir) {
|
|
20
|
+
const root = path.resolve(rootDir);
|
|
21
|
+
const server = http.createServer((req, res) => {
|
|
22
|
+
void handleRequest(root, req, res);
|
|
23
|
+
});
|
|
24
|
+
await new Promise((resolve, reject) => {
|
|
25
|
+
server.once('error', reject);
|
|
26
|
+
server.listen(0, '127.0.0.1', () => {
|
|
27
|
+
server.off('error', reject);
|
|
28
|
+
resolve();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
const address = server.address();
|
|
32
|
+
return {
|
|
33
|
+
baseUrl: `http://127.0.0.1:${address.port}/`,
|
|
34
|
+
close() {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
server.close((err) => err ? reject(err) : resolve());
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async function handleRequest(root, req, res) {
|
|
42
|
+
setCorsHeaders(res);
|
|
43
|
+
if (req.method === 'OPTIONS') {
|
|
44
|
+
res.writeHead(204);
|
|
45
|
+
res.end();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (req.method !== 'GET' && req.method !== 'HEAD') {
|
|
49
|
+
res.writeHead(405);
|
|
50
|
+
res.end('Method Not Allowed');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const url = new URL(req.url ?? '/', 'http://127.0.0.1');
|
|
54
|
+
const filePath = resolveContainedPath(root, decodeURIComponent(url.pathname));
|
|
55
|
+
if (!filePath) {
|
|
56
|
+
res.writeHead(403);
|
|
57
|
+
res.end('Forbidden');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const stat = await fs.promises.stat(filePath);
|
|
62
|
+
if (!stat.isFile()) {
|
|
63
|
+
res.writeHead(404);
|
|
64
|
+
res.end('Not Found');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
res.writeHead(200, {
|
|
68
|
+
'content-type': MIME_TYPES[path.extname(filePath)] ?? 'application/octet-stream',
|
|
69
|
+
'content-length': stat.size,
|
|
70
|
+
'cache-control': 'no-store',
|
|
71
|
+
});
|
|
72
|
+
if (req.method === 'HEAD') {
|
|
73
|
+
res.end();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
fs.createReadStream(filePath).pipe(res);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
res.writeHead(404);
|
|
80
|
+
res.end('Not Found');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function resolveContainedPath(root, pathname) {
|
|
84
|
+
const relative = pathname.replace(/^\/+/, '') || 'index.html';
|
|
85
|
+
const resolved = path.resolve(root, relative);
|
|
86
|
+
if (resolved !== root && !resolved.startsWith(root + path.sep))
|
|
87
|
+
return null;
|
|
88
|
+
return resolved;
|
|
89
|
+
}
|
|
90
|
+
function setCorsHeaders(res) {
|
|
91
|
+
res.setHeader('access-control-allow-origin', '*');
|
|
92
|
+
res.setHeader('access-control-allow-headers', '*');
|
|
93
|
+
res.setHeader('access-control-allow-methods', 'GET,HEAD,OPTIONS');
|
|
94
|
+
res.setHeader('cross-origin-resource-policy', 'cross-origin');
|
|
95
|
+
}
|
|
96
|
+
export function toSourceUrl(filePath) {
|
|
97
|
+
return pathToFileURL(filePath).toString();
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=dimina-resource-server.js.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { WebContents } from 'electron';
|
|
2
|
+
import type { ConnectionRegistry } from '@dimina-kit/electron-deck/main';
|
|
3
|
+
import type { BridgeRouterHandle } from '../../ipc/bridge-router.js';
|
|
4
|
+
/** Which target a front-end CDP command is routed to. */
|
|
5
|
+
export type CdpRoute = 'render' | 'service';
|
|
6
|
+
/**
|
|
7
|
+
* Decide where a front-end CDP `method` is routed.
|
|
8
|
+
*
|
|
9
|
+
* render → DOM./CSS./Overlay./DOMSnapshot./DOMDebugger. (the Elements tree)
|
|
10
|
+
* service → EVERYTHING ELSE, and in particular:
|
|
11
|
+
* • Emulation.* — RED LINE: routing this to the render guest would let the
|
|
12
|
+
* front-end overwrite the safe-area service's `setSafeAreaInsetsOverride`.
|
|
13
|
+
* It MUST stay on the service-host inspection path (pass-through).
|
|
14
|
+
* • Runtime./Console./Debugger./Network./Page./Target./Input./Profiler./Log.
|
|
15
|
+
* — the service host owns these; leave them on the original channel.
|
|
16
|
+
*
|
|
17
|
+
* Pure (no I/O). The hook script inlines an equivalent prefix test driven by the
|
|
18
|
+
* same `RENDER_DOMAIN_PREFIXES` literal, so the two cannot silently drift.
|
|
19
|
+
*/
|
|
20
|
+
export declare function routeByDomain(method: string): CdpRoute;
|
|
21
|
+
/** True for an event method we re-inject from the render guest into the panel. */
|
|
22
|
+
export declare function isRenderEventMethod(method: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* The JS injected into the DevTools front-end realm. Idempotent (sentinel guard).
|
|
25
|
+
* Wraps `InspectorFrontendHost.sendMessageToBackend`: a RENDER-domain command is
|
|
26
|
+
* pushed onto `globalThis.__diminaElementsOutbound` (drained by main) and NOT
|
|
27
|
+
* forwarded to the original embedder channel (main answers it from the render
|
|
28
|
+
* guest); every other command calls through to the original (service-host path).
|
|
29
|
+
*
|
|
30
|
+
* Returns `'installed'` / `'already'` on success, `'partial'` while the embedder
|
|
31
|
+
* global is not yet present (so the caller retries), `'error:…'` on a real fault.
|
|
32
|
+
*/
|
|
33
|
+
export declare function buildElementsHookScript(): string;
|
|
34
|
+
export interface ElementsForwardDeps {
|
|
35
|
+
/** The wc hosting the right-panel Chrome DevTools FRONT-END (injection target). */
|
|
36
|
+
devtoolsWc: WebContents;
|
|
37
|
+
/** Router handle — resolves the active render guest + render-event stream. */
|
|
38
|
+
bridge: BridgeRouterHandle;
|
|
39
|
+
/**
|
|
40
|
+
* The app whose active render guest we route to. `undefined` means "the
|
|
41
|
+
* router's current app" (resolved fresh on every use, like the safe-area /
|
|
42
|
+
* devtools-follow paths) — what the wire-up passes.
|
|
43
|
+
*/
|
|
44
|
+
appId?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Optional connection registry. When present, per-webContents teardowns
|
|
47
|
+
* (the devtools front-end wc's `stop`, and each render guest's `onDestroyed`)
|
|
48
|
+
* are routed through `connections.acquire(wc).own(cleanup)` so they fire
|
|
49
|
+
* deterministically on wc destroy / connection reset — replacing the bespoke
|
|
50
|
+
* `wc.once('destroyed', cleanup)` hook. Optional so existing callers compile
|
|
51
|
+
* unchanged; absent → the `once('destroyed')` fallback is used.
|
|
52
|
+
*/
|
|
53
|
+
connections?: ConnectionRegistry;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Install Elements forwarding on a DevTools front-end host wc. Returns a disposer
|
|
57
|
+
* (`stop`) that clears timers, unsubscribes render events, detaches ONLY the
|
|
58
|
+
* debugger sessions this feature attached, and removes every listener it added.
|
|
59
|
+
*
|
|
60
|
+
* Best-effort + defensive throughout: a destroyed wc ends the feature; every
|
|
61
|
+
* executeJavaScript / sendCommand is wrapped so a torn-down guest never throws
|
|
62
|
+
* and an in-flight command always settles (we dispatch an error back rather than
|
|
63
|
+
* leaving the front-end pending).
|
|
64
|
+
*/
|
|
65
|
+
export declare function installElementsForward(deps: ElementsForwardDeps): () => void;
|
|
66
|
+
//# sourceMappingURL=index.d.ts.map
|