@dimina-kit/devtools 0.4.0-dev.20260831134112 → 0.4.0-dev.20260907055341
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 +52 -729
- package/dist/main/app/app.d.ts +27 -7
- package/dist/main/app/app.js +285 -681
- package/dist/main/app/editor-view.d.ts +21 -0
- package/dist/main/app/editor-view.js +71 -0
- package/dist/main/app/global-mirrors.d.ts +23 -0
- package/dist/main/app/global-mirrors.js +37 -0
- package/dist/main/app/host-sidebar-default.d.ts +19 -0
- package/dist/main/app/host-sidebar-default.js +44 -0
- package/dist/main/app/menu-setup.d.ts +13 -0
- package/dist/main/app/menu-setup.js +49 -0
- package/dist/main/app/open-project-ipc.d.ts +13 -0
- package/dist/main/app/open-project-ipc.js +21 -0
- package/dist/main/app/project-list-surface.d.ts +31 -0
- package/dist/main/app/project-list-surface.js +20 -0
- package/dist/main/app/project-window.d.ts +36 -0
- package/dist/main/app/project-window.js +93 -0
- package/dist/main/app/servers.d.ts +17 -0
- package/dist/main/app/servers.js +60 -0
- package/dist/main/app/ui-extension-targets.d.ts +42 -0
- package/dist/main/app/ui-extension-targets.js +101 -0
- package/dist/main/app/window-close-reveal.harness.d.ts +34 -0
- package/dist/main/app/window-close-reveal.harness.js +65 -0
- package/dist/main/app/window-events.d.ts +15 -0
- package/dist/main/app/window-events.js +45 -0
- package/dist/main/app/window-runtime-services.d.ts +41 -0
- package/dist/main/app/window-runtime-services.js +178 -0
- package/dist/main/app/workbench-modules.d.ts +24 -0
- package/dist/main/app/workbench-modules.js +51 -0
- package/dist/main/app/workbench-window.d.ts +85 -0
- package/dist/main/app/workbench-window.js +310 -0
- package/dist/main/index.bundle.js +10669 -9096
- package/dist/main/ipc/app.d.ts +4 -1
- package/dist/main/ipc/app.js +4 -3
- package/dist/main/ipc/device-picker.d.ts +16 -0
- package/dist/main/ipc/device-picker.js +27 -0
- package/dist/main/ipc/index.d.ts +1 -0
- package/dist/main/ipc/index.js +1 -0
- package/dist/main/ipc/internal-devtools.d.ts +2 -1
- package/dist/main/ipc/internal-devtools.js +4 -3
- package/dist/main/ipc/popover.d.ts +4 -1
- package/dist/main/ipc/popover.js +25 -9
- package/dist/main/ipc/project-create.d.ts +2 -1
- package/dist/main/ipc/project-create.js +6 -5
- package/dist/main/ipc/project-fs.d.ts +3 -1
- package/dist/main/ipc/project-fs.js +17 -17
- package/dist/main/ipc/projects.d.ts +3 -3
- package/dist/main/ipc/projects.js +13 -12
- package/dist/main/ipc/session.d.ts +4 -1
- package/dist/main/ipc/session.js +16 -11
- package/dist/main/ipc/settings.d.ts +4 -1
- package/dist/main/ipc/settings.js +12 -19
- package/dist/main/ipc/simulator-module.d.ts +5 -0
- package/dist/main/ipc/simulator-module.js +9 -5
- package/dist/main/ipc/simulator.d.ts +4 -1
- package/dist/main/ipc/simulator.js +12 -18
- package/dist/main/ipc/tooltip.d.ts +2 -1
- package/dist/main/ipc/tooltip.js +8 -7
- package/dist/main/ipc/views.d.ts +4 -1
- package/dist/main/ipc/views.js +20 -9
- package/dist/main/runtime/devtools-backend-before-quit.harness.d.ts +2 -20
- package/dist/main/runtime/devtools-backend-before-quit.harness.js +14 -283
- package/dist/main/runtime/devtools-backend.js +14 -3
- package/dist/main/runtime/devtools-runtime-mock.harness.d.ts +21 -0
- package/dist/main/runtime/devtools-runtime-mock.harness.js +313 -0
- package/dist/main/services/app-services.d.ts +62 -0
- package/dist/main/services/app-services.js +64 -0
- package/dist/main/services/automation/connection-target.d.ts +36 -0
- package/dist/main/services/automation/connection-target.js +29 -0
- package/dist/main/services/automation/console-bridge.d.ts +28 -0
- package/dist/main/services/automation/console-bridge.js +91 -0
- package/dist/main/services/automation/handlers/app.js +4 -4
- package/dist/main/services/automation/handlers/element.js +55 -21
- package/dist/main/services/automation/index.d.ts +12 -1
- package/dist/main/services/automation/index.js +54 -133
- package/dist/main/services/default-adapter.js +1 -1
- package/dist/main/services/fs-bridge-protocol.d.ts +61 -0
- package/dist/main/services/fs-bridge-protocol.js +34 -0
- package/dist/main/services/fs-watch-sse.d.ts +8 -1
- package/dist/main/services/fs-watch-sse.js +19 -5
- package/dist/main/services/mcp/connection-owner.d.ts +38 -0
- package/dist/main/services/mcp/connection-owner.js +79 -0
- package/dist/main/services/mcp/index.d.ts +3 -1
- package/dist/main/services/mcp/index.js +4 -3
- package/dist/main/services/mcp/opened-project.d.ts +88 -0
- package/dist/main/services/mcp/opened-project.js +60 -0
- package/dist/main/services/mcp/target-manager.d.ts +71 -23
- package/dist/main/services/mcp/target-manager.js +269 -142
- package/dist/main/services/mcp/target-selection.d.ts +47 -0
- package/dist/main/services/mcp/target-selection.js +71 -0
- package/dist/main/services/mcp/tools/context-tools.js +20 -5
- package/dist/main/services/mcp/tools/project-tools.d.ts +29 -6
- package/dist/main/services/mcp/tools/project-tools.js +37 -25
- package/dist/main/services/module.d.ts +13 -5
- package/dist/main/services/notifications/renderer-notifier.d.ts +28 -4
- package/dist/main/services/notifications/renderer-notifier.js +15 -3
- package/dist/main/services/projects/local-provider.js +2 -0
- package/dist/main/services/projects/project-repository.d.ts +31 -1
- package/dist/main/services/projects/project-repository.js +144 -20
- package/dist/main/services/projects/types.d.ts +31 -8
- package/dist/main/services/safe-area/index.d.ts +19 -5
- package/dist/main/services/safe-area/index.js +38 -13
- package/dist/main/services/simulator/ui-extensions.d.ts +8 -0
- package/dist/main/services/simulator/ui-extensions.js +16 -6
- package/dist/main/services/simulator-storage/index.d.ts +12 -1
- package/dist/main/services/simulator-storage/index.js +22 -7
- package/dist/main/services/simulator-storage/window-scope.d.ts +20 -0
- package/dist/main/services/simulator-storage/window-scope.js +20 -0
- package/dist/main/services/views/host-slot-port-channel.d.ts +20 -3
- package/dist/main/services/views/host-slot-port-channel.js +33 -5
- package/dist/main/services/views/managed-web-contents-view.js +21 -1
- package/dist/main/services/views/native-simulator-view.js +13 -16
- package/dist/main/services/views/overlay-panels-view.d.ts +13 -0
- package/dist/main/services/views/overlay-panels-view.js +31 -0
- package/dist/main/services/views/view-manager.d.ts +1 -1
- package/dist/main/services/views/view-manager.js +3 -0
- package/dist/main/services/window-contexts/context-router.d.ts +36 -0
- package/dist/main/services/window-contexts/context-router.js +55 -0
- package/dist/main/services/workbench-coi-host.d.ts +52 -0
- package/dist/main/services/workbench-coi-host.js +227 -0
- package/dist/main/services/workbench-coi-server.js +75 -133
- package/dist/main/services/workbench-coi-shutdown.d.ts +40 -0
- package/dist/main/services/workbench-coi-shutdown.js +69 -0
- package/dist/main/services/workbench-coi-static.d.ts +23 -0
- package/dist/main/services/workbench-coi-static.js +87 -0
- package/dist/main/services/workbench-context.d.ts +27 -3
- package/dist/main/services/workbench-context.js +10 -5
- package/dist/main/services/workspace/compile-mode-adapter.d.ts +18 -0
- package/dist/main/services/workspace/compile-mode-adapter.js +57 -0
- package/dist/main/services/workspace/compile-mode-store.d.ts +25 -0
- package/dist/main/services/workspace/compile-mode-store.js +71 -0
- package/dist/main/services/workspace/workspace-compile-modes.d.ts +59 -0
- package/dist/main/services/workspace/workspace-compile-modes.js +93 -0
- package/dist/main/services/workspace/workspace-referer.d.ts +17 -0
- package/dist/main/services/workspace/workspace-referer.js +26 -0
- package/dist/main/services/workspace/workspace-service.d.ts +4 -0
- package/dist/main/services/workspace/workspace-service.js +51 -84
- package/dist/main/services/workspace/workspace-thumbnails.d.ts +22 -0
- package/dist/main/services/workspace/workspace-thumbnails.js +67 -0
- package/dist/main/utils/ipc-context-source.d.ts +40 -0
- package/dist/main/utils/ipc-context-source.js +23 -0
- package/dist/main/utils/ipc-registry.d.ts +42 -36
- package/dist/main/utils/ipc-registry.js +117 -50
- package/dist/main/utils/sender-policy.d.ts +9 -0
- package/dist/main/utils/sender-policy.js +26 -3
- package/dist/main/utils/theme.d.ts +3 -2
- package/dist/main/utils/theme.js +3 -2
- package/dist/main/windows/main-window/create.d.ts +16 -0
- package/dist/main/windows/main-window/create.js +19 -11
- package/dist/main/windows/main-window/events.d.ts +1 -1
- package/dist/main/windows/main-window/events.js +26 -13
- package/dist/main/windows/main-window/index.d.ts +1 -1
- package/dist/main/windows/main-window/index.js +1 -1
- package/dist/native-host/common/common.js +94 -73
- package/dist/native-host/render/render.js +4079 -3171
- package/dist/native-host/service/service.js +2 -2
- package/dist/preload/runtime/native-host.d.ts +4 -0
- package/dist/preload/runtime/temp-files.js +9 -2
- package/dist/preload/runtime/wait-for-slot-root.d.ts +7 -4
- package/dist/preload/runtime/wait-for-slot-root.js +36 -8
- package/dist/preload/windows/host-dialog-runtime.cjs +10 -3
- package/dist/preload/windows/host-dialog-runtime.cjs.map +2 -2
- package/dist/preload/windows/host-sidebar-runtime.cjs +10 -3
- package/dist/preload/windows/host-sidebar-runtime.cjs.map +2 -2
- package/dist/preload/windows/host-toolbar-runtime.cjs +10 -3
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
- package/dist/preload/windows/main.cjs +181 -4
- package/dist/preload/windows/main.cjs.map +4 -4
- package/dist/preload/windows/simulator.cjs +10 -0
- package/dist/preload/windows/simulator.cjs.map +2 -2
- package/dist/preload/windows/simulator.js +10 -0
- package/dist/renderer/assets/button-CB2MWjHY.js +2 -0
- package/dist/renderer/assets/constants-CkoGPQTS.js +2 -0
- package/dist/renderer/assets/constants-zQZ2-y21.js +2 -0
- package/dist/renderer/assets/{createLucideIcon-Bqi8hpdi.js → createLucideIcon-cZ9FlZZw.js} +2 -2
- package/dist/renderer/assets/devicePicker-H2eIO4e1.js +2 -0
- package/dist/renderer/assets/dialog-pHzEA8Vx.js +46 -0
- package/dist/renderer/assets/dist-B5HADirS.js +2 -0
- package/dist/renderer/assets/{dist-DKWdE1TK.js → dist-DIFlRMKe.js} +2 -2
- package/dist/renderer/assets/hostSidebarDefault-DRWh6OCt.js +2 -0
- package/dist/renderer/assets/index-CEL_XFge.js +2 -0
- package/dist/renderer/assets/{input-Ct3alvkq.js → input-CAObw95L.js} +2 -2
- package/dist/renderer/assets/ipc-channels-overlays-gIPUFnqc.js +2 -0
- package/dist/renderer/assets/jsx-runtime-DICEQH_0.css +1 -0
- package/dist/renderer/assets/{jsx-runtime-DGLHmmOq.js → jsx-runtime-DIw5wnYl.js} +1 -1
- package/dist/renderer/assets/plus-BQ9u5EbL.js +2 -0
- package/dist/renderer/assets/popover-Cw7G2Ctp.js +2 -0
- package/dist/renderer/assets/presets-DMZOb9ay.js +2 -0
- package/dist/renderer/assets/project-api-YTOr_Yvo.js +2 -0
- package/dist/renderer/assets/{projectCreateDialog-Bbjz75bP.js → projectCreateDialog-BmLqiYxn.js} +2 -2
- package/dist/renderer/assets/search-BMvuYF48.js +2 -0
- package/dist/renderer/assets/select-nFP95TxM.js +2 -0
- package/dist/renderer/assets/settings-CnpVfSWt.js +2 -0
- package/dist/renderer/assets/settings-api-Ccsf-Nsj.js +2 -0
- package/dist/renderer/assets/settings-tab-bar-CAzrv32m.js +2 -0
- package/dist/renderer/assets/smartphone-Bb2GdIKy.js +2 -0
- package/dist/renderer/assets/tabs-CPKN3Mmq.js +2 -0
- package/dist/renderer/assets/{tooltip-B_-_YVbw.js → tooltip-D6AxXRk5.js} +2 -2
- package/dist/renderer/assets/types-Bh0hA7El.js +2 -0
- package/dist/renderer/assets/updateDialog-CwndJ0Bl.js +2 -0
- package/dist/renderer/assets/{utils-kfQov6Pa.js → utils-sEB5OZEQ.js} +2 -2
- package/dist/renderer/assets/view-api-B-2zPBR5.js +2 -0
- package/dist/renderer/assets/view-ids-BfaDVV5P.js +2 -0
- package/dist/renderer/assets/workbench-BLJ0wKsg.js +5 -0
- package/dist/renderer/assets/{workbenchSettings-CV4LVA9b.js → workbenchSettings-YD0Ctbm_.js} +3 -3
- package/dist/renderer/entries/device-picker/index.html +28 -0
- package/dist/renderer/entries/host-sidebar-default/index.html +6 -5
- package/dist/renderer/entries/main/index.html +16 -17
- package/dist/renderer/entries/popover/index.html +16 -10
- package/dist/renderer/entries/project-create-dialog/index.html +12 -12
- package/dist/renderer/entries/settings/index.html +10 -10
- package/dist/renderer/entries/tooltip/index.html +5 -5
- package/dist/renderer/entries/update-dialog/index.html +10 -10
- package/dist/renderer/entries/workbench/index.html +49 -0
- package/dist/renderer/entries/workbench-settings/index.html +12 -11
- package/dist/service-host/host-env-update.cjs +23 -0
- package/dist/service-host/preload.cjs +24 -49
- package/dist/service-host/service-message-queue.cjs +71 -0
- package/dist/service-host/sync-impls/system-info.js +31 -9
- package/dist/shared/compile-mode-state.d.ts +73 -0
- package/dist/shared/compile-mode-state.js +100 -0
- package/dist/shared/compile-modes.d.ts +152 -0
- package/dist/shared/compile-modes.js +237 -0
- package/dist/shared/ipc-channels-overlays.d.ts +8 -2
- package/dist/shared/ipc-channels-overlays.js +19 -2
- package/dist/shared/ipc-channels.d.ts +5 -10
- package/dist/shared/ipc-channels.js +17 -14
- package/dist/shared/ipc-schemas.d.ts +76 -24
- package/dist/shared/ipc-schemas.js +55 -10
- package/dist/shared/project-window-types.d.ts +42 -0
- package/dist/shared/project-window-types.js +2 -0
- package/dist/shared/types.d.ts +43 -17
- package/dist/shared/view-ids.d.ts +1 -0
- package/dist/shared/view-ids.js +3 -1
- package/dist/simulator/assets/bridge-channels-B3JAmRfl.js +2 -0
- package/dist/simulator/assets/device-shell-ATEhHV2_.css +1 -0
- package/dist/simulator/assets/device-shell-pxnZZp10.js +431 -0
- package/dist/simulator/assets/simulator-Dwp7lnvu.js +10 -0
- package/dist/simulator/assets/simulator-mini-app-DFo7fhi5.js +2 -0
- package/dist/simulator/assets/simulator-ui-B2ddJB1R.js +2 -0
- package/dist/simulator/simulator.html +3 -3
- package/dist/simulator/temp-files.d.ts +6 -0
- package/dist/simulator/temp-files.js +46 -4
- package/dist/simulator/types.d.ts +7 -0
- package/dist/vscode-workbench/assets/__vite-browser-external-JIkWewFf.js +1 -0
- package/dist/vscode-workbench/assets/{dist-CMfmHflW.js → dist-CXG-u1VB.js} +3 -3
- package/dist/vscode-workbench/assets/{iconv-lite-umd-Bx8CgaZq.js → iconv-lite-umd-Dxx9Qyb4.js} +1 -1
- package/dist/vscode-workbench/assets/{index-CdG6YWhW.js → index-6VJMsaWj.js} +460 -460
- package/dist/vscode-workbench/assets/{jschardet-M0qgd2lN.js → jschardet-Ba3D16vt.js} +1 -1
- package/dist/vscode-workbench/index.html +1 -1
- package/package.json +11 -8
- package/dist/renderer/assets/button-D5Q2wkXq.js +0 -2
- package/dist/renderer/assets/constants-D7DfVqMp.js +0 -2
- package/dist/renderer/assets/constants-D8zsejFq.js +0 -2
- package/dist/renderer/assets/dialog-e1TecTOY.js +0 -46
- package/dist/renderer/assets/hostSidebarDefault-B3yLfy8j.js +0 -2
- package/dist/renderer/assets/index-CsPD68N_.js +0 -5
- package/dist/renderer/assets/ipc-channels-overlays-LsDzGAtV.js +0 -2
- package/dist/renderer/assets/jsx-runtime-2vXHouwr.css +0 -1
- package/dist/renderer/assets/popover-Dix5cm_b.js +0 -2
- package/dist/renderer/assets/project-api-k7Oq9iaq.js +0 -2
- package/dist/renderer/assets/select-acGb0AmJ.js +0 -2
- package/dist/renderer/assets/settings-CQrTMr43.js +0 -2
- package/dist/renderer/assets/settings-api-CrUQ9rYV.js +0 -2
- package/dist/renderer/assets/settings-tab-bar-Cw1kVIf2.js +0 -2
- package/dist/renderer/assets/types-CsEKtFyr.js +0 -2
- package/dist/renderer/assets/updateDialog-NsF8223A.js +0 -2
- package/dist/renderer/assets/view-api-CLn3rcQE.js +0 -2
- package/dist/simulator/assets/bridge-channels-zhsumfky.js +0 -2
- package/dist/simulator/assets/device-shell-CmtM1QxP.js +0 -2
- package/dist/simulator/assets/device-shell-iFZo1igL.css +0 -1
- package/dist/simulator/assets/simulator-CIobn3Mh.js +0 -10
- package/dist/simulator/assets/simulator-mini-app-CRe6n9br.js +0 -2
- package/dist/simulator/assets/simulator-ui-C_cP602X.js +0 -2
- package/dist/vscode-workbench/assets/__vite-browser-external-Bc1vizTf.js +0 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CustomFileTypes, WorkbenchAppConfig } from '../../shared/types.js';
|
|
2
|
+
import type { ViewManager } from '../services/views/view-manager.js';
|
|
3
|
+
import type { WorkspaceService } from '../services/workspace/workspace-service.js';
|
|
4
|
+
import type { DisposableRegistry } from '@dimina-kit/electron-deck/main';
|
|
5
|
+
/** Narrow view of the context fields the embedded editor depends on. */
|
|
6
|
+
export interface EditorViewContext {
|
|
7
|
+
workspace: WorkspaceService;
|
|
8
|
+
fileTypes: CustomFileTypes;
|
|
9
|
+
views: ViewManager;
|
|
10
|
+
registry: DisposableRegistry;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Embedded workbench editor — the sole devtools editor. Stands up the COI http
|
|
14
|
+
* server that serves the workbench bundle with the SharedArrayBuffer isolation
|
|
15
|
+
* headers and bridges `/__fs/*` onto the active project, then hands its base URL
|
|
16
|
+
* to the view manager so the 'editor' dock slot mounts the workbench
|
|
17
|
+
* WebContentsView. Both the server and the WCV tear down with the context
|
|
18
|
+
* registry.
|
|
19
|
+
*/
|
|
20
|
+
export declare function setupEditorView(config: WorkbenchAppConfig, context: EditorViewContext, getActiveAppId: () => string | null): Promise<void>;
|
|
21
|
+
//# sourceMappingURL=editor-view.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { devtoolsPackageRoot } from '../utils/paths.js';
|
|
4
|
+
import { startWorkbenchCoiServer } from '../services/workbench-coi-server.js';
|
|
5
|
+
/**
|
|
6
|
+
* Embedded workbench editor — the sole devtools editor. Stands up the COI http
|
|
7
|
+
* server that serves the workbench bundle with the SharedArrayBuffer isolation
|
|
8
|
+
* headers and bridges `/__fs/*` onto the active project, then hands its base URL
|
|
9
|
+
* to the view manager so the 'editor' dock slot mounts the workbench
|
|
10
|
+
* WebContentsView. Both the server and the WCV tear down with the context
|
|
11
|
+
* registry.
|
|
12
|
+
*/
|
|
13
|
+
export async function setupEditorView(config, context, getActiveAppId) {
|
|
14
|
+
// Default the bundle dir to the devtools package's OWN `dist/vscode-workbench`
|
|
15
|
+
// (resolved from the package root), NOT relative to the caller's rendererDir:
|
|
16
|
+
// a host that overrides `rendererDir` but omits `editorViewConfig.bundleDir`
|
|
17
|
+
// would otherwise compute a path next to ITS renderer, where no workbench
|
|
18
|
+
// bundle exists → 404 / blank editor.
|
|
19
|
+
const bundleDir = config.editorViewConfig?.bundleDir ?? path.join(devtoolsPackageRoot, 'dist/vscode-workbench');
|
|
20
|
+
// Skip the entire editor assembly when the bundle is missing. Starting the COI
|
|
21
|
+
// server and attaching the WCV against a non-existent bundle yields a silent
|
|
22
|
+
// blank editor (the WCV loads index.html → 404); a launchable app with no
|
|
23
|
+
// editor is strictly better. The view manager never gets a source, so the
|
|
24
|
+
// 'editor' slot's lazy attach is a no-op.
|
|
25
|
+
if (!fs.existsSync(path.join(bundleDir, 'index.html'))) {
|
|
26
|
+
console.warn(`[workbench] editor bundle not found at ${bundleDir} — skipping embedded editor assembly`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const coiServer = await startWorkbenchCoiServer({
|
|
30
|
+
rootDir: bundleDir,
|
|
31
|
+
getProjectRoot: () => context.workspace.getProjectPath(),
|
|
32
|
+
extensionsDir: config.editorViewConfig?.extensionsDir,
|
|
33
|
+
getFileTypes: () => context.fileTypes,
|
|
34
|
+
// Names the editor's VS Code workspace after the active miniapp, so each
|
|
35
|
+
// project gets its own open-editors/view-state bucket instead of all of
|
|
36
|
+
// them sharing the one derived from the constant mirror root.
|
|
37
|
+
getProjectIdentity: () => ({
|
|
38
|
+
appId: getActiveAppId(),
|
|
39
|
+
projectPath: context.workspace.getProjectPath(),
|
|
40
|
+
}),
|
|
41
|
+
});
|
|
42
|
+
try {
|
|
43
|
+
// Return the close promise so the registry awaits server shutdown on dispose
|
|
44
|
+
// instead of fire-and-forgetting it (a dangling http server would keep the
|
|
45
|
+
// port + event loop alive past teardown).
|
|
46
|
+
context.registry.add(() => coiServer.close());
|
|
47
|
+
// The registry disposes LIFO, so this runs BEFORE the context-level
|
|
48
|
+
// disposeAll: void any in-flight open's attach hold here too, or a stale
|
|
49
|
+
// release / cap firing could rebuild the workbench during the awaited
|
|
50
|
+
// coiServer.close() above, before disposeAll's own cancel runs.
|
|
51
|
+
context.registry.add(() => {
|
|
52
|
+
context.views.cancelWorkbenchAttachHold();
|
|
53
|
+
context.views.detachWorkbench();
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
// The window was torn down while the bridge was still binding, so the
|
|
58
|
+
// registry that would have closed it is already disposed and refuses new
|
|
59
|
+
// entries. Close it here instead: an orphaned route keeps the shared COI
|
|
60
|
+
// listener (and its port) alive for the rest of the process.
|
|
61
|
+
await coiServer.close().catch(() => { });
|
|
62
|
+
throw err;
|
|
63
|
+
}
|
|
64
|
+
// Only HAND the view manager the COI URL — do NOT load yet. The heavy
|
|
65
|
+
// WebContentsView load (10MB bundle + ext-host) is deferred to the first time
|
|
66
|
+
// the 'editor' dock slot becomes visible (first non-zero bounds), so it never
|
|
67
|
+
// sits on the app boot critical path. Loading it eagerly here delayed
|
|
68
|
+
// preload/window-ready enough to trip the e2e launch health check.
|
|
69
|
+
context.views.setWorkbenchSource(coiServer.baseUrl);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=editor-view.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { BrowserWindow } from 'electron';
|
|
2
|
+
import type { ConsoleForwarder } from '../services/console-forward/index.js';
|
|
3
|
+
import type { DiagnosticsBus } from '../services/diagnostics/index.js';
|
|
4
|
+
import type { CdpSessionBroker } from '../services/cdp-session/index.js';
|
|
5
|
+
import type { InternalDevtoolsWindow } from '../windows/internal-devtools-window/index.js';
|
|
6
|
+
import { type DisposableRegistry } from '@dimina-kit/electron-deck/main';
|
|
7
|
+
/** Narrow view of the context fields the two global mirrors depend on. */
|
|
8
|
+
export interface GlobalMirrorContext {
|
|
9
|
+
consoleForwarder?: ConsoleForwarder;
|
|
10
|
+
diagnostics?: DiagnosticsBus;
|
|
11
|
+
internalDevtoolsWindow?: InternalDevtoolsWindow;
|
|
12
|
+
cdpSessionBroker: CdpSessionBroker;
|
|
13
|
+
registry: DisposableRegistry;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Console + diagnostics mirrors into the standalone internal DevTools window.
|
|
17
|
+
*
|
|
18
|
+
* Both mirrors target the INSPECTED side — `mainWindow.webContents`, per
|
|
19
|
+
* internal-devtools-window.ts's setDevToolsWebContents relationship — and NOT
|
|
20
|
+
* the front-end host page the `onHostChanged` callback hands them.
|
|
21
|
+
*/
|
|
22
|
+
export declare function installGlobalMirrors(context: GlobalMirrorContext, mainWindow: BrowserWindow): void;
|
|
23
|
+
//# sourceMappingURL=global-mirrors.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createGlobalConsoleMirror } from '../services/console-forward/global-console-mirror.js';
|
|
2
|
+
import { createGlobalDiagnosticsMirror } from '../services/console-forward/global-diagnostics-mirror.js';
|
|
3
|
+
import { toDisposable } from '@dimina-kit/electron-deck/main';
|
|
4
|
+
/**
|
|
5
|
+
* Console + diagnostics mirrors into the standalone internal DevTools window.
|
|
6
|
+
*
|
|
7
|
+
* Both mirrors target the INSPECTED side — `mainWindow.webContents`, per
|
|
8
|
+
* internal-devtools-window.ts's setDevToolsWebContents relationship — and NOT
|
|
9
|
+
* the front-end host page the `onHostChanged` callback hands them.
|
|
10
|
+
*/
|
|
11
|
+
export function installGlobalMirrors(context, mainWindow) {
|
|
12
|
+
// While the standalone internal DevTools window is open, mirror every guest
|
|
13
|
+
// console entry (service + render, UNFILTERED — see global-console-mirror.ts)
|
|
14
|
+
// into it — each open replays the forwarder's current history buffer first
|
|
15
|
+
// (see that module's doc comment for why the subscribe lifecycle is gated on
|
|
16
|
+
// onHostChanged rather than subscribed once at construction time).
|
|
17
|
+
// `context.consoleForwarder` is assembled by the simulator module's
|
|
18
|
+
// installBridgeRouter; absent only when that builtin module was disabled via
|
|
19
|
+
// config.
|
|
20
|
+
if (context.consoleForwarder && context.internalDevtoolsWindow) {
|
|
21
|
+
const consoleMirror = createGlobalConsoleMirror(context.consoleForwarder, mainWindow.webContents, context.internalDevtoolsWindow.onHostChanged,
|
|
22
|
+
// CDP transport (never executeJavaScript) — see the mirror's inject()
|
|
23
|
+
// doc for the setDevToolsWebContents + external-CDP double-attach hang.
|
|
24
|
+
{ broker: context.cdpSessionBroker });
|
|
25
|
+
context.registry.add(toDisposable(() => consoleMirror.dispose()));
|
|
26
|
+
}
|
|
27
|
+
// Same wiring for diagnostics: every diagnostic — including
|
|
28
|
+
// `audience:'internal'` ones console-forward's own service-host injection
|
|
29
|
+
// now skips (see compile-standby.ts / index.ts's handleDiagnostic gate) —
|
|
30
|
+
// surfaces here instead of vanishing. `context.diagnostics` is assembled
|
|
31
|
+
// alongside `context.consoleForwarder` by the same installBridgeRouter call.
|
|
32
|
+
if (context.diagnostics && context.internalDevtoolsWindow) {
|
|
33
|
+
const diagnosticsMirror = createGlobalDiagnosticsMirror(context.diagnostics, mainWindow.webContents, context.internalDevtoolsWindow.onHostChanged, { broker: context.cdpSessionBroker });
|
|
34
|
+
context.registry.add(toDisposable(() => diagnosticsMirror.dispose()));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=global-mirrors.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ViewManager } from '../services/views/view-manager.js';
|
|
2
|
+
import type { RendererNotifier } from '../services/notifications/renderer-notifier.js';
|
|
3
|
+
import type { DisposableRegistry } from '@dimina-kit/electron-deck/main';
|
|
4
|
+
/** Narrow view of the context fields the default sidebar content depends on. */
|
|
5
|
+
export interface HostSidebarContext {
|
|
6
|
+
views: ViewManager;
|
|
7
|
+
notify: RendererNotifier;
|
|
8
|
+
registry: DisposableRegistry;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* devtools' own default content for the host-sidebar slot: a narrow icon rail
|
|
12
|
+
* (logo + 小程序/小游戏 toggle) filtering the project-list grid by
|
|
13
|
+
* `Project.type`. Loaded BEFORE `config.onSetup` runs, so any downstream
|
|
14
|
+
* `loadURL`/`loadFile` call inside onSetup necessarily happens later and
|
|
15
|
+
* naturally supersedes this default via plain chronological ordering — no
|
|
16
|
+
* override flag needed.
|
|
17
|
+
*/
|
|
18
|
+
export declare function installHostSidebarDefault(context: HostSidebarContext, rendererDir: string): void;
|
|
19
|
+
//# sourceMappingURL=host-sidebar-default.d.ts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { HOST_SIDEBAR_DEFAULT_WIDTH } from '../../shared/constants.js';
|
|
3
|
+
/**
|
|
4
|
+
* devtools' own default content for the host-sidebar slot: a narrow icon rail
|
|
5
|
+
* (logo + 小程序/小游戏 toggle) filtering the project-list grid by
|
|
6
|
+
* `Project.type`. Loaded BEFORE `config.onSetup` runs, so any downstream
|
|
7
|
+
* `loadURL`/`loadFile` call inside onSetup necessarily happens later and
|
|
8
|
+
* naturally supersedes this default via plain chronological ordering — no
|
|
9
|
+
* override flag needed.
|
|
10
|
+
*/
|
|
11
|
+
export function installHostSidebarDefault(context, rendererDir) {
|
|
12
|
+
context.registry.add(context.views.hostSidebar.onMessage('project-category-selected', (payload) => {
|
|
13
|
+
const category = payload?.category;
|
|
14
|
+
if (category !== 'miniprogram' && category !== 'minigame')
|
|
15
|
+
return;
|
|
16
|
+
context.notify.hostSidebarCategorySelected(category);
|
|
17
|
+
}));
|
|
18
|
+
context.views.hostSidebar
|
|
19
|
+
.loadFile(path.join(rendererDir, 'entries/host-sidebar-default/index.html'))
|
|
20
|
+
.catch((err) => {
|
|
21
|
+
console.warn('[workbench] failed to load host-sidebar default content:', err);
|
|
22
|
+
});
|
|
23
|
+
// Seed the notified width with the rail's own known intrinsic width
|
|
24
|
+
// (`HOST_SIDEBAR_DEFAULT_WIDTH`) instead of leaving it at 0 until the
|
|
25
|
+
// rail's in-page advertiser reports back. That report can never arrive on
|
|
26
|
+
// its own: the placeholder above only becomes "desired visible" once a
|
|
27
|
+
// nonzero width is known (project-list-screen.tsx), attach only happens
|
|
28
|
+
// for a "desired visible" view (placement-reconciler.ts), and the rail's
|
|
29
|
+
// advertiser (view-anchor's measure-loop.ts) only ever fires via
|
|
30
|
+
// `requestAnimationFrame`, which Chromium never schedules for a
|
|
31
|
+
// WebContentsView that was never attached — a structural deadlock, not a
|
|
32
|
+
// slow-to-resolve race. `setWidthMode({fixed})` pushes the seed
|
|
33
|
+
// synchronously (no attach/rAF dependency) and, critically, retains it in
|
|
34
|
+
// `getHostSidebarWidth()` too, so a renderer that mounts and pulls before
|
|
35
|
+
// any push replays the real seed instead of a stale 0. Flipping back to
|
|
36
|
+
// 'auto' immediately after, before anything has attached or advertised, is
|
|
37
|
+
// a same-tick no-op past the seed (`setExtentMode`'s reapply branch only
|
|
38
|
+
// fires once something has actually been advertised) — it leaves the slot
|
|
39
|
+
// in 'auto' for whichever content ends up loaded (this rail's own later
|
|
40
|
+
// report, or a downstream replacement's), not pinned.
|
|
41
|
+
context.views.hostSidebar.setWidthMode({ fixed: HOST_SIDEBAR_DEFAULT_WIDTH });
|
|
42
|
+
context.views.hostSidebar.setWidthMode('auto');
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=host-sidebar-default.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BrowserWindow } from 'electron';
|
|
2
|
+
import type { WorkbenchAppConfig } from '../../shared/types.js';
|
|
3
|
+
import type { WorkspaceService } from '../services/workspace/workspace-service.js';
|
|
4
|
+
import type { RendererNotifier } from '../services/notifications/renderer-notifier.js';
|
|
5
|
+
/** Narrow view of the context fields the menu surface closes over. */
|
|
6
|
+
export interface MenuHostContext {
|
|
7
|
+
appName: string;
|
|
8
|
+
workspace: WorkspaceService;
|
|
9
|
+
openSettings: () => Promise<void>;
|
|
10
|
+
notify: RendererNotifier;
|
|
11
|
+
}
|
|
12
|
+
export declare function installMenu(config: WorkbenchAppConfig, mainWindow: BrowserWindow, activeContext: () => MenuHostContext, revealProjectList: () => void): void;
|
|
13
|
+
//# sourceMappingURL=menu-setup.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { installAppMenu } from '../menu/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Build the hand-written narrow `MenuContext` a host menu builder receives —
|
|
4
|
+
* explicit construction (not clone+delete), so the runtime object carries
|
|
5
|
+
* EXACTLY the contract members and nothing else. Every member is a lazy
|
|
6
|
+
* closure over the live context: a host monkey-patch of
|
|
7
|
+
* `context.workspace.openProject` (the documented permission-gate pattern)
|
|
8
|
+
* still intercepts calls made through this menu surface.
|
|
9
|
+
*
|
|
10
|
+
* The context is resolved per call, never captured: the menu is installed once
|
|
11
|
+
* before any project exists, and a project lives in its own window, so a menu
|
|
12
|
+
* item run later must reach the window the user is actually in.
|
|
13
|
+
*/
|
|
14
|
+
function toMenuContext(activeContext, revealProjectList) {
|
|
15
|
+
return {
|
|
16
|
+
get appName() { return activeContext().appName; },
|
|
17
|
+
workspace: {
|
|
18
|
+
hasActiveSession: () => activeContext().workspace.hasActiveSession(),
|
|
19
|
+
getProjectPath: () => activeContext().workspace.getProjectPath(),
|
|
20
|
+
openProject: (projectPath) => activeContext().workspace.openProject(projectPath),
|
|
21
|
+
closeProject: () => activeContext().workspace.closeProject(),
|
|
22
|
+
getSession: () => activeContext().workspace.getSession(),
|
|
23
|
+
},
|
|
24
|
+
openSettings: () => activeContext().openSettings(),
|
|
25
|
+
notify: {
|
|
26
|
+
projectStatus: (payload) => activeContext().notify.projectStatus(payload),
|
|
27
|
+
// A project opens in its own window, so "back to the project list" is
|
|
28
|
+
// no longer a screen change inside one window — it brings the list
|
|
29
|
+
// window forward. That window owns its own context, which may not be
|
|
30
|
+
// `activeContext()` (a project window can be the active one), so this
|
|
31
|
+
// routes through the injected surface instead of notifying whatever is
|
|
32
|
+
// currently active.
|
|
33
|
+
windowNavigateBack: () => revealProjectList(),
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function installMenu(config, mainWindow, activeContext, revealProjectList) {
|
|
38
|
+
// Menu: use host-provided builder or fall back to default. Both consume the
|
|
39
|
+
// same narrow MenuContext, so the built-in menu proves the hand-written
|
|
40
|
+
// contract covers the real internal consumption.
|
|
41
|
+
const menuContext = toMenuContext(activeContext, revealProjectList);
|
|
42
|
+
if (config.menuBuilder) {
|
|
43
|
+
config.menuBuilder(mainWindow, menuContext);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
installAppMenu(menuContext);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=menu-setup.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IpcContextSource } from '../utils/ipc-context-source.js';
|
|
2
|
+
import { IpcRegistry } from '../utils/ipc-registry.js';
|
|
3
|
+
import type { ProjectRef } from './project-window.js';
|
|
4
|
+
/**
|
|
5
|
+
* Opening a project from the list — and from MCP's project_open, which the
|
|
6
|
+
* list renderer forwards here — always means "give it its own window", so the
|
|
7
|
+
* channel does nothing but hand the request to the workbench window manager.
|
|
8
|
+
*
|
|
9
|
+
* Generic over the context type: the handler never touches the context, and
|
|
10
|
+
* naming it would drag `WorkbenchContext` into this module.
|
|
11
|
+
*/
|
|
12
|
+
export declare function registerOpenProjectWindowIpc<TCtx>(router: IpcContextSource<TCtx>, open: (project: ProjectRef) => Promise<unknown>): IpcRegistry<TCtx>;
|
|
13
|
+
//# sourceMappingURL=open-project-ipc.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { WindowChannel } from '../../shared/ipc-channels.js';
|
|
2
|
+
import { IpcRegistry } from '../utils/ipc-registry.js';
|
|
3
|
+
/**
|
|
4
|
+
* Opening a project from the list — and from MCP's project_open, which the
|
|
5
|
+
* list renderer forwards here — always means "give it its own window", so the
|
|
6
|
+
* channel does nothing but hand the request to the workbench window manager.
|
|
7
|
+
*
|
|
8
|
+
* Generic over the context type: the handler never touches the context, and
|
|
9
|
+
* naming it would drag `WorkbenchContext` into this module.
|
|
10
|
+
*/
|
|
11
|
+
export function registerOpenProjectWindowIpc(router, open) {
|
|
12
|
+
const windowIpc = new IpcRegistry(router);
|
|
13
|
+
windowIpc.handleRouted(WindowChannel.OpenProjectWindow, async (_ctx, _event, ...args) => {
|
|
14
|
+
const project = args[0];
|
|
15
|
+
if (!project?.path)
|
|
16
|
+
throw new Error('openProjectWindow requires a project path');
|
|
17
|
+
await open({ path: project.path, name: project.name });
|
|
18
|
+
});
|
|
19
|
+
return windowIpc;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=open-project-ipc.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { BrowserWindow } from 'electron';
|
|
2
|
+
import type { UpdateInfo } from '../../shared/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Narrow view of the context fields the project-list surface closes over —
|
|
5
|
+
* structural, not `WorkbenchContext` (see eslint-workbench-context-gate) —
|
|
6
|
+
* so the surface carries no dependency on the whole workbench.
|
|
7
|
+
*/
|
|
8
|
+
export interface ProjectListSurfaceContext {
|
|
9
|
+
notify: {
|
|
10
|
+
windowNavigateBack: () => void;
|
|
11
|
+
};
|
|
12
|
+
views: {
|
|
13
|
+
showUpdateDialog: (info: UpdateInfo) => void;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface ProjectListSurfaceDeps {
|
|
17
|
+
window: BrowserWindow;
|
|
18
|
+
context: ProjectListSurfaceContext;
|
|
19
|
+
}
|
|
20
|
+
export interface ProjectListSurface {
|
|
21
|
+
revealProjectList: () => void;
|
|
22
|
+
showUpdate: (info: UpdateInfo) => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* "回到项目列表" 和更新弹窗都属于列表窗口本身,而不是当时 activeContext() 恰好
|
|
26
|
+
* 解析到的窗口——那个窗口可能是某个项目工作台。这里是两条路径共同的入口:
|
|
27
|
+
* revealProjectList 把列表窗口带到前台并通知它自己的 context 刷新;showUpdate
|
|
28
|
+
* 先做同一件事,再弹更新对话框,避免窗口还处于 hide() 状态时用户看不到弹窗。
|
|
29
|
+
*/
|
|
30
|
+
export declare function createProjectListSurface(deps: ProjectListSurfaceDeps): ProjectListSurface;
|
|
31
|
+
//# sourceMappingURL=project-list-surface.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { revealWindow } from './window-events.js';
|
|
2
|
+
/**
|
|
3
|
+
* "回到项目列表" 和更新弹窗都属于列表窗口本身,而不是当时 activeContext() 恰好
|
|
4
|
+
* 解析到的窗口——那个窗口可能是某个项目工作台。这里是两条路径共同的入口:
|
|
5
|
+
* revealProjectList 把列表窗口带到前台并通知它自己的 context 刷新;showUpdate
|
|
6
|
+
* 先做同一件事,再弹更新对话框,避免窗口还处于 hide() 状态时用户看不到弹窗。
|
|
7
|
+
*/
|
|
8
|
+
export function createProjectListSurface(deps) {
|
|
9
|
+
const { window, context } = deps;
|
|
10
|
+
const revealProjectList = () => {
|
|
11
|
+
revealWindow(window);
|
|
12
|
+
context.notify.windowNavigateBack();
|
|
13
|
+
};
|
|
14
|
+
const showUpdate = (info) => {
|
|
15
|
+
revealProjectList();
|
|
16
|
+
context.views.showUpdateDialog(info);
|
|
17
|
+
};
|
|
18
|
+
return { revealProjectList, showUpdate };
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=project-list-surface.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { BrowserWindow } from 'electron';
|
|
2
|
+
import type { WorkbenchAppConfig } from '../../shared/types.js';
|
|
3
|
+
import { type WorkbenchContext } from '../services/workbench-context.js';
|
|
4
|
+
import type { AppServices } from '../services/app-services.js';
|
|
5
|
+
import type { WindowContextRouter } from '../services/window-contexts/context-router.js';
|
|
6
|
+
/** The project a workbench window is opened for. */
|
|
7
|
+
export interface ProjectRef {
|
|
8
|
+
path: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
}
|
|
11
|
+
/** A window and the context that answers IPC coming from it. */
|
|
12
|
+
export interface ProjectWindow {
|
|
13
|
+
window: BrowserWindow;
|
|
14
|
+
context: WorkbenchContext;
|
|
15
|
+
dispose: () => Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export interface CreateProjectWindowOptions {
|
|
18
|
+
config: WorkbenchAppConfig;
|
|
19
|
+
rendererDir: string;
|
|
20
|
+
appServices: AppServices;
|
|
21
|
+
router: WindowContextRouter<WorkbenchContext>;
|
|
22
|
+
}
|
|
23
|
+
export declare function disposeContext(ctx: WorkbenchContext): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* The project-list window. It is the application's root window: the app-level
|
|
26
|
+
* IPC surface is registered while it exists, and it stays open for the whole
|
|
27
|
+
* session so workbench windows can come and go around it.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createLauncherWindow(opts: CreateProjectWindowOptions): ProjectWindow;
|
|
30
|
+
/**
|
|
31
|
+
* A workbench window: one open mini-program project, with its own simulator,
|
|
32
|
+
* panels and editor. The project identity travels in the URL query so the
|
|
33
|
+
* renderer entry can mount straight into the project without asking main.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createWorkbenchWindow(opts: CreateProjectWindowOptions, project: ProjectRef): ProjectWindow;
|
|
36
|
+
//# sourceMappingURL=project-window.d.ts.map
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { nativeImage } from 'electron';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { defaultPreloadPath } from '../utils/paths.js';
|
|
4
|
+
import { createMainWindow } from '../windows/main-window/index.js';
|
|
5
|
+
// eslint-disable-next-line no-restricted-syntax -- grandfathered(workbench-context): shrink-only
|
|
6
|
+
import { createWorkbenchContext } from '../services/workbench-context.js';
|
|
7
|
+
function createConfiguredMainWindow(config, rendererDir, entry, title, autoShow, query) {
|
|
8
|
+
const mainWindow = createMainWindow({
|
|
9
|
+
title,
|
|
10
|
+
indexHtml: path.join(rendererDir, entry),
|
|
11
|
+
query,
|
|
12
|
+
width: config.window?.width,
|
|
13
|
+
height: config.window?.height,
|
|
14
|
+
minWidth: config.window?.minWidth,
|
|
15
|
+
minHeight: config.window?.minHeight,
|
|
16
|
+
autoShow,
|
|
17
|
+
});
|
|
18
|
+
// Set window/taskbar icon if provided (Linux/Windows; macOS uses app bundle icon)
|
|
19
|
+
if (config.icon) {
|
|
20
|
+
const icon = nativeImage.createFromPath(config.icon);
|
|
21
|
+
if (!icon.isEmpty())
|
|
22
|
+
mainWindow.setIcon(icon);
|
|
23
|
+
}
|
|
24
|
+
return mainWindow;
|
|
25
|
+
}
|
|
26
|
+
function createContext(config, mainWindow, rendererDir, appServices) {
|
|
27
|
+
return createWorkbenchContext({
|
|
28
|
+
mainWindow,
|
|
29
|
+
appServices,
|
|
30
|
+
adapter: config.adapter,
|
|
31
|
+
preloadPath: config.preloadPath ?? defaultPreloadPath,
|
|
32
|
+
rendererDir,
|
|
33
|
+
appName: config.appName,
|
|
34
|
+
apiNamespaces: config.apiNamespaces,
|
|
35
|
+
fileTypes: config.fileTypes,
|
|
36
|
+
brandingProvider: config.brandingProvider,
|
|
37
|
+
customCreateProjectDialog: config.customCreateProjectDialog,
|
|
38
|
+
// No cast needed here: the hook receives the project record, so the
|
|
39
|
+
// main-process `Project` the context hands it satisfies the structural
|
|
40
|
+
// `EditableProject` the config declares.
|
|
41
|
+
customEditProjectDialog: config.customEditProjectDialog,
|
|
42
|
+
onBeforeOpenProject: config.onBeforeOpenProject,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
export async function disposeContext(ctx) {
|
|
46
|
+
await ctx.workspace.closeProject();
|
|
47
|
+
await ctx.registry.dispose().catch((err) => {
|
|
48
|
+
console.warn('[workbench] dispose registry encountered errors:', err);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build a window together with the context that owns it, and publish that
|
|
53
|
+
* context to the router so IPC arriving from this window is answered by it.
|
|
54
|
+
*
|
|
55
|
+
* The router registration is parked on the context's own registry: a window
|
|
56
|
+
* that is torn down must stop claiming senders in the same breath, or a
|
|
57
|
+
* recycled `webContents.id` would resolve to a dead context.
|
|
58
|
+
*/
|
|
59
|
+
function createWindowWithContext(opts, entry, title, autoShow, query) {
|
|
60
|
+
const { config, rendererDir, appServices, router } = opts;
|
|
61
|
+
const window = createConfiguredMainWindow(config, rendererDir, entry, title, autoShow, query);
|
|
62
|
+
const context = createContext(config, window, rendererDir, appServices);
|
|
63
|
+
// Anchor the window's renderer as the first Connection. Resources scoped to
|
|
64
|
+
// that webContents (acquired by later wiring) tear down with it; see
|
|
65
|
+
// packages/electron-deck/docs/foundation.md (teardown paths).
|
|
66
|
+
context.connections.acquire(window.webContents);
|
|
67
|
+
context.registry.add(router.register(context));
|
|
68
|
+
return { window, context, dispose: () => disposeContext(context) };
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The project-list window. It is the application's root window: the app-level
|
|
72
|
+
* IPC surface is registered while it exists, and it stays open for the whole
|
|
73
|
+
* session so workbench windows can come and go around it.
|
|
74
|
+
*/
|
|
75
|
+
export function createLauncherWindow(opts) {
|
|
76
|
+
return createWindowWithContext(opts, 'entries/main/index.html', opts.config.appName ?? 'Dimina DevTools', opts.config.window?.autoShow);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* A workbench window: one open mini-program project, with its own simulator,
|
|
80
|
+
* panels and editor. The project identity travels in the URL query so the
|
|
81
|
+
* renderer entry can mount straight into the project without asking main.
|
|
82
|
+
*/
|
|
83
|
+
export function createWorkbenchWindow(opts, project) {
|
|
84
|
+
return createWindowWithContext(opts, 'entries/workbench/index.html', project.name || opts.config.appName || 'Dimina DevTools',
|
|
85
|
+
// Always hidden: `workbench-window.ts`'s reveal gate is the sole place
|
|
86
|
+
// that ever shows a project window, once BOTH `setupProjectWindow` has
|
|
87
|
+
// resolved and the renderer's own `ready-to-show` has fired. Passing
|
|
88
|
+
// anything but `false` here would let `createMainWindow`'s own
|
|
89
|
+
// `ready-to-show` handler show the window itself and race that gate.
|
|
90
|
+
// `config.projectWindow?.autoShow` is read by the gate instead, not here.
|
|
91
|
+
false, { path: project.path, name: project.name ?? '' });
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=project-window.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { WorkbenchAppInstance } from './app.js';
|
|
2
|
+
import { startAutomationServer } from '../services/automation/index.js';
|
|
3
|
+
import { type McpOpenedProject, type McpProjectTarget } from '../services/mcp/index.js';
|
|
4
|
+
import type { Disposable } from '@dimina-kit/electron-deck/main';
|
|
5
|
+
/**
|
|
6
|
+
* The automation server outlives every window: it binds its port at boot,
|
|
7
|
+
* before any project is open, so it cannot capture a context at start and
|
|
8
|
+
* takes `getContext` instead. What that resolver hands back is only the
|
|
9
|
+
* starting point — each connection pins the first project window it reaches
|
|
10
|
+
* and stays there, so window focus cannot redirect a live client.
|
|
11
|
+
*/
|
|
12
|
+
export declare function setupAutomation(instance: WorkbenchAppInstance, getContext: Parameters<typeof startAutomationServer>[0], senders: Parameters<typeof startAutomationServer>[1]): Promise<Disposable | null>;
|
|
13
|
+
export declare function setupMcp(currentProject: () => McpProjectTarget, openProjectWindow: (project: {
|
|
14
|
+
path: string;
|
|
15
|
+
name: string;
|
|
16
|
+
}) => Promise<McpOpenedProject>): Disposable | null;
|
|
17
|
+
//# sourceMappingURL=servers.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { app } from 'electron';
|
|
2
|
+
import { startAutomationServer } from '../services/automation/index.js';
|
|
3
|
+
import { startMcpServer, } from '../services/mcp/index.js';
|
|
4
|
+
import { loadWorkbenchSettings } from '../services/settings/index.js';
|
|
5
|
+
/** Parse --auto, --auto-port, --project from process.argv. */
|
|
6
|
+
function parseAutoArgs() {
|
|
7
|
+
const argv = process.argv;
|
|
8
|
+
let auto = false;
|
|
9
|
+
let autoPort = 9420;
|
|
10
|
+
let projectPath = '';
|
|
11
|
+
for (let i = 0; i < argv.length; i++) {
|
|
12
|
+
if (argv[i] === 'auto' || argv[i] === '--auto')
|
|
13
|
+
auto = true;
|
|
14
|
+
if ((argv[i] === '--auto-port' || argv[i] === '--auto_port') && argv[i + 1]) {
|
|
15
|
+
const parsed = parseInt(argv[i + 1], 10);
|
|
16
|
+
// 0 → OS-assigned free port (used by parallel e2e workers)
|
|
17
|
+
if (Number.isFinite(parsed) && parsed >= 0)
|
|
18
|
+
autoPort = parsed;
|
|
19
|
+
}
|
|
20
|
+
if (argv[i] === '--project' && argv[i + 1]) {
|
|
21
|
+
projectPath = argv[i + 1];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return { auto, autoPort, projectPath };
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The automation server outlives every window: it binds its port at boot,
|
|
28
|
+
* before any project is open, so it cannot capture a context at start and
|
|
29
|
+
* takes `getContext` instead. What that resolver hands back is only the
|
|
30
|
+
* starting point — each connection pins the first project window it reaches
|
|
31
|
+
* and stays there, so window focus cannot redirect a live client.
|
|
32
|
+
*/
|
|
33
|
+
export async function setupAutomation(instance, getContext, senders) {
|
|
34
|
+
// Start automation server if --auto flag is present
|
|
35
|
+
const autoArgs = parseAutoArgs();
|
|
36
|
+
if (!autoArgs.auto)
|
|
37
|
+
return null;
|
|
38
|
+
const server = await startAutomationServer(getContext, senders, autoArgs.autoPort);
|
|
39
|
+
instance.automationServer = server;
|
|
40
|
+
// Stable, parseable line for e2e harnesses that scrape stdout.
|
|
41
|
+
console.log(`[automation] listening on ws://127.0.0.1:${server.port}`);
|
|
42
|
+
return { dispose: () => server.close() };
|
|
43
|
+
}
|
|
44
|
+
export function setupMcp(currentProject, openProjectWindow) {
|
|
45
|
+
const settings = loadWorkbenchSettings();
|
|
46
|
+
if (!settings.mcp.enabled)
|
|
47
|
+
return null;
|
|
48
|
+
const cdpPortSwitch = app.commandLine.getSwitchValue('remote-debugging-port');
|
|
49
|
+
const cdpPort = cdpPortSwitch ? parseInt(cdpPortSwitch, 10) : settings.cdp.port;
|
|
50
|
+
// Resolved per tool call, not once at boot: the project MCP drives lives in
|
|
51
|
+
// whichever workbench window is active, and that changes as windows open and
|
|
52
|
+
// close. Each call then holds the target it got.
|
|
53
|
+
return startMcpServer(cdpPort, settings.mcp.port, {
|
|
54
|
+
currentProject,
|
|
55
|
+
// A project opens into its own window; the renderer entry mounted there
|
|
56
|
+
// compiles it and attaches the simulator.
|
|
57
|
+
requestOpenInUi: (p) => openProjectWindow(p),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=servers.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ledger of host-registered simulator UI extensions.
|
|
3
|
+
*
|
|
4
|
+
* A registration is app-level — the host makes it once — but an extension can
|
|
5
|
+
* only exist inside a PROJECT window: it mounts into that window's device
|
|
6
|
+
* frame and talks to its simulator renderer. So one registration becomes one
|
|
7
|
+
* live extension per project window, and the ledger is what keeps those copies
|
|
8
|
+
* in step with the windows: every project window that opens gets its own copy,
|
|
9
|
+
* and a copy exists exactly as long as the window that owns it.
|
|
10
|
+
*
|
|
11
|
+
* The project list is deliberately not a target. It runs no bridge router and
|
|
12
|
+
* no simulator, so an extension registered into it could never mount, and
|
|
13
|
+
* `invoke` — which follows the window the user works in — would be answered by
|
|
14
|
+
* that dead copy every time the list window has focus.
|
|
15
|
+
*/
|
|
16
|
+
import { type Disposable } from '@dimina-kit/electron-deck/main';
|
|
17
|
+
import type { SimulatorUiExtensionHandle, SimulatorUiExtensionRegistration } from '../../shared/simulator-ui.js';
|
|
18
|
+
/**
|
|
19
|
+
* The window surface the ledger needs, described structurally so this module
|
|
20
|
+
* does not import WorkbenchContext (see eslint-workbench-context-gate).
|
|
21
|
+
*/
|
|
22
|
+
export interface UiExtensionWindow {
|
|
23
|
+
simulatorUiExtensions: {
|
|
24
|
+
register: (registration: SimulatorUiExtensionRegistration) => SimulatorUiExtensionHandle;
|
|
25
|
+
};
|
|
26
|
+
registry: {
|
|
27
|
+
add: (d: Disposable) => Disposable;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface UiExtensionTargetsDeps<W extends UiExtensionWindow> {
|
|
31
|
+
/** Every open project window, in open order. */
|
|
32
|
+
projectWindows: () => W[];
|
|
33
|
+
/** The project window the user is working in, or null when none is open. */
|
|
34
|
+
activeWindow: () => W | null;
|
|
35
|
+
}
|
|
36
|
+
export interface UiExtensionTargets<W extends UiExtensionWindow> {
|
|
37
|
+
/** Give a freshly opened project window its copy of every registration. */
|
|
38
|
+
attachTo: (window: W) => void;
|
|
39
|
+
register: (registration: SimulatorUiExtensionRegistration) => SimulatorUiExtensionHandle;
|
|
40
|
+
}
|
|
41
|
+
export declare function createUiExtensionTargets<W extends UiExtensionWindow>(deps: UiExtensionTargetsDeps<W>): UiExtensionTargets<W>;
|
|
42
|
+
//# sourceMappingURL=ui-extension-targets.d.ts.map
|