@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
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
13
13
|
import type { CompileLogBuffer } from '../../workspace/compile-log-buffer.js';
|
|
14
14
|
import type { SessionStatusStore } from '../../workspace/session-status-store.js';
|
|
15
|
+
import type { McpOpenedProject } from '../opened-project.js';
|
|
15
16
|
/**
|
|
16
17
|
* Narrow structural slice of WorkspaceService the project tools need.
|
|
17
18
|
* Structural (not a Pick of the real interface) so tests can hand in a
|
|
@@ -32,18 +33,40 @@ export interface McpProjectWorkspace {
|
|
|
32
33
|
getProjectPath(): string;
|
|
33
34
|
hasActiveSession(): boolean;
|
|
34
35
|
}
|
|
35
|
-
/**
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* One project window's surfaces, resolved together. A project lives in its own
|
|
38
|
+
* window with its own workspace, status store and log buffer, so a tool call
|
|
39
|
+
* that read them one by one could mix two projects: every surface here comes
|
|
40
|
+
* from the same window at the same instant.
|
|
41
|
+
*/
|
|
42
|
+
export interface McpProjectTarget {
|
|
37
43
|
workspace: McpProjectWorkspace;
|
|
38
44
|
sessionStatus: SessionStatusStore;
|
|
39
45
|
compileLogs: CompileLogBuffer;
|
|
40
|
-
/**
|
|
46
|
+
/** Close this target's project window; a no-op when it has none. */
|
|
47
|
+
closeWindow(): void;
|
|
48
|
+
}
|
|
49
|
+
/** Everything `registerProjectTools` needs, assembled by app bootstrap. */
|
|
50
|
+
export interface McpProjectHost {
|
|
51
|
+
/**
|
|
52
|
+
* The project window a call arriving now is aimed at. Taken ONCE per tool
|
|
53
|
+
* call and held for its whole lifetime: tools await compiles and teardowns,
|
|
54
|
+
* and the user is free to focus another project meanwhile — re-resolving
|
|
55
|
+
* afterwards would report one project's compile as another's, or close the
|
|
56
|
+
* window they just moved to.
|
|
57
|
+
*/
|
|
58
|
+
currentProject(): McpProjectTarget;
|
|
59
|
+
/**
|
|
60
|
+
* Push the renderer to open the project (the user-click-equivalent path) and
|
|
61
|
+
* resolve with the window it landed in. A project lives in its own window
|
|
62
|
+
* with its own status store, so the caller can only await the right compile
|
|
63
|
+
* by holding that window — the window active when the call arrived is a
|
|
64
|
+
* different project.
|
|
65
|
+
*/
|
|
41
66
|
requestOpenInUi(project: {
|
|
42
67
|
name: string;
|
|
43
68
|
path: string;
|
|
44
|
-
}):
|
|
45
|
-
/** Push the renderer back to the project list after a close. */
|
|
46
|
-
requestNavigateBack(): void;
|
|
69
|
+
}): Promise<McpOpenedProject>;
|
|
47
70
|
}
|
|
48
71
|
export declare function registerProjectTools(server: McpServer, host: McpProjectHost): void;
|
|
49
72
|
//# sourceMappingURL=project-tools.d.ts.map
|
|
@@ -30,13 +30,14 @@ function publicPhase(snapshot, sessionActive) {
|
|
|
30
30
|
return 'idle';
|
|
31
31
|
return snapshot.phase;
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
33
|
+
/** Reads one window's own status: the pinned target, or the window an open landed in. */
|
|
34
|
+
function statusPayload(source) {
|
|
35
|
+
const snapshot = source.sessionStatus.get();
|
|
36
|
+
const sessionActive = source.workspace.hasActiveSession();
|
|
36
37
|
return {
|
|
37
38
|
phase: publicPhase(snapshot, sessionActive),
|
|
38
39
|
message: snapshot.message,
|
|
39
|
-
projectPath:
|
|
40
|
+
projectPath: source.workspace.getProjectPath(),
|
|
40
41
|
sessionActive,
|
|
41
42
|
watcherAlive: snapshot.watcherAlive,
|
|
42
43
|
updatedAt: snapshot.updatedAt,
|
|
@@ -49,32 +50,37 @@ export function registerProjectTools(server, host) {
|
|
|
49
50
|
timeoutMs: z.number().optional().default(DEFAULT_OPEN_TIMEOUT_MS)
|
|
50
51
|
.describe('Max time to wait for the compile to settle'),
|
|
51
52
|
}, async ({ path: rawPath, timeoutMs }) => {
|
|
53
|
+
const target = host.currentProject();
|
|
52
54
|
const dir = path.resolve(rawPath);
|
|
53
55
|
// Already open and settled: report instead of re-triggering a compile.
|
|
54
|
-
const current =
|
|
55
|
-
if (
|
|
56
|
-
&&
|
|
56
|
+
const current = target.sessionStatus.get();
|
|
57
|
+
if (target.workspace.getProjectPath() === dir
|
|
58
|
+
&& target.workspace.hasActiveSession()
|
|
57
59
|
&& current.phase === 'ready') {
|
|
58
|
-
return text({ ...statusPayload(
|
|
60
|
+
return text({ ...statusPayload(target), note: 'project already open' });
|
|
59
61
|
}
|
|
60
|
-
const invalid = await
|
|
62
|
+
const invalid = await target.workspace.validateProjectDir(dir);
|
|
61
63
|
if (invalid)
|
|
62
64
|
return errorText(invalid);
|
|
63
65
|
let project;
|
|
64
|
-
if (await
|
|
65
|
-
const known = (await
|
|
66
|
+
if (await target.workspace.hasProject(dir)) {
|
|
67
|
+
const known = (await target.workspace.listProjects()).find((p) => p.path === dir);
|
|
66
68
|
project = known ?? { name: path.basename(dir), path: dir };
|
|
67
69
|
}
|
|
68
70
|
else {
|
|
69
|
-
project = await
|
|
71
|
+
project = await target.workspace.addProject(dir);
|
|
70
72
|
}
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
// The open hands back the window it landed in; that window's store is the
|
|
74
|
+
// only place this compile is reported, and its `afterGeneration` keeps a
|
|
75
|
+
// state that predates the open from being read as this open's result.
|
|
76
|
+
let opened;
|
|
75
77
|
let settled;
|
|
76
78
|
try {
|
|
77
|
-
|
|
79
|
+
opened = await host.requestOpenInUi({ name: project.name, path: project.path });
|
|
80
|
+
settled = await opened.sessionStatus.waitForSettled({
|
|
81
|
+
afterGeneration: opened.afterGeneration,
|
|
82
|
+
timeoutMs,
|
|
83
|
+
});
|
|
78
84
|
}
|
|
79
85
|
catch (err) {
|
|
80
86
|
return errorText(err instanceof Error ? err.message : String(err));
|
|
@@ -82,30 +88,36 @@ export function registerProjectTools(server, host) {
|
|
|
82
88
|
if (settled.phase === 'error') {
|
|
83
89
|
return errorText(`compile failed: ${settled.message} — call compile_logs (stream: "stderr") for details`);
|
|
84
90
|
}
|
|
85
|
-
return text(statusPayload(
|
|
91
|
+
return text(statusPayload(opened));
|
|
86
92
|
});
|
|
87
93
|
server.tool('project_close', 'Close the currently open project session and return the workbench to the project list.', {}, async () => {
|
|
88
|
-
|
|
94
|
+
// Held across the await: `closeProject()` yields, and a window the user
|
|
95
|
+
// focuses while it runs must not become the window this close takes down.
|
|
96
|
+
const target = host.currentProject();
|
|
97
|
+
if (!target.workspace.getProjectPath() && !target.workspace.hasActiveSession()) {
|
|
89
98
|
return text({ closed: false, note: 'no project is open' });
|
|
90
99
|
}
|
|
91
|
-
await
|
|
92
|
-
|
|
100
|
+
await target.workspace.closeProject();
|
|
101
|
+
target.closeWindow();
|
|
93
102
|
return text({ closed: true });
|
|
94
103
|
});
|
|
95
|
-
server.tool('project_status', 'Query the current project compile status (phase: idle | compiling | ready | error). Includes `generation` — pass it to project_wait_ready to await the NEXT settled state.', {}, async () => text(statusPayload(host)));
|
|
104
|
+
server.tool('project_status', 'Query the current project compile status (phase: idle | compiling | ready | error). Includes `generation` — pass it to project_wait_ready to await the NEXT settled state.', {}, async () => text(statusPayload(host.currentProject())));
|
|
96
105
|
server.tool('project_wait_ready', 'Wait until the compile pipeline settles (phase leaves "compiling"). Watcher rebuilds emit no "compiling" phase, so to await a rebuild after editing files pass the `generation` from a prior project_status.', {
|
|
97
106
|
afterGeneration: z.number().optional()
|
|
98
107
|
.describe('Only accept states recorded after this generation (from project_status). Omit to accept the current state when already settled.'),
|
|
99
108
|
timeoutMs: z.number().optional().default(DEFAULT_WAIT_TIMEOUT_MS)
|
|
100
109
|
.describe('Max time to wait'),
|
|
101
110
|
}, async ({ afterGeneration, timeoutMs }) => {
|
|
111
|
+
// Held across the wait: the state this call reports must come from the
|
|
112
|
+
// window it was aimed at, whichever window is focused when it settles.
|
|
113
|
+
const target = host.currentProject();
|
|
102
114
|
try {
|
|
103
|
-
await
|
|
115
|
+
await target.sessionStatus.waitForSettled({ afterGeneration, timeoutMs });
|
|
104
116
|
}
|
|
105
117
|
catch (err) {
|
|
106
118
|
return errorText(err instanceof Error ? err.message : String(err));
|
|
107
119
|
}
|
|
108
|
-
return text(statusPayload(
|
|
120
|
+
return text(statusPayload(target));
|
|
109
121
|
});
|
|
110
122
|
server.tool('compile_logs', 'Pull compile log lines incrementally. Pass the previous call\'s nextCursor as `cursor` to receive only new lines. The buffer resets on each fresh project open; watcher rebuilds append to the same timeline.', {
|
|
111
123
|
cursor: z.number().optional().default(0)
|
|
@@ -114,7 +126,7 @@ export function registerProjectTools(server, host) {
|
|
|
114
126
|
stream: z.enum(['stdout', 'stderr']).optional()
|
|
115
127
|
.describe('Only lines from this stream (stderr carries compile errors)'),
|
|
116
128
|
}, async ({ cursor, limit, stream }) => {
|
|
117
|
-
const read = host.compileLogs.read({ afterSeq: cursor, limit, stream });
|
|
129
|
+
const read = host.currentProject().compileLogs.read({ afterSeq: cursor, limit, stream });
|
|
118
130
|
return text(read);
|
|
119
131
|
});
|
|
120
132
|
}
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
import type { Disposable } from '@dimina-kit/electron-deck/main';
|
|
2
2
|
import type { WorkbenchContext } from './workbench-context.js';
|
|
3
|
+
import type { IpcContextSource } from '../utils/ipc-context-source.js';
|
|
3
4
|
/**
|
|
4
5
|
* A composable unit of workbench functionality.
|
|
5
6
|
*
|
|
6
7
|
* Built-in modules (projects, session, simulator, popover, settings) are
|
|
7
8
|
* implemented as `WorkbenchModule` values.
|
|
8
9
|
*
|
|
9
|
-
* `setup`
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* The two hooks differ in what they own. `setup` registers IPC once for the
|
|
11
|
+
* application and answers each message with the context the sender belongs to,
|
|
12
|
+
* so its handlers must read everything from that argument. `setupWindow` is the
|
|
13
|
+
* escape hatch for wiring that genuinely belongs to a single window — it
|
|
14
|
+
* receives that window's concrete context and may mutate it.
|
|
15
|
+
*
|
|
16
|
+
* Both returned Disposables are added to a registry so module teardown is
|
|
17
|
+
* symmetric with the rest of the workbench lifecycle.
|
|
12
18
|
*/
|
|
13
19
|
export interface WorkbenchModule {
|
|
14
|
-
/**
|
|
15
|
-
setup(
|
|
20
|
+
/** Register the module's IPC against every live window context. */
|
|
21
|
+
setup(source: IpcContextSource<WorkbenchContext>): Disposable;
|
|
22
|
+
/** Optional per-window wiring, run once for each window that opens. */
|
|
23
|
+
setupWindow?(ctx: WorkbenchContext): Disposable;
|
|
16
24
|
}
|
|
17
25
|
//# sourceMappingURL=module.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BrowserWindow, WebContents, WebContentsView } from 'electron';
|
|
2
|
-
import type {
|
|
2
|
+
import type { CompileModeChange } from '../workspace/compile-mode-store.js';
|
|
3
3
|
import { type EditorOpenFilePayload } from '../../../shared/ipc-channels.js';
|
|
4
4
|
import type { WorkbenchSettings } from '../settings/index.js';
|
|
5
5
|
import type { ProjectSettings, ProjectType } from '../projects/project-repository.js';
|
|
@@ -65,7 +65,6 @@ export interface CompileLogPayload {
|
|
|
65
65
|
*/
|
|
66
66
|
export interface SettingsInitPayload {
|
|
67
67
|
projectPath: string;
|
|
68
|
-
config: CompileConfig;
|
|
69
68
|
projectSettings: ProjectSettings;
|
|
70
69
|
}
|
|
71
70
|
/**
|
|
@@ -108,8 +107,21 @@ export interface RendererNotifier {
|
|
|
108
107
|
}): void;
|
|
109
108
|
/** Tell the main renderer the compile popover has been closed. */
|
|
110
109
|
popoverClosed(): void;
|
|
111
|
-
/**
|
|
112
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Push the open project's `CompileModeStore` after it advanced — via the
|
|
112
|
+
* popover or any other command source. `relaunch` is true when the change
|
|
113
|
+
* affects what is currently running, so the renderer restarts the
|
|
114
|
+
* simulator with it.
|
|
115
|
+
*/
|
|
116
|
+
compileModesChanged(change: CompileModeChange): void;
|
|
117
|
+
/**
|
|
118
|
+
* Push a rejected `applyCompileModeCommand` (e.g. a failed persist). The
|
|
119
|
+
* renderer surfaces this as a compile-status error without touching its
|
|
120
|
+
* mirrored `compileModes`.
|
|
121
|
+
*/
|
|
122
|
+
compileModesApplyFailed(payload: {
|
|
123
|
+
message: string;
|
|
124
|
+
}): void;
|
|
113
125
|
/**
|
|
114
126
|
* Push the reserved host-toolbar height to the main renderer so its toolbar
|
|
115
127
|
* placeholder div resizes (closes the host-toolbar dynamic-height loop).
|
|
@@ -141,6 +153,14 @@ export interface RendererNotifier {
|
|
|
141
153
|
path: string;
|
|
142
154
|
templateId: string;
|
|
143
155
|
}): void;
|
|
156
|
+
/**
|
|
157
|
+
* Relay the device picked in the device-picker overlay back to the main
|
|
158
|
+
* renderer, whose simulator toolbar owns the device state — the panel only
|
|
159
|
+
* renders the list.
|
|
160
|
+
*/
|
|
161
|
+
devicePickerSelected(payload: {
|
|
162
|
+
deviceName: string;
|
|
163
|
+
}): void;
|
|
144
164
|
/** Initialise the currently shown compile popover overlay. */
|
|
145
165
|
popoverInit(popoverView: WebContentsView, payload: unknown): void;
|
|
146
166
|
/** Initialise the currently shown settings overlay (no-op if hidden). */
|
|
@@ -154,6 +174,10 @@ export interface RendererNotifier {
|
|
|
154
174
|
}): void;
|
|
155
175
|
/** Push a discovered update's info into the update overlay. */
|
|
156
176
|
updateAvailable(dialogView: WebContentsView, payload: UpdateInfo): void;
|
|
177
|
+
/** Push the currently selected device into the device-picker overlay. */
|
|
178
|
+
devicePickerInit(pickerView: WebContentsView, payload: {
|
|
179
|
+
deviceName: string;
|
|
180
|
+
}): void;
|
|
157
181
|
/** Initialise the standalone workbench-settings window. */
|
|
158
182
|
workbenchSettingsInit(window: BrowserWindow, payload: WorkbenchSettingsInitPayload): void;
|
|
159
183
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ProjectChannel, SessionChannel, WindowChannel, WorkbenchSettingsChannel, EditorChannel, } from '../../../shared/ipc-channels.js';
|
|
2
|
-
import { SettingsChannel, PopoverChannel, TooltipChannel, ProjectCreateChannel, UpdateChannel, ViewChannel, } from '../../../shared/ipc-channels-overlays.js';
|
|
2
|
+
import { SettingsChannel, PopoverChannel, TooltipChannel, ProjectCreateChannel, DevicePickerChannel, UpdateChannel, ViewChannel, } from '../../../shared/ipc-channels-overlays.js';
|
|
3
3
|
/** Safely resolve a WebContents, skipping destroyed / missing targets. */
|
|
4
4
|
function liveWebContents(wc) {
|
|
5
5
|
if (!wc)
|
|
@@ -40,8 +40,11 @@ export function createRendererNotifier(ctx) {
|
|
|
40
40
|
popoverClosed() {
|
|
41
41
|
sendToMain(PopoverChannel.Closed);
|
|
42
42
|
},
|
|
43
|
-
|
|
44
|
-
sendToMain(
|
|
43
|
+
compileModesChanged(change) {
|
|
44
|
+
sendToMain(ProjectChannel.CompileModesChanged, change);
|
|
45
|
+
},
|
|
46
|
+
compileModesApplyFailed(payload) {
|
|
47
|
+
sendToMain(ProjectChannel.CompileModesApplyFailed, payload);
|
|
45
48
|
},
|
|
46
49
|
hostToolbarHeightChanged(height) {
|
|
47
50
|
sendToMain(ViewChannel.HostToolbarHeightChanged, height);
|
|
@@ -58,6 +61,9 @@ export function createRendererNotifier(ctx) {
|
|
|
58
61
|
projectCreateSubmitted(payload) {
|
|
59
62
|
sendToMain(ProjectCreateChannel.Submitted, payload);
|
|
60
63
|
},
|
|
64
|
+
devicePickerSelected(payload) {
|
|
65
|
+
sendToMain(DevicePickerChannel.Selected, payload);
|
|
66
|
+
},
|
|
61
67
|
popoverInit(popoverView, payload) {
|
|
62
68
|
const wc = liveWebContents(popoverView.webContents);
|
|
63
69
|
if (!wc)
|
|
@@ -82,6 +88,12 @@ export function createRendererNotifier(ctx) {
|
|
|
82
88
|
return;
|
|
83
89
|
wc.send(UpdateChannel.Available, payload);
|
|
84
90
|
},
|
|
91
|
+
devicePickerInit(pickerView, payload) {
|
|
92
|
+
const wc = liveWebContents(pickerView.webContents);
|
|
93
|
+
if (!wc)
|
|
94
|
+
return;
|
|
95
|
+
wc.send(DevicePickerChannel.Init, payload);
|
|
96
|
+
},
|
|
85
97
|
settingsInit(payload) {
|
|
86
98
|
const wc = liveWebContents(ctx.views.getSettingsWebContents());
|
|
87
99
|
if (!wc)
|
|
@@ -24,6 +24,8 @@ export function createLocalProjectsProvider() {
|
|
|
24
24
|
updateLastOpened: (dirPath) => repo.updateLastOpened(dirPath),
|
|
25
25
|
getCompileConfig: (dirPath) => repo.getCompileConfig(dirPath),
|
|
26
26
|
saveCompileConfig: (dirPath, cfg) => repo.saveCompileConfig(dirPath, cfg),
|
|
27
|
+
getCompileModes: (dirPath) => repo.getCompileModes(dirPath),
|
|
28
|
+
saveCompileModes: (dirPath, modes) => repo.saveCompileModes(dirPath, modes),
|
|
27
29
|
saveThumbnail: (dirPath, dataUrl) => saveThumbnailFromDataUrl(dirPath, dataUrl),
|
|
28
30
|
getThumbnail: (dirPath) => loadThumbnail(dirPath),
|
|
29
31
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CompileConfig, ProjectType } from '../../../shared/types.js';
|
|
1
|
+
import type { CompileConfig, CompileModes, ProjectType } from '../../../shared/types.js';
|
|
2
2
|
export type { ProjectType };
|
|
3
3
|
export interface Project {
|
|
4
4
|
name: string;
|
|
@@ -46,8 +46,38 @@ export declare function removeProject(dirPath: string): void;
|
|
|
46
46
|
*/
|
|
47
47
|
export declare function updateProject(dirPath: string, patch: ProjectPatch): Project | null;
|
|
48
48
|
export declare function updateLastOpened(dirPath: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* Read a project's compile modes from `project.config.json`'s
|
|
51
|
+
* `condition.miniprogram` — WeChat DevTools' own location and shape, so a
|
|
52
|
+
* project checked into git carries its modes to every machine, and the same
|
|
53
|
+
* directory opened in that tool shows the same list.
|
|
54
|
+
*
|
|
55
|
+
* Projects imported before compile modes existed fall back to migrating the
|
|
56
|
+
* legacy single config out of the project list file.
|
|
57
|
+
*/
|
|
58
|
+
export declare function getCompileModes(dirPath: string): CompileModes;
|
|
59
|
+
/**
|
|
60
|
+
* Persist compile modes, merged so the rest of the target file survives —
|
|
61
|
+
* including the rest of `condition`, which for a mini-game project holds its
|
|
62
|
+
* own `condition.game` block.
|
|
63
|
+
*/
|
|
64
|
+
export declare function saveCompileModes(dirPath: string, modes: CompileModes): void;
|
|
65
|
+
/**
|
|
66
|
+
* The launch parameters the selected mode resolves to. 普通编译 resolves to
|
|
67
|
+
* an empty start page; it is filled in here with the project's real entry
|
|
68
|
+
* page (mirrors getProjectPages: 'game' for mini-games, app.json's
|
|
69
|
+
* entryPagePath for mini-programs) rather than a mini-program-only literal —
|
|
70
|
+
* the simulator URL builders' own 'pages/index/index' fallback only fires
|
|
71
|
+
* when this is still empty (unreadable/malformed manifest).
|
|
72
|
+
*/
|
|
49
73
|
export declare function getCompileConfig(dirPath: string): CompileConfig;
|
|
50
74
|
export declare function getProjectPages(dirPath: string): ProjectPages;
|
|
75
|
+
/**
|
|
76
|
+
* @deprecated Compile modes are the stored form — call `saveCompileModes`.
|
|
77
|
+
* Kept working for embedding hosts still on the single-config setter: the
|
|
78
|
+
* config lands on the selected mode, or becomes a new selected mode when
|
|
79
|
+
* 普通编译 is selected and the config asks for more than it can express.
|
|
80
|
+
*/
|
|
51
81
|
export declare function saveCompileConfig(dirPath: string, config: CompileConfig): void;
|
|
52
82
|
/** Read a subset of `project.config.json` exposed to the settings panel. */
|
|
53
83
|
export declare function getProjectSettings(projectPath: string): ProjectSettings;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { app } from 'electron';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import fs from 'fs';
|
|
4
|
-
import {
|
|
4
|
+
import { NORMAL_COMPILE_INDEX, compileConfigToMode, compileConfigToModes, emptyCompileModes, isNormalCompile, normalizeCompileModes, resolveCompileConfig, } from '../../../shared/compile-modes.js';
|
|
5
5
|
import { createLogger } from '../../utils/logger.js';
|
|
6
6
|
const log = createLogger('projects');
|
|
7
|
+
function isRecord(value) {
|
|
8
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
9
|
+
}
|
|
7
10
|
/**
|
|
8
11
|
* Merge project.config.json + project.private.config.json (private wins),
|
|
9
12
|
* mirroring `dimina/fe/packages/compiler/src/env.js`'s `storeInfo`.
|
|
@@ -206,21 +209,130 @@ export function updateLastOpened(dirPath) {
|
|
|
206
209
|
save(projects);
|
|
207
210
|
}
|
|
208
211
|
}
|
|
209
|
-
|
|
212
|
+
/**
|
|
213
|
+
* Read a project's compile modes from `project.config.json`'s
|
|
214
|
+
* `condition.miniprogram` — WeChat DevTools' own location and shape, so a
|
|
215
|
+
* project checked into git carries its modes to every machine, and the same
|
|
216
|
+
* directory opened in that tool shows the same list.
|
|
217
|
+
*
|
|
218
|
+
* Projects imported before compile modes existed fall back to migrating the
|
|
219
|
+
* legacy single config out of the project list file.
|
|
220
|
+
*/
|
|
221
|
+
export function getCompileModes(dirPath) {
|
|
222
|
+
if (!dirPath)
|
|
223
|
+
return emptyCompileModes();
|
|
224
|
+
const condition = readProjectConfig(dirPath).condition;
|
|
225
|
+
const stored = isRecord(condition) && condition.miniprogram !== undefined
|
|
226
|
+
? normalizeCompileModes(condition.miniprogram)
|
|
227
|
+
: null;
|
|
228
|
+
// A stored list with entries is the answer — it is the user's own edit. An
|
|
229
|
+
// EMPTY block is not evidence that the project has no modes: WeChat DevTools
|
|
230
|
+
// writes `"miniprogram": {"list": []}` into any project it opens, and taking
|
|
231
|
+
// that as "no modes" would drop the start page a user configured before
|
|
232
|
+
// compile modes existed.
|
|
233
|
+
if (stored && stored.list.length > 0)
|
|
234
|
+
return stored;
|
|
235
|
+
return migrateLegacyCompileConfig(dirPath) ?? stored ?? emptyCompileModes();
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Which config file owns `condition` for this project — the one a save has to
|
|
239
|
+
* land in to be read back.
|
|
240
|
+
*
|
|
241
|
+
* `readProjectConfig` merges the private file over the public one key by key,
|
|
242
|
+
* so a private file carrying any `condition` at all (even one that only holds
|
|
243
|
+
* a mini-game block, with no `miniprogram` in it) replaces the whole merged
|
|
244
|
+
* `condition`. Writing modes to the public file in that case reports success
|
|
245
|
+
* and then reads back as if nothing had been saved.
|
|
246
|
+
*
|
|
247
|
+
* With no private `condition`, modes stay in the shared public file, where the
|
|
248
|
+
* team gets them from git.
|
|
249
|
+
*/
|
|
250
|
+
function compileModesConfigPath(dirPath) {
|
|
251
|
+
const privatePath = path.join(dirPath, 'project.private.config.json');
|
|
252
|
+
if (fs.existsSync(privatePath)) {
|
|
253
|
+
try {
|
|
254
|
+
const privateConfig = JSON.parse(fs.readFileSync(privatePath, 'utf-8'));
|
|
255
|
+
if (isRecord(privateConfig) && privateConfig.condition !== undefined)
|
|
256
|
+
return privatePath;
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
// Unparseable — readProjectConfig skips this file too, so the public one
|
|
260
|
+
// is what a read actually sees.
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return path.join(dirPath, 'project.config.json');
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Persist compile modes, merged so the rest of the target file survives —
|
|
267
|
+
* including the rest of `condition`, which for a mini-game project holds its
|
|
268
|
+
* own `condition.game` block.
|
|
269
|
+
*/
|
|
270
|
+
export function saveCompileModes(dirPath, modes) {
|
|
271
|
+
if (!dirPath)
|
|
272
|
+
return;
|
|
273
|
+
const configPath = compileModesConfigPath(dirPath);
|
|
274
|
+
let config = {};
|
|
275
|
+
if (fs.existsSync(configPath)) {
|
|
276
|
+
try {
|
|
277
|
+
config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// Refuse rather than overwrite: this file also holds the project's
|
|
281
|
+
// build settings, which a blind rewrite would drop.
|
|
282
|
+
throw new Error(`无法保存编译模式:${configPath} 不是合法 JSON`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const condition = isRecord(config.condition) ? config.condition : {};
|
|
286
|
+
fs.writeFileSync(configPath, JSON.stringify({ ...config, condition: { ...condition, miniprogram: modes } }, null, 2));
|
|
287
|
+
// The user has now said what this project's modes are, so the pre-compile-
|
|
288
|
+
// modes single config is spent. Retiring it here is what makes deleting a
|
|
289
|
+
// migrated mode stick: an empty stored list would otherwise be read as
|
|
290
|
+
// "nothing stored yet" and migrate the old config back.
|
|
291
|
+
clearLegacyCompileConfig(dirPath);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Projects imported before compile modes existed stored one unnamed compile
|
|
295
|
+
* config in the project list file. Surface it as a selected mode rather than
|
|
296
|
+
* silently dropping the user's start page — but only when it asks for
|
|
297
|
+
* something 普通编译 can't already do, so the common case stays an empty list.
|
|
298
|
+
* Returns null when there is nothing to migrate.
|
|
299
|
+
*
|
|
300
|
+
* Read-only: opening a project must not rewrite the user's git-tracked
|
|
301
|
+
* project.config.json. The legacy record is retired instead by the first
|
|
302
|
+
* explicit save (see `saveCompileModes`), which is also what keeps a deleted
|
|
303
|
+
* mode deleted — without that, an empty stored list would migrate again and
|
|
304
|
+
* put the mode back.
|
|
305
|
+
*/
|
|
306
|
+
function migrateLegacyCompileConfig(dirPath) {
|
|
307
|
+
const legacy = load().find((p) => p.path === dirPath)?.compileConfig;
|
|
308
|
+
if (!legacy)
|
|
309
|
+
return null;
|
|
310
|
+
const modes = compileConfigToModes(legacy, getProjectPages(dirPath).entryPagePath);
|
|
311
|
+
return modes.list.length > 0 ? modes : null;
|
|
312
|
+
}
|
|
313
|
+
/** Remove the pre-compile-modes single config from a project record. */
|
|
314
|
+
function clearLegacyCompileConfig(dirPath) {
|
|
210
315
|
const projects = load();
|
|
211
|
-
const
|
|
212
|
-
if (
|
|
213
|
-
return
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
316
|
+
const idx = projects.findIndex((p) => p.path === dirPath);
|
|
317
|
+
if (idx < 0 || projects[idx].compileConfig === undefined)
|
|
318
|
+
return;
|
|
319
|
+
const { compileConfig: _legacy, ...rest } = projects[idx];
|
|
320
|
+
projects[idx] = rest;
|
|
321
|
+
save(projects);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* The launch parameters the selected mode resolves to. 普通编译 resolves to
|
|
325
|
+
* an empty start page; it is filled in here with the project's real entry
|
|
326
|
+
* page (mirrors getProjectPages: 'game' for mini-games, app.json's
|
|
327
|
+
* entryPagePath for mini-programs) rather than a mini-program-only literal —
|
|
328
|
+
* the simulator URL builders' own 'pages/index/index' fallback only fires
|
|
329
|
+
* when this is still empty (unreadable/malformed manifest).
|
|
330
|
+
*/
|
|
331
|
+
export function getCompileConfig(dirPath) {
|
|
332
|
+
const config = resolveCompileConfig(getCompileModes(dirPath));
|
|
333
|
+
if (config.startPage)
|
|
334
|
+
return config;
|
|
335
|
+
return { ...config, startPage: getProjectPages(dirPath).entryPagePath };
|
|
224
336
|
}
|
|
225
337
|
export function getProjectPages(dirPath) {
|
|
226
338
|
if (detectRuntimeType(dirPath) === 'minigame') {
|
|
@@ -242,13 +354,25 @@ export function getProjectPages(dirPath) {
|
|
|
242
354
|
return { pages: [], entryPagePath: '' };
|
|
243
355
|
}
|
|
244
356
|
}
|
|
357
|
+
/**
|
|
358
|
+
* @deprecated Compile modes are the stored form — call `saveCompileModes`.
|
|
359
|
+
* Kept working for embedding hosts still on the single-config setter: the
|
|
360
|
+
* config lands on the selected mode, or becomes a new selected mode when
|
|
361
|
+
* 普通编译 is selected and the config asks for more than it can express.
|
|
362
|
+
*/
|
|
245
363
|
export function saveCompileConfig(dirPath, config) {
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
364
|
+
const modes = getCompileModes(dirPath);
|
|
365
|
+
if (modes.current === NORMAL_COMPILE_INDEX) {
|
|
366
|
+
if (isNormalCompile(config, getProjectPages(dirPath).entryPagePath))
|
|
367
|
+
return;
|
|
368
|
+
saveCompileModes(dirPath, {
|
|
369
|
+
current: modes.list.length,
|
|
370
|
+
list: [...modes.list, compileConfigToMode(config, '')],
|
|
371
|
+
});
|
|
372
|
+
return;
|
|
251
373
|
}
|
|
374
|
+
const list = modes.list.map((mode, i) => (i === modes.current ? { ...mode, ...compileConfigToMode(config, mode.name) } : mode));
|
|
375
|
+
saveCompileModes(dirPath, { ...modes, list });
|
|
252
376
|
}
|
|
253
377
|
/** Read a subset of `project.config.json` exposed to the settings panel. */
|
|
254
378
|
export function getProjectSettings(projectPath) {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* `WorkbenchAppConfig` to fully take over the project source-of-truth, the
|
|
5
5
|
* template catalog, and the "新建项目" dialog.
|
|
6
6
|
*/
|
|
7
|
-
import type { CompileConfig } from '../../../shared/types.js';
|
|
7
|
+
import type { CompileConfig, CompileModes } from '../../../shared/types.js';
|
|
8
8
|
import type { Project, ProjectPatch } from './project-repository.js';
|
|
9
9
|
export type { Project, ProjectPatch };
|
|
10
10
|
export type { ProjectTemplate, CreateProjectInput } from '../../../shared/types.js';
|
|
@@ -59,20 +59,43 @@ export interface ProjectsProvider {
|
|
|
59
59
|
*/
|
|
60
60
|
updateLastOpened?(dirPath: string): void | Promise<void>;
|
|
61
61
|
/**
|
|
62
|
-
* Read the per-project compile config
|
|
62
|
+
* Read the per-project compile config — the launch parameters the
|
|
63
|
+
* SELECTED compile mode resolves to.
|
|
63
64
|
*
|
|
64
|
-
* Default when omitted:
|
|
65
|
-
* (`{ startPage: '', scene: 1001, queryParams: [] }`)
|
|
65
|
+
* Default when omitted: derived from `getCompileModes`, or
|
|
66
|
+
* `DEFAULT_COMPILE_CONFIG` (`{ startPage: '', scene: 1001, queryParams: [] }`)
|
|
67
|
+
* when that is absent too. Implement this only if you can resolve the
|
|
68
|
+
* project's own entry page for 普通编译 — the derived default leaves
|
|
69
|
+
* `startPage` empty and lets the renderer substitute it.
|
|
66
70
|
*/
|
|
67
71
|
getCompileConfig?(dirPath: string): CompileConfig | Promise<CompileConfig>;
|
|
68
72
|
/**
|
|
69
|
-
*
|
|
73
|
+
* @deprecated Implement `saveCompileModes` instead — the named mode list
|
|
74
|
+
* is the stored form, and this setter can only express the selected
|
|
75
|
+
* mode's parameters.
|
|
70
76
|
*
|
|
71
|
-
* Default when omitted: silently no-ops
|
|
72
|
-
* not survive a reload. Implement this if your UI exposes the compile
|
|
73
|
-
* config panel.
|
|
77
|
+
* Default when omitted: silently no-ops.
|
|
74
78
|
*/
|
|
75
79
|
saveCompileConfig?(dirPath: string, cfg: CompileConfig): void | Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Read the project's compile modes and which one is selected. The stored
|
|
82
|
+
* form behind the toolbar's compile-mode dropdown; `LocalProjectsProvider`
|
|
83
|
+
* keeps it in the project's own `project.config.json` under
|
|
84
|
+
* `condition.miniprogram` (WeChat DevTools' location and shape).
|
|
85
|
+
*
|
|
86
|
+
* Default when omitted: `{ current: -1, list: [] }` — the dropdown then
|
|
87
|
+
* offers 普通编译 only.
|
|
88
|
+
*/
|
|
89
|
+
getCompileModes?(dirPath: string): CompileModes | Promise<CompileModes>;
|
|
90
|
+
/**
|
|
91
|
+
* Persist the project's compile modes and selection.
|
|
92
|
+
*
|
|
93
|
+
* Default when omitted: falls back to `saveCompileConfig` with the
|
|
94
|
+
* resolved launch parameters, so a host on the older setter keeps the
|
|
95
|
+
* selection's effect but not the named list. With neither, edits do not
|
|
96
|
+
* survive a reload.
|
|
97
|
+
*/
|
|
98
|
+
saveCompileModes?(dirPath: string, modes: CompileModes): void | Promise<void>;
|
|
76
99
|
/**
|
|
77
100
|
* Persist a captured screenshot for the given project. `imageDataUrl`
|
|
78
101
|
* is a `data:image/png;base64,...` string so a remote provider can ship
|