@dimina-kit/devtools 0.3.2-dev.20260601115343 → 0.3.2-dev.20260610082053

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/README.md +49 -59
  2. package/dist/main/api.d.ts +1 -2
  3. package/dist/main/api.js +5 -1
  4. package/dist/main/app/app.d.ts +15 -5
  5. package/dist/main/app/app.js +242 -122
  6. package/dist/main/app/bootstrap.d.ts +16 -0
  7. package/dist/main/app/bootstrap.js +20 -0
  8. package/dist/main/app/launch.d.ts +8 -4
  9. package/dist/main/app/launch.js +9 -4
  10. package/dist/main/index.bundle.js +5812 -1729
  11. package/dist/main/index.js +9 -1
  12. package/dist/main/ipc/app.d.ts +1 -1
  13. package/dist/main/ipc/bridge-router.d.ts +61 -0
  14. package/dist/main/ipc/bridge-router.js +1300 -0
  15. package/dist/main/ipc/panels.d.ts +1 -1
  16. package/dist/main/ipc/panels.js +6 -2
  17. package/dist/main/ipc/popover.d.ts +1 -1
  18. package/dist/main/ipc/project-fs.d.ts +1 -1
  19. package/dist/main/ipc/projects.d.ts +1 -1
  20. package/dist/main/ipc/session.d.ts +1 -1
  21. package/dist/main/ipc/settings.d.ts +1 -1
  22. package/dist/main/ipc/simulator-module.d.ts +6 -0
  23. package/dist/main/ipc/simulator-module.js +9 -1
  24. package/dist/main/ipc/simulator.d.ts +2 -2
  25. package/dist/main/ipc/simulator.js +49 -5
  26. package/dist/main/ipc/toolbar.d.ts +1 -1
  27. package/dist/main/ipc/views.d.ts +1 -1
  28. package/dist/main/ipc/views.js +40 -2
  29. package/dist/main/runtime/devtools-backend.d.ts +17 -0
  30. package/dist/main/runtime/devtools-backend.js +49 -0
  31. package/dist/main/runtime/miniapp-runtime.d.ts +39 -0
  32. package/dist/main/runtime/miniapp-runtime.js +17 -0
  33. package/dist/main/services/automation/exec.d.ts +27 -2
  34. package/dist/main/services/automation/exec.js +37 -3
  35. package/dist/main/services/automation/handlers/app.js +127 -11
  36. package/dist/main/services/automation/handlers/page.js +36 -19
  37. package/dist/main/services/automation/index.js +40 -13
  38. package/dist/main/services/automation/wait-active-page.d.ts +56 -0
  39. package/dist/main/services/automation/wait-active-page.js +71 -0
  40. package/dist/main/services/console-forward/index.d.ts +36 -0
  41. package/dist/main/services/console-forward/index.js +81 -0
  42. package/dist/main/services/dimina-resource-server.d.ts +7 -0
  43. package/dist/main/services/dimina-resource-server.js +99 -0
  44. package/dist/main/services/elements-forward/index.d.ts +66 -0
  45. package/dist/main/services/elements-forward/index.js +583 -0
  46. package/dist/main/services/layout/index.d.ts +22 -0
  47. package/dist/main/services/layout/index.js +25 -0
  48. package/dist/main/services/mcp/index.d.ts +1 -0
  49. package/dist/main/services/mcp/index.js +3 -0
  50. package/dist/main/services/mcp/server.d.ts +1 -1
  51. package/dist/main/services/mcp/server.js +1 -1
  52. package/dist/main/services/mcp/target-manager.d.ts +35 -0
  53. package/dist/main/services/mcp/target-manager.js +63 -1
  54. package/dist/main/services/mcp/tools/context-tools.js +15 -1
  55. package/dist/main/services/module.d.ts +1 -1
  56. package/dist/main/services/network-forward/index.d.ts +190 -0
  57. package/dist/main/services/network-forward/index.js +765 -0
  58. package/dist/main/services/notifications/renderer-notifier.d.ts +11 -0
  59. package/dist/main/services/notifications/renderer-notifier.js +7 -1
  60. package/dist/main/services/render-inspect/index.d.ts +41 -0
  61. package/dist/main/services/render-inspect/index.js +88 -0
  62. package/dist/main/services/safe-area/index.d.ts +17 -0
  63. package/dist/main/services/safe-area/index.js +59 -0
  64. package/dist/main/services/service-host-pool/pool.d.ts +197 -0
  65. package/dist/main/services/service-host-pool/pool.js +364 -0
  66. package/dist/main/services/simulator/custom-apis.d.ts +34 -0
  67. package/dist/main/services/simulator/custom-apis.js +22 -0
  68. package/dist/main/services/simulator-appdata/index.d.ts +35 -0
  69. package/dist/main/services/simulator-appdata/index.js +71 -0
  70. package/dist/main/services/simulator-current-page/index.d.ts +24 -0
  71. package/dist/main/services/simulator-current-page/index.js +19 -0
  72. package/dist/main/services/simulator-storage/index.d.ts +37 -2
  73. package/dist/main/services/simulator-storage/index.js +209 -32
  74. package/dist/main/services/simulator-storage/service-storage-ops.d.ts +40 -0
  75. package/dist/main/services/simulator-storage/service-storage-ops.js +67 -0
  76. package/dist/main/services/simulator-temp-files/index.d.ts +1 -1
  77. package/dist/main/services/simulator-temp-files/index.js +1 -1
  78. package/dist/main/services/simulator-wxml/index.d.ts +29 -0
  79. package/dist/main/services/simulator-wxml/index.js +28 -0
  80. package/dist/main/services/toolbar/toolbar-store.d.ts +3 -3
  81. package/dist/main/services/toolbar/toolbar-store.js +1 -18
  82. package/dist/main/services/views/devtools-tabs.d.ts +47 -0
  83. package/dist/main/services/views/devtools-tabs.js +95 -0
  84. package/dist/main/services/views/view-manager.d.ts +125 -0
  85. package/dist/main/services/views/view-manager.js +839 -4
  86. package/dist/main/services/workbench-context.d.ts +67 -7
  87. package/dist/main/services/workbench-context.js +6 -1
  88. package/dist/main/services/workspace/workspace-service.js +7 -13
  89. package/dist/main/utils/ipc-registry.d.ts +1 -1
  90. package/dist/main/utils/ipc-registry.js +21 -4
  91. package/dist/main/utils/paths.d.ts +15 -0
  92. package/dist/main/utils/paths.js +19 -0
  93. package/dist/main/utils/sender-policy.d.ts +9 -3
  94. package/dist/main/utils/sender-policy.js +18 -4
  95. package/dist/main/utils/theme.d.ts +1 -1
  96. package/dist/main/utils/theme.js +1 -1
  97. package/dist/main/windows/main-window/create.d.ts +0 -6
  98. package/dist/main/windows/main-window/create.js +11 -59
  99. package/dist/main/windows/main-window/events.d.ts +1 -1
  100. package/dist/main/windows/main-window/events.js +1 -1
  101. package/dist/main/windows/service-host-window/create.d.ts +52 -0
  102. package/dist/main/windows/service-host-window/create.js +112 -0
  103. package/dist/native-host/common/common.js +368 -0
  104. package/dist/native-host/container/pageFrame.css +1 -0
  105. package/dist/native-host/render/render.js +9334 -0
  106. package/dist/native-host/service/service.js +6 -0
  107. package/dist/preload/index.d.ts +2 -0
  108. package/dist/preload/index.js +6 -0
  109. package/dist/preload/instrumentation/app-data.d.ts +18 -20
  110. package/dist/preload/instrumentation/app-data.js +23 -160
  111. package/dist/preload/instrumentation/wxml-extract.d.ts +1 -1
  112. package/dist/preload/instrumentation/wxml-extract.js +1 -1
  113. package/dist/preload/runtime/bridge.d.ts +3 -8
  114. package/dist/preload/runtime/bridge.js +2 -32
  115. package/dist/preload/runtime/custom-apis.js +20 -17
  116. package/dist/preload/runtime/host-toolbar-advertiser.d.ts +27 -0
  117. package/dist/preload/runtime/host-toolbar-advertiser.js +55 -0
  118. package/dist/preload/runtime/main-api-runner.d.ts +9 -0
  119. package/dist/preload/runtime/main-api-runner.js +85 -0
  120. package/dist/preload/runtime/native-host.d.ts +43 -0
  121. package/dist/preload/runtime/native-host.js +83 -0
  122. package/dist/preload/shared/expose.d.ts +10 -5
  123. package/dist/preload/shared/expose.js +30 -12
  124. package/dist/preload/shared/sid-registry.d.ts +11 -0
  125. package/dist/preload/shared/sid-registry.js +38 -0
  126. package/dist/preload/windows/host-toolbar.cjs +161 -0
  127. package/dist/preload/windows/host-toolbar.cjs.map +7 -0
  128. package/dist/preload/windows/host-toolbar.d.ts +2 -0
  129. package/dist/preload/windows/host-toolbar.js +12 -0
  130. package/dist/preload/windows/main.cjs +1935 -0
  131. package/dist/preload/windows/main.cjs.map +4 -4
  132. package/dist/preload/windows/simulator.cjs +925 -0
  133. package/dist/preload/windows/simulator.cjs.map +7 -0
  134. package/dist/preload/windows/simulator.js +244 -574
  135. package/dist/render-host/pageFrame.html +29 -0
  136. package/dist/render-host/preload.cjs +154 -0
  137. package/dist/render-host/render-inspect.js +295 -0
  138. package/dist/renderer/assets/index-CcJKzatF.js +50 -0
  139. package/dist/renderer/assets/{input-CCYS8Ave.js → input-QGx6FFX1.js} +2 -2
  140. package/dist/renderer/assets/ipc-transport-BT4QYQqu.css +1 -0
  141. package/dist/renderer/assets/{ipc-transport-Bn4KXvhu.js → ipc-transport-DvZvwK-Z.js} +2 -2
  142. package/dist/renderer/assets/{popover-CH4rwpdt.js → popover-BOH1If1J.js} +2 -2
  143. package/dist/renderer/assets/select-C7JQ8G5N.js +2 -0
  144. package/dist/renderer/assets/{settings-CMTB-t0x.js → settings-DpAbTJyF.js} +2 -2
  145. package/dist/renderer/assets/{settings-api-Csdngf9Z.js → settings-api-RD2IZF53.js} +2 -2
  146. package/dist/renderer/assets/{workbenchSettings-CODFCzOg.js → workbenchSettings-CNJX4Qna.js} +2 -2
  147. package/dist/renderer/entries/main/index.html +5 -5
  148. package/dist/renderer/entries/popover/index.html +5 -5
  149. package/dist/renderer/entries/settings/index.html +5 -5
  150. package/dist/renderer/entries/workbench-settings/index.html +4 -4
  151. package/dist/service-host/preload.cjs +254 -0
  152. package/dist/service-host/service.html +10 -0
  153. package/dist/service-host/sourcemap-rewrite.cjs +58 -0
  154. package/dist/service-host/sync-api-patch.js +20 -0
  155. package/dist/service-host/sync-impls/menu-button.js +16 -0
  156. package/dist/service-host/sync-impls/storage.js +50 -0
  157. package/dist/service-host/sync-impls/system-info.js +54 -0
  158. package/dist/shared/appdata-accumulator.d.ts +95 -0
  159. package/dist/shared/appdata-accumulator.js +213 -0
  160. package/dist/shared/bridge-channels.d.ts +364 -0
  161. package/dist/shared/bridge-channels.js +54 -0
  162. package/dist/shared/ipc-channels.d.ts +84 -1
  163. package/dist/shared/ipc-channels.js +90 -10
  164. package/dist/shared/ipc-schemas.d.ts +59 -2
  165. package/dist/shared/ipc-schemas.js +64 -3
  166. package/dist/shared/open-in-editor.d.ts +71 -0
  167. package/dist/shared/open-in-editor.js +138 -0
  168. package/dist/shared/simulator-api-metadata.d.ts +21 -0
  169. package/dist/shared/simulator-api-metadata.js +23 -0
  170. package/dist/shared/types.d.ts +2 -39
  171. package/dist/simulator/assets/device-shell-DsdcNEkt.css +1 -0
  172. package/dist/simulator/assets/device-shell-vwYSOVrh.js +2 -0
  173. package/dist/simulator/assets/jsx-runtime-P6ZegaOf.js +2 -0
  174. package/dist/simulator/assets/simulator-DddliUL5.js +10 -0
  175. package/dist/simulator/assets/simulator-mini-app-BDNu5n26.js +2 -0
  176. package/dist/simulator/device-shell/menu-button-geometry.js +8 -0
  177. package/dist/simulator/simulator.html +2 -112
  178. package/package.json +8 -9
  179. package/dist/main/utils/disposable.d.ts +0 -18
  180. package/dist/main/utils/disposable.js +0 -67
  181. package/dist/renderer/assets/index-BDMxXUfn.js +0 -50
  182. package/dist/renderer/assets/ipc-transport-Cu7tubyg.css +0 -1
  183. package/dist/renderer/assets/select-Ct4-sijm.js +0 -2
  184. package/dist/simulator/assets/simulator-B4e3c6_O.js +0 -9
