@dimina-kit/devtools 0.3.1 → 0.3.2-dev.20260522085907
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 +297 -133
- package/dist/main/api.d.ts +6 -2
- package/dist/main/api.js +5 -2
- package/dist/main/app/app.d.ts +1 -1
- package/dist/main/app/app.js +84 -36
- package/dist/main/app/bootstrap.js +2 -1
- package/dist/main/app/launch.d.ts +2 -2
- package/dist/main/app/launch.js +10 -8
- package/dist/main/index.bundle.js +1567 -477
- package/dist/main/ipc/app.d.ts +2 -1
- package/dist/main/ipc/app.js +5 -4
- package/dist/main/ipc/index.d.ts +5 -4
- package/dist/main/ipc/index.js +5 -4
- package/dist/main/ipc/panels.d.ts +2 -1
- package/dist/main/ipc/panels.js +16 -13
- package/dist/main/ipc/popover.d.ts +4 -1
- package/dist/main/ipc/popover.js +15 -5
- package/dist/main/ipc/projects.d.ts +6 -1
- package/dist/main/ipc/projects.js +127 -6
- package/dist/main/ipc/session.d.ts +4 -1
- package/dist/main/ipc/session.js +34 -6
- package/dist/main/ipc/settings.d.ts +4 -1
- package/dist/main/ipc/settings.js +51 -23
- package/dist/main/ipc/simulator-module.d.ts +8 -0
- package/dist/main/ipc/simulator-module.js +19 -0
- package/dist/main/ipc/simulator.d.ts +2 -1
- package/dist/main/ipc/simulator.js +23 -18
- package/dist/main/ipc/toolbar.d.ts +2 -1
- package/dist/main/ipc/toolbar.js +3 -2
- package/dist/main/menu/index.js +11 -0
- package/dist/main/services/automation/exec.d.ts +2 -0
- package/dist/main/services/automation/exec.js +7 -9
- package/dist/main/services/automation/handlers/app.js +37 -51
- package/dist/main/services/automation/handlers/element.js +27 -41
- package/dist/main/services/automation/index.js +88 -13
- package/dist/main/services/default-adapter.js +3 -3
- package/dist/main/services/mcp/index.d.ts +1 -0
- package/dist/main/services/mcp/index.js +1 -0
- package/dist/main/services/mcp/server.d.ts +2 -1
- package/dist/main/services/mcp/server.js +10 -0
- package/dist/main/services/mcp/status.d.ts +10 -0
- package/dist/main/services/mcp/status.js +14 -0
- package/dist/main/services/mcp/target-manager.js +2 -1
- package/dist/main/services/module.d.ts +18 -0
- package/dist/main/services/module.js +2 -0
- package/dist/main/services/notifications/renderer-notifier.d.ts +5 -3
- package/dist/main/services/notifications/renderer-notifier.js +3 -6
- package/dist/main/services/projects/builtin-templates.d.ts +3 -0
- package/dist/main/services/projects/builtin-templates.js +24 -0
- package/dist/main/services/projects/create-project-service.d.ts +7 -0
- package/dist/main/services/projects/create-project-service.js +84 -0
- package/dist/main/services/projects/index.d.ts +7 -0
- package/dist/main/services/projects/index.js +9 -0
- package/dist/main/services/projects/local-provider.d.ts +3 -0
- package/dist/main/services/projects/local-provider.js +25 -0
- package/dist/main/services/projects/project-repository.d.ts +1 -1
- package/dist/main/services/projects/project-repository.js +3 -0
- package/dist/main/services/projects/templates.d.ts +21 -0
- package/dist/main/services/projects/templates.js +39 -0
- package/dist/main/services/projects/thumbnail.d.ts +8 -0
- package/dist/main/services/projects/thumbnail.js +37 -0
- package/dist/main/services/projects/types.d.ts +118 -0
- package/dist/main/services/projects/types.js +19 -0
- package/dist/main/services/settings/index.d.ts +11 -0
- package/dist/main/services/settings/index.js +18 -2
- package/dist/main/services/simulator/custom-apis.d.ts +10 -0
- package/dist/main/services/simulator/custom-apis.js +26 -0
- package/dist/main/services/simulator-storage/index.d.ts +22 -1
- package/dist/main/services/simulator-storage/index.js +334 -97
- package/dist/main/services/update/update-manager.d.ts +16 -1
- package/dist/main/services/update/update-manager.js +18 -15
- package/dist/main/services/views/view-manager.d.ts +7 -7
- package/dist/main/services/views/view-manager.js +53 -29
- package/dist/main/services/window-service.d.ts +24 -0
- package/dist/main/services/window-service.js +26 -0
- package/dist/main/services/workbench-context.d.ts +49 -2
- package/dist/main/services/workbench-context.js +15 -2
- package/dist/main/services/workspace/workspace-service.d.ts +9 -6
- package/dist/main/services/workspace/workspace-service.js +71 -11
- package/dist/main/simulator-apis.d.ts +23 -0
- package/dist/main/simulator-apis.js +24 -0
- package/dist/main/utils/disposable.d.ts +13 -0
- package/dist/main/utils/disposable.js +60 -0
- package/dist/main/utils/ipc-registry.d.ts +39 -0
- package/dist/main/utils/ipc-registry.js +109 -0
- package/dist/main/utils/ipc-schema.d.ts +28 -0
- package/dist/main/utils/ipc-schema.js +38 -0
- package/dist/main/utils/paths.d.ts +6 -0
- package/dist/main/utils/paths.js +6 -0
- package/dist/main/utils/sender-policy.d.ts +25 -0
- package/dist/main/utils/sender-policy.js +44 -0
- package/dist/main/utils/theme.d.ts +24 -0
- package/dist/main/utils/theme.js +38 -1
- package/dist/main/windows/main-window/create.d.ts +6 -0
- package/dist/main/windows/main-window/create.js +66 -10
- package/dist/main/windows/main-window/events.d.ts +2 -1
- package/dist/main/windows/main-window/events.js +25 -2
- package/dist/main/windows/navigation-hardening.d.ts +24 -0
- package/dist/main/windows/navigation-hardening.js +55 -0
- package/dist/main/windows/settings-window/create.js +11 -1
- package/dist/preload/index.d.ts +22 -0
- package/dist/preload/index.js +19 -0
- package/dist/preload/instrumentation/app-data.d.ts +32 -2
- package/dist/preload/instrumentation/app-data.js +253 -79
- package/dist/preload/instrumentation/index.d.ts +2 -2
- package/dist/preload/instrumentation/index.js +2 -2
- package/dist/preload/instrumentation/wxml.d.ts +16 -4
- package/dist/preload/instrumentation/wxml.js +188 -178
- package/dist/preload/miniapp-snapshot/host.d.ts +12 -0
- package/dist/preload/miniapp-snapshot/host.js +117 -0
- package/dist/preload/miniapp-snapshot/types.d.ts +62 -0
- package/dist/preload/miniapp-snapshot/types.js +15 -0
- package/dist/preload/runtime/bridge.js +5 -24
- package/dist/preload/runtime/custom-apis.d.ts +6 -0
- package/dist/preload/runtime/custom-apis.js +43 -0
- package/dist/preload/runtime/host.d.ts +1 -0
- package/dist/preload/runtime/host.js +13 -0
- package/dist/preload/shared/expose.d.ts +15 -0
- package/dist/preload/shared/expose.js +33 -0
- package/dist/preload/shared/page-iframe.d.ts +3 -0
- package/dist/preload/shared/page-iframe.js +6 -0
- package/dist/preload/shared/types.d.ts +2 -0
- package/dist/preload/windows/main.cjs +47 -0
- package/dist/preload/windows/main.cjs.map +7 -0
- package/dist/preload/windows/simulator.js +501 -272
- package/dist/renderer/assets/constants-DI382mTP.js +2 -0
- package/dist/renderer/assets/index-D8VFYBh-.js +46 -0
- package/dist/renderer/assets/{input-DxfYnzX_.js → input-CoWcfa8u.js} +2 -2
- package/dist/renderer/assets/ipc-transport-Cd2xPrsa.js +9 -0
- package/dist/renderer/assets/ipc-transport-DqbRdZNO.css +1 -0
- package/dist/renderer/assets/popover-Nq5gT9DO.js +2 -0
- package/dist/renderer/assets/select-By5KH-UG.js +2 -0
- package/dist/renderer/assets/{settings-DteGraEU.js → settings-Dj_N70qR.js} +2 -2
- package/dist/renderer/assets/settings-api-Do0_Smq1.js +2 -0
- package/dist/renderer/assets/workbenchSettings-CazSLGYt.js +8 -0
- package/dist/renderer/entries/main/index.html +13 -5
- package/dist/renderer/entries/popover/index.html +8 -5
- package/dist/renderer/entries/settings/index.html +7 -5
- package/dist/renderer/entries/workbench-settings/index.html +7 -4
- package/dist/shared/ipc-channels.d.ts +46 -13
- package/dist/shared/ipc-channels.js +60 -14
- package/dist/shared/ipc-schemas.d.ts +118 -0
- package/dist/shared/ipc-schemas.js +133 -0
- package/dist/shared/simulator-route.d.ts +72 -0
- package/dist/shared/simulator-route.js +169 -0
- package/dist/shared/types.d.ts +82 -8
- package/dist/simulator/assets/simulator-DJCozrU5.js +9 -0
- package/dist/simulator/simulator.html +6 -43
- package/package.json +18 -29
- package/templates/blank/app.js +6 -0
- package/templates/blank/app.json +11 -0
- package/templates/blank/app.wxss +5 -0
- package/templates/blank/pages/index/index.js +6 -0
- package/templates/blank/pages/index/index.json +3 -0
- package/templates/blank/pages/index/index.wxml +3 -0
- package/templates/blank/pages/index/index.wxss +11 -0
- package/templates/blank/project.config.json +13 -0
- package/templates/blank/sitemap.json +9 -0
- package/templates/taro-todo/app.js +1 -0
- package/templates/taro-todo/app.json +1 -0
- package/templates/taro-todo/app.wxss +1 -0
- package/templates/taro-todo/base.wxml +851 -0
- package/templates/taro-todo/common.js +1 -0
- package/templates/taro-todo/comp.js +1 -0
- package/templates/taro-todo/comp.json +1 -0
- package/templates/taro-todo/comp.wxml +2 -0
- package/templates/taro-todo/custom-wrapper.js +1 -0
- package/templates/taro-todo/custom-wrapper.json +1 -0
- package/templates/taro-todo/custom-wrapper.wxml +4 -0
- package/templates/taro-todo/pages/index/index.js +2 -0
- package/templates/taro-todo/pages/index/index.json +1 -0
- package/templates/taro-todo/pages/index/index.wxml +2 -0
- package/templates/taro-todo/pages/index/index.wxss +1 -0
- package/templates/taro-todo/project.config.json +44 -0
- package/templates/taro-todo/runtime.js +1 -0
- package/templates/taro-todo/taro.js +2 -0
- package/templates/taro-todo/utils.wxs +39 -0
- package/templates/taro-todo/vendors.js +2 -0
- package/dist/preload/instrumentation/disposable.d.ts +0 -11
- package/dist/preload/instrumentation/disposable.js +0 -15
- package/dist/preload/windows/main.d.ts +0 -6
- package/dist/preload/windows/main.js +0 -6
- package/dist/renderer/assets/index-D1p6crtf.js +0 -46
- package/dist/renderer/assets/ipc-transport-ClIvDcYY.js +0 -9
- package/dist/renderer/assets/ipc-transport-EiWxu_hG.css +0 -1
- package/dist/renderer/assets/popover-CtXcBJtM.js +0 -2
- package/dist/renderer/assets/select-DMfp49f1.js +0 -2
- package/dist/renderer/assets/settings-api-CY84UMpN.js +0 -2
- package/dist/renderer/assets/workbenchSettings-DjELLnSJ.js +0 -8
- package/dist/simulator/assets/simulator-C1eHXnuq.js +0 -9
package/README.md
CHANGED
|
@@ -83,6 +83,7 @@ import { app, globalShortcut } from 'electron'
|
|
|
83
83
|
import path from 'path'
|
|
84
84
|
import { createMainWindow } from '@dimina-kit/devtools/create-window'
|
|
85
85
|
import { createWorkbenchContext } from '@dimina-kit/devtools/context'
|
|
86
|
+
import { registerAppIpc } from '@dimina-kit/devtools'
|
|
86
87
|
import { registerSimulatorIpc } from '@dimina-kit/devtools/ipc-simulator'
|
|
87
88
|
import { registerPanelsIpc } from '@dimina-kit/devtools/ipc-panels'
|
|
88
89
|
import { registerToolbarIpc } from '@dimina-kit/devtools/ipc-toolbar'
|
|
@@ -95,7 +96,7 @@ import { rendererDir, defaultPreloadPath } from '@dimina-kit/devtools/paths'
|
|
|
95
96
|
app.whenReady().then(() => {
|
|
96
97
|
const mainWindow = createMainWindow({
|
|
97
98
|
title: 'My DevTools',
|
|
98
|
-
indexHtml: path.join(rendererDir, 'index.html'),
|
|
99
|
+
indexHtml: path.join(rendererDir, 'entries/main/index.html'),
|
|
99
100
|
})
|
|
100
101
|
|
|
101
102
|
const ctx = createWorkbenchContext({
|
|
@@ -105,6 +106,9 @@ app.whenReady().then(() => {
|
|
|
105
106
|
rendererDir,
|
|
106
107
|
})
|
|
107
108
|
|
|
109
|
+
// registerAppIpc 必装:renderer 启动时调用 app:getPreloadPath / app:getBranding,
|
|
110
|
+
// 缺它会卡在加载阶段。
|
|
111
|
+
registerAppIpc(ctx)
|
|
108
112
|
registerProjectsIpc(ctx)
|
|
109
113
|
registerSessionIpc(ctx)
|
|
110
114
|
registerSimulatorIpc(ctx)
|
|
@@ -112,6 +116,11 @@ app.whenReady().then(() => {
|
|
|
112
116
|
registerToolbarIpc(ctx)
|
|
113
117
|
registerPopoverIpc(ctx)
|
|
114
118
|
|
|
119
|
+
// Storage / 元素选区面板的后端 handler 由 setupSimulatorStorage 单独装。
|
|
120
|
+
// 该函数当前**未列入稳定公共 API**(在 `@dimina-kit/devtools` 之外)。
|
|
121
|
+
// 若需要这两个面板,建议改用上方的 `createWorkbenchApp({ onSetup })` 路线,
|
|
122
|
+
// 框架会自动注册;模块组装路线下你只能用不依赖它们的精简面板集。
|
|
123
|
+
|
|
115
124
|
// 添加自定义 IPC — 通过 ctx.workspace 访问会话状态
|
|
116
125
|
ipcMain.handle('my:action', () => {
|
|
117
126
|
console.log('current project:', ctx.workspace.getProjectPath())
|
|
@@ -150,9 +159,6 @@ src/
|
|
|
150
159
|
app.ts # createWorkbenchApp 工厂
|
|
151
160
|
bootstrap.ts # suppressEpipe / setupCdpPort
|
|
152
161
|
lifecycle.ts # Electron app 生命周期注册
|
|
153
|
-
windows/
|
|
154
|
-
main-window/ # 主窗口创建 + 事件接线
|
|
155
|
-
settings-window/ # 独立设置窗口
|
|
156
162
|
ipc/ # 只做 handler 注册,不写业务
|
|
157
163
|
index.ts # 聚合 register 函数导出
|
|
158
164
|
simulator.ts # simulator attach/detach/resize
|
|
@@ -166,17 +172,33 @@ src/
|
|
|
166
172
|
settings/ # 用户级 workbench 设置读写 + 主题应用
|
|
167
173
|
projects/ # 项目列表 CRUD(持久化)
|
|
168
174
|
layout/ # 布局常量 + bounds 计算
|
|
175
|
+
views/ # ViewManager(settings / popover overlay 等)
|
|
176
|
+
workspace/ # 项目会话生命周期
|
|
177
|
+
notifications/ # 主进程 → renderer 的事件通知
|
|
169
178
|
mcp/ # MCP server
|
|
170
179
|
automation/ # 自动化 WebSocket 服务
|
|
171
180
|
simulator/ # simulator dir / referer
|
|
181
|
+
simulator-storage/ # CDP DOMStorage + 元素 inspect 桥接
|
|
182
|
+
update/ # UpdateManager + GitHubReleaseChecker
|
|
172
183
|
workbench-context.ts # 共享状态类型 + 工厂 + 辅助函数
|
|
184
|
+
window-service.ts # main / settings 窗口聚合访问
|
|
185
|
+
module.ts # WorkbenchModule 协议
|
|
173
186
|
default-adapter.ts # 默认 CompilationAdapter
|
|
174
187
|
menu/ # 应用菜单
|
|
175
|
-
utils/
|
|
188
|
+
utils/
|
|
189
|
+
paths.ts # rendererDir / defaultPreloadPath / simulatorDir
|
|
190
|
+
disposable.ts # DisposableRegistry + AggregateError 聚合
|
|
191
|
+
ipc-registry.ts # ipcMain.handle 包装 + SenderPolicy 闸门
|
|
192
|
+
sender-policy.ts # sender webContents id 白名单
|
|
193
|
+
ipc-schema.ts # zod schema 校验工具
|
|
194
|
+
windows/
|
|
195
|
+
main-window/ # 主窗口创建 + 事件接线
|
|
196
|
+
settings-window/ # 独立设置窗口
|
|
197
|
+
navigation-hardening.ts # will-navigate / setWindowOpenHandler 限流
|
|
176
198
|
|
|
177
199
|
preload/ # 按注入目标分
|
|
178
200
|
windows/ # contextBridge 类型 preload
|
|
179
|
-
main.ts #
|
|
201
|
+
main.ts # workbench 三窗口 preload,仅暴露 window.devtools.ipc
|
|
180
202
|
simulator.ts # simulator webview 的默认 preload
|
|
181
203
|
shared/ # preload 之间共享
|
|
182
204
|
api-compat.ts # setupApiCompatHook
|
|
@@ -184,19 +206,23 @@ src/
|
|
|
184
206
|
types.ts
|
|
185
207
|
instrumentation/ # 注入到小程序 runtime 的探针
|
|
186
208
|
console.ts # 控制台拦截
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
209
|
+
app-data.ts # Worker setData 拦截 → createAppDataSource
|
|
210
|
+
wxml.ts # Vue 组件树提取 → createWxmlSource
|
|
211
|
+
disposable.ts # instrumentation 共用的清理工具
|
|
212
|
+
miniapp-snapshot/ # 面板数据统一快照框架(docs/miniapp-snapshot.md)
|
|
213
|
+
types.ts # MiniappSnapshotSource / SnapshotEnvelope
|
|
214
|
+
host.ts # createMiniappSnapshotHost → push/pull/__miniappSnapshot
|
|
190
215
|
runtime/
|
|
191
|
-
bridge.ts # installSimulatorBridge
|
|
192
|
-
|
|
216
|
+
bridge.ts # installSimulatorBridge → window.__simulatorData
|
|
217
|
+
custom-apis.ts # installCustomApisBridge → window.__diminaCustomApis
|
|
218
|
+
host.ts # sendToHost 推送封装
|
|
193
219
|
|
|
194
220
|
renderer/
|
|
195
221
|
entries/ # 各窗口 HTML + React 挂载点
|
|
196
222
|
main/ popover/ settings/ workbench-settings/
|
|
197
223
|
modules/ # 先按窗口分,再按区域
|
|
198
224
|
main/
|
|
199
|
-
|
|
225
|
+
main.tsx # 主窗口 React 根
|
|
200
226
|
features/ # 主窗口内的业务区域
|
|
201
227
|
project-runtime/ # 项目视图 + 工具栏 + 右侧面板切换
|
|
202
228
|
right-panel/ # WXML / AppData / Storage 面板
|
|
@@ -248,6 +274,8 @@ src/
|
|
|
248
274
|
| `onSetup` | `(instance) => void` | — | 窗口和 context 创建后的回调,用于注册自定义 IPC |
|
|
249
275
|
| `onBeforeClose` | `(instance) => void` | — | 窗口关闭前的回调,session 关闭由框架自动处理 |
|
|
250
276
|
| `window` | `WorkbenchWindowConfig` | — | 窗口尺寸覆盖 |
|
|
277
|
+
| `updateChecker` | `UpdateChecker` | — | 自定义更新检查器;提供后启用"检查更新"功能 |
|
|
278
|
+
| `updateOptions` | `{ checkInterval?, initialDelay?, getCurrentVersion? }` | — | 仅当 `updateChecker` 提供时生效,默认 1h / 5s |
|
|
251
279
|
|
|
252
280
|
### 内置面板 ID
|
|
253
281
|
|
|
@@ -259,6 +287,126 @@ src/
|
|
|
259
287
|
|
|
260
288
|
---
|
|
261
289
|
|
|
290
|
+
## Embedding & Extending the Project Panel
|
|
291
|
+
|
|
292
|
+
宿主(如 qdmp)通过 `createWorkbenchApp({...})` 嵌入 devtools 时,可对项目面板做三个正交扩展:
|
|
293
|
+
|
|
294
|
+
| 扩展点 | 用途 |
|
|
295
|
+
| --- | --- |
|
|
296
|
+
| `projectsProvider` | 接管项目列表存储 —— 替换默认 `<userData>/dimina-projects.json`,对接 qdmp 后台 / IDE workspace / 远端工程库 |
|
|
297
|
+
| `projectTemplates` + `builtinTemplates` | 注入/覆盖/裁剪"新建项目"模板列表(同 id 覆盖内置;`builtinTemplates` 控制内置策略) |
|
|
298
|
+
| `customCreateProjectDialog` | 用宿主自家页面替换内置"新建项目"对话框(main 进程 hook,可 `new BrowserWindow` 加载任意 URL,通过 IPC/postMessage 回传结果) |
|
|
299
|
+
|
|
300
|
+
### 何时需要哪个扩展点
|
|
301
|
+
|
|
302
|
+
| 场景 | 需要的扩展点 |
|
|
303
|
+
| --- | --- |
|
|
304
|
+
| 项目列表来自 qdmp 后台 / 团队工程库 | `projectsProvider` |
|
|
305
|
+
| 仅替换可选模板(e.g. 只提供 taro / qdmp 自家脚手架) | `projectTemplates` + `builtinTemplates` |
|
|
306
|
+
| 创建项目流程要走宿主自己的 wizard / 登录态 | `customCreateProjectDialog` |
|
|
307
|
+
|
|
308
|
+
### 最小示例
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { createWorkbenchApp } from '@dimina-kit/devtools/app'
|
|
312
|
+
import type { ProjectsProvider, ProjectTemplate } from '@dimina-kit/devtools/projects-provider'
|
|
313
|
+
import { BrowserWindow } from 'electron'
|
|
314
|
+
|
|
315
|
+
const provider: ProjectsProvider = {
|
|
316
|
+
async listProjects() {
|
|
317
|
+
return await qdmp.api.listProjects()
|
|
318
|
+
},
|
|
319
|
+
async validateProjectDir(dirPath) {
|
|
320
|
+
return (await qdmp.api.isMiniApp(dirPath)) ? null : '不是合法的小程序工程'
|
|
321
|
+
},
|
|
322
|
+
async addProject(dirPath) {
|
|
323
|
+
return await qdmp.api.addProject(dirPath)
|
|
324
|
+
},
|
|
325
|
+
async removeProject(dirPath) {
|
|
326
|
+
await qdmp.api.removeProject(dirPath)
|
|
327
|
+
},
|
|
328
|
+
async updateLastOpened(dirPath) {
|
|
329
|
+
await qdmp.api.touchLastOpened(dirPath)
|
|
330
|
+
},
|
|
331
|
+
async getCompileConfig(dirPath) {
|
|
332
|
+
return await qdmp.api.getCompileConfig(dirPath)
|
|
333
|
+
},
|
|
334
|
+
async saveCompileConfig(dirPath, cfg) {
|
|
335
|
+
await qdmp.api.saveCompileConfig(dirPath, cfg)
|
|
336
|
+
},
|
|
337
|
+
// 缩略图走云端存储——dataUrl 形如 'data:image/png;base64,...'
|
|
338
|
+
async saveThumbnail(dirPath, imageDataUrl) {
|
|
339
|
+
await qdmp.api.uploadThumbnail(dirPath, imageDataUrl)
|
|
340
|
+
},
|
|
341
|
+
async getThumbnail(dirPath) {
|
|
342
|
+
return await qdmp.api.fetchThumbnail(dirPath)
|
|
343
|
+
},
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const qdmpBlank: ProjectTemplate = {
|
|
347
|
+
id: 'blank', // 同 id 覆盖内置 blank
|
|
348
|
+
name: 'qdmp 空白工程',
|
|
349
|
+
description: '由 qdmp 维护的官方空白模板',
|
|
350
|
+
source: { type: 'directory', path: '/abs/path/to/template' },
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
createWorkbenchApp({
|
|
354
|
+
projectsProvider: provider,
|
|
355
|
+
projectTemplates: [qdmpBlank],
|
|
356
|
+
builtinTemplates: ['taro-todo'], // 只保留 taro-todo,干掉默认 blank
|
|
357
|
+
customCreateProjectDialog: async ({ parentWindow }) => {
|
|
358
|
+
const win = new BrowserWindow({ parent: parentWindow, modal: true, width: 720, height: 520 })
|
|
359
|
+
await win.loadURL('https://qdmp.example.com/devtools/new-project')
|
|
360
|
+
return await new Promise((resolve) => {
|
|
361
|
+
win.webContents.ipc.once('qdmp:create-project:done', (_e, payload) => {
|
|
362
|
+
win.close()
|
|
363
|
+
// payload 三选一(CustomCreateProjectDialogResult):
|
|
364
|
+
// null → 用户取消
|
|
365
|
+
// CreateProjectInput → 让 devtools 在本地物化模板并注册到 provider
|
|
366
|
+
// { ready: Project } → 宿主后端已经创建好,devtools 直接刷新列表
|
|
367
|
+
resolve(payload ?? null)
|
|
368
|
+
})
|
|
369
|
+
win.on('closed', () => resolve(null))
|
|
370
|
+
})
|
|
371
|
+
},
|
|
372
|
+
}).start()
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### `customCreateProjectDialog` 返回值
|
|
376
|
+
|
|
377
|
+
`hook` 返回 `CustomCreateProjectDialogResult`,三种情形分别对应不同后续动作:
|
|
378
|
+
|
|
379
|
+
| 返回 | 行为 |
|
|
380
|
+
| --- | --- |
|
|
381
|
+
| `null` | 用户取消,无副作用 |
|
|
382
|
+
| `CreateProjectInput`(`{ name, path, templateId?, extra? }`) | devtools 在本地拷贝/生成模板 → 改写 `project.config.json` → `provider.addProject(path)`;适合"只想换 UI 但物化由 devtools 兜底" |
|
|
383
|
+
| `{ ready: Project }` | devtools 跳过物化,只刷新列表并打开该项目;适合宿主后端已经远端创建好项目,本地完全无需落盘 |
|
|
384
|
+
|
|
385
|
+
物化失败(路径已存在/模板缺失/`provider.addProject` reject)会经 native dialog 弹出错误,再 reject 给渲染层;宿主端无需自己 toast。
|
|
386
|
+
|
|
387
|
+
### 内置模板
|
|
388
|
+
|
|
389
|
+
devtools 自带两个 `source`-style 模板,位于 `packages/devtools/templates/`:
|
|
390
|
+
|
|
391
|
+
- `blank` — 最小空白小程序骨架(pages/index + app.js/json/wxss + project.config.json,约 8 个文件)
|
|
392
|
+
- `taro-todo` — 复制自 `dimina/fe/example/taro-todo`,作为 Taro 编译产物的端到端演示工程
|
|
393
|
+
|
|
394
|
+
`builtinTemplates: 'none'` 排除全部内置;`builtinTemplates: ['taro-todo']` 仅保留指定 id;`projectTemplates` 同 id 注入会覆盖(例如上文 `qdmpBlank` 覆盖了内置 `blank`)。
|
|
395
|
+
|
|
396
|
+
### Provider 部分实现 / fallback 行为
|
|
397
|
+
|
|
398
|
+
`ProjectsProvider` 的多数方法是可选的;当宿主只实现 `listProjects` / `addProject` / `removeProject` 时:
|
|
399
|
+
|
|
400
|
+
- `validateProjectDir` 缺省 → 返回 `null`(不校验)
|
|
401
|
+
- `updateLastOpened` 缺省 → 静默 no-op,"最近"排序退化为 `listProjects` 返回顺序
|
|
402
|
+
- `getCompileConfig` 缺省 → 返回 `DEFAULT_COMPILE_CONFIG`(`{ startPage: '', scene: 1001, queryParams: [] }`)
|
|
403
|
+
- `saveCompileConfig` 缺省 → 静默 no-op,编译配置面板的编辑不会持久化
|
|
404
|
+
- `saveThumbnail` / `getThumbnail` 缺省 → save 静默 no-op,get 返回 `null`;项目卡缩略图不显示。实现这两个方法可让远端项目用云端缩略图(详见示例)
|
|
405
|
+
|
|
406
|
+
> 完整契约、参数语义和默认值见 `src/main/services/projects/types.ts` 的 JSDoc,那是 source of truth。
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
262
410
|
## CompilationAdapter
|
|
263
411
|
|
|
264
412
|
实现此接口接入自定义构建流程:
|
|
@@ -285,37 +433,63 @@ const myAdapter: CompilationAdapter = {
|
|
|
285
433
|
|
|
286
434
|
## Preload Instrumentation
|
|
287
435
|
|
|
288
|
-
模拟器 webview 注入 preload
|
|
436
|
+
模拟器 webview 注入 preload 脚本,在 webview 全局上安装两类东西:**桥接**(把数据通道暴露到 webview)+ **instrumentation**(监听运行时事件并写入桥接)。内置 preload 见 `src/preload/windows/simulator.ts`。
|
|
437
|
+
|
|
438
|
+
### 必装:桥接
|
|
439
|
+
|
|
440
|
+
| 函数 | 作用 | 不装会怎样 |
|
|
441
|
+
| --- | --- | --- |
|
|
442
|
+
| `installSimulatorBridge()` | 暴露 `window.__simulatorData`,承载 `highlightElement` / `unhighlightElement` / `getAppdata` / `getWxml` / `getStorageSnapshot` 等只读 API(供主进程 `executeJavaScript` 拉取) | 元素选区 overlay 不显示;automation `Page.getData` 返回空对象;MCP `simulator_get_overview` 在 hints 中追加 `simulator bridge not ready (window.__simulatorData missing)`。注:Storage 面板走主进程 CDP,不受影响;Console/AppData/WXML 推送走 `sendToHost`,也不受影响 |
|
|
443
|
+
| `installCustomApisBridge()` | 暴露 `window.__diminaCustomApis`,承载 `list` / `invoke`,让模拟器侧把主进程注册的 API 代理回小程序 runtime | `registerSimulatorApi` 注册的业务 API 在小程序里调用全部 no-op(参见下方 "Simulator 自定义 API") |
|
|
444
|
+
| `setupApiCompatHook()` | 兼容上游 API 名称变更 | 部分 API 调用兼容性问题 |
|
|
445
|
+
|
|
446
|
+
下游写自定义 preload 时,这三项原则上都要装。若不需要 `registerSimulatorApi`,`installCustomApisBridge` 可省略。
|
|
289
447
|
|
|
290
|
-
|
|
291
|
-
| ----------------------------------------- | ----------------------------------------------- |
|
|
292
|
-
| Console (`installConsoleInstrumentation`) | `console.*`、`window.onerror`、未捕获 rejection |
|
|
293
|
-
| Storage (`installStorageInstrumentation`) | `localStorage.setItem/removeItem`、全量快照 |
|
|
294
|
-
| AppData (`installAppDataInstrumentation`) | Worker `type='u'` 消息、setData 调用 |
|
|
295
|
-
| WXML (`installWxmlInstrumentation`) | Vue 组件树提取、MutationObserver 自动更新 |
|
|
448
|
+
### 按需:instrumentation
|
|
296
449
|
|
|
297
|
-
|
|
450
|
+
Console 是独立 instrumentation;AppData 与 WXML 已迁移到 **miniappSnapshot** 框架——各自实现一个 `MiniappSnapshotSource`,由 `MiniappSnapshotHost` 统一负责推送 / 拉取 / reload 重同步(详见 `docs/miniapp-snapshot.md`)。
|
|
451
|
+
|
|
452
|
+
| 探针 | 捕获内容 | 数据通道 |
|
|
453
|
+
| --- | --- | --- |
|
|
454
|
+
| `installConsoleInstrumentation()` | `console.*`、`window.onerror`、未捕获 rejection | `sendToHost` |
|
|
455
|
+
| `createAppDataSource()` | Worker `ub` 消息、setData / page init | miniappSnapshot 框架(`miniapp-snapshot:push`) |
|
|
456
|
+
| `createWxmlSource()` | Vue 组件树提取、MutationObserver 自动更新 | miniappSnapshot 框架(`miniapp-snapshot:push`) |
|
|
457
|
+
|
|
458
|
+
> Storage 面板的数据由主进程通过 CDP `DOMStorage` 域抓取(`src/main/services/simulator-storage`),**不需要 preload 侧 instrumentation**。
|
|
459
|
+
|
|
460
|
+
各面板的数据流详见下方 "数据流" 章节。
|
|
298
461
|
|
|
299
462
|
### 自定义 Preload
|
|
300
463
|
|
|
301
|
-
|
|
464
|
+
参考 `src/preload/windows/simulator.ts`:
|
|
302
465
|
|
|
303
466
|
```typescript
|
|
304
467
|
// my-preload.ts
|
|
305
468
|
import {
|
|
306
469
|
installSimulatorBridge,
|
|
470
|
+
installCustomApisBridge,
|
|
307
471
|
installConsoleInstrumentation,
|
|
308
|
-
|
|
472
|
+
createMiniappSnapshotHost,
|
|
473
|
+
createAppDataSource,
|
|
474
|
+
createWxmlSource,
|
|
309
475
|
setupApiCompatHook,
|
|
310
476
|
} from '@dimina-kit/devtools/preload'
|
|
311
|
-
// 不需要 WXML/AppData,不导入
|
|
312
477
|
|
|
478
|
+
// 1. 兼容 hook + 桥接(必装,且应在 instrumentation 之前)
|
|
313
479
|
setupApiCompatHook()
|
|
314
480
|
installSimulatorBridge()
|
|
481
|
+
installCustomApisBridge() // 若用到 registerSimulatorApi,必装
|
|
482
|
+
|
|
483
|
+
// 2. Console instrumentation(按需)
|
|
315
484
|
installConsoleInstrumentation()
|
|
316
|
-
installStorageInstrumentation()
|
|
317
485
|
|
|
318
|
-
//
|
|
486
|
+
// 3. miniappSnapshot 框架:注册面板数据源后 install()
|
|
487
|
+
const snapshotHost = createMiniappSnapshotHost()
|
|
488
|
+
snapshotHost.register(createAppDataSource())
|
|
489
|
+
snapshotHost.register(createWxmlSource())
|
|
490
|
+
snapshotHost.install()
|
|
491
|
+
|
|
492
|
+
// 4. 自定义 hook
|
|
319
493
|
window.addEventListener('error', (e) => {
|
|
320
494
|
console.error('[my-preload]', e.message)
|
|
321
495
|
})
|
|
@@ -329,49 +503,94 @@ launch({ preloadPath: '/absolute/path/to/my-preload.js' })
|
|
|
329
503
|
|
|
330
504
|
---
|
|
331
505
|
|
|
506
|
+
## Simulator 自定义 API
|
|
507
|
+
|
|
508
|
+
下游可以通过 `registerSimulatorApi` 把业务 API 注入到模拟器内运行的小程序。Handler 在 Electron **主进程**执行,能用任何 Node 能力(fs、net、原生模块、持久状态);模拟器侧拿到 `wx.<name>(params)` 调用后通过 IPC 转发到主进程,await 返回结果,handler 抛错则原型回传给小程序。
|
|
509
|
+
|
|
510
|
+
> ⚠️ 使用本功能要求模拟器 preload 调用 `installCustomApisBridge()`(详见上方 "Preload Instrumentation")。内置 preload 已包含此调用;若你用了自定义 preload 又忘记调用,注册的 API 在小程序运行时**没有任何反应**,且不会报错。
|
|
511
|
+
|
|
512
|
+
### 命名约定
|
|
513
|
+
|
|
514
|
+
`name` 是 dimina service 层 `invokeAPI(name, opts)` 用的**裸名**,不带 `wx.` 前缀。注册之后小程序里通过 `wx.<name>(...)`(以及你在 `apiNamespaces` 配的其它命名空间)调用都会命中:
|
|
515
|
+
|
|
516
|
+
| 小程序里写 | `registerSimulatorApi` 的 name |
|
|
517
|
+
| --- | --- |
|
|
518
|
+
| `wx.login(...)` | `'login'` |
|
|
519
|
+
| `wx.request(...)` | `'request'` |
|
|
520
|
+
| `wx.getStorage(...)` 覆盖内置 | `'getStorage'`(小心:这会**屏蔽** dimina 容器的实现) |
|
|
521
|
+
|
|
522
|
+
```typescript
|
|
523
|
+
import { registerSimulatorApi } from '@dimina-kit/devtools/simulator-apis'
|
|
524
|
+
|
|
525
|
+
// 提供 wx.login 的实现(dimina 容器默认未实现,注册后才能用)
|
|
526
|
+
const dispose = registerSimulatorApi('login', async ({ success }) => {
|
|
527
|
+
// 主进程上下文:可调用内部 HTTP、读取凭证文件、访问原生模块
|
|
528
|
+
const code = await callInternalAuth()
|
|
529
|
+
return { code }
|
|
530
|
+
})
|
|
531
|
+
|
|
532
|
+
// 不再需要时取消注册(不传也行,进程退出会一起清理)
|
|
533
|
+
dispose()
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### 行为约定
|
|
537
|
+
|
|
538
|
+
- **命中顺序**:小程序运行时按 `apiRegistry[name] → MiniApp 实例方法 → 扩展模块兜底` 查找,所以 `registerSimulatorApi` 注册的 name **优先于内置实现**——既能给"未实现"的 wx.* 补功能(如 `wx.login`),也能覆盖默认的 wx.* 行为(如 `wx.request`,dimina-kit 本身就在用这条路把 `request` 接到主进程 fetch)。
|
|
539
|
+
- 同名重复注册:后注册的覆盖前者,静默替换。
|
|
540
|
+
- `dispose()` 只会移除自己创建的那次注册——如果之后被别人覆盖了,旧的 disposer 是 no-op。
|
|
541
|
+
- 调用未注册且容器内也没有的 name:小程序侧拿到 reject,错误信息里带 name。
|
|
542
|
+
- Handler 可同步或异步返回;**返回值需可 JSON 序列化**(IPC 限制)。函数、Symbol、Map/Set、循环引用都会丢失。
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
332
546
|
## 模块导出一览
|
|
333
547
|
|
|
548
|
+
### Stable public exports
|
|
549
|
+
|
|
550
|
+
`@dimina-kit/devtools` 的稳定入口,签名遵循 semver;新版本不会做破坏性改动(除非 major bump)。
|
|
551
|
+
|
|
334
552
|
```
|
|
335
553
|
@dimina-kit/devtools launch, createWorkbenchApp, buildDefaultMenu,
|
|
336
554
|
openSettingsWindow, suppressEpipe, setupCdpPort,
|
|
337
|
-
createWorkbenchContext, createMainWindow,
|
|
338
|
-
|
|
555
|
+
createWorkbenchContext, createMainWindow,
|
|
556
|
+
createViewManager, register*Ipc,
|
|
557
|
+
registerSimulatorApi,
|
|
558
|
+
setHeaderHeight, UpdateManager,
|
|
559
|
+
createGitHubReleaseChecker, ...
|
|
560
|
+
(api.ts 聚合了所有公共 API;优先从根入口导入)
|
|
339
561
|
@dimina-kit/devtools/launch launch(config?), buildDefaultMenu, openSettingsWindow
|
|
340
562
|
@dimina-kit/devtools/app createWorkbenchApp(config?)
|
|
341
563
|
@dimina-kit/devtools/types TypeScript 类型定义
|
|
564
|
+
@dimina-kit/devtools/bootstrap suppressEpipe(), setupCdpPort()
|
|
565
|
+
@dimina-kit/devtools/paths rendererDir, defaultPreloadPath, simulatorDir,
|
|
566
|
+
getRendererDir, getPreloadDir, getRendererHtml
|
|
567
|
+
@dimina-kit/devtools/simulator-apis registerSimulatorApi(name, handler) →
|
|
568
|
+
注入由主进程托管的小程序 API(详见上方"Simulator 自定义 API")
|
|
569
|
+
@dimina-kit/devtools/preload installSimulatorBridge,
|
|
570
|
+
installCustomApisBridge,
|
|
571
|
+
installConsoleInstrumentation,
|
|
572
|
+
createMiniappSnapshotHost,
|
|
573
|
+
createAppDataSource, createWxmlSource,
|
|
574
|
+
setupApiCompatHook
|
|
575
|
+
(storage 面板数据由主进程 CDP 抓取,无 preload 侧 hook)
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### Experimental exports (v0.x — signatures may change in minor versions)
|
|
579
|
+
|
|
580
|
+
下列子路径主要用于"模块组装"等深度定制场景。在 0.x 阶段,函数签名和模块边界可能在 minor 版本之间调整;如果你不需要逐模块组装,请优先使用上方的 stable 入口或根 barrel。
|
|
581
|
+
|
|
582
|
+
```
|
|
342
583
|
@dimina-kit/devtools/context createWorkbenchContext(opts),
|
|
343
584
|
hasBuiltinPanel(ctx, panelId), getDefaultTab(ctx)
|
|
344
585
|
@dimina-kit/devtools/create-window createMainWindow(opts)
|
|
345
|
-
@dimina-kit/devtools/view-manager createViewManager(ctx) → ViewManager
|
|
346
|
-
(attachSimulator, detachSimulator, showSimulator,
|
|
347
|
-
hideSimulator, showSettings, hideSettings,
|
|
348
|
-
showPopover, hidePopover, resize,
|
|
349
|
-
setVisible, repositionAll, disposeAll)
|
|
350
|
-
@dimina-kit/devtools/layout computeRightPanelBounds, computeSimulatorBounds,
|
|
351
|
-
computeSettingsBounds, computePopoverBounds,
|
|
352
|
-
setHeaderHeight, getRightX,
|
|
353
|
-
HEADER_H, SPLITTER_W, SETTINGS_W
|
|
354
|
-
@dimina-kit/devtools/projects listProjects, addProject, removeProject,
|
|
355
|
-
getCompileConfig, saveCompileConfig,
|
|
356
|
-
updateLastOpened
|
|
357
|
-
@dimina-kit/devtools/paths rendererDir, defaultPreloadPath,
|
|
358
|
-
getRendererDir, getPreloadDir, getRendererHtml
|
|
359
586
|
@dimina-kit/devtools/ipc-simulator registerSimulatorIpc(ctx)
|
|
360
587
|
@dimina-kit/devtools/ipc-panels registerPanelsIpc(ctx)
|
|
361
588
|
@dimina-kit/devtools/ipc-toolbar registerToolbarIpc(ctx)
|
|
362
589
|
@dimina-kit/devtools/ipc-popover registerPopoverIpc(ctx)
|
|
363
590
|
@dimina-kit/devtools/ipc-settings registerSettingsIpc(ctx)
|
|
364
591
|
@dimina-kit/devtools/ipc-projects registerProjectsIpc(ctx)
|
|
365
|
-
@dimina-kit/devtools/ipc-session registerSessionIpc(ctx),
|
|
366
|
-
@dimina-kit/devtools/bootstrap suppressEpipe(), setupCdpPort()
|
|
592
|
+
@dimina-kit/devtools/ipc-session registerSessionIpc(ctx), sessionModule
|
|
367
593
|
@dimina-kit/devtools/workbench-settings loadWorkbenchSettings(), saveWorkbenchSettings(), applyTheme()
|
|
368
|
-
@dimina-kit/devtools/preload installConsoleInstrumentation,
|
|
369
|
-
installStorageInstrumentation,
|
|
370
|
-
installAppDataInstrumentation, sendAllAppData,
|
|
371
|
-
installWxmlInstrumentation, sendWxmlTree,
|
|
372
|
-
setupWxmlObserver, installSimulatorBridge,
|
|
373
|
-
setupApiCompatHook
|
|
374
|
-
@dimina-kit/devtools/simulator-dir simulatorDir
|
|
375
594
|
```
|
|
376
595
|
|
|
377
596
|
---
|
|
@@ -382,7 +601,6 @@ launch({ preloadPath: '/absolute/path/to/my-preload.js' })
|
|
|
382
601
|
|
|
383
602
|
```typescript
|
|
384
603
|
interface WorkbenchContext {
|
|
385
|
-
mainWindow: BrowserWindow
|
|
386
604
|
adapter: CompilationAdapter
|
|
387
605
|
preloadPath: string
|
|
388
606
|
rendererDir: string
|
|
@@ -391,24 +609,24 @@ interface WorkbenchContext {
|
|
|
391
609
|
appName: string
|
|
392
610
|
toolbarActions?: () => Promise<ToolbarAction[]> | ToolbarAction[]
|
|
393
611
|
brandingProvider?: () => Promise<{ appName: string }> | { appName: string }
|
|
394
|
-
workbenchSettingsWindow: BrowserWindow | null
|
|
395
612
|
|
|
396
613
|
// ── Services(运行时状态封装在内部,通过方法访问)──
|
|
614
|
+
windows: WindowService // ctx.windows.mainWindow, ctx.windows.settingsWindow, ...
|
|
397
615
|
views: ViewManager // ctx.views.repositionAll(), ctx.views.getSimulatorWebContentsId(), ...
|
|
398
616
|
notify: RendererNotifier // ctx.notify.projectStatus(), ctx.notify.windowNavigateBack(), ...
|
|
399
617
|
workspace: WorkspaceService // ctx.workspace.getProjectPath(), ctx.workspace.hasActiveSession(), ...
|
|
618
|
+
|
|
619
|
+
// ── Internal lifecycle / security (host 不直接消费) ──
|
|
620
|
+
registry: DisposableRegistry // 框架在创建时统一聚合 dispose
|
|
621
|
+
senderPolicy: SenderPolicy // IpcRegistry 自动校验 sender 白名单
|
|
400
622
|
}
|
|
401
623
|
```
|
|
402
624
|
|
|
403
|
-
|
|
625
|
+
会话和视图状态封装在对应 service 的私有闭包中,通过方法访问,例如:
|
|
404
626
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
| `ctx.currentSession` | `ctx.workspace.getSession()` / `ctx.workspace.hasActiveSession()` |
|
|
409
|
-
| `ctx.simulatorWebContentsId` | `ctx.views.getSimulatorWebContentsId()` |
|
|
410
|
-
| `ctx.devToolsViewAdded` | `ctx.views.isSimulatorAdded()` |
|
|
411
|
-
| `ctx.lastSimWidth` | `ctx.views.getLastSimWidth()` |
|
|
627
|
+
- `ctx.workspace.getProjectPath()` / `ctx.workspace.getSession()` / `ctx.workspace.hasActiveSession()`
|
|
628
|
+
- `ctx.views.getSimulatorWebContentsId()` / `ctx.views.isSimulatorAdded()` / `ctx.views.getLastSimWidth()`
|
|
629
|
+
- `ctx.windows.mainWindow` / `ctx.windows.settingsWindow`
|
|
412
630
|
|
|
413
631
|
---
|
|
414
632
|
|
|
@@ -438,76 +656,22 @@ flowchart TB
|
|
|
438
656
|
|
|
439
657
|
### 数据流
|
|
440
658
|
|
|
441
|
-
|
|
659
|
+
按面板 / 场景拆分:
|
|
442
660
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
participant M as main<br/>ipc/panels.ts
|
|
450
|
-
participant P as preload<br/>instrumentation
|
|
451
|
-
|
|
452
|
-
User->>UI: 打开面板 / 刷新
|
|
453
|
-
UI->>R: invokeMain('panel:eval', expression)
|
|
454
|
-
R->>M: IPC: panel:eval
|
|
455
|
-
M->>P: webContents.executeJavaScript(expression)
|
|
456
|
-
Note over P: window 上已挂好取值函数
|
|
457
|
-
P-->>M: 结构化数据
|
|
458
|
-
M-->>R: 返回结果
|
|
459
|
-
R-->>UI: 渲染
|
|
460
|
-
```
|
|
661
|
+
| 面板 / 场景 | 模式 | 路径 |
|
|
662
|
+
| --- | --- | --- |
|
|
663
|
+
| Console | 推送 | `installConsoleInstrumentation` 经 `runtime/host.ts:sendToHost` → webview `ipcRenderer.sendToHost` 推到宿主 → renderer 监听 `ipc-message` |
|
|
664
|
+
| AppData / WXML 树 | 推送 + 拉取 | **miniappSnapshot 框架**:preload `MiniappSnapshotHost` 经 `miniapp-snapshot:push` 推全量快照,renderer `useMiniappSnapshot` 整份投影;面板「刷新」走 `miniapp-snapshot:pull`(详见 `docs/miniapp-snapshot.md`) |
|
|
665
|
+
| Storage | 拉取 + 推送 | renderer `ipcInvoke(SimulatorStorageChannel.GetSnapshot)` → 主进程 CDP `DOMStorage` 域;变更事件由主进程通过 `SimulatorStorageChannel.Event` 推回 renderer |
|
|
666
|
+
| 元素选区 / `Page.getData` / MCP overview | 拉取 | 主进程 `webContents.executeJavaScript(...)` 或 `Runtime.evaluate(...)` 读 `window.__simulatorData.*`(由 `installSimulatorBridge` 暴露);面板快照亦可经 `window.__miniappSnapshot.get(id)` 同步读取(由 `MiniappSnapshotHost` 暴露) |
|
|
461
667
|
|
|
462
|
-
|
|
668
|
+
> `src/main/ipc/panels.ts` 暴露 `panel:eval` handler 供外部 host 自定义面板复用,内置 renderer 不消费它。
|
|
463
669
|
|
|
464
670
|
---
|
|
465
671
|
|
|
466
672
|
## IPC 通信总览
|
|
467
673
|
|
|
468
|
-
|
|
469
|
-
| --------------------------------- | ----- | ---------------------------------------------- |
|
|
470
|
-
| `projects:list` | R→M | 获取项目列表 |
|
|
471
|
-
| `projects:add` | R→M | 添加项目 |
|
|
472
|
-
| `projects:remove` | R→M | 删除项目 |
|
|
473
|
-
| `dialog:openDirectory` | R→M | 打开目录选择对话框 |
|
|
474
|
-
| `project:open` | R→M | 编译并启动项目 |
|
|
475
|
-
| `project:close` | R→M | 停止编译,清理 View |
|
|
476
|
-
| `project:status` | M→R | 编译状态推送 |
|
|
477
|
-
| `project:getPages` | R→M | 读取 app.json pages |
|
|
478
|
-
| `project:getCompileConfig` | R→M | 读取编译配置 |
|
|
479
|
-
| `project:saveCompileConfig` | R→M | 保存编译配置 |
|
|
480
|
-
| `app:getPreloadPath` | R→M | 获取 preload 脚本路径 |
|
|
481
|
-
| `app:getBranding` | R→M | 读取品牌信息(`brandingProvider`) |
|
|
482
|
-
| `toolbar:getActions` | R→M | 读取自定义工具栏按钮 |
|
|
483
|
-
| `workbench:getPanelConfig` | R→M | 获取 panels 配置 |
|
|
484
|
-
| `workbench:getApiNamespaces` | R→M | 获取自定义 API namespaces |
|
|
485
|
-
| `simulator:attach` | R→M | 绑定 simulator webContents,创建 simulatorView |
|
|
486
|
-
| `simulator:detach` | R→M | 销毁所有 View |
|
|
487
|
-
| `simulator:resize` | R→M | 更新 View 位置(分割线拖动) |
|
|
488
|
-
| `simulator:setVisible` | R→M | 显示/隐藏 simulator 面板 |
|
|
489
|
-
| `workbench:reset` | R→M | 通知主窗口重置面板状态 |
|
|
490
|
-
| `panel:list` | R→M | 获取启用的内置面板列表 |
|
|
491
|
-
| `panel:eval` | R→M | 在 simulator webContents 执行 JS 并返回结果 |
|
|
492
|
-
| `panel:select` | R→M | 切换到指定内置面板 |
|
|
493
|
-
| `panel:selectSimulator` | R→M | 切换到 simulator tab |
|
|
494
|
-
| `popover:show` | R→M | 创建弹窗 |
|
|
495
|
-
| `popover:hide` | R→M | 销毁弹窗 |
|
|
496
|
-
| `popover:init` | M→P | 初始化弹窗数据 |
|
|
497
|
-
| `popover:relaunch` | P→M→R | 重新编译 |
|
|
498
|
-
| `popover:closed` | M→R | 弹窗关闭通知 |
|
|
499
|
-
| `settings:setVisible` | R→M | 显示/隐藏设置视图 |
|
|
500
|
-
| `settings:init` | M→P | 初始化设置面板 |
|
|
501
|
-
| `settings:configChanged` | P→M→R | 编译配置变更通知 |
|
|
502
|
-
| `settings:projectSettingsChanged` | P→M | 项目级设置(如 sourcemap)落盘 |
|
|
503
|
-
| `settings:closed` | M→R | 设置面板关闭通知 |
|
|
504
|
-
| `workbenchSettings:get` | R→M | 读取用户级 workbench 设置 |
|
|
505
|
-
| `workbenchSettings:save` | R→M | 保存 workbench 设置并应用主题 |
|
|
506
|
-
| `workbenchSettings:setTheme` | R→M | 仅切换主题 |
|
|
507
|
-
| `workbenchSettings:getCdpStatus` | R→M | 读取当前 CDP 端口状态 |
|
|
508
|
-
| `workbenchSettings:setVisible` | R→M | 打开/关闭独立设置窗口 |
|
|
509
|
-
|
|
510
|
-
R=渲染进程,M=主进程,P=子 WebContentsView
|
|
674
|
+
IPC 频道名常量集中定义在 `src/shared/ipc-channels.ts`,按域分组(`SimulatorChannel` / `ProjectChannel` / `PanelChannel` / `WorkbenchSettingsChannel` 等)。该文件是频道清单的唯一真相源;此处不再维护手抄表,以免与代码漂移。
|
|
511
675
|
|
|
512
676
|
---
|
|
513
677
|
|
|
@@ -545,18 +709,18 @@ pnpm test # 运行测试
|
|
|
545
709
|
|
|
546
710
|
## 安全说明
|
|
547
711
|
|
|
548
|
-
|
|
549
|
-
- 为方便开发调试,BrowserWindow 启用了 `nodeIntegration` 并禁用了 `contextIsolation`,这在生产环境中存在安全风险
|
|
550
|
-
- 仅在受信任的本地开发环境中使用本工具
|
|
551
|
-
- 不要在 devtools 窗口中加载不受信任的远程内容
|
|
552
|
-
- 如需在非本地环境使用,请自行评估并加固安全配置
|
|
712
|
+
本工具仅用于本地开发调试。当前的安全配置:
|
|
553
713
|
|
|
554
|
-
|
|
714
|
+
- **Workbench 窗口**(main / settings / popover overlay)均启用 `contextIsolation` 并禁用 `nodeIntegration`;renderer 通过 main preload 经 `contextBridge` 拿到 `window.devtools.ipc`,每个 IPC handler 经 sender whitelist 校验调用方
|
|
715
|
+
- **Simulator 加载的小程序代码** 运行在独立 `<webview>` 中(`partition='persist:simulator'`、`nodeIntegration=false`),preload 由 `session.registerPreloadScript` 在 session 层固定,渲染进程无法替换
|
|
716
|
+
- **renderer 入口** 启用了保守 CSP;`will-navigate` / `setWindowOpenHandler` 屏蔽外部跳转
|
|
555
717
|
|
|
556
|
-
|
|
718
|
+
仍然不要在 devtools 窗口中加载不受信任的远程内容;本工具不打算在非本地环境部署。
|
|
719
|
+
|
|
720
|
+
### MCP Server 风险
|
|
557
721
|
|
|
558
|
-
|
|
722
|
+
内置的 MCP server 默认关闭,由 `startMcpServer` 入口显式启动,或通过 workbench 设置中的 `mcp.enabled` 开启。开启后会在本机监听 SSE 端点,向任何可以连接到该端点的 MCP 客户端暴露一组工具,能力包括:读取 DOM 结构、截屏、拉取网络日志、触发导航等。
|
|
559
723
|
|
|
560
|
-
|
|
724
|
+
`workbench_evaluate` 已从 MCP 工具集中移除,workbench 只暴露只读诊断工具(截屏、console 日志、DOM、网络日志等)。`simulator_evaluate` 仍然保留,但 simulator 使用 `<webview>`、`nodeIntegration=false`,其 `evaluate` 仅在页面 JS 上下文执行,不具备 Node API 访问能力。
|
|
561
725
|
|
|
562
|
-
|
|
726
|
+
仅在连接到可信的本机 MCP 客户端或被信任的 AI 工具时启用该功能;不要在公共 WiFi、共享机器或存在远程 SSH 端口转发的场景下开启,以免监听端口被非预期的客户端访问。
|
package/dist/main/api.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ export type { WorkbenchContext, CreateContextOptions } from './services/workbenc
|
|
|
7
7
|
export { createMainWindow } from './windows/main-window/index.js';
|
|
8
8
|
export { createViewManager } from './services/views/view-manager.js';
|
|
9
9
|
export type { ViewManager } from './services/views/view-manager.js';
|
|
10
|
+
export type { WorkspaceService } from './services/workspace/workspace-service.js';
|
|
11
|
+
export type { Project, ProjectPages, ProjectSettings } from './services/projects/project-repository.js';
|
|
12
|
+
export { registerSimulatorApi } from './simulator-apis.js';
|
|
13
|
+
export type { SimulatorApiHandler } from './simulator-apis.js';
|
|
10
14
|
export { registerAppIpc } from './ipc/app.js';
|
|
11
15
|
export { registerSimulatorIpc } from './ipc/simulator.js';
|
|
12
16
|
export { registerPanelsIpc } from './ipc/panels.js';
|
|
@@ -15,8 +19,8 @@ export { registerSettingsIpc } from './ipc/settings.js';
|
|
|
15
19
|
export { registerProjectsIpc } from './ipc/projects.js';
|
|
16
20
|
export { registerSessionIpc } from './ipc/session.js';
|
|
17
21
|
export { registerToolbarIpc } from './ipc/toolbar.js';
|
|
18
|
-
export { rendererDir, defaultPreloadPath, getRendererDir, getPreloadDir, getRendererHtml } from './utils/paths.js';
|
|
19
|
-
export {
|
|
22
|
+
export { rendererDir, defaultPreloadPath, simulatorDir, getRendererDir, getPreloadDir, getRendererHtml, } from './utils/paths.js';
|
|
23
|
+
export { setHeaderHeight } from './services/layout/index.js';
|
|
20
24
|
export { UpdateManager, createGitHubReleaseChecker } from './services/update/index.js';
|
|
21
25
|
export type { UpdateManagerOptions, GitHubReleaseCheckerOptions, PickAssetContext, VersionScheme, } from './services/update/index.js';
|
|
22
26
|
export type { WorkbenchConfig, WorkbenchAppConfig, CompilationAdapter, ProjectSession, ToolbarAction, BuiltinPanelId, BuiltinModuleId, UpdateChecker, UpdateInfo, } from '../shared/types.js';
|