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

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 (189) 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 +249 -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 +6071 -1863
  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 +1333 -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 +29 -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 +39 -17
  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/miniapp-partition.d.ts +80 -0
  85. package/dist/main/services/views/miniapp-partition.js +138 -0
  86. package/dist/main/services/views/simulator-session-policy.d.ts +28 -0
  87. package/dist/main/services/views/simulator-session-policy.js +82 -0
  88. package/dist/main/services/views/view-manager.d.ts +125 -0
  89. package/dist/main/services/views/view-manager.js +852 -4
  90. package/dist/main/services/workbench-context.d.ts +67 -7
  91. package/dist/main/services/workbench-context.js +6 -1
  92. package/dist/main/services/workspace/workspace-service.js +7 -13
  93. package/dist/main/utils/ipc-registry.d.ts +1 -1
  94. package/dist/main/utils/ipc-registry.js +21 -4
  95. package/dist/main/utils/paths.d.ts +15 -0
  96. package/dist/main/utils/paths.js +19 -0
  97. package/dist/main/utils/sender-policy.d.ts +9 -3
  98. package/dist/main/utils/sender-policy.js +18 -4
  99. package/dist/main/utils/theme.d.ts +1 -1
  100. package/dist/main/utils/theme.js +1 -1
  101. package/dist/main/windows/main-window/create.d.ts +0 -6
  102. package/dist/main/windows/main-window/create.js +6 -80
  103. package/dist/main/windows/main-window/events.d.ts +1 -1
  104. package/dist/main/windows/main-window/events.js +1 -1
  105. package/dist/main/windows/service-host-window/create.d.ts +67 -0
  106. package/dist/main/windows/service-host-window/create.js +138 -0
  107. package/dist/native-host/common/common.js +368 -0
  108. package/dist/native-host/container/pageFrame.css +1 -0
  109. package/dist/native-host/render/render.js +9334 -0
  110. package/dist/native-host/service/service.js +6 -0
  111. package/dist/preload/index.d.ts +2 -0
  112. package/dist/preload/index.js +6 -0
  113. package/dist/preload/instrumentation/app-data.d.ts +18 -20
  114. package/dist/preload/instrumentation/app-data.js +23 -160
  115. package/dist/preload/instrumentation/wxml-extract.d.ts +1 -1
  116. package/dist/preload/instrumentation/wxml-extract.js +1 -1
  117. package/dist/preload/runtime/bridge.d.ts +3 -8
  118. package/dist/preload/runtime/bridge.js +2 -32
  119. package/dist/preload/runtime/custom-apis.js +20 -17
  120. package/dist/preload/runtime/host-toolbar-advertiser.d.ts +27 -0
  121. package/dist/preload/runtime/host-toolbar-advertiser.js +55 -0
  122. package/dist/preload/runtime/main-api-runner.d.ts +9 -0
  123. package/dist/preload/runtime/main-api-runner.js +85 -0
  124. package/dist/preload/runtime/native-host.d.ts +43 -0
  125. package/dist/preload/runtime/native-host.js +83 -0
  126. package/dist/preload/shared/expose.d.ts +10 -5
  127. package/dist/preload/shared/expose.js +30 -12
  128. package/dist/preload/shared/sid-registry.d.ts +11 -0
  129. package/dist/preload/shared/sid-registry.js +38 -0
  130. package/dist/preload/windows/host-toolbar.cjs +161 -0
  131. package/dist/preload/windows/host-toolbar.cjs.map +7 -0
  132. package/dist/preload/windows/host-toolbar.d.ts +2 -0
  133. package/dist/preload/windows/host-toolbar.js +12 -0
  134. package/dist/preload/windows/main.cjs +1935 -0
  135. package/dist/preload/windows/main.cjs.map +4 -4
  136. package/dist/preload/windows/simulator.cjs +925 -0
  137. package/dist/preload/windows/simulator.cjs.map +7 -0
  138. package/dist/preload/windows/simulator.js +244 -574
  139. package/dist/render-host/pageFrame.html +29 -0
  140. package/dist/render-host/preload.cjs +154 -0
  141. package/dist/render-host/render-inspect.js +295 -0
  142. package/dist/renderer/assets/index-CcJKzatF.js +50 -0
  143. package/dist/renderer/assets/{input-CCYS8Ave.js → input-QGx6FFX1.js} +2 -2
  144. package/dist/renderer/assets/ipc-transport-BT4QYQqu.css +1 -0
  145. package/dist/renderer/assets/{ipc-transport-Bn4KXvhu.js → ipc-transport-DvZvwK-Z.js} +2 -2
  146. package/dist/renderer/assets/{popover-CH4rwpdt.js → popover-BOH1If1J.js} +2 -2
  147. package/dist/renderer/assets/select-C7JQ8G5N.js +2 -0
  148. package/dist/renderer/assets/{settings-CMTB-t0x.js → settings-DpAbTJyF.js} +2 -2
  149. package/dist/renderer/assets/{settings-api-Csdngf9Z.js → settings-api-RD2IZF53.js} +2 -2
  150. package/dist/renderer/assets/{workbenchSettings-CODFCzOg.js → workbenchSettings-CNJX4Qna.js} +2 -2
  151. package/dist/renderer/entries/main/index.html +5 -5
  152. package/dist/renderer/entries/popover/index.html +5 -5
  153. package/dist/renderer/entries/settings/index.html +5 -5
  154. package/dist/renderer/entries/workbench-settings/index.html +4 -4
  155. package/dist/service-host/preload.cjs +254 -0
  156. package/dist/service-host/service.html +10 -0
  157. package/dist/service-host/sourcemap-rewrite.cjs +58 -0
  158. package/dist/service-host/sync-api-patch.js +20 -0
  159. package/dist/service-host/sync-impls/menu-button-geometry.js +8 -0
  160. package/dist/service-host/sync-impls/menu-button.js +16 -0
  161. package/dist/service-host/sync-impls/storage.js +50 -0
  162. package/dist/service-host/sync-impls/system-info.js +54 -0
  163. package/dist/shared/appdata-accumulator.d.ts +95 -0
  164. package/dist/shared/appdata-accumulator.js +213 -0
  165. package/dist/shared/bridge-channels.d.ts +378 -0
  166. package/dist/shared/bridge-channels.js +81 -0
  167. package/dist/shared/ipc-channels.d.ts +84 -1
  168. package/dist/shared/ipc-channels.js +90 -10
  169. package/dist/shared/ipc-schemas.d.ts +59 -2
  170. package/dist/shared/ipc-schemas.js +64 -3
  171. package/dist/shared/open-in-editor.d.ts +71 -0
  172. package/dist/shared/open-in-editor.js +138 -0
  173. package/dist/shared/simulator-api-metadata.d.ts +21 -0
  174. package/dist/shared/simulator-api-metadata.js +23 -0
  175. package/dist/shared/types.d.ts +2 -39
  176. package/dist/simulator/assets/device-shell-DsdcNEkt.css +1 -0
  177. package/dist/simulator/assets/device-shell-fH2cI-3q.js +2 -0
  178. package/dist/simulator/assets/jsx-runtime-P6ZegaOf.js +2 -0
  179. package/dist/simulator/assets/simulator-DHylZf9Z.js +10 -0
  180. package/dist/simulator/assets/simulator-mini-app-BDNu5n26.js +2 -0
  181. package/dist/simulator/device-shell/menu-button-geometry.js +8 -0
  182. package/dist/simulator/simulator.html +2 -112
  183. package/package.json +12 -12
  184. package/dist/main/utils/disposable.d.ts +0 -18
  185. package/dist/main/utils/disposable.js +0 -67
  186. package/dist/renderer/assets/index-BDMxXUfn.js +0 -50
  187. package/dist/renderer/assets/ipc-transport-Cu7tubyg.css +0 -1
  188. package/dist/renderer/assets/select-Ct4-sijm.js +0 -2
  189. package/dist/simulator/assets/simulator-B4e3c6_O.js +0 -9
