@dimina-kit/devtools 0.3.2-dev.20260611135124 → 0.4.0-dev.20260612152115
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 +11 -9
- package/dist/main/api.d.ts +1 -1
- package/dist/main/app/app.js +22 -12
- package/dist/main/app/launch.d.ts +4 -4
- package/dist/main/app/launch.js +5 -17
- package/dist/main/index.bundle.js +372 -225
- package/dist/main/ipc/bridge-router.js +35 -8
- package/dist/main/ipc/views.js +10 -1
- package/dist/main/menu/index.d.ts +2 -2
- package/dist/main/menu/index.js +4 -2
- package/dist/main/runtime/miniapp-runtime.d.ts +79 -11
- package/dist/main/services/notifications/renderer-notifier.d.ts +11 -0
- package/dist/main/services/notifications/renderer-notifier.js +3 -0
- package/dist/main/services/views/host-toolbar-port-channel.d.ts +10 -0
- package/dist/main/services/views/host-toolbar-port-channel.js +89 -10
- package/dist/main/services/views/view-manager.d.ts +28 -4
- package/dist/main/services/views/view-manager.js +42 -8
- package/dist/main/services/workbench-context.d.ts +7 -0
- package/dist/main/services/workbench-context.js +5 -0
- package/dist/main/services/workspace/workspace-service.d.ts +3 -7
- package/dist/main/services/workspace/workspace-service.js +66 -0
- package/dist/main/windows/settings-window/index.d.ts +33 -0
- package/dist/main/windows/settings-window/index.js +59 -0
- package/dist/preload/index.d.ts +2 -2
- package/dist/preload/index.js +2 -2
- package/dist/preload/runtime/host-toolbar-port.d.ts +10 -5
- package/dist/preload/runtime/host-toolbar-port.js +24 -0
- package/dist/preload/windows/host-toolbar-runtime.cjs +20 -1
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
- package/dist/preload/windows/main.cjs +9 -7
- package/dist/preload/windows/main.cjs.map +2 -2
- package/dist/preload/windows/simulator.cjs.map +1 -1
- package/dist/renderer/assets/index-Bi_6SS-L.js +50 -0
- package/dist/renderer/assets/{input-6fpCXV-n.js → input-DgqX2UvN.js} +2 -2
- package/dist/renderer/assets/{ipc-transport-D22e4dv7.js → ipc-transport-CsFhDJ7q.js} +2 -2
- package/dist/renderer/assets/ipc-transport-SnOAk0Jq.css +1 -0
- package/dist/renderer/assets/{popover-CdGdKkkc.js → popover-D_2o_52M.js} +2 -2
- package/dist/renderer/assets/{select-X0sbjwdP.js → select-BJYsdghn.js} +2 -2
- package/dist/renderer/assets/{settings-CS4jYaCw.js → settings-CivkfizP.js} +2 -2
- package/dist/renderer/assets/{settings-api-CCWTAao_.js → settings-api-7mXkBy5-.js} +2 -2
- package/dist/renderer/assets/{workbenchSettings-Bpzaj3bm.js → workbenchSettings-BwpwxuzM.js} +2 -2
- package/dist/renderer/entries/main/index.html +6 -6
- package/dist/renderer/entries/popover/index.html +5 -5
- package/dist/renderer/entries/settings/index.html +5 -5
- package/dist/renderer/entries/workbench-settings/index.html +4 -4
- package/dist/shared/ipc-channels.d.ts +11 -0
- package/dist/shared/ipc-channels.js +14 -0
- package/dist/shared/types.d.ts +48 -11
- package/dist/simulator/assets/bridge-channels-BUQ5AbvJ.js +2 -0
- package/dist/simulator/assets/device-shell-BEnc2k-W.js +2 -0
- package/dist/simulator/assets/{simulator-DHylZf9Z.js → simulator-cV1PERi6.js} +3 -3
- package/dist/simulator/assets/simulator-mini-app-CYtW6bMd.js +2 -0
- package/dist/simulator/simulator.html +1 -1
- package/package.json +4 -4
- package/dist/renderer/assets/index-DLzjz1wv.js +0 -50
- package/dist/renderer/assets/ipc-transport-Bs8Sf1B2.css +0 -1
- package/dist/simulator/assets/device-shell-fH2cI-3q.js +0 -2
- package/dist/simulator/assets/simulator-mini-app-BDNu5n26.js +0 -2
|
@@ -374,6 +374,10 @@ var ProjectChannel = {
|
|
|
374
374
|
GetCompileConfig: "project:getCompileConfig",
|
|
375
375
|
SaveCompileConfig: "project:saveCompileConfig",
|
|
376
376
|
Status: "project:status",
|
|
377
|
+
// Main → renderer push of per-line dmcc compile logs (devkit `onLog`).
|
|
378
|
+
// Dedicated channel: `project:status` keeps its one-event-per-payload
|
|
379
|
+
// contract (compileEvents), this one carries the line stream (compileLogs).
|
|
380
|
+
CompileLog: "project:compileLog",
|
|
377
381
|
CaptureThumbnail: "project:captureThumbnail",
|
|
378
382
|
GetThumbnail: "project:getThumbnail"
|
|
379
383
|
};
|
|
@@ -440,7 +444,17 @@ var ViewChannel = {
|
|
|
440
444
|
* main → main-window renderer: push the reserved host-toolbar height so the
|
|
441
445
|
* renderer placeholder div resizes (closing the dynamic-height loop).
|
|
442
446
|
*/
|
|
443
|
-
HostToolbarHeightChanged: "view:host-toolbar:height-changed"
|
|
447
|
+
HostToolbarHeightChanged: "view:host-toolbar:height-changed",
|
|
448
|
+
/**
|
|
449
|
+
* main ← main-window renderer (invoke): pull the last NOTIFIED toolbar
|
|
450
|
+
* height retained in main. Mount-time replay companion to
|
|
451
|
+
* `HostToolbarHeightChanged`: the push listener mounts with the project
|
|
452
|
+
* view and the toolbar's size-advertiser deduplicates (never re-reports),
|
|
453
|
+
* so a height pushed while no project view was mounted would otherwise be
|
|
454
|
+
* lost forever (cold start on the project list races it; close-project →
|
|
455
|
+
* reopen hits it deterministically). No payload; resolves a number.
|
|
456
|
+
*/
|
|
457
|
+
HostToolbarGetHeight: "view:host-toolbar:get-height"
|
|
444
458
|
};
|
|
445
459
|
var PopoverChannel = {
|
|
446
460
|
Show: "popover:show",
|
|
@@ -740,9 +754,9 @@ function registerProjectFsIpc(ctx) {
|
|
|
740
754
|
}
|
|
741
755
|
|
|
742
756
|
// src/main/app/app.ts
|
|
743
|
-
import { app as app14, BrowserWindow as
|
|
757
|
+
import { app as app14, BrowserWindow as BrowserWindow8, nativeImage, session as session4 } from "electron";
|
|
744
758
|
import fs10 from "fs";
|
|
745
|
-
import
|
|
759
|
+
import path21 from "path";
|
|
746
760
|
|
|
747
761
|
// src/main/utils/paths.ts
|
|
748
762
|
import fs3 from "fs";
|
|
@@ -966,6 +980,9 @@ function createRendererNotifier(ctx) {
|
|
|
966
980
|
projectStatus(payload) {
|
|
967
981
|
sendToMain(ProjectChannel.Status, payload);
|
|
968
982
|
},
|
|
983
|
+
compileLog(payload) {
|
|
984
|
+
sendToMain(ProjectChannel.CompileLog, payload);
|
|
985
|
+
},
|
|
969
986
|
windowNavigateBack() {
|
|
970
987
|
sendToMain(WindowChannel.NavigateBack);
|
|
971
988
|
},
|
|
@@ -1655,8 +1672,10 @@ import { MessageChannelMain } from "electron";
|
|
|
1655
1672
|
function createHostToolbarPortChannel(opts) {
|
|
1656
1673
|
let activePort = null;
|
|
1657
1674
|
let activeWc = null;
|
|
1658
|
-
let
|
|
1675
|
+
let state = "absent";
|
|
1676
|
+
let generation = 0;
|
|
1659
1677
|
const handlers2 = [];
|
|
1678
|
+
const readyHandlers = [];
|
|
1660
1679
|
function dispatch(data) {
|
|
1661
1680
|
if (typeof data !== "object" || data === null) return;
|
|
1662
1681
|
const { channel, payload } = data;
|
|
@@ -1665,10 +1684,11 @@ function createHostToolbarPortChannel(opts) {
|
|
|
1665
1684
|
if (entry.channel === channel) entry.handler(payload);
|
|
1666
1685
|
}
|
|
1667
1686
|
}
|
|
1668
|
-
function dropActivePort(close) {
|
|
1687
|
+
function dropActivePort(close, next) {
|
|
1669
1688
|
const port = activePort;
|
|
1670
1689
|
activePort = null;
|
|
1671
1690
|
activeWc = null;
|
|
1691
|
+
if (state !== "disposed") state = next;
|
|
1672
1692
|
if (close && port) {
|
|
1673
1693
|
try {
|
|
1674
1694
|
port.close();
|
|
@@ -1676,21 +1696,36 @@ function createHostToolbarPortChannel(opts) {
|
|
|
1676
1696
|
}
|
|
1677
1697
|
}
|
|
1678
1698
|
}
|
|
1699
|
+
function invokeReadyHandler(handler) {
|
|
1700
|
+
try {
|
|
1701
|
+
handler();
|
|
1702
|
+
} catch (err) {
|
|
1703
|
+
console.error("[host-toolbar] onReady handler threw:", err);
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
function fireReadyHandlers() {
|
|
1707
|
+
for (const entry of [...readyHandlers]) {
|
|
1708
|
+
if (readyHandlers.includes(entry)) invokeReadyHandler(entry.handler);
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1679
1711
|
function handshake(wc) {
|
|
1680
|
-
if (disposed) return;
|
|
1712
|
+
if (state === "disposed") return;
|
|
1681
1713
|
if (!opts.isCurrent(wc)) return;
|
|
1682
|
-
dropActivePort(true);
|
|
1714
|
+
dropActivePort(true, "awaitingHandshake");
|
|
1683
1715
|
const { port1, port2 } = new MessageChannelMain();
|
|
1684
1716
|
port1.on("message", (event) => {
|
|
1685
1717
|
dispatch(event.data);
|
|
1686
1718
|
});
|
|
1687
1719
|
port1.on("close", () => {
|
|
1688
|
-
if (activePort === port1) dropActivePort(false);
|
|
1720
|
+
if (activePort === port1) dropActivePort(false, "absent");
|
|
1689
1721
|
});
|
|
1690
1722
|
wc.postMessage(ViewChannel.HostToolbarPort, null, [port2]);
|
|
1691
1723
|
port1.start();
|
|
1692
1724
|
activePort = port1;
|
|
1693
1725
|
activeWc = wc;
|
|
1726
|
+
state = "ready";
|
|
1727
|
+
generation++;
|
|
1728
|
+
fireReadyHandlers();
|
|
1694
1729
|
}
|
|
1695
1730
|
return {
|
|
1696
1731
|
attach(wc) {
|
|
@@ -1702,15 +1737,15 @@ function createHostToolbarPortChannel(opts) {
|
|
|
1702
1737
|
const isSameDocument = typeof details?.isSameDocument === "boolean" ? details.isSameDocument : isInPlace;
|
|
1703
1738
|
const isMainFrame = typeof details?.isMainFrame === "boolean" ? details.isMainFrame : isMainFramePositional;
|
|
1704
1739
|
if (isSameDocument || !isMainFrame) return;
|
|
1705
|
-
dropActivePort(true);
|
|
1740
|
+
dropActivePort(true, "awaitingHandshake");
|
|
1706
1741
|
}
|
|
1707
1742
|
);
|
|
1708
1743
|
wc.on("destroyed", () => {
|
|
1709
|
-
if (activeWc === wc) dropActivePort(true);
|
|
1744
|
+
if (activeWc === wc) dropActivePort(true, "absent");
|
|
1710
1745
|
});
|
|
1711
1746
|
},
|
|
1712
1747
|
invalidate() {
|
|
1713
|
-
dropActivePort(true);
|
|
1748
|
+
dropActivePort(true, "awaitingHandshake");
|
|
1714
1749
|
},
|
|
1715
1750
|
onMessage(channel, handler) {
|
|
1716
1751
|
if (typeof channel !== "string" || channel === "") {
|
|
@@ -1727,15 +1762,38 @@ function createHostToolbarPortChannel(opts) {
|
|
|
1727
1762
|
}
|
|
1728
1763
|
};
|
|
1729
1764
|
},
|
|
1765
|
+
onReady(handler) {
|
|
1766
|
+
if (state === "disposed") {
|
|
1767
|
+
return { dispose() {
|
|
1768
|
+
} };
|
|
1769
|
+
}
|
|
1770
|
+
const entry = { handler };
|
|
1771
|
+
readyHandlers.push(entry);
|
|
1772
|
+
if (state === "ready") {
|
|
1773
|
+
const scheduledGeneration = generation;
|
|
1774
|
+
queueMicrotask(() => {
|
|
1775
|
+
if (state !== "ready" || generation !== scheduledGeneration || !activePort) return;
|
|
1776
|
+
if (!readyHandlers.includes(entry)) return;
|
|
1777
|
+
invokeReadyHandler(entry.handler);
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
return {
|
|
1781
|
+
dispose() {
|
|
1782
|
+
const i = readyHandlers.indexOf(entry);
|
|
1783
|
+
if (i >= 0) readyHandlers.splice(i, 1);
|
|
1784
|
+
}
|
|
1785
|
+
};
|
|
1786
|
+
},
|
|
1730
1787
|
send(channel, payload) {
|
|
1731
1788
|
if (!activePort) return false;
|
|
1732
1789
|
activePort.postMessage({ channel, payload });
|
|
1733
1790
|
return true;
|
|
1734
1791
|
},
|
|
1735
1792
|
dispose() {
|
|
1736
|
-
|
|
1737
|
-
|
|
1793
|
+
dropActivePort(true, "absent");
|
|
1794
|
+
state = "disposed";
|
|
1738
1795
|
handlers2.length = 0;
|
|
1796
|
+
readyHandlers.length = 0;
|
|
1739
1797
|
}
|
|
1740
1798
|
};
|
|
1741
1799
|
}
|
|
@@ -1800,6 +1858,7 @@ function createViewManager(ctx) {
|
|
|
1800
1858
|
let hostToolbarViewAdded = false;
|
|
1801
1859
|
let hostToolbarRuntimeAcquired = false;
|
|
1802
1860
|
let hostToolbarHeightMode = "auto";
|
|
1861
|
+
let hostToolbarLastHeight = 0;
|
|
1803
1862
|
const hostToolbarPort = createHostToolbarPortChannel({
|
|
1804
1863
|
isCurrent: (wc) => liveHostToolbarWebContents() === wc
|
|
1805
1864
|
});
|
|
@@ -1902,9 +1961,13 @@ function createViewManager(ctx) {
|
|
|
1902
1961
|
}
|
|
1903
1962
|
view.setBounds(bounds);
|
|
1904
1963
|
}
|
|
1964
|
+
function notifyHostToolbarHeight(height) {
|
|
1965
|
+
hostToolbarLastHeight = height;
|
|
1966
|
+
ctx.notify.hostToolbarHeightChanged(height);
|
|
1967
|
+
}
|
|
1905
1968
|
function setHostToolbarHeight(extent) {
|
|
1906
1969
|
if (hostToolbarHeightMode !== "auto") return;
|
|
1907
|
-
|
|
1970
|
+
notifyHostToolbarHeight(extent);
|
|
1908
1971
|
}
|
|
1909
1972
|
function hideHostToolbar() {
|
|
1910
1973
|
if (hostToolbarView && hostToolbarViewAdded && !ctx.windows.mainWindow.isDestroyed()) {
|
|
@@ -1914,7 +1977,7 @@ function createViewManager(ctx) {
|
|
|
1914
1977
|
}
|
|
1915
1978
|
}
|
|
1916
1979
|
hostToolbarViewAdded = false;
|
|
1917
|
-
|
|
1980
|
+
notifyHostToolbarHeight(0);
|
|
1918
1981
|
}
|
|
1919
1982
|
const hostToolbar = {
|
|
1920
1983
|
async loadURL(url) {
|
|
@@ -1937,14 +2000,22 @@ function createViewManager(ctx) {
|
|
|
1937
2000
|
hostToolbarPreloadOverride = path22;
|
|
1938
2001
|
},
|
|
1939
2002
|
setHeightMode(mode) {
|
|
2003
|
+
if (mode !== "auto" && !(Number.isFinite(mode.fixed) && mode.fixed >= 0)) {
|
|
2004
|
+
throw new TypeError(
|
|
2005
|
+
`hostToolbar.setHeightMode: fixed height must be a finite, non-negative number (got ${mode.fixed})`
|
|
2006
|
+
);
|
|
2007
|
+
}
|
|
1940
2008
|
hostToolbarHeightMode = mode;
|
|
1941
2009
|
if (mode !== "auto") {
|
|
1942
|
-
|
|
2010
|
+
notifyHostToolbarHeight(mode.fixed);
|
|
1943
2011
|
}
|
|
1944
2012
|
},
|
|
1945
2013
|
onMessage(channel, handler) {
|
|
1946
2014
|
return hostToolbarPort.onMessage(channel, handler);
|
|
1947
2015
|
},
|
|
2016
|
+
onReady(handler) {
|
|
2017
|
+
return hostToolbarPort.onReady(handler);
|
|
2018
|
+
},
|
|
1948
2019
|
send(channel, payload) {
|
|
1949
2020
|
return hostToolbarPort.send(channel, payload);
|
|
1950
2021
|
}
|
|
@@ -2497,6 +2568,7 @@ function createViewManager(ctx) {
|
|
|
2497
2568
|
return popoverView.webContents.id;
|
|
2498
2569
|
},
|
|
2499
2570
|
getHostToolbarWebContentsId: () => liveHostToolbarWebContents()?.id ?? null,
|
|
2571
|
+
getHostToolbarHeight: () => hostToolbarLastHeight,
|
|
2500
2572
|
setNativeSimulatorViewBounds,
|
|
2501
2573
|
resize,
|
|
2502
2574
|
setSimulatorDevtoolsBounds,
|
|
@@ -2532,13 +2604,82 @@ function createWindowService(mainWindow) {
|
|
|
2532
2604
|
};
|
|
2533
2605
|
}
|
|
2534
2606
|
|
|
2607
|
+
// src/main/windows/settings-window/create.ts
|
|
2608
|
+
import { BrowserWindow as BrowserWindow3 } from "electron";
|
|
2609
|
+
import path8 from "path";
|
|
2610
|
+
async function createSettingsWindow(parent, rendererDir2) {
|
|
2611
|
+
const win = new BrowserWindow3({
|
|
2612
|
+
width: 420,
|
|
2613
|
+
height: 560,
|
|
2614
|
+
minWidth: 380,
|
|
2615
|
+
minHeight: 480,
|
|
2616
|
+
parent: parent ?? void 0,
|
|
2617
|
+
title: "\u5F00\u53D1\u5DE5\u5177\u8BBE\u7F6E",
|
|
2618
|
+
backgroundColor: themeBg(),
|
|
2619
|
+
webPreferences: {
|
|
2620
|
+
nodeIntegration: false,
|
|
2621
|
+
contextIsolation: true,
|
|
2622
|
+
sandbox: false,
|
|
2623
|
+
preload: mainPreloadPath
|
|
2624
|
+
}
|
|
2625
|
+
});
|
|
2626
|
+
applyNavigationHardening(win.webContents, rendererDir2);
|
|
2627
|
+
await win.loadFile(path8.join(rendererDir2, "entries/workbench-settings/index.html"));
|
|
2628
|
+
return win;
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
// src/main/windows/settings-window/events.ts
|
|
2632
|
+
function wireSettingsWindowEvents(win, onClosed) {
|
|
2633
|
+
win.on("closed", () => {
|
|
2634
|
+
onClosed();
|
|
2635
|
+
});
|
|
2636
|
+
}
|
|
2637
|
+
|
|
2638
|
+
// src/main/windows/settings-window/index.ts
|
|
2639
|
+
var inFlightCreations = /* @__PURE__ */ new WeakMap();
|
|
2640
|
+
async function getOrCreateSettingsWindow(deps) {
|
|
2641
|
+
const existing = deps.windows.settingsWindow;
|
|
2642
|
+
if (existing && !existing.isDestroyed()) return existing;
|
|
2643
|
+
const inFlight = inFlightCreations.get(deps.windows);
|
|
2644
|
+
if (inFlight) return inFlight;
|
|
2645
|
+
const creation = (async () => {
|
|
2646
|
+
const win = await createSettingsWindow(deps.windows.mainWindow, deps.rendererDir);
|
|
2647
|
+
deps.windows.setSettingsWindow(win);
|
|
2648
|
+
wireSettingsWindowEvents(win, () => {
|
|
2649
|
+
if (deps.windows.settingsWindow === win) {
|
|
2650
|
+
deps.windows.setSettingsWindow(null);
|
|
2651
|
+
}
|
|
2652
|
+
});
|
|
2653
|
+
return win;
|
|
2654
|
+
})();
|
|
2655
|
+
inFlightCreations.set(deps.windows, creation);
|
|
2656
|
+
try {
|
|
2657
|
+
return await creation;
|
|
2658
|
+
} finally {
|
|
2659
|
+
if (inFlightCreations.get(deps.windows) === creation) {
|
|
2660
|
+
inFlightCreations.delete(deps.windows);
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
async function openSettingsWindow(deps) {
|
|
2665
|
+
const win = await getOrCreateSettingsWindow(deps);
|
|
2666
|
+
win.show();
|
|
2667
|
+
win.focus();
|
|
2668
|
+
deps.notify.workbenchSettingsInit(win, {
|
|
2669
|
+
settings: loadWorkbenchSettings()
|
|
2670
|
+
});
|
|
2671
|
+
}
|
|
2672
|
+
|
|
2673
|
+
// src/main/services/workspace/workspace-service.ts
|
|
2674
|
+
import { z as z2 } from "zod";
|
|
2675
|
+
|
|
2535
2676
|
// src/main/services/projects/project-repository.ts
|
|
2536
2677
|
import { app as app5 } from "electron";
|
|
2537
|
-
import
|
|
2678
|
+
import path9 from "path";
|
|
2538
2679
|
import fs4 from "fs";
|
|
2539
2680
|
var log2 = createLogger("projects");
|
|
2540
2681
|
function getProjectsFile() {
|
|
2541
|
-
return
|
|
2682
|
+
return path9.join(app5.getPath("userData"), "dimina-projects.json");
|
|
2542
2683
|
}
|
|
2543
2684
|
function load() {
|
|
2544
2685
|
try {
|
|
@@ -2560,13 +2701,13 @@ function validateProjectDir(dirPath) {
|
|
|
2560
2701
|
if (!fs4.existsSync(dirPath)) {
|
|
2561
2702
|
return `\u5C0F\u7A0B\u5E8F\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${dirPath}`;
|
|
2562
2703
|
}
|
|
2563
|
-
if (!fs4.existsSync(
|
|
2564
|
-
const configPath =
|
|
2704
|
+
if (!fs4.existsSync(path9.join(dirPath, "app.json"))) {
|
|
2705
|
+
const configPath = path9.join(dirPath, "project.config.json");
|
|
2565
2706
|
if (fs4.existsSync(configPath)) {
|
|
2566
2707
|
try {
|
|
2567
2708
|
const cfg = JSON.parse(fs4.readFileSync(configPath, "utf-8"));
|
|
2568
2709
|
if (cfg.miniprogramRoot) {
|
|
2569
|
-
const resolvedRoot =
|
|
2710
|
+
const resolvedRoot = path9.resolve(dirPath, cfg.miniprogramRoot);
|
|
2570
2711
|
return `\u8BE5\u76EE\u5F55\u7F3A\u5C11 app.json\uFF0Cproject.config.json \u4E2D\u6307\u5B9A\u4E86 miniprogramRoot: "${cfg.miniprogramRoot}"\uFF0C\u8BF7\u5BFC\u5165 ${resolvedRoot}`;
|
|
2571
2712
|
}
|
|
2572
2713
|
} catch (err) {
|
|
@@ -2579,9 +2720,9 @@ function validateProjectDir(dirPath) {
|
|
|
2579
2720
|
}
|
|
2580
2721
|
function addProject(dirPath) {
|
|
2581
2722
|
const projects = load();
|
|
2582
|
-
let name =
|
|
2723
|
+
let name = path9.basename(dirPath);
|
|
2583
2724
|
try {
|
|
2584
|
-
const configPath =
|
|
2725
|
+
const configPath = path9.join(dirPath, "project.config.json");
|
|
2585
2726
|
if (fs4.existsSync(configPath)) {
|
|
2586
2727
|
const cfg = JSON.parse(fs4.readFileSync(configPath, "utf-8"));
|
|
2587
2728
|
if (cfg.projectname) name = cfg.projectname;
|
|
@@ -2620,7 +2761,7 @@ function getCompileConfig(dirPath) {
|
|
|
2620
2761
|
};
|
|
2621
2762
|
}
|
|
2622
2763
|
function getProjectPages(dirPath) {
|
|
2623
|
-
const appJsonPath =
|
|
2764
|
+
const appJsonPath = path9.join(dirPath, "app.json");
|
|
2624
2765
|
try {
|
|
2625
2766
|
const appJson = JSON.parse(
|
|
2626
2767
|
fs4.readFileSync(appJsonPath, "utf-8")
|
|
@@ -2646,7 +2787,7 @@ function getProjectSettings(projectPath) {
|
|
|
2646
2787
|
return { uploadWithSourceMap: false };
|
|
2647
2788
|
}
|
|
2648
2789
|
try {
|
|
2649
|
-
const configPath =
|
|
2790
|
+
const configPath = path9.join(projectPath, "project.config.json");
|
|
2650
2791
|
const config = JSON.parse(fs4.readFileSync(configPath, "utf-8"));
|
|
2651
2792
|
return {
|
|
2652
2793
|
uploadWithSourceMap: !!config.setting?.uploadWithSourceMap
|
|
@@ -2657,7 +2798,7 @@ function getProjectSettings(projectPath) {
|
|
|
2657
2798
|
}
|
|
2658
2799
|
function updateProjectSettings(projectPath, patch) {
|
|
2659
2800
|
if (!projectPath) return;
|
|
2660
|
-
const configPath =
|
|
2801
|
+
const configPath = path9.join(projectPath, "project.config.json");
|
|
2661
2802
|
let config = {};
|
|
2662
2803
|
try {
|
|
2663
2804
|
config = JSON.parse(fs4.readFileSync(configPath, "utf-8"));
|
|
@@ -2700,10 +2841,12 @@ function getSimulatorServicewechatReferer() {
|
|
|
2700
2841
|
}
|
|
2701
2842
|
|
|
2702
2843
|
// src/main/services/workspace/workspace-service.ts
|
|
2844
|
+
var SessionAppInfoSchema = z2.looseObject({ appId: z2.string() });
|
|
2703
2845
|
function createWorkspaceService(ctx) {
|
|
2704
2846
|
let currentSession = null;
|
|
2705
2847
|
let currentProjectPath = "";
|
|
2706
2848
|
let lastClosedProjectPath = "";
|
|
2849
|
+
let logGeneration = 0;
|
|
2707
2850
|
function sendStatus(status2, message, hotReload) {
|
|
2708
2851
|
ctx.notify.projectStatus(hotReload ? { status: status2, message, hotReload: true } : { status: status2, message });
|
|
2709
2852
|
}
|
|
@@ -2752,6 +2895,7 @@ function createWorkspaceService(ctx) {
|
|
|
2752
2895
|
validateProjectDir: async (dirPath) => provider.validateProjectDir ? provider.validateProjectDir(dirPath) : null,
|
|
2753
2896
|
async openProject(projectPath) {
|
|
2754
2897
|
clearSimulatorServicewechatReferer();
|
|
2898
|
+
logGeneration++;
|
|
2755
2899
|
await disposeSession();
|
|
2756
2900
|
currentProjectPath = "";
|
|
2757
2901
|
lastClosedProjectPath = "";
|
|
@@ -2762,6 +2906,7 @@ function createWorkspaceService(ctx) {
|
|
|
2762
2906
|
}
|
|
2763
2907
|
sendStatus("compiling", "\u6B63\u5728\u7F16\u8BD1...");
|
|
2764
2908
|
const { compile } = loadWorkbenchSettings();
|
|
2909
|
+
const sessionGeneration = ++logGeneration;
|
|
2765
2910
|
let session5;
|
|
2766
2911
|
try {
|
|
2767
2912
|
session5 = await ctx.adapter.openProject({
|
|
@@ -2769,13 +2914,40 @@ function createWorkspaceService(ctx) {
|
|
|
2769
2914
|
sourcemap: true,
|
|
2770
2915
|
watch: compile.watch,
|
|
2771
2916
|
onRebuild: () => sendStatus("ready", "\u7F16\u8BD1\u5B8C\u6210\uFF0C\u5DF2\u70ED\u66F4\u65B0", true),
|
|
2772
|
-
onBuildError: (err) => sendStatus("error", String(err))
|
|
2917
|
+
onBuildError: (err) => sendStatus("error", String(err)),
|
|
2918
|
+
// Per-line dmcc log (already filtered in devkit). Stamp the
|
|
2919
|
+
// wall-clock capture time here and push verbatim on the dedicated
|
|
2920
|
+
// compile-log channel — never through projectStatus, whose
|
|
2921
|
+
// one-event-per-payload contract feeds compileEvents. Stale lines
|
|
2922
|
+
// (a closed/replaced session's worker flushing its buffers) are
|
|
2923
|
+
// dropped via the generation check.
|
|
2924
|
+
onLog: (entry) => {
|
|
2925
|
+
if (sessionGeneration !== logGeneration) return;
|
|
2926
|
+
ctx.notify.compileLog({
|
|
2927
|
+
stream: entry.stream,
|
|
2928
|
+
text: entry.text,
|
|
2929
|
+
at: Date.now()
|
|
2930
|
+
});
|
|
2931
|
+
}
|
|
2773
2932
|
});
|
|
2774
2933
|
} catch (err) {
|
|
2775
2934
|
clearSimulatorServicewechatReferer();
|
|
2776
2935
|
sendStatus("error", String(err));
|
|
2777
2936
|
return { success: false, error: String(err) };
|
|
2778
2937
|
}
|
|
2938
|
+
if (!SessionAppInfoSchema.safeParse(session5.appInfo).success) {
|
|
2939
|
+
try {
|
|
2940
|
+
await session5.close();
|
|
2941
|
+
} catch (closeErr) {
|
|
2942
|
+
console.warn(
|
|
2943
|
+
"[workspace] closing appId-less adapter session failed (non-fatal):",
|
|
2944
|
+
closeErr
|
|
2945
|
+
);
|
|
2946
|
+
}
|
|
2947
|
+
const error = "adapter returned session.appInfo without a string appId \u2014 the CompilationAdapter must supply appInfo.appId";
|
|
2948
|
+
sendStatus("error", error);
|
|
2949
|
+
return { success: false, error };
|
|
2950
|
+
}
|
|
2779
2951
|
currentSession = session5;
|
|
2780
2952
|
currentProjectPath = projectPath;
|
|
2781
2953
|
bestEffort("updateLastOpened", () => {
|
|
@@ -2790,6 +2962,7 @@ function createWorkspaceService(ctx) {
|
|
|
2790
2962
|
};
|
|
2791
2963
|
},
|
|
2792
2964
|
async closeProject() {
|
|
2965
|
+
logGeneration++;
|
|
2793
2966
|
clearSimulatorServicewechatReferer();
|
|
2794
2967
|
await disposeSession();
|
|
2795
2968
|
if (currentProjectPath !== "") lastClosedProjectPath = currentProjectPath;
|
|
@@ -2839,16 +3012,16 @@ function createWorkspaceService(ctx) {
|
|
|
2839
3012
|
// src/main/services/projects/thumbnail.ts
|
|
2840
3013
|
import { createHash } from "crypto";
|
|
2841
3014
|
import fs5 from "fs";
|
|
2842
|
-
import
|
|
3015
|
+
import path10 from "path";
|
|
2843
3016
|
import { app as app6 } from "electron";
|
|
2844
3017
|
function getThumbnailDir() {
|
|
2845
|
-
return
|
|
3018
|
+
return path10.join(app6.getPath("userData"), "thumbnails");
|
|
2846
3019
|
}
|
|
2847
3020
|
function hashProjectPath(projectPath) {
|
|
2848
3021
|
return createHash("sha256").update(projectPath).digest("hex").slice(0, 16);
|
|
2849
3022
|
}
|
|
2850
3023
|
function getThumbnailPath(projectPath) {
|
|
2851
|
-
return
|
|
3024
|
+
return path10.join(getThumbnailDir(), `${hashProjectPath(projectPath)}.png`);
|
|
2852
3025
|
}
|
|
2853
3026
|
var DATA_URL_PNG_PREFIX = "data:image/png;base64,";
|
|
2854
3027
|
function saveThumbnailFromDataUrl(projectPath, imageDataUrl) {
|
|
@@ -2909,20 +3082,20 @@ function sanitizeTemplates(templates) {
|
|
|
2909
3082
|
}
|
|
2910
3083
|
|
|
2911
3084
|
// src/main/services/projects/builtin-templates.ts
|
|
2912
|
-
import
|
|
2913
|
-
var TEMPLATES_DIR =
|
|
3085
|
+
import path11 from "node:path";
|
|
3086
|
+
var TEMPLATES_DIR = path11.join(devtoolsPackageRoot, "templates");
|
|
2914
3087
|
var BUILTIN_TEMPLATES = [
|
|
2915
3088
|
{
|
|
2916
3089
|
id: "blank",
|
|
2917
3090
|
name: "Blank",
|
|
2918
3091
|
description: "\u6700\u5C0F\u9AA8\u67B6\uFF1Aapp.* + \u4E00\u4E2A index \u9875\u9762",
|
|
2919
|
-
source: { type: "directory", path:
|
|
3092
|
+
source: { type: "directory", path: path11.join(TEMPLATES_DIR, "blank") }
|
|
2920
3093
|
},
|
|
2921
3094
|
{
|
|
2922
3095
|
id: "taro-todo",
|
|
2923
3096
|
name: "Taro Todo",
|
|
2924
3097
|
description: "Taro \u7F16\u8BD1\u4EA7\u7269\u7684 Todo \u793A\u4F8B",
|
|
2925
|
-
source: { type: "directory", path:
|
|
3098
|
+
source: { type: "directory", path: path11.join(TEMPLATES_DIR, "taro-todo") }
|
|
2926
3099
|
}
|
|
2927
3100
|
];
|
|
2928
3101
|
|
|
@@ -2943,6 +3116,7 @@ function createWorkbenchContext(opts) {
|
|
|
2943
3116
|
ctx.windows = createWindowService(opts.mainWindow);
|
|
2944
3117
|
ctx.views = createViewManager(ctx);
|
|
2945
3118
|
ctx.notify = createRendererNotifier(ctx);
|
|
3119
|
+
ctx.openSettings = () => openSettingsWindow(ctx);
|
|
2946
3120
|
ctx.projectsProvider = opts.projectsProvider ?? createLocalProjectsProvider();
|
|
2947
3121
|
ctx.projectTemplates = resolveTemplates(
|
|
2948
3122
|
BUILTIN_TEMPLATES,
|
|
@@ -2965,7 +3139,7 @@ function installAppMenu(ctx) {
|
|
|
2965
3139
|
{
|
|
2966
3140
|
label: "\u5F00\u53D1\u5DE5\u5177\u8BBE\u7F6E",
|
|
2967
3141
|
click: () => {
|
|
2968
|
-
void
|
|
3142
|
+
void ctx.openSettings().catch(() => {
|
|
2969
3143
|
});
|
|
2970
3144
|
}
|
|
2971
3145
|
},
|
|
@@ -3041,111 +3215,111 @@ function registerAppIpc(ctx) {
|
|
|
3041
3215
|
}
|
|
3042
3216
|
|
|
3043
3217
|
// src/shared/ipc-schemas.ts
|
|
3044
|
-
import { z as
|
|
3045
|
-
var AbsolutePath =
|
|
3218
|
+
import { z as z3 } from "zod";
|
|
3219
|
+
var AbsolutePath = z3.string().min(1).refine(
|
|
3046
3220
|
(p) => p.startsWith("/") || /^[a-zA-Z]:\\/.test(p) || /^[a-zA-Z]:\//.test(p),
|
|
3047
3221
|
"must be an absolute path"
|
|
3048
3222
|
);
|
|
3049
|
-
var ProjectsAddSchema =
|
|
3050
|
-
var ProjectOpenSchema =
|
|
3051
|
-
var CompileConfigShape =
|
|
3052
|
-
startPage:
|
|
3053
|
-
scene:
|
|
3054
|
-
queryParams:
|
|
3223
|
+
var ProjectsAddSchema = z3.tuple([AbsolutePath]);
|
|
3224
|
+
var ProjectOpenSchema = z3.tuple([AbsolutePath]);
|
|
3225
|
+
var CompileConfigShape = z3.looseObject({
|
|
3226
|
+
startPage: z3.string().optional(),
|
|
3227
|
+
scene: z3.number().optional(),
|
|
3228
|
+
queryParams: z3.array(z3.looseObject({ key: z3.string(), value: z3.string() })).optional()
|
|
3055
3229
|
});
|
|
3056
|
-
var ProjectSaveCompileConfigSchema =
|
|
3230
|
+
var ProjectSaveCompileConfigSchema = z3.tuple([
|
|
3057
3231
|
AbsolutePath,
|
|
3058
3232
|
CompileConfigShape
|
|
3059
3233
|
]);
|
|
3060
|
-
var PopoverShowSchema =
|
|
3061
|
-
var SimWidth =
|
|
3062
|
-
var SimulatorAttachNativeSchema =
|
|
3063
|
-
|
|
3234
|
+
var PopoverShowSchema = z3.tuple([z3.looseObject({})]);
|
|
3235
|
+
var SimWidth = z3.number().int().min(100).max(2e3);
|
|
3236
|
+
var SimulatorAttachNativeSchema = z3.tuple([
|
|
3237
|
+
z3.string().url().refine((u) => u.startsWith("http://") || u.startsWith("https://"), {
|
|
3064
3238
|
message: "simulator URL must be http(s)"
|
|
3065
3239
|
}),
|
|
3066
3240
|
SimWidth
|
|
3067
3241
|
]);
|
|
3068
|
-
var SimulatorSetNativeBoundsSchema =
|
|
3069
|
-
|
|
3070
|
-
x:
|
|
3071
|
-
y:
|
|
3072
|
-
width:
|
|
3073
|
-
height:
|
|
3074
|
-
zoom:
|
|
3242
|
+
var SimulatorSetNativeBoundsSchema = z3.tuple([
|
|
3243
|
+
z3.object({
|
|
3244
|
+
x: z3.number().finite(),
|
|
3245
|
+
y: z3.number().finite(),
|
|
3246
|
+
width: z3.number().finite(),
|
|
3247
|
+
height: z3.number().finite(),
|
|
3248
|
+
zoom: z3.number().finite().positive()
|
|
3075
3249
|
})
|
|
3076
3250
|
]);
|
|
3077
|
-
var SimulatorSetDeviceInfoSchema =
|
|
3078
|
-
|
|
3079
|
-
brand:
|
|
3080
|
-
model:
|
|
3081
|
-
system:
|
|
3082
|
-
platform:
|
|
3083
|
-
pixelRatio:
|
|
3084
|
-
screenWidth:
|
|
3085
|
-
screenHeight:
|
|
3086
|
-
statusBarHeight:
|
|
3087
|
-
safeAreaBottom:
|
|
3088
|
-
notchType:
|
|
3089
|
-
safeAreaInsets:
|
|
3090
|
-
top:
|
|
3091
|
-
right:
|
|
3092
|
-
bottom:
|
|
3093
|
-
left:
|
|
3251
|
+
var SimulatorSetDeviceInfoSchema = z3.tuple([
|
|
3252
|
+
z3.object({
|
|
3253
|
+
brand: z3.string().max(64),
|
|
3254
|
+
model: z3.string().max(64),
|
|
3255
|
+
system: z3.string().max(64),
|
|
3256
|
+
platform: z3.string().max(32),
|
|
3257
|
+
pixelRatio: z3.number().finite().positive(),
|
|
3258
|
+
screenWidth: z3.number().int().min(100).max(4e3),
|
|
3259
|
+
screenHeight: z3.number().int().min(100).max(4e3),
|
|
3260
|
+
statusBarHeight: z3.number().finite().min(0).max(400),
|
|
3261
|
+
safeAreaBottom: z3.number().finite().min(0).max(400),
|
|
3262
|
+
notchType: z3.enum(["none", "notch", "dynamic-island"]),
|
|
3263
|
+
safeAreaInsets: z3.object({
|
|
3264
|
+
top: z3.number().finite().min(0).max(400),
|
|
3265
|
+
right: z3.number().finite().min(0).max(400),
|
|
3266
|
+
bottom: z3.number().finite().min(0).max(400),
|
|
3267
|
+
left: z3.number().finite().min(0).max(400)
|
|
3094
3268
|
})
|
|
3095
3269
|
})
|
|
3096
3270
|
]);
|
|
3097
|
-
var NonNegInt =
|
|
3098
|
-
var ViewBoundsSchema =
|
|
3099
|
-
|
|
3271
|
+
var NonNegInt = z3.number().int().min(0).max(1e5);
|
|
3272
|
+
var ViewBoundsSchema = z3.tuple([
|
|
3273
|
+
z3.object({
|
|
3100
3274
|
x: NonNegInt,
|
|
3101
3275
|
y: NonNegInt,
|
|
3102
3276
|
width: NonNegInt,
|
|
3103
3277
|
height: NonNegInt
|
|
3104
3278
|
})
|
|
3105
3279
|
]);
|
|
3106
|
-
var HostToolbarAdvertiseHeightSchema =
|
|
3107
|
-
|
|
3108
|
-
axis:
|
|
3280
|
+
var HostToolbarAdvertiseHeightSchema = z3.tuple([
|
|
3281
|
+
z3.object({
|
|
3282
|
+
axis: z3.literal("block"),
|
|
3109
3283
|
extent: NonNegInt
|
|
3110
3284
|
})
|
|
3111
3285
|
]);
|
|
3112
|
-
var SimulatorCustomApiInvokeSchema =
|
|
3113
|
-
|
|
3114
|
-
|
|
3286
|
+
var SimulatorCustomApiInvokeSchema = z3.tuple([
|
|
3287
|
+
z3.string().min(1).max(256),
|
|
3288
|
+
z3.unknown()
|
|
3115
3289
|
]);
|
|
3116
|
-
var ProjectGetPagesSchema =
|
|
3117
|
-
var ProjectGetCompileConfigSchema =
|
|
3118
|
-
var ProjectsRemoveSchema =
|
|
3119
|
-
var WorkbenchSettingsSaveSchema =
|
|
3120
|
-
|
|
3121
|
-
cdp:
|
|
3122
|
-
enabled:
|
|
3123
|
-
port:
|
|
3290
|
+
var ProjectGetPagesSchema = z3.tuple([AbsolutePath]);
|
|
3291
|
+
var ProjectGetCompileConfigSchema = z3.tuple([AbsolutePath]);
|
|
3292
|
+
var ProjectsRemoveSchema = z3.tuple([AbsolutePath]);
|
|
3293
|
+
var WorkbenchSettingsSaveSchema = z3.tuple([
|
|
3294
|
+
z3.looseObject({
|
|
3295
|
+
cdp: z3.looseObject({
|
|
3296
|
+
enabled: z3.boolean(),
|
|
3297
|
+
port: z3.number().int().min(0).max(65535)
|
|
3124
3298
|
}),
|
|
3125
|
-
mcp:
|
|
3126
|
-
enabled:
|
|
3127
|
-
port:
|
|
3299
|
+
mcp: z3.looseObject({
|
|
3300
|
+
enabled: z3.boolean(),
|
|
3301
|
+
port: z3.number().int().min(0).max(65535)
|
|
3128
3302
|
}),
|
|
3129
|
-
compile:
|
|
3130
|
-
watch:
|
|
3303
|
+
compile: z3.looseObject({
|
|
3304
|
+
watch: z3.boolean()
|
|
3131
3305
|
}),
|
|
3132
|
-
theme:
|
|
3133
|
-
lastCreateBaseDir:
|
|
3306
|
+
theme: z3.enum(["system", "light", "dark"]),
|
|
3307
|
+
lastCreateBaseDir: z3.union([z3.string(), z3.null()])
|
|
3134
3308
|
})
|
|
3135
3309
|
]);
|
|
3136
|
-
var WorkbenchSettingsSetThemeSchema =
|
|
3137
|
-
|
|
3310
|
+
var WorkbenchSettingsSetThemeSchema = z3.tuple([
|
|
3311
|
+
z3.enum(["system", "light", "dark"])
|
|
3138
3312
|
]);
|
|
3139
|
-
var SettingsSetVisibleSchema =
|
|
3140
|
-
var SettingsConfigChangedSchema =
|
|
3141
|
-
var PopoverRelaunchSchema =
|
|
3142
|
-
var SettingsProjectSettingsChangedSchema =
|
|
3143
|
-
|
|
3144
|
-
uploadWithSourceMap:
|
|
3313
|
+
var SettingsSetVisibleSchema = z3.tuple([z3.boolean()]);
|
|
3314
|
+
var SettingsConfigChangedSchema = z3.tuple([CompileConfigShape]);
|
|
3315
|
+
var PopoverRelaunchSchema = z3.tuple([CompileConfigShape]);
|
|
3316
|
+
var SettingsProjectSettingsChangedSchema = z3.tuple([
|
|
3317
|
+
z3.looseObject({
|
|
3318
|
+
uploadWithSourceMap: z3.boolean().optional()
|
|
3145
3319
|
})
|
|
3146
3320
|
]);
|
|
3147
|
-
var ProjectCaptureThumbnailSchema =
|
|
3148
|
-
var ProjectGetThumbnailSchema =
|
|
3321
|
+
var ProjectCaptureThumbnailSchema = z3.tuple([AbsolutePath]);
|
|
3322
|
+
var ProjectGetThumbnailSchema = z3.tuple([AbsolutePath]);
|
|
3149
3323
|
|
|
3150
3324
|
// src/shared/bridge-channels.ts
|
|
3151
3325
|
var BRIDGE_CHANNELS = {
|
|
@@ -3258,11 +3432,11 @@ var popoverModule = {
|
|
|
3258
3432
|
|
|
3259
3433
|
// src/main/ipc/projects.ts
|
|
3260
3434
|
import { app as app7, dialog } from "electron";
|
|
3261
|
-
import
|
|
3435
|
+
import path13 from "path";
|
|
3262
3436
|
|
|
3263
3437
|
// src/main/services/projects/create-project-service.ts
|
|
3264
3438
|
import fs6 from "node:fs";
|
|
3265
|
-
import
|
|
3439
|
+
import path12 from "node:path";
|
|
3266
3440
|
var DEFAULT_TEMPLATE_ID = "blank";
|
|
3267
3441
|
async function createProject(input, ctx) {
|
|
3268
3442
|
const name = (input.name ?? "").trim();
|
|
@@ -3309,7 +3483,7 @@ async function createProject(input, ctx) {
|
|
|
3309
3483
|
force: true
|
|
3310
3484
|
});
|
|
3311
3485
|
}
|
|
3312
|
-
const cfgPath =
|
|
3486
|
+
const cfgPath = path12.join(target, "project.config.json");
|
|
3313
3487
|
let cfg = {};
|
|
3314
3488
|
if (fs6.existsSync(cfgPath)) {
|
|
3315
3489
|
try {
|
|
@@ -3395,7 +3569,7 @@ function registerProjectsIpc(ctx) {
|
|
|
3395
3569
|
}
|
|
3396
3570
|
try {
|
|
3397
3571
|
const settings = loadWorkbenchSettings();
|
|
3398
|
-
const newBase =
|
|
3572
|
+
const newBase = path13.dirname(input.path);
|
|
3399
3573
|
if (newBase && settings.lastCreateBaseDir !== newBase) {
|
|
3400
3574
|
saveWorkbenchSettings({ ...settings, lastCreateBaseDir: newBase });
|
|
3401
3575
|
}
|
|
@@ -3567,7 +3741,7 @@ import { DisposableRegistry as DisposableRegistry6 } from "@dimina-kit/electron-
|
|
|
3567
3741
|
|
|
3568
3742
|
// src/main/ipc/bridge-router.ts
|
|
3569
3743
|
import { app as app11, ipcMain as ipcMain3, protocol as protocol2, session as electronSession, webContents as webContents2 } from "electron";
|
|
3570
|
-
import
|
|
3744
|
+
import path16 from "node:path";
|
|
3571
3745
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
3572
3746
|
|
|
3573
3747
|
// src/shared/simulator-api-metadata.ts
|
|
@@ -3582,7 +3756,7 @@ import { createDebugTap } from "@dimina-kit/electron-deck/main";
|
|
|
3582
3756
|
// src/main/services/dimina-resource-server.ts
|
|
3583
3757
|
import http from "node:http";
|
|
3584
3758
|
import fs7 from "node:fs";
|
|
3585
|
-
import
|
|
3759
|
+
import path14 from "node:path";
|
|
3586
3760
|
var MIME_TYPES = {
|
|
3587
3761
|
".css": "text/css; charset=utf-8",
|
|
3588
3762
|
".html": "text/html; charset=utf-8",
|
|
@@ -3598,7 +3772,7 @@ var MIME_TYPES = {
|
|
|
3598
3772
|
".wasm": "application/wasm"
|
|
3599
3773
|
};
|
|
3600
3774
|
async function startDiminaResourceServer(rootDir) {
|
|
3601
|
-
const root =
|
|
3775
|
+
const root = path14.resolve(rootDir);
|
|
3602
3776
|
const server = http.createServer((req, res) => {
|
|
3603
3777
|
void handleRequest(root, req, res);
|
|
3604
3778
|
});
|
|
@@ -3646,7 +3820,7 @@ async function handleRequest(root, req, res) {
|
|
|
3646
3820
|
return;
|
|
3647
3821
|
}
|
|
3648
3822
|
res.writeHead(200, {
|
|
3649
|
-
"content-type": MIME_TYPES[
|
|
3823
|
+
"content-type": MIME_TYPES[path14.extname(filePath)] ?? "application/octet-stream",
|
|
3650
3824
|
"content-length": stat.size,
|
|
3651
3825
|
"cache-control": "no-store"
|
|
3652
3826
|
});
|
|
@@ -3662,8 +3836,8 @@ async function handleRequest(root, req, res) {
|
|
|
3662
3836
|
}
|
|
3663
3837
|
function resolveContainedPath(root, pathname) {
|
|
3664
3838
|
const relative = pathname.replace(/^\/+/, "") || "index.html";
|
|
3665
|
-
const resolved =
|
|
3666
|
-
if (resolved !== root && !resolved.startsWith(root +
|
|
3839
|
+
const resolved = path14.resolve(root, relative);
|
|
3840
|
+
if (resolved !== root && !resolved.startsWith(root + path14.sep)) return null;
|
|
3667
3841
|
return resolved;
|
|
3668
3842
|
}
|
|
3669
3843
|
function setCorsHeaders(res) {
|
|
@@ -3674,16 +3848,16 @@ function setCorsHeaders(res) {
|
|
|
3674
3848
|
}
|
|
3675
3849
|
|
|
3676
3850
|
// src/main/windows/service-host-window/create.ts
|
|
3677
|
-
import { app as app9, BrowserWindow as
|
|
3678
|
-
import
|
|
3851
|
+
import { app as app9, BrowserWindow as BrowserWindow4 } from "electron";
|
|
3852
|
+
import path15 from "node:path";
|
|
3679
3853
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
3680
3854
|
var SERVICE_HOST_PARTITION = SHARED_MINIAPP_PARTITION;
|
|
3681
|
-
var serviceHostPreloadPath =
|
|
3682
|
-
var serviceHostHtmlPath =
|
|
3855
|
+
var serviceHostPreloadPath = path15.join(devtoolsPackageRoot, "dist/service-host/preload.cjs");
|
|
3856
|
+
var serviceHostHtmlPath = path15.join(devtoolsPackageRoot, "dist/service-host/service.html");
|
|
3683
3857
|
function constructServiceHostWindow(opts = {}) {
|
|
3684
3858
|
const partition = opts.partition ?? SERVICE_HOST_PARTITION;
|
|
3685
3859
|
configureMiniappSession(partition);
|
|
3686
|
-
return new
|
|
3860
|
+
return new BrowserWindow4({
|
|
3687
3861
|
width: 980,
|
|
3688
3862
|
height: 720,
|
|
3689
3863
|
show: false,
|
|
@@ -3754,7 +3928,7 @@ function createServiceHostWindow(opts) {
|
|
|
3754
3928
|
}
|
|
3755
3929
|
|
|
3756
3930
|
// src/main/services/service-host-pool/pool.ts
|
|
3757
|
-
import { BrowserWindow as
|
|
3931
|
+
import { BrowserWindow as BrowserWindow5 } from "electron";
|
|
3758
3932
|
var BLANK_URL = "about:blank";
|
|
3759
3933
|
var HARD_MAX_POOL_SIZE = 4;
|
|
3760
3934
|
var RESET_STORAGES = [
|
|
@@ -3951,7 +4125,7 @@ var ServiceHostPool = class {
|
|
|
3951
4125
|
}
|
|
3952
4126
|
}
|
|
3953
4127
|
createWindow(spec) {
|
|
3954
|
-
return new
|
|
4128
|
+
return new BrowserWindow5({
|
|
3955
4129
|
show: false,
|
|
3956
4130
|
width: spec.size?.width,
|
|
3957
4131
|
height: spec.size?.height,
|
|
@@ -4623,12 +4797,16 @@ function summarizeBridgeMsg(payload) {
|
|
|
4623
4797
|
var API_CALL_TIMEOUT_MS = 5e3;
|
|
4624
4798
|
function resolveCurrentApp(state, ctx, appId) {
|
|
4625
4799
|
if (appId) {
|
|
4626
|
-
|
|
4800
|
+
let match;
|
|
4801
|
+
for (const ap of state.appSessions.values()) if (ap.appId === appId) match = ap;
|
|
4802
|
+
if (match) return match;
|
|
4627
4803
|
}
|
|
4628
4804
|
const appInfo = ctx.workspace?.getSession?.()?.appInfo;
|
|
4629
4805
|
const activeAppId = appInfo?.appId;
|
|
4630
4806
|
if (activeAppId) {
|
|
4631
|
-
|
|
4807
|
+
let match;
|
|
4808
|
+
for (const ap of state.appSessions.values()) if (ap.appId === activeAppId) match = ap;
|
|
4809
|
+
if (match) return match;
|
|
4632
4810
|
}
|
|
4633
4811
|
let last;
|
|
4634
4812
|
for (const ap of state.appSessions.values()) last = ap;
|
|
@@ -4645,7 +4823,11 @@ function installBridgeRouter(ctx) {
|
|
|
4645
4823
|
emitRenderEvent: () => {
|
|
4646
4824
|
},
|
|
4647
4825
|
connections: ctx.connections,
|
|
4648
|
-
debugTap: createDebugTap({ enabled: resolveDebugTapEnabled() })
|
|
4826
|
+
debugTap: createDebugTap({ enabled: resolveDebugTapEnabled() }),
|
|
4827
|
+
evictAppDataBridges: (ap) => {
|
|
4828
|
+
if (!ctx.appData) return;
|
|
4829
|
+
for (const page of ap.pages.values()) ctx.appData.evictBridge(ap.appId, page.bridgeId);
|
|
4830
|
+
}
|
|
4649
4831
|
};
|
|
4650
4832
|
const prewarmPoolSize = resolvePrewarmPoolSize();
|
|
4651
4833
|
if (prewarmPoolSize > 0) {
|
|
@@ -4664,8 +4846,8 @@ function installBridgeRouter(ctx) {
|
|
|
4664
4846
|
const onNativeHostQuery = (event) => {
|
|
4665
4847
|
const reply = {
|
|
4666
4848
|
enabled: true,
|
|
4667
|
-
renderHostHtmlUrl: pathToFileURL3(
|
|
4668
|
-
renderPreloadUrl: pathToFileURL3(
|
|
4849
|
+
renderHostHtmlUrl: pathToFileURL3(path16.join(devtoolsPackageRoot, "dist/render-host/pageFrame.html")).toString(),
|
|
4850
|
+
renderPreloadUrl: pathToFileURL3(path16.join(devtoolsPackageRoot, "dist/render-host/preload.cjs")).toString(),
|
|
4669
4851
|
device: currentDevice ?? void 0
|
|
4670
4852
|
};
|
|
4671
4853
|
event.returnValue = reply;
|
|
@@ -4817,9 +4999,6 @@ function installBridgeRouter(ctx) {
|
|
|
4817
4999
|
console.warn(`[bridge-router] DISPOSE rejected: sender belongs to ${senderApp.appSessionId}, target ${target.appSessionId}`);
|
|
4818
5000
|
return;
|
|
4819
5001
|
}
|
|
4820
|
-
if (ctx.appData) {
|
|
4821
|
-
for (const page of target.pages.values()) ctx.appData.evictBridge(target.appId, page.bridgeId);
|
|
4822
|
-
}
|
|
4823
5002
|
void disposeAppSession(state, target.appSessionId);
|
|
4824
5003
|
};
|
|
4825
5004
|
ipcMain3.on(BRIDGE_CHANNELS.DISPOSE, onDispose);
|
|
@@ -4915,14 +5094,14 @@ async function handleSpawn(state, ctx, event, opts) {
|
|
|
4915
5094
|
const appSessionId = bridgeId;
|
|
4916
5095
|
const simulatorWc = resolveSimulatorWebContents(ctx, opts.simulatorWcId, event.sender);
|
|
4917
5096
|
const pagePath = normalizePagePath(opts.pagePath || "pages/index/index");
|
|
4918
|
-
const pkgRoot =
|
|
5097
|
+
const pkgRoot = path16.resolve(opts.pkgRoot || process.cwd());
|
|
4919
5098
|
const root = opts.root || "main";
|
|
4920
5099
|
let resourceServer = null;
|
|
4921
5100
|
let resourceBaseUrl;
|
|
4922
5101
|
if (opts.resourceBaseUrl) {
|
|
4923
5102
|
resourceBaseUrl = opts.resourceBaseUrl.endsWith("/") ? opts.resourceBaseUrl : `${opts.resourceBaseUrl}/`;
|
|
4924
5103
|
} else {
|
|
4925
|
-
resourceServer = await startDiminaResourceServer(
|
|
5104
|
+
resourceServer = await startDiminaResourceServer(path16.resolve(pkgRoot, root));
|
|
4926
5105
|
resourceBaseUrl = resourceServer.baseUrl;
|
|
4927
5106
|
}
|
|
4928
5107
|
const selectedDevice = ctx.bridge?.getDevice?.() ?? null;
|
|
@@ -5002,6 +5181,10 @@ async function handleSpawn(state, ctx, event, opts) {
|
|
|
5002
5181
|
};
|
|
5003
5182
|
appSession.onServiceClosed = onServiceClosed;
|
|
5004
5183
|
serviceWindow.once("closed", onServiceClosed);
|
|
5184
|
+
const onSimulatorDestroyed = () => {
|
|
5185
|
+
void disposeAppSession(state, appSessionId);
|
|
5186
|
+
};
|
|
5187
|
+
simulatorWc.once("destroyed", onSimulatorDestroyed);
|
|
5005
5188
|
if (usedPool) {
|
|
5006
5189
|
const bootOnServiceLoad = () => {
|
|
5007
5190
|
if (serviceWindow.isDestroyed()) return;
|
|
@@ -5506,6 +5689,7 @@ async function disposeAppSession(state, appSessionId, opts = {}) {
|
|
|
5506
5689
|
const ap = state.appSessions.get(appSessionId);
|
|
5507
5690
|
if (!ap) return;
|
|
5508
5691
|
state.appSessions.delete(appSessionId);
|
|
5692
|
+
state.evictAppDataBridges(ap);
|
|
5509
5693
|
for (const [requestId, pending] of state.pendingApiCalls) {
|
|
5510
5694
|
if (pending.appSessionId !== appSessionId) continue;
|
|
5511
5695
|
clearTimeout(pending.timer);
|
|
@@ -5671,7 +5855,7 @@ function registerViewsIpc(ctx) {
|
|
|
5671
5855
|
args
|
|
5672
5856
|
);
|
|
5673
5857
|
ctx.views.setHostToolbarBounds(bounds);
|
|
5674
|
-
});
|
|
5858
|
+
}).handle(ViewChannel.HostToolbarGetHeight, () => ctx.views.getHostToolbarHeight());
|
|
5675
5859
|
const onAdvertiseHeight = (event, ...args) => {
|
|
5676
5860
|
if (event.sender.id !== ctx.views.getHostToolbarWebContentsId()) return;
|
|
5677
5861
|
let extent;
|
|
@@ -6542,7 +6726,7 @@ function getClient(kind) {
|
|
|
6542
6726
|
}
|
|
6543
6727
|
|
|
6544
6728
|
// src/main/services/mcp/tool-registry.ts
|
|
6545
|
-
import { z as
|
|
6729
|
+
import { z as z4 } from "zod";
|
|
6546
6730
|
function registerCommonTargetTools(server, kind) {
|
|
6547
6731
|
const descriptions = kind === "simulator" ? {
|
|
6548
6732
|
screenshot: "Take a screenshot of the simulator webview",
|
|
@@ -6563,9 +6747,9 @@ function registerCommonTargetTools(server, kind) {
|
|
|
6563
6747
|
return { content: [{ type: "image", data, mimeType: "image/png" }] };
|
|
6564
6748
|
});
|
|
6565
6749
|
server.tool(`${kind}_console_logs`, descriptions.consoleLogs, {
|
|
6566
|
-
limit:
|
|
6567
|
-
level:
|
|
6568
|
-
sinceTimestamp:
|
|
6750
|
+
limit: z4.number().optional().default(50).describe("Maximum number of log entries"),
|
|
6751
|
+
level: z4.enum(["error", "warning", "warn", "info", "log", "debug"]).optional().describe("Only return entries with this level"),
|
|
6752
|
+
sinceTimestamp: z4.string().optional().describe("ISO timestamp; only return entries at or after this time")
|
|
6569
6753
|
}, async ({ limit, level, sinceTimestamp }) => {
|
|
6570
6754
|
getClient(kind);
|
|
6571
6755
|
let entries = getTargetState(kind).consoleLogs;
|
|
@@ -6580,7 +6764,7 @@ function registerCommonTargetTools(server, kind) {
|
|
|
6580
6764
|
});
|
|
6581
6765
|
if (kind !== "workbench") {
|
|
6582
6766
|
server.tool(`${kind}_evaluate`, descriptions.evaluate, {
|
|
6583
|
-
expression:
|
|
6767
|
+
expression: z4.string().describe("JavaScript expression to evaluate")
|
|
6584
6768
|
}, async ({ expression }) => {
|
|
6585
6769
|
const c = getClient(kind);
|
|
6586
6770
|
const result = await c.Runtime.evaluate({ expression, returnByValue: true, awaitPromise: true });
|
|
@@ -6593,15 +6777,15 @@ ${JSON.stringify(result.exceptionDetails, null, 2)}` }], isError: true };
|
|
|
6593
6777
|
});
|
|
6594
6778
|
}
|
|
6595
6779
|
server.tool(`${kind}_get_dom`, descriptions.getDom, {
|
|
6596
|
-
depth:
|
|
6780
|
+
depth: z4.number().optional().default(3).describe("Maximum depth")
|
|
6597
6781
|
}, async ({ depth }) => {
|
|
6598
6782
|
const c = getClient(kind);
|
|
6599
6783
|
const { root } = await c.DOM.getDocument({ depth });
|
|
6600
6784
|
return { content: [{ type: "text", text: JSON.stringify(root, null, 2) }] };
|
|
6601
6785
|
});
|
|
6602
6786
|
server.tool(`${kind}_network_log`, descriptions.networkLog, {
|
|
6603
|
-
limit:
|
|
6604
|
-
minStatus:
|
|
6787
|
+
limit: z4.number().optional().default(20).describe("Maximum number of entries"),
|
|
6788
|
+
minStatus: z4.number().optional().describe("Only return entries with status >= minStatus (status 0 = failed before response is included when minStatus >= 400)")
|
|
6605
6789
|
}, async ({ limit, minStatus }) => {
|
|
6606
6790
|
getClient(kind);
|
|
6607
6791
|
let entries = getTargetState(kind).networkRequests;
|
|
@@ -6856,11 +7040,11 @@ function registerContextTools(server) {
|
|
|
6856
7040
|
}
|
|
6857
7041
|
|
|
6858
7042
|
// src/main/services/mcp/tools/simulator-tools.ts
|
|
6859
|
-
import { z as
|
|
7043
|
+
import { z as z5 } from "zod";
|
|
6860
7044
|
function registerSimulatorTools(server) {
|
|
6861
7045
|
server.tool("simulator_navigate", "Navigate the simulator to a URL, or reload the current page", {
|
|
6862
|
-
url:
|
|
6863
|
-
reload:
|
|
7046
|
+
url: z5.string().optional().describe("URL to navigate to"),
|
|
7047
|
+
reload: z5.boolean().optional().describe("If true, reload current page instead of navigating")
|
|
6864
7048
|
}, async ({ url, reload }) => {
|
|
6865
7049
|
const c = getClient("simulator");
|
|
6866
7050
|
if (reload) {
|
|
@@ -6875,15 +7059,15 @@ function registerSimulatorTools(server) {
|
|
|
6875
7059
|
return { content: [{ type: "text", text: "Error: either url or reload is required" }], isError: true };
|
|
6876
7060
|
});
|
|
6877
7061
|
server.tool("simulator_input", "Dispatch input to the simulator. `tap_coord` requires x and y. `tap_selector` requires selector and optional nth. `type` requires selector and text. `scroll` requires x, y, deltaX, and deltaY. `key` is best-effort for common keys such as Enter, Escape, Tab, Arrow* and Space.", {
|
|
6878
|
-
action:
|
|
6879
|
-
x:
|
|
6880
|
-
y:
|
|
6881
|
-
selector:
|
|
6882
|
-
nth:
|
|
6883
|
-
text:
|
|
6884
|
-
key:
|
|
6885
|
-
deltaX:
|
|
6886
|
-
deltaY:
|
|
7062
|
+
action: z5.enum(["tap_coord", "tap_selector", "type", "scroll", "key"]).describe("Input action to dispatch"),
|
|
7063
|
+
x: z5.number().optional().describe("Viewport x coordinate for `tap_coord` or `scroll`"),
|
|
7064
|
+
y: z5.number().optional().describe("Viewport y coordinate for `tap_coord` or `scroll`"),
|
|
7065
|
+
selector: z5.string().optional().describe("CSS selector for `tap_selector` or `type`"),
|
|
7066
|
+
nth: z5.number().int().optional().describe("Zero-based index when selector matches multiple elements; defaults to 0"),
|
|
7067
|
+
text: z5.string().optional().describe("Text to insert for `type`"),
|
|
7068
|
+
key: z5.string().optional().describe("Best-effort keyboard key name for `key`; common keys such as Enter, Escape, Tab, Arrow* and Space work best"),
|
|
7069
|
+
deltaX: z5.number().optional().describe("Horizontal wheel delta for `scroll`"),
|
|
7070
|
+
deltaY: z5.number().optional().describe("Vertical wheel delta for `scroll`")
|
|
6887
7071
|
}, async ({ action, x, y, selector, nth, text, key, deltaX, deltaY }) => {
|
|
6888
7072
|
const c = getClient("simulator");
|
|
6889
7073
|
const err = (msg) => ({ content: [{ type: "text", text: `Error: ${msg}` }], isError: true });
|
|
@@ -7794,10 +7978,10 @@ function setupSimulatorCurrentPage(host, options) {
|
|
|
7794
7978
|
|
|
7795
7979
|
// src/main/services/render-inspect/index.ts
|
|
7796
7980
|
import { readFileSync } from "node:fs";
|
|
7797
|
-
import
|
|
7981
|
+
import path17 from "node:path";
|
|
7798
7982
|
var DEFAULT_SOURCE_PATH = "dist/render-host/render-inspect.js";
|
|
7799
7983
|
function createRenderInspector(options = {}) {
|
|
7800
|
-
const loadSource = options.loadSource ?? (() => readFileSync(
|
|
7984
|
+
const loadSource = options.loadSource ?? (() => readFileSync(path17.join(devtoolsPackageRoot, DEFAULT_SOURCE_PATH), "utf8"));
|
|
7801
7985
|
let cachedSource = null;
|
|
7802
7986
|
const injected = /* @__PURE__ */ new Set();
|
|
7803
7987
|
function source() {
|
|
@@ -7883,14 +8067,14 @@ function revokeAllTempFiles(store) {
|
|
|
7883
8067
|
|
|
7884
8068
|
// src/shared/vpath.ts
|
|
7885
8069
|
import os from "node:os";
|
|
7886
|
-
import
|
|
8070
|
+
import path18 from "node:path";
|
|
7887
8071
|
var DIFILE_PREFIX = "difile://";
|
|
7888
8072
|
function sandboxBase() {
|
|
7889
8073
|
const env = typeof process !== "undefined" && process.env && process.env.DIMINA_HOME || "";
|
|
7890
8074
|
if (env) {
|
|
7891
|
-
return
|
|
8075
|
+
return path18.join(env, "files");
|
|
7892
8076
|
}
|
|
7893
|
-
return
|
|
8077
|
+
return path18.join(os.homedir(), ".dimina", "files");
|
|
7894
8078
|
}
|
|
7895
8079
|
function resolveVPath(url) {
|
|
7896
8080
|
if (typeof url !== "string") return null;
|
|
@@ -7924,15 +8108,15 @@ function resolveVPath(url) {
|
|
|
7924
8108
|
return { kind, writable };
|
|
7925
8109
|
}
|
|
7926
8110
|
const base = sandboxBase();
|
|
7927
|
-
const joined =
|
|
7928
|
-
const normalized =
|
|
7929
|
-
if (normalized !== base && !normalized.startsWith(base +
|
|
8111
|
+
const joined = path18.join(base, decoded);
|
|
8112
|
+
const normalized = path18.normalize(joined);
|
|
8113
|
+
if (normalized !== base && !normalized.startsWith(base + path18.sep)) return null;
|
|
7930
8114
|
return { kind, writable, realPath: normalized };
|
|
7931
8115
|
}
|
|
7932
8116
|
|
|
7933
8117
|
// src/main/services/simulator-temp-files/disk.ts
|
|
7934
8118
|
import fs8 from "node:fs/promises";
|
|
7935
|
-
import
|
|
8119
|
+
import path19 from "node:path";
|
|
7936
8120
|
var EXT_MIME = {
|
|
7937
8121
|
".txt": "text/plain",
|
|
7938
8122
|
".log": "text/plain",
|
|
@@ -7997,7 +8181,7 @@ function sniffMime(head) {
|
|
|
7997
8181
|
return null;
|
|
7998
8182
|
}
|
|
7999
8183
|
function extMime(realPath) {
|
|
8000
|
-
const ext =
|
|
8184
|
+
const ext = path19.extname(realPath).toLowerCase();
|
|
8001
8185
|
if (!ext) return null;
|
|
8002
8186
|
return EXT_MIME[ext] ?? null;
|
|
8003
8187
|
}
|
|
@@ -8067,7 +8251,7 @@ async function readDiskFile(realPath, opts) {
|
|
|
8067
8251
|
}
|
|
8068
8252
|
async function writeDiskFile(realPath, bytes) {
|
|
8069
8253
|
const buf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(new Uint8Array(bytes));
|
|
8070
|
-
await fs8.mkdir(
|
|
8254
|
+
await fs8.mkdir(path19.dirname(realPath), { recursive: true });
|
|
8071
8255
|
await fs8.writeFile(realPath, buf);
|
|
8072
8256
|
}
|
|
8073
8257
|
async function readDiskDir(realPath) {
|
|
@@ -8209,28 +8393,28 @@ async function handleDifileRequest(ctx, req) {
|
|
|
8209
8393
|
|
|
8210
8394
|
// src/main/services/simulator-temp-files/fs-channels.ts
|
|
8211
8395
|
import fs9 from "node:fs/promises";
|
|
8212
|
-
import
|
|
8396
|
+
import path20 from "node:path";
|
|
8213
8397
|
async function enforceSandbox(realPath) {
|
|
8214
8398
|
if (typeof realPath !== "string" || realPath.length === 0) {
|
|
8215
8399
|
throw new Error("sandbox: realPath must be a non-empty string");
|
|
8216
8400
|
}
|
|
8217
8401
|
const base = sandboxBase();
|
|
8218
8402
|
const baseReal = await fs9.realpath(base).catch(() => base);
|
|
8219
|
-
const normalized =
|
|
8220
|
-
if (normalized !== base && !normalized.startsWith(base +
|
|
8403
|
+
const normalized = path20.normalize(realPath);
|
|
8404
|
+
if (normalized !== base && !normalized.startsWith(base + path20.sep)) {
|
|
8221
8405
|
throw new Error("sandbox: realPath escapes the user-data base");
|
|
8222
8406
|
}
|
|
8223
8407
|
let probe = normalized;
|
|
8224
|
-
while (probe !==
|
|
8408
|
+
while (probe !== path20.parse(probe).root) {
|
|
8225
8409
|
try {
|
|
8226
8410
|
const resolved = await fs9.realpath(probe);
|
|
8227
|
-
if (resolved !== baseReal && !resolved.startsWith(baseReal +
|
|
8411
|
+
if (resolved !== baseReal && !resolved.startsWith(baseReal + path20.sep)) {
|
|
8228
8412
|
throw new Error("sandbox: realPath escapes the user-data base via symlink");
|
|
8229
8413
|
}
|
|
8230
8414
|
break;
|
|
8231
8415
|
} catch (err) {
|
|
8232
8416
|
if (err.code === "ENOENT") {
|
|
8233
|
-
probe =
|
|
8417
|
+
probe = path20.dirname(probe);
|
|
8234
8418
|
continue;
|
|
8235
8419
|
}
|
|
8236
8420
|
throw err;
|
|
@@ -8614,7 +8798,7 @@ async function disposeContext(ctx) {
|
|
|
8614
8798
|
function createConfiguredMainWindow(config, rendererDir2) {
|
|
8615
8799
|
const mainWindow = createMainWindow({
|
|
8616
8800
|
title: config.appName ?? "Dimina DevTools",
|
|
8617
|
-
indexHtml:
|
|
8801
|
+
indexHtml: path21.join(rendererDir2, "entries/main/index.html"),
|
|
8618
8802
|
width: config.window?.width,
|
|
8619
8803
|
height: config.window?.height,
|
|
8620
8804
|
minWidth: config.window?.minWidth,
|
|
@@ -8652,12 +8836,21 @@ function registerBuiltinModules(config, context) {
|
|
|
8652
8836
|
});
|
|
8653
8837
|
}
|
|
8654
8838
|
function toMenuContext(context) {
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
8839
|
+
return {
|
|
8840
|
+
appName: context.appName,
|
|
8841
|
+
workspace: {
|
|
8842
|
+
hasActiveSession: () => context.workspace.hasActiveSession(),
|
|
8843
|
+
getProjectPath: () => context.workspace.getProjectPath(),
|
|
8844
|
+
openProject: (projectPath) => context.workspace.openProject(projectPath),
|
|
8845
|
+
closeProject: () => context.workspace.closeProject(),
|
|
8846
|
+
getSession: () => context.workspace.getSession()
|
|
8847
|
+
},
|
|
8848
|
+
openSettings: () => context.openSettings(),
|
|
8849
|
+
notify: {
|
|
8850
|
+
projectStatus: (payload) => context.notify.projectStatus(payload),
|
|
8851
|
+
windowNavigateBack: () => context.notify.windowNavigateBack()
|
|
8852
|
+
}
|
|
8853
|
+
};
|
|
8661
8854
|
}
|
|
8662
8855
|
function installMenu(config, mainWindow, context) {
|
|
8663
8856
|
if (config.menuBuilder) {
|
|
@@ -8714,7 +8907,7 @@ function enableDevRendererAutoReload(rendererDir2) {
|
|
|
8714
8907
|
const watcher = fs10.watch(rendererDir2, { recursive: true }, () => {
|
|
8715
8908
|
if (reloadTimer) clearTimeout(reloadTimer);
|
|
8716
8909
|
reloadTimer = setTimeout(() => {
|
|
8717
|
-
for (const win of
|
|
8910
|
+
for (const win of BrowserWindow8.getAllWindows()) {
|
|
8718
8911
|
win.webContents.reload();
|
|
8719
8912
|
}
|
|
8720
8913
|
}, 300);
|
|
@@ -8932,56 +9125,10 @@ function createDevtoolsBackend(config = {}) {
|
|
|
8932
9125
|
};
|
|
8933
9126
|
}
|
|
8934
9127
|
|
|
8935
|
-
// src/main/windows/settings-window/create.ts
|
|
8936
|
-
import { BrowserWindow as BrowserWindow8 } from "electron";
|
|
8937
|
-
import path21 from "path";
|
|
8938
|
-
async function createSettingsWindow(parent, rendererDir2) {
|
|
8939
|
-
const win = new BrowserWindow8({
|
|
8940
|
-
width: 420,
|
|
8941
|
-
height: 560,
|
|
8942
|
-
minWidth: 380,
|
|
8943
|
-
minHeight: 480,
|
|
8944
|
-
parent: parent ?? void 0,
|
|
8945
|
-
title: "\u5F00\u53D1\u5DE5\u5177\u8BBE\u7F6E",
|
|
8946
|
-
backgroundColor: themeBg(),
|
|
8947
|
-
webPreferences: {
|
|
8948
|
-
nodeIntegration: false,
|
|
8949
|
-
contextIsolation: true,
|
|
8950
|
-
sandbox: false,
|
|
8951
|
-
preload: mainPreloadPath
|
|
8952
|
-
}
|
|
8953
|
-
});
|
|
8954
|
-
applyNavigationHardening(win.webContents, rendererDir2);
|
|
8955
|
-
await win.loadFile(path21.join(rendererDir2, "entries/workbench-settings/index.html"));
|
|
8956
|
-
return win;
|
|
8957
|
-
}
|
|
8958
|
-
|
|
8959
|
-
// src/main/windows/settings-window/events.ts
|
|
8960
|
-
function wireSettingsWindowEvents(win, onClosed) {
|
|
8961
|
-
win.on("closed", () => {
|
|
8962
|
-
onClosed();
|
|
8963
|
-
});
|
|
8964
|
-
}
|
|
8965
|
-
|
|
8966
9128
|
// src/main/app/launch.ts
|
|
8967
9129
|
function launch(config = {}) {
|
|
8968
9130
|
return frameworkElectronDeck({ backend: createDevtoolsBackend(config) });
|
|
8969
9131
|
}
|
|
8970
|
-
async function openSettingsWindow(ctx) {
|
|
8971
|
-
let win = ctx.windows.settingsWindow;
|
|
8972
|
-
if (!win || win.isDestroyed()) {
|
|
8973
|
-
win = await createSettingsWindow(ctx.windows.mainWindow, ctx.rendererDir);
|
|
8974
|
-
ctx.windows.setSettingsWindow(win);
|
|
8975
|
-
wireSettingsWindowEvents(win, () => {
|
|
8976
|
-
ctx.windows.setSettingsWindow(null);
|
|
8977
|
-
});
|
|
8978
|
-
}
|
|
8979
|
-
win.show();
|
|
8980
|
-
win.focus();
|
|
8981
|
-
ctx.notify.workbenchSettingsInit(win, {
|
|
8982
|
-
settings: loadWorkbenchSettings()
|
|
8983
|
-
});
|
|
8984
|
-
}
|
|
8985
9132
|
|
|
8986
9133
|
// src/main/index.ts
|
|
8987
9134
|
launch().catch((err) => {
|