@@ -1,22 +1,26 @@
1
- import { setupCdpPort, registerDifileScheme } from './bootstrap.js';
1
+ import { setupCdpPort, registerDifileScheme, suppressInsecureCspWarnings } from './bootstrap.js';
2
2
  import { registerProjectFsIpc } from '../ipc/project-fs.js';
3
3
  import { app, BrowserWindow, nativeImage, session } from 'electron';
4
4
  import fs from 'fs';
5
5
  import path from 'path';
6
6
  import { rendererDir as defaultRendererDir, defaultPreloadPath } from '../utils/paths.js';
7
7
  import { installThemeBackgroundSync } from '../utils/theme.js';
8
- import { registerAppLifecycle } from './lifecycle.js';
9
8
  import { createMainWindow, wireMainWindowEvents } from '../windows/main-window/index.js';
10
9
  import { createWorkbenchContext } from '../services/workbench-context.js';
11
10
  import { loadWorkbenchSettings, applyTheme } from '../services/settings/index.js';
12
11
  import { installAppMenu } from '../menu/index.js';
13
12
  import { registerAppIpc, popoverModule, projectsModule, sessionModule, settingsModule, simulatorModule, } from '../ipc/index.js';
14
13
  import { startAutomationServer } from '../services/automation/index.js';
15
- import { startMcpServer } from '../services/mcp/index.js';
14
+ import { startMcpServer, setNativeHost, setActiveBridgeId, setNativeOverviewProvider, } from '../services/mcp/index.js';
16
15
  import { setupSimulatorStorage } from '../services/simulator-storage/index.js';
16
+ import { createNetworkForwarder } from '../services/network-forward/index.js';
17
+ import { setupSimulatorWxml } from '../services/simulator-wxml/index.js';
18
+ import { setupSimulatorAppData } from '../services/simulator-appdata/index.js';
19
+ import { setupSimulatorCurrentPage } from '../services/simulator-current-page/index.js';
20
+ import { createRenderInspector } from '../services/render-inspect/index.js';
17
21
  import { setupSimulatorTempFiles } from '../services/simulator-temp-files/index.js';
18
22
  import { UpdateManager } from '../services/update/index.js';
19
- import { toDisposable } from '../utils/disposable.js';
23
+ import { toDisposable } from '@dimina-kit/electron-deck/main';
20
24
  import { IpcRegistry } from '../utils/ipc-registry.js';
21
25
  const DEFAULT_MODULES = {
22
26
  projects: true,
@@ -124,11 +128,6 @@ function createConfiguredMainWindow(config, rendererDir) {
124
128
  height: config.window?.height,
125
129
  minWidth: config.window?.minWidth,
126
130
  minHeight: config.window?.minHeight,
127
- // P1: pass the same preload path the workbench context stores on
128
- // ctx.preloadPath so hosts that ship a custom simulator preload are the
129
- // ones registered on the persist:simulator session — otherwise the
130
- // backstop wouldn't be the host's script.
131
- simulatorPreloadPath: config.preloadPath ?? defaultPreloadPath,
132
131
  });
133
132
  // Set window/taskbar icon if provided (Linux/Windows; macOS uses app bundle icon)
134
133
  if (config.icon) {
@@ -213,6 +212,10 @@ function setupMcp() {
213
212
  }
214
213
  function wireAppWindowEvents(config, instance) {
215
214
  const { mainWindow, context } = instance;
215
+ // In-flight guard: `closeProject()` is async, and the window stays open
216
+ // (preventDefault'd) while it runs — a second close click during that window
217
+ // would re-enter and tear the same session down twice. Swallow re-entrancy.
218
+ let closing = false;
216
219
  return wireMainWindowEvents(mainWindow, {
217
220
  context,
218
221
  onResize: () => context.views.repositionAll(),
@@ -226,11 +229,19 @@ function wireAppWindowEvents(config, instance) {
226
229
  // unable to invoke anything, so subsequent clicks on Import/etc. would
227
230
  // raise `No handler registered for ...`.
228
231
  e.preventDefault();
229
- if (config.onBeforeClose) {
230
- await config.onBeforeClose(instance);
232
+ if (closing)
233
+ return;
234
+ closing = true;
235
+ try {
236
+ if (config.onBeforeClose) {
237
+ await config.onBeforeClose(instance);
238
+ }
239
+ await context.workspace.closeProject();
240
+ context.notify.windowNavigateBack();
241
+ }
242
+ finally {
243
+ closing = false;
231
244
  }
232
- await context.workspace.closeProject();
233
- context.notify.windowNavigateBack();
234
245
  },
235
246
  });
236
247
  }
@@ -257,125 +268,234 @@ function enableDevRendererAutoReload(rendererDir) {
257
268
  watcher.close();
258
269
  });
259
270
  }
260
- export function createWorkbenchApp(config = {}) {
261
- let setupPromise = null;
262
- let appEventsRegistered = false;
263
- // Lock the visible app name BEFORE app.whenReady so the dock label,
264
- // ⌘-Tab card and macOS app-menu first item all read "Dimina DevTools"
265
- // in both dev (unpackaged Electron) and packaged builds. `app.setName`
266
- // overrides the unpackaged process name ("Electron") and is harmless
267
- // when the packaged Info.plist already says the same thing.
268
- // Host integrators that brand the app differently can still override
269
- // `config.appName`; we keep our default consistent with `electron-builder.yml#productName`.
271
+ /**
272
+ * Pre-ready bootstrap side effects (app name, CDP port, CSP suppression,
273
+ * privileged scheme). MUST run before `app.whenReady()`. Extracted so the `RuntimeBackend.beforeReady` hook (which launch()
274
+ * routes through) runs it before the framework awaits app.whenReady().
275
+ */
276
+ export function runDevtoolsBootstrap(config = {}) {
277
+ // Lock the visible app name BEFORE app.whenReady so the dock label, ⌘-Tab
278
+ // card and macOS app-menu first item read the brand in dev + packaged.
270
279
  try {
271
280
  app.setName(config.appName ?? 'Dimina DevTools');
272
281
  }
273
282
  catch { /* electron stub in tests */ }
274
283
  setupCdpPort();
275
- // Privileged scheme registration must run before `app.whenReady` —
276
- // registering it later throws.
284
+ // Dev-only: silence Electron Insecure-CSP warning; no-op when packaged.
285
+ suppressInsecureCspWarnings();
286
+ // Privileged scheme registration must run before app.whenReady (else throws).
277
287
  registerDifileScheme();
278
- async function setup() {
279
- if (setupPromise)
280
- return setupPromise;
281
- setupPromise = app.whenReady().then(async () => {
282
- applyTheme(loadWorkbenchSettings().theme);
283
- const rendererDir = config.rendererDir ?? defaultRendererDir;
284
- const mainWindow = createConfiguredMainWindow(config, rendererDir);
285
- const context = createContext(config, mainWindow, rendererDir);
286
- context.registry.add(registerAppIpc(context));
287
- // Sandboxed project file-system IPC for the in-renderer Monaco editor.
288
- context.registry.add(registerProjectFsIpc(context));
289
- // One process-wide listener that re-syncs every window's native
290
- // backgroundColor on theme change — windows otherwise keep the stale
291
- // creation-time color (see installThemeBackgroundSync).
292
- context.registry.add(installThemeBackgroundSync());
293
- registerBuiltinModules(config, context);
294
- // Wire the simulator-side difile:// protocol handler + temp-file IPC
295
- // before host onSetup so any host-driven simulator boot sees the
296
- // protocol live. The module installs its own narrow sender-policy
297
- // (simulator-session-only) see file header because the default
298
- // workbench policy intentionally rejects the simulator <webview>.
299
- const simSession = session.fromPartition('persist:simulator');
300
- context.registry.add(setupSimulatorTempFiles(simSession));
301
- installMenu(config, mainWindow, context);
302
- // Gated custom-IPC surface for the host. Bound to ctx.senderPolicy so
303
- // host channels go through the same gateway as built-in IPC, and
304
- // registered into ctx.registry so its handlers are torn down with the
305
- // context.
306
- const hostIpc = new IpcRegistry(context.senderPolicy);
307
- context.registry.add(hostIpc);
308
- const instance = {
309
- mainWindow,
310
- context,
311
- ipc: hostIpc,
312
- // Return the registry wrapper, not the raw disposable: disposing the
313
- // wrapper splices the registry entry out AND drives the underlying
314
- // teardown, so a single dispose leaves no dead entry behind.
315
- registerTrustedWindow: (win) => context.registry.add(registerTrustedWindow(context, win)),
316
- registerSimulatorApi: (name, handler) => context.registry.add(toDisposable(context.simulatorApis.register(name, handler))),
317
- toolbar: {
318
- set: (actions) => {
319
- // `context.toolbar.set` validates id-uniqueness and throws on a
320
- // duplicate BEFORE mutating, so a rejected batch never reaches
321
- // the notify below — no phantom ActionsChanged.
322
- context.toolbar.set(actions);
323
- context.notify.toolbarActionsChanged();
324
- },
325
- },
326
- dispose: () => disposeContext(context),
288
+ }
289
+ /**
290
+ * Domain runtime assembly — the post-whenReady body. Builds the main window +
291
+ * context, registers IPC modules, stands up simulator/storage/CDP/native-host
292
+ * services, and returns the fat {@link WorkbenchAppInstance}. Extracted so the
293
+ * v2 `RuntimeBackend.assemble` reuses the exact same body (parity by shared
294
+ * implementation, not behavioural re-creation).
295
+ */
296
+ export async function createDevtoolsRuntime(config = {}) {
297
+ // Self-gate on Electron readiness: this builds a BrowserWindow immediately, so
298
+ // it must run after `app.whenReady()`. The framework backend path already
299
+ // awaited it (idempotent no-op here); this guards any direct caller against
300
+ // constructing Electron resources before ready.
301
+ await app.whenReady();
302
+ applyTheme(loadWorkbenchSettings().theme);
303
+ const rendererDir = config.rendererDir ?? defaultRendererDir;
304
+ const mainWindow = createConfiguredMainWindow(config, rendererDir);
305
+ const context = createContext(config, mainWindow, rendererDir);
306
+ // Anchor the main window's renderer as the first Connection. Resources
307
+ // scoped to the main webContents (acquired by later wiring) tear down with
308
+ // it; see packages/electron-deck/docs/foundation.md §4.
309
+ context.connections.acquire(mainWindow.webContents);
310
+ context.registry.add(registerAppIpc(context));
311
+ // Sandboxed project file-system IPC for the in-renderer Monaco editor.
312
+ context.registry.add(registerProjectFsIpc(context));
313
+ // One process-wide listener that re-syncs every window's native
314
+ // backgroundColor on theme change windows otherwise keep the stale
315
+ // creation-time color (see installThemeBackgroundSync).
316
+ context.registry.add(installThemeBackgroundSync());
317
+ registerBuiltinModules(config, context);
318
+ // Wire the simulator-side difile:// protocol handler + temp-file IPC
319
+ // before host onSetup so any host-driven simulator boot sees the
320
+ // protocol live. The module installs its own narrow sender-policy
321
+ // (simulator-session-only) — see file header — because the default
322
+ // workbench policy intentionally rejects the simulator <webview>.
323
+ const simSession = session.fromPartition('persist:simulator');
324
+ context.registry.add(setupSimulatorTempFiles(simSession));
325
+ installMenu(config, mainWindow, context);
326
+ // Gated custom-IPC surface for the host. Bound to ctx.senderPolicy so
327
+ // host channels go through the same gateway as built-in IPC, and
328
+ // registered into ctx.registry so its handlers are torn down with the
329
+ // context.
330
+ const hostIpc = new IpcRegistry(context.senderPolicy);
331
+ context.registry.add(hostIpc);
332
+ const instance = {
333
+ mainWindow,
334
+ context,
335
+ ipc: hostIpc,
336
+ // Return the registry wrapper, not the raw disposable: disposing the
337
+ // wrapper splices the registry entry out AND drives the underlying
338
+ // teardown, so a single dispose leaves no dead entry behind.
339
+ registerTrustedWindow: (win) => context.registry.add(registerTrustedWindow(context, win)),
340
+ registerSimulatorApi: (name, handler) => context.registry.add(toDisposable(context.simulatorApis.register(name, handler))),
341
+ toolbar: {
342
+ set: (actions) => {
343
+ // `context.toolbar.set` validates id-uniqueness and throws on a
344
+ // duplicate BEFORE mutating, so a rejected batch never reaches
345
+ // the notify below — no phantom ActionsChanged.
346
+ context.toolbar.set(actions);
347
+ context.notify.toolbarActionsChanged();
348
+ },
349
+ },
350
+ dispose: () => disposeContext(context),
351
+ };
352
+ if (config.onSetup) {
353
+ await config.onSetup(instance);
354
+ }
355
+ if (config.updateChecker) {
356
+ instance.updateManager = new UpdateManager({
357
+ checker: config.updateChecker,
358
+ mainWindow,
359
+ senderPolicy: context.senderPolicy,
360
+ checkInterval: config.updateOptions?.checkInterval,
361
+ initialDelay: config.updateOptions?.initialDelay,
362
+ getCurrentVersion: config.updateOptions?.getCurrentVersion,
363
+ });
364
+ context.registry.add(() => instance.updateManager.dispose());
365
+ }
366
+ await setupAutomation(instance);
367
+ const mcp = setupMcp();
368
+ if (mcp)
369
+ context.registry.add(mcp);
370
+ // Resolve the active project's appId. Shared by the storage panel filter
371
+ // and the native-host WXML/element-inspect services (which scope the
372
+ // active render guest by appId).
373
+ const getActiveAppId = () => {
374
+ const session = context.workspace.getSession();
375
+ const appInfo = session?.appInfo;
376
+ return appInfo?.appId ?? null;
377
+ };
378
+ // Native-host: the real mini-app page runs in a nested render-host
379
+ // <webview> guest, not the localhost:7788 shell. Point the MCP
380
+ // `simulator` CDP target at the active render guest and keep it following
381
+ // the visible page across navigation/tab switches. Only wired under
382
+ // native-host so the default path stays byte-identical.
383
+ if (context.bridge?.isNativeHost()) {
384
+ setNativeHost(true);
385
+ setNativeOverviewProvider(async () => {
386
+ const appId = getActiveAppId();
387
+ const stack = context.bridge?.getPageStack?.(appId ?? undefined) ?? [];
388
+ const top = stack[stack.length - 1];
389
+ const overview = {
390
+ currentRoute: top?.pagePath ?? null,
391
+ pageStackDepth: stack.length,
392
+ storageKeys: [],
393
+ storageCount: 0,
394
+ appDataKeys: [],
327
395
  };
328
- if (config.onBeforeOpenProject) {
329
- context.beforeOpenProject = (projectPath) => config.onBeforeOpenProject({ projectPath, instance });
396
+ if (appId) {
397
+ try {
398
+ const info = await context.storageApi?.invoke(appId, 'getStorageInfo', {});
399
+ if (info && typeof info === 'object') {
400
+ const keys = info.keys;
401
+ if (Array.isArray(keys)) {
402
+ overview.storageKeys = keys.filter((key) => typeof key === 'string');
403
+ overview.storageCount = keys.length;
404
+ }
405
+ }
406
+ }
407
+ catch {
408
+ // Leave native storage empty when it is temporarily unavailable.
409
+ }
410
+ try {
411
+ const snapshot = context.appData?.snapshot?.(appId);
412
+ if (snapshot && typeof snapshot === 'object') {
413
+ const entries = snapshot.entries;
414
+ if (entries && typeof entries === 'object') {
415
+ overview.appDataKeys = Object.keys(entries);
416
+ }
417
+ }
418
+ }
419
+ catch {
420
+ // Leave native appdata empty when it has not been initialized yet.
421
+ }
330
422
  }
331
- if (config.onSetup) {
332
- await config.onSetup(instance);
333
- }
334
- if (config.updateChecker) {
335
- instance.updateManager = new UpdateManager({
336
- checker: config.updateChecker,
337
- mainWindow,
338
- senderPolicy: context.senderPolicy,
339
- checkInterval: config.updateOptions?.checkInterval,
340
- initialDelay: config.updateOptions?.initialDelay,
341
- getCurrentVersion: config.updateOptions?.getCurrentVersion,
342
- });
343
- context.registry.add(() => instance.updateManager.dispose());
344
- }
345
- await setupAutomation(instance);
346
- const mcp = setupMcp();
347
- if (mcp)
348
- context.registry.add(mcp);
349
- context.registry.add(setupSimulatorStorage(mainWindow.webContents, {
350
- senderPolicy: context.senderPolicy,
351
- // Per-project filter for the simulator-storage panel: the simulator
352
- // uses a fixed `persist:simulator` partition + a fixed simulator.html
353
- // origin, so localStorage is shared across every project that has
354
- // ever opened. The dimina runtime isolates writes with `${appId}_`
355
- // prefixes; this callback lets the storage panel filter the CDP
356
- // snapshot/event stream to the active appId.
357
- getActiveAppId: () => {
358
- const session = context.workspace.getSession();
359
- const appInfo = session?.appInfo;
360
- return appInfo?.appId ?? null;
361
- },
362
- }));
363
- context.registry.add(wireAppWindowEvents(config, instance));
364
- context.registry.add(enableDevRendererAutoReload(rendererDir));
365
- return instance;
423
+ return overview;
366
424
  });
367
- return setupPromise;
425
+ const off = context.bridge.onRenderEvent((ev) => setActiveBridgeId(ev.bridgeId));
426
+ context.registry.add(off);
427
+ context.registry.add(() => setNativeHost(false));
428
+ context.registry.add(() => setNativeOverviewProvider(null));
368
429
  }
369
- function start() {
370
- if (!appEventsRegistered) {
371
- appEventsRegistered = true;
372
- registerAppLifecycle();
373
- }
374
- return setup().then(() => undefined);
430
+ // Native-host inspector: injects the render-guest IIFE and drives WXML /
431
+ // element-highlight against the active render-host <webview>. Reused by
432
+ // the storage panel (element inspect) and the WXML panel service.
433
+ const renderInspector = createRenderInspector({ connections: context.connections });
434
+ const storage = setupSimulatorStorage(mainWindow.webContents, {
435
+ senderPolicy: context.senderPolicy,
436
+ connections: context.connections,
437
+ // Per-project filter for the simulator-storage panel: the simulator
438
+ // uses a fixed `persist:simulator` partition + a fixed simulator.html
439
+ // origin, so localStorage is shared across every project that has
440
+ // ever opened. The dimina runtime isolates writes with `${appId}_`
441
+ // prefixes; this callback lets the storage panel filter the CDP
442
+ // snapshot/event stream to the active appId.
443
+ getActiveAppId,
444
+ // Native-host: route element inspection to the active render guest, and
445
+ // read/write storage from the service-host window's file:// store.
446
+ bridge: context.bridge,
447
+ renderInspector,
448
+ });
449
+ context.registry.add(storage);
450
+ // Native-host: expose the async-storage runtime hook so bridge-router
451
+ // routes async wx.setStorage/etc. to the unified service-host store.
452
+ if (storage.storageApi) {
453
+ context.storageApi = storage.storageApi;
454
+ context.registry.add(() => { context.storageApi = undefined; });
375
455
  }
376
- return {
377
- setup,
378
- start,
379
- };
456
+ // Native-host WXML + AppData panels: main sources the data (WXML pulled
457
+ // from the active render guest; AppData tapped from the service→render
458
+ // setData stream in bridge-router) and pushes it to the renderer. Inert on
459
+ // the default dimina-fe path (which sources both from the simulator
460
+ // miniappSnapshot transport), so only wire them when native-host is on.
461
+ if (context.bridge?.isNativeHost()) {
462
+ // Native-host: surface the simulator WCV's network (wx.request/download/
463
+ // upload run there, not in the service host) in the embedded DevTools by
464
+ // injecting its raw Network.* CDP events into the DevTools front-end so the
465
+ // native Network tab renders them (service-host console line is the
466
+ // fallback). The ViewManager calls attachSimulator + setDevtoolsHost from
467
+ // attachNativeSimulator once the simulator WCV + DevTools host exist;
468
+ // getServiceWc here is the fallback sink target.
469
+ const networkForward = createNetworkForwarder({
470
+ getServiceWc: (appId) => context.bridge?.getServiceWc(appId) ?? null,
471
+ connections: context.connections,
472
+ });
473
+ context.networkForward = networkForward;
474
+ context.registry.add(networkForward);
475
+ context.registry.add(() => { context.networkForward = undefined; });
476
+ context.registry.add(setupSimulatorWxml(mainWindow.webContents, {
477
+ senderPolicy: context.senderPolicy,
478
+ bridge: context.bridge,
479
+ inspector: renderInspector,
480
+ getActiveAppId,
481
+ }));
482
+ const appDataService = setupSimulatorAppData(mainWindow.webContents, {
483
+ senderPolicy: context.senderPolicy,
484
+ getActiveAppId,
485
+ });
486
+ // bridge-router feeds this via ctx.appData (service→render tap + evict).
487
+ context.appData = appDataService;
488
+ context.registry.add(appDataService);
489
+ context.registry.add(() => { context.appData = undefined; });
490
+ // Push the visible page route to the toolbar on every navigation (the
491
+ // page stack lives in the DeviceShell WCV, invisible to renderer
492
+ // <webview> nav events).
493
+ context.registry.add(setupSimulatorCurrentPage(mainWindow.webContents, {
494
+ bridge: context.bridge,
495
+ }));
496
+ }
497
+ context.registry.add(wireAppWindowEvents(config, instance));
498
+ context.registry.add(enableDevRendererAutoReload(rendererDir));
499
+ return instance;
380
500
  }
381
501
  //# sourceMappingURL=app.js.map
@@ -12,6 +12,22 @@ export declare function registerDifileScheme(): void;
12
12
  * Call at the very top of your entry file, before any imports that may write.
13
13
  */
14
14
  export declare function suppressEpipe(): void;
15
+ /**
16
+ * Silence Electron's built-in "Insecure Content-Security-Policy" dev warning.
17
+ *
18
+ * In dev (unpackaged) the renderer is served from the Vite dev server, which
19
+ * does not ship a strict CSP header, so Electron prints its `Electron Security
20
+ * Warning (Insecure Content-Security-Policy)` notice in every frame's console.
21
+ * It is pure dev noise — Electron already suppresses it automatically once the
22
+ * app is packaged (`app.isPackaged`).
23
+ *
24
+ * This sets ONLY the log-suppression env var, and ONLY when unpackaged. It does
25
+ * not touch contextIsolation / sandbox / webSecurity or any other CSP-relevant
26
+ * window setting — the actual security posture is unchanged; we only stop the
27
+ * console from re-printing the warning. Must run before any window is created
28
+ * (Electron reads the env var when it emits the warning).
29
+ */
30
+ export declare function suppressInsecureCspWarnings(): void;
15
31
  /**
16
32
  * Configure Chrome DevTools Protocol remote-debugging-port.
17
33
  * Must be called before `app.whenReady()`.
@@ -43,6 +43,26 @@ export function suppressEpipe() {
43
43
  ignore(process.stdout);
44
44
  ignore(process.stderr);
45
45
  }
46
+ /**
47
+ * Silence Electron's built-in "Insecure Content-Security-Policy" dev warning.
48
+ *
49
+ * In dev (unpackaged) the renderer is served from the Vite dev server, which
50
+ * does not ship a strict CSP header, so Electron prints its `Electron Security
51
+ * Warning (Insecure Content-Security-Policy)` notice in every frame's console.
52
+ * It is pure dev noise — Electron already suppresses it automatically once the
53
+ * app is packaged (`app.isPackaged`).
54
+ *
55
+ * This sets ONLY the log-suppression env var, and ONLY when unpackaged. It does
56
+ * not touch contextIsolation / sandbox / webSecurity or any other CSP-relevant
57
+ * window setting — the actual security posture is unchanged; we only stop the
58
+ * console from re-printing the warning. Must run before any window is created
59
+ * (Electron reads the env var when it emits the warning).
60
+ */
61
+ export function suppressInsecureCspWarnings() {
62
+ if (app.isPackaged)
63
+ return;
64
+ process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true';
65
+ }
46
66
  /**
47
67
  * Configure Chrome DevTools Protocol remote-debugging-port.
48
68
  * Must be called before `app.whenReady()`.
@@ -1,10 +1,14 @@
1
- import type { WorkbenchConfig } from '../../shared/types.js';
1
+ import type { WorkbenchAppConfig } from '../../shared/types.js';
2
2
  import type { WorkbenchContext } from '../services/workbench-context.js';
3
3
  /**
4
- * Convenience launcher for the default full-featured app.
5
- * Use createWorkbenchApp() when you want to customize modules or window setup.
4
+ * Host-shell entry for the devtools app. Boots through the
5
+ * `@dimina-kit/electron-deck` framework orchestrator (process lifecycle gate +
6
+ * wire/trust) with the devtools {@link createDevtoolsBackend} supplying the full
7
+ * runtime — the framework is the single entry. The instance builder
8
+ * (`createDevtoolsRuntime`) is internal; hosts integrate via `launch(config)`,
9
+ * passing `WorkbenchAppConfig` (incl. `onSetup`, `apiNamespaces`, `menuBuilder`, …).
6
10
  */
7
- export declare function launch(config?: WorkbenchConfig): Promise<void>;
11
+ export declare function launch(config?: WorkbenchAppConfig): Promise<void>;
8
12
  export declare function buildDefaultMenu(ctx: WorkbenchContext): void;
9
13
  export declare function openSettingsWindow(ctx: Pick<WorkbenchContext, 'rendererDir' | 'notify' | 'windows'>): Promise<void>;
10
14
  //# sourceMappingURL=launch.d.ts.map
@@ -1,13 +1,18 @@
1
- import { createWorkbenchApp } from './app.js';
1
+ import { electronDeck as frameworkElectronDeck } from '@dimina-kit/electron-deck';
2
+ import { createDevtoolsBackend } from '../runtime/devtools-backend.js';
2
3
  import { installAppMenu } from '../menu/index.js';
3
4
  import { createSettingsWindow, wireSettingsWindowEvents } from '../windows/settings-window/index.js';
4
5
  import { loadWorkbenchSettings } from '../services/settings/index.js';
5
6
  /**
6
- * Convenience launcher for the default full-featured app.
7
- * Use createWorkbenchApp() when you want to customize modules or window setup.
7
+ * Host-shell entry for the devtools app. Boots through the
8
+ * `@dimina-kit/electron-deck` framework orchestrator (process lifecycle gate +
9
+ * wire/trust) with the devtools {@link createDevtoolsBackend} supplying the full
10
+ * runtime — the framework is the single entry. The instance builder
11
+ * (`createDevtoolsRuntime`) is internal; hosts integrate via `launch(config)`,
12
+ * passing `WorkbenchAppConfig` (incl. `onSetup`, `apiNamespaces`, `menuBuilder`, …).
8
13
  */
9
14
  export function launch(config = {}) {
10
- return createWorkbenchApp(config).start();
15
+ return frameworkElectronDeck({ backend: createDevtoolsBackend(config) });
11
16
  }
12
17
  export function buildDefaultMenu(ctx) {
13
18
  installAppMenu(ctx);