@@ -1,22 +1,28 @@
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';
22
+ import { SHARED_MINIAPP_PARTITION } from '../services/views/miniapp-partition.js';
23
+ import { setupSimulatorSessionPolicy } from '../services/views/simulator-session-policy.js';
18
24
  import { UpdateManager } from '../services/update/index.js';
19
- import { toDisposable } from '../utils/disposable.js';
25
+ import { toDisposable } from '@dimina-kit/electron-deck/main';
20
26
  import { IpcRegistry } from '../utils/ipc-registry.js';
21
27
  const DEFAULT_MODULES = {
22
28
  projects: true,
@@ -124,11 +130,6 @@ function createConfiguredMainWindow(config, rendererDir) {
124
130
  height: config.window?.height,
125
131
  minWidth: config.window?.minWidth,
126
132
  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
133
  });
133
134
  // Set window/taskbar icon if provided (Linux/Windows; macOS uses app bundle icon)
134
135
  if (config.icon) {
@@ -213,6 +214,10 @@ function setupMcp() {
213
214
  }
214
215
  function wireAppWindowEvents(config, instance) {
215
216
  const { mainWindow, context } = instance;
217
+ // In-flight guard: `closeProject()` is async, and the window stays open
218
+ // (preventDefault'd) while it runs — a second close click during that window
219
+ // would re-enter and tear the same session down twice. Swallow re-entrancy.
220
+ let closing = false;
216
221
  return wireMainWindowEvents(mainWindow, {
217
222
  context,
218
223
  onResize: () => context.views.repositionAll(),
@@ -226,11 +231,19 @@ function wireAppWindowEvents(config, instance) {
226
231
  // unable to invoke anything, so subsequent clicks on Import/etc. would
227
232
  // raise `No handler registered for ...`.
228
233
  e.preventDefault();
229
- if (config.onBeforeClose) {
230
- await config.onBeforeClose(instance);
234
+ if (closing)
235
+ return;
236
+ closing = true;
237
+ try {
238
+ if (config.onBeforeClose) {
239
+ await config.onBeforeClose(instance);
240
+ }
241
+ await context.workspace.closeProject();
242
+ context.notify.windowNavigateBack();
243
+ }
244
+ finally {
245
+ closing = false;
231
246
  }
232
- await context.workspace.closeProject();
233
- context.notify.windowNavigateBack();
234
247
  },
235
248
  });
236
249
  }
@@ -257,125 +270,239 @@ function enableDevRendererAutoReload(rendererDir) {
257
270
  watcher.close();
258
271
  });
259
272
  }
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`.
273
+ /**
274
+ * Pre-ready bootstrap side effects (app name, CDP port, CSP suppression,
275
+ * privileged scheme). MUST run before `app.whenReady()`. Extracted so the `RuntimeBackend.beforeReady` hook (which launch()
276
+ * routes through) runs it before the framework awaits app.whenReady().
277
+ */
278
+ export function runDevtoolsBootstrap(config = {}) {
279
+ // Lock the visible app name BEFORE app.whenReady so the dock label, ⌘-Tab
280
+ // card and macOS app-menu first item read the brand in dev + packaged.
270
281
  try {
271
282
  app.setName(config.appName ?? 'Dimina DevTools');
272
283
  }
273
284
  catch { /* electron stub in tests */ }
274
285
  setupCdpPort();
275
- // Privileged scheme registration must run before `app.whenReady` —
276
- // registering it later throws.
286
+ // Dev-only: silence Electron Insecure-CSP warning; no-op when packaged.
287
+ suppressInsecureCspWarnings();
288
+ // Privileged scheme registration must run before app.whenReady (else throws).
277
289
  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),
290
+ }
291
+ /**
292
+ * Domain runtime assembly — the post-whenReady body. Builds the main window +
293
+ * context, registers IPC modules, stands up simulator/storage/CDP/native-host
294
+ * services, and returns the fat {@link WorkbenchAppInstance}. Extracted so the
295
+ * v2 `RuntimeBackend.assemble` reuses the exact same body (parity by shared
296
+ * implementation, not behavioural re-creation).
297
+ */
298
+ export async function createDevtoolsRuntime(config = {}) {
299
+ // Self-gate on Electron readiness: this builds a BrowserWindow immediately, so
300
+ // it must run after `app.whenReady()`. The framework backend path already
301
+ // awaited it (idempotent no-op here); this guards any direct caller against
302
+ // constructing Electron resources before ready.
303
+ await app.whenReady();
304
+ applyTheme(loadWorkbenchSettings().theme);
305
+ const rendererDir = config.rendererDir ?? defaultRendererDir;
306
+ const mainWindow = createConfiguredMainWindow(config, rendererDir);
307
+ const context = createContext(config, mainWindow, rendererDir);
308
+ // Anchor the main window's renderer as the first Connection. Resources
309
+ // scoped to the main webContents (acquired by later wiring) tear down with
310
+ // it; see packages/electron-deck/docs/foundation.md §4.
311
+ context.connections.acquire(mainWindow.webContents);
312
+ context.registry.add(registerAppIpc(context));
313
+ // Sandboxed project file-system IPC for the in-renderer Monaco editor.
314
+ context.registry.add(registerProjectFsIpc(context));
315
+ // Referer/CORS webRequest policy for the simulator runtime's sessions (shared
316
+ // fallback + every per-project partition). Registered into the context
317
+ // registry so its configurator + per-session listeners are torn down with the
318
+ // context re-creating the app never leaks a duplicate configurator.
319
+ context.registry.add(setupSimulatorSessionPolicy());
320
+ // One process-wide listener that re-syncs every window's native
321
+ // backgroundColor on theme change — windows otherwise keep the stale
322
+ // creation-time color (see installThemeBackgroundSync).
323
+ context.registry.add(installThemeBackgroundSync());
324
+ registerBuiltinModules(config, context);
325
+ // Wire the simulator-side difile:// protocol handler + temp-file IPC
326
+ // before host onSetup so any host-driven simulator boot sees the
327
+ // protocol live. The module installs its own narrow sender-policy
328
+ // (simulator-session-only) see file header — because the default
329
+ // workbench policy intentionally rejects the simulator <webview>.
330
+ const simSession = session.fromPartition(SHARED_MINIAPP_PARTITION);
331
+ context.registry.add(setupSimulatorTempFiles(simSession));
332
+ installMenu(config, mainWindow, context);
333
+ // Gated custom-IPC surface for the host. Bound to ctx.senderPolicy so
334
+ // host channels go through the same gateway as built-in IPC, and
335
+ // registered into ctx.registry so its handlers are torn down with the
336
+ // context.
337
+ const hostIpc = new IpcRegistry(context.senderPolicy);
338
+ context.registry.add(hostIpc);
339
+ const instance = {
340
+ mainWindow,
341
+ context,
342
+ ipc: hostIpc,
343
+ // Return the registry wrapper, not the raw disposable: disposing the
344
+ // wrapper splices the registry entry out AND drives the underlying
345
+ // teardown, so a single dispose leaves no dead entry behind.
346
+ registerTrustedWindow: (win) => context.registry.add(registerTrustedWindow(context, win)),
347
+ registerSimulatorApi: (name, handler) => context.registry.add(toDisposable(context.simulatorApis.register(name, handler))),
348
+ toolbar: {
349
+ set: (actions) => {
350
+ // `context.toolbar.set` validates id-uniqueness and throws on a
351
+ // duplicate BEFORE mutating, so a rejected batch never reaches
352
+ // the notify below — no phantom ActionsChanged.
353
+ context.toolbar.set(actions);
354
+ context.notify.toolbarActionsChanged();
355
+ },
356
+ },
357
+ dispose: () => disposeContext(context),
358
+ };
359
+ if (config.onSetup) {
360
+ await config.onSetup(instance);
361
+ }
362
+ if (config.updateChecker) {
363
+ instance.updateManager = new UpdateManager({
364
+ checker: config.updateChecker,
365
+ mainWindow,
366
+ senderPolicy: context.senderPolicy,
367
+ checkInterval: config.updateOptions?.checkInterval,
368
+ initialDelay: config.updateOptions?.initialDelay,
369
+ getCurrentVersion: config.updateOptions?.getCurrentVersion,
370
+ });
371
+ context.registry.add(() => instance.updateManager.dispose());
372
+ }
373
+ await setupAutomation(instance);
374
+ const mcp = setupMcp();
375
+ if (mcp)
376
+ context.registry.add(mcp);
377
+ // Resolve the active project's appId. Shared by the storage panel filter
378
+ // and the native-host WXML/element-inspect services (which scope the
379
+ // active render guest by appId).
380
+ const getActiveAppId = () => {
381
+ const session = context.workspace.getSession();
382
+ const appInfo = session?.appInfo;
383
+ return appInfo?.appId ?? null;
384
+ };
385
+ // Native-host: the real mini-app page runs in a nested render-host
386
+ // <webview> guest, not the localhost:7788 shell. Point the MCP
387
+ // `simulator` CDP target at the active render guest and keep it following
388
+ // the visible page across navigation/tab switches. Only wired under
389
+ // native-host so the default path stays byte-identical.
390
+ if (context.bridge?.isNativeHost()) {
391
+ setNativeHost(true);
392
+ setNativeOverviewProvider(async () => {
393
+ const appId = getActiveAppId();
394
+ const stack = context.bridge?.getPageStack?.(appId ?? undefined) ?? [];
395
+ const top = stack[stack.length - 1];
396
+ const overview = {
397
+ currentRoute: top?.pagePath ?? null,
398
+ pageStackDepth: stack.length,
399
+ storageKeys: [],
400
+ storageCount: 0,
401
+ appDataKeys: [],
327
402
  };
328
- if (config.onBeforeOpenProject) {
329
- context.beforeOpenProject = (projectPath) => config.onBeforeOpenProject({ projectPath, instance });
403
+ if (appId) {
404
+ try {
405
+ const info = await context.storageApi?.invoke(appId, 'getStorageInfo', {});
406
+ if (info && typeof info === 'object') {
407
+ const keys = info.keys;
408
+ if (Array.isArray(keys)) {
409
+ overview.storageKeys = keys.filter((key) => typeof key === 'string');
410
+ overview.storageCount = keys.length;
411
+ }
412
+ }
413
+ }
414
+ catch {
415
+ // Leave native storage empty when it is temporarily unavailable.
416
+ }
417
+ try {
418
+ const snapshot = context.appData?.snapshot?.(appId);
419
+ if (snapshot && typeof snapshot === 'object') {
420
+ const entries = snapshot.entries;
421
+ if (entries && typeof entries === 'object') {
422
+ overview.appDataKeys = Object.keys(entries);
423
+ }
424
+ }
425
+ }
426
+ catch {
427
+ // Leave native appdata empty when it has not been initialized yet.
428
+ }
330
429
  }
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;
430
+ return overview;
366
431
  });
367
- return setupPromise;
432
+ const off = context.bridge.onRenderEvent((ev) => setActiveBridgeId(ev.bridgeId));
433
+ context.registry.add(off);
434
+ context.registry.add(() => setNativeHost(false));
435
+ context.registry.add(() => setNativeOverviewProvider(null));
368
436
  }
369
- function start() {
370
- if (!appEventsRegistered) {
371
- appEventsRegistered = true;
372
- registerAppLifecycle();
373
- }
374
- return setup().then(() => undefined);
437
+ // Native-host inspector: injects the render-guest IIFE and drives WXML /
438
+ // element-highlight against the active render-host <webview>. Reused by
439
+ // the storage panel (element inspect) and the WXML panel service.
440
+ const renderInspector = createRenderInspector({ connections: context.connections });
441
+ const storage = setupSimulatorStorage(mainWindow.webContents, {
442
+ senderPolicy: context.senderPolicy,
443
+ connections: context.connections,
444
+ // Per-project filter for the simulator-storage panel: the simulator
445
+ // uses a fixed `persist:simulator` partition + a fixed simulator.html
446
+ // origin, so localStorage is shared across every project that has
447
+ // ever opened. The dimina runtime isolates writes with `${appId}_`
448
+ // prefixes; this callback lets the storage panel filter the CDP
449
+ // snapshot/event stream to the active appId.
450
+ getActiveAppId,
451
+ // Native-host: route element inspection to the active render guest, and
452
+ // read/write storage from the service-host window's file:// store.
453
+ bridge: context.bridge,
454
+ renderInspector,
455
+ });
456
+ context.registry.add(storage);
457
+ // Native-host: expose the async-storage runtime hook so bridge-router
458
+ // routes async wx.setStorage/etc. to the unified service-host store.
459
+ if (storage.storageApi) {
460
+ context.storageApi = storage.storageApi;
461
+ context.registry.add(() => { context.storageApi = undefined; });
375
462
  }
376
- return {
377
- setup,
378
- start,
379
- };
463
+ // Native-host WXML + AppData panels: main sources the data (WXML pulled
464
+ // from the active render guest; AppData tapped from the service→render
465
+ // setData stream in bridge-router) and pushes it to the renderer. Inert on
466
+ // the default dimina-fe path (which sources both from the simulator
467
+ // miniappSnapshot transport), so only wire them when native-host is on.
468
+ if (context.bridge?.isNativeHost()) {
469
+ // Native-host: surface the simulator WCV's network (wx.request/download/
470
+ // upload run there, not in the service host) in the embedded DevTools by
471
+ // injecting its raw Network.* CDP events into the DevTools front-end so the
472
+ // native Network tab renders them (service-host console line is the
473
+ // fallback). The ViewManager calls attachSimulator + setDevtoolsHost from
474
+ // attachNativeSimulator once the simulator WCV + DevTools host exist;
475
+ // getServiceWc here is the fallback sink target.
476
+ const networkForward = createNetworkForwarder({
477
+ getServiceWc: (appId) => context.bridge?.getServiceWc(appId) ?? null,
478
+ connections: context.connections,
479
+ });
480
+ context.networkForward = networkForward;
481
+ context.registry.add(networkForward);
482
+ context.registry.add(() => { context.networkForward = undefined; });
483
+ context.registry.add(setupSimulatorWxml(mainWindow.webContents, {
484
+ senderPolicy: context.senderPolicy,
485
+ bridge: context.bridge,
486
+ inspector: renderInspector,
487
+ getActiveAppId,
488
+ }));
489
+ const appDataService = setupSimulatorAppData(mainWindow.webContents, {
490
+ senderPolicy: context.senderPolicy,
491
+ getActiveAppId,
492
+ });
493
+ // bridge-router feeds this via ctx.appData (service→render tap + evict).
494
+ context.appData = appDataService;
495
+ context.registry.add(appDataService);
496
+ context.registry.add(() => { context.appData = undefined; });
497
+ // Push the visible page route to the toolbar on every navigation (the
498
+ // page stack lives in the DeviceShell WCV, invisible to renderer
499
+ // <webview> nav events).
500
+ context.registry.add(setupSimulatorCurrentPage(mainWindow.webContents, {
501
+ bridge: context.bridge,
502
+ }));
503
+ }
504
+ context.registry.add(wireAppWindowEvents(config, instance));
505
+ context.registry.add(enableDevRendererAutoReload(rendererDir));
506
+ return instance;
380
507
  }
381
508
  //# 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);