@dimina-kit/devtools 0.3.2-dev.20260525152421 → 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 (295) hide show
  1. package/README.md +43 -40
  2. package/dist/main/api.d.ts +0 -1
  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 +247 -110
  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 +6607 -2102
  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 +57 -0
  19. package/dist/main/ipc/project-fs.js +448 -0
  20. package/dist/main/ipc/projects.d.ts +1 -1
  21. package/dist/main/ipc/session.d.ts +1 -1
  22. package/dist/main/ipc/settings.d.ts +1 -1
  23. package/dist/main/ipc/simulator-module.d.ts +6 -0
  24. package/dist/main/ipc/simulator-module.js +11 -1
  25. package/dist/main/ipc/simulator.d.ts +2 -2
  26. package/dist/main/ipc/simulator.js +49 -5
  27. package/dist/main/ipc/toolbar.d.ts +1 -1
  28. package/dist/main/ipc/views.d.ts +19 -0
  29. package/dist/main/ipc/views.js +65 -0
  30. package/dist/main/runtime/devtools-backend.d.ts +17 -0
  31. package/dist/main/runtime/devtools-backend.js +49 -0
  32. package/dist/main/runtime/miniapp-runtime.d.ts +39 -0
  33. package/dist/main/runtime/miniapp-runtime.js +17 -0
  34. package/dist/main/services/automation/exec.d.ts +27 -2
  35. package/dist/main/services/automation/exec.js +37 -3
  36. package/dist/main/services/automation/handlers/app.js +127 -11
  37. package/dist/main/services/automation/handlers/page.js +36 -19
  38. package/dist/main/services/automation/index.js +40 -13
  39. package/dist/main/services/automation/wait-active-page.d.ts +56 -0
  40. package/dist/main/services/automation/wait-active-page.js +71 -0
  41. package/dist/main/services/console-forward/index.d.ts +36 -0
  42. package/dist/main/services/console-forward/index.js +81 -0
  43. package/dist/main/services/dimina-resource-server.d.ts +7 -0
  44. package/dist/main/services/dimina-resource-server.js +99 -0
  45. package/dist/main/services/elements-forward/index.d.ts +66 -0
  46. package/dist/main/services/elements-forward/index.js +583 -0
  47. package/dist/main/services/layout/index.d.ts +23 -1
  48. package/dist/main/services/layout/index.js +28 -3
  49. package/dist/main/services/mcp/index.d.ts +1 -0
  50. package/dist/main/services/mcp/index.js +3 -0
  51. package/dist/main/services/mcp/server.d.ts +1 -1
  52. package/dist/main/services/mcp/server.js +1 -1
  53. package/dist/main/services/mcp/target-manager.d.ts +35 -0
  54. package/dist/main/services/mcp/target-manager.js +63 -1
  55. package/dist/main/services/mcp/tools/context-tools.js +15 -1
  56. package/dist/main/services/module.d.ts +1 -1
  57. package/dist/main/services/network-forward/index.d.ts +190 -0
  58. package/dist/main/services/network-forward/index.js +765 -0
  59. package/dist/main/services/notifications/renderer-notifier.d.ts +11 -0
  60. package/dist/main/services/notifications/renderer-notifier.js +7 -1
  61. package/dist/main/services/render-inspect/index.d.ts +41 -0
  62. package/dist/main/services/render-inspect/index.js +88 -0
  63. package/dist/main/services/safe-area/index.d.ts +17 -0
  64. package/dist/main/services/safe-area/index.js +59 -0
  65. package/dist/main/services/service-host-pool/pool.d.ts +197 -0
  66. package/dist/main/services/service-host-pool/pool.js +364 -0
  67. package/dist/main/services/simulator/custom-apis.d.ts +34 -0
  68. package/dist/main/services/simulator/custom-apis.js +22 -0
  69. package/dist/main/services/simulator-appdata/index.d.ts +35 -0
  70. package/dist/main/services/simulator-appdata/index.js +71 -0
  71. package/dist/main/services/simulator-current-page/index.d.ts +24 -0
  72. package/dist/main/services/simulator-current-page/index.js +19 -0
  73. package/dist/main/services/simulator-storage/index.d.ts +37 -2
  74. package/dist/main/services/simulator-storage/index.js +209 -32
  75. package/dist/main/services/simulator-storage/service-storage-ops.d.ts +40 -0
  76. package/dist/main/services/simulator-storage/service-storage-ops.js +67 -0
  77. package/dist/main/services/simulator-temp-files/fs-channels.js +1 -1
  78. package/dist/main/services/simulator-temp-files/index.d.ts +1 -1
  79. package/dist/main/services/simulator-temp-files/index.js +1 -1
  80. package/dist/main/services/simulator-temp-files/request-handler.js +1 -1
  81. package/dist/main/services/simulator-wxml/index.d.ts +29 -0
  82. package/dist/main/services/simulator-wxml/index.js +28 -0
  83. package/dist/main/services/update/update-manager.d.ts +10 -0
  84. package/dist/main/services/update/update-manager.js +16 -3
  85. package/dist/main/services/views/devtools-tabs.d.ts +47 -0
  86. package/dist/main/services/views/devtools-tabs.js +95 -0
  87. package/dist/main/services/views/view-manager.d.ts +142 -4
  88. package/dist/main/services/views/view-manager.js +909 -17
  89. package/dist/main/services/workbench-context.d.ts +66 -1
  90. package/dist/main/services/workbench-context.js +6 -1
  91. package/dist/main/services/workspace/workspace-service.d.ts +8 -0
  92. package/dist/main/services/workspace/workspace-service.js +12 -0
  93. package/dist/main/utils/ipc-registry.d.ts +11 -2
  94. package/dist/main/utils/ipc-registry.js +63 -3
  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 +11 -59
  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 +52 -0
  106. package/dist/main/windows/service-host-window/create.js +112 -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 +29 -11
  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 +1939 -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 +243 -573
  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/abap-DiwvWnMr.js +2 -0
  143. package/dist/renderer/assets/apex-CmtZjKlf.js +2 -0
  144. package/dist/renderer/assets/azcli-DL2My_i-.js +2 -0
  145. package/dist/renderer/assets/bat-B-nC98wG.js +2 -0
  146. package/dist/renderer/assets/bicep-Ju5MwOgh.js +3 -0
  147. package/dist/renderer/assets/cameligo-8Eu1TyBr.js +2 -0
  148. package/dist/renderer/assets/chunk-DPI0Y_ll.js +1 -0
  149. package/dist/renderer/assets/clojure-u-RpMkH3.js +2 -0
  150. package/dist/renderer/assets/codicon-ngg6Pgfi.ttf +0 -0
  151. package/dist/renderer/assets/coffee-CdA7bbTe.js +2 -0
  152. package/dist/renderer/assets/constants-CLAQX6VZ.js +2 -0
  153. package/dist/renderer/assets/cpp-CzNFP8ks.js +2 -0
  154. package/dist/renderer/assets/csharp-j1LThmcE.js +2 -0
  155. package/dist/renderer/assets/csp-CLRC61y6.js +2 -0
  156. package/dist/renderer/assets/css-r6rC_7P2.js +4 -0
  157. package/dist/renderer/assets/css.worker-DyDu5ynT.js +90 -0
  158. package/dist/renderer/assets/cssMode-BCBgxrnA.js +2 -0
  159. package/dist/renderer/assets/cypher-CW08XVUh.js +2 -0
  160. package/dist/renderer/assets/dart-Cs9aL5T_.js +2 -0
  161. package/dist/renderer/assets/dockerfile-BWM0M184.js +2 -0
  162. package/dist/renderer/assets/ecl-MJJuer5P.js +2 -0
  163. package/dist/renderer/assets/editor-CWI9TnMM.css +1 -0
  164. package/dist/renderer/assets/editor.api2-BTaYmRq7.js +873 -0
  165. package/dist/renderer/assets/editor.worker-Dpt_xPrs.js +27 -0
  166. package/dist/renderer/assets/elixir-D2AIuXqn.js +2 -0
  167. package/dist/renderer/assets/flow9-B2H24giC.js +2 -0
  168. package/dist/renderer/assets/freemarker2-DGDGzimW.js +4 -0
  169. package/dist/renderer/assets/fsharp-CMk2OIJN.js +2 -0
  170. package/dist/renderer/assets/go-BrMkuJg0.js +2 -0
  171. package/dist/renderer/assets/graphql-PSR1UKGv.js +2 -0
  172. package/dist/renderer/assets/handlebars-bOHhw3EG.js +2 -0
  173. package/dist/renderer/assets/hcl-DAQrbDOW.js +2 -0
  174. package/dist/renderer/assets/html-BMyuX0_c.js +2 -0
  175. package/dist/renderer/assets/html.worker-IWNXhnIC.js +503 -0
  176. package/dist/renderer/assets/htmlMode-DR4kXJ7l.js +2 -0
  177. package/dist/renderer/assets/index-CcJKzatF.js +50 -0
  178. package/dist/renderer/assets/ini-0TG5BxW0.js +2 -0
  179. package/dist/renderer/assets/input-QGx6FFX1.js +2 -0
  180. package/dist/renderer/assets/ipc-transport-BT4QYQqu.css +1 -0
  181. package/dist/renderer/assets/{ipc-transport-BzPzxPwf.js → ipc-transport-DvZvwK-Z.js} +5 -5
  182. package/dist/renderer/assets/java-rgorz17v.js +2 -0
  183. package/dist/renderer/assets/javascript-Bu-tl1P7.js +2 -0
  184. package/dist/renderer/assets/json.worker-c4h5s80L.js +59 -0
  185. package/dist/renderer/assets/jsonMode-MQV_ffLR.js +8 -0
  186. package/dist/renderer/assets/julia-C8VMdHm8.js +2 -0
  187. package/dist/renderer/assets/kotlin-AhhC4Qhm.js +2 -0
  188. package/dist/renderer/assets/less-Cgca25AP.js +3 -0
  189. package/dist/renderer/assets/lexon-D0GHdBaw.js +2 -0
  190. package/dist/renderer/assets/liquid-ClkfOvhB.js +2 -0
  191. package/dist/renderer/assets/lspLanguageFeatures-Bke_4Ie9.js +5 -0
  192. package/dist/renderer/assets/lua-DmRsNG-P.js +2 -0
  193. package/dist/renderer/assets/m3-BgL5dNKT.js +2 -0
  194. package/dist/renderer/assets/markdown-BuJfycGS.js +2 -0
  195. package/dist/renderer/assets/mdx-RZdUskPu.js +2 -0
  196. package/dist/renderer/assets/mips-C9m_93PR.js +2 -0
  197. package/dist/renderer/assets/monaco.contribution-B7rUMaEv.js +3 -0
  198. package/dist/renderer/assets/msdax-CpFHC9OI.js +2 -0
  199. package/dist/renderer/assets/mysql-qFvltsqN.js +2 -0
  200. package/dist/renderer/assets/objective-c-Bnmr858J.js +2 -0
  201. package/dist/renderer/assets/pascal-WP0_D5AO.js +2 -0
  202. package/dist/renderer/assets/pascaligo-Blom4Rij.js +2 -0
  203. package/dist/renderer/assets/perl-B-vk8g64.js +2 -0
  204. package/dist/renderer/assets/pgsql-Cgvz6v67.js +2 -0
  205. package/dist/renderer/assets/php-8a3Lrw9m.js +2 -0
  206. package/dist/renderer/assets/pla-DuFqEZ8V.js +2 -0
  207. package/dist/renderer/assets/popover-BOH1If1J.js +2 -0
  208. package/dist/renderer/assets/postiats-DkLtSgkp.js +2 -0
  209. package/dist/renderer/assets/powerquery-BJ1aNepW.js +2 -0
  210. package/dist/renderer/assets/powershell-rE98k687.js +2 -0
  211. package/dist/renderer/assets/protobuf-CUheFacr.js +3 -0
  212. package/dist/renderer/assets/pug-LDcAMD8w.js +2 -0
  213. package/dist/renderer/assets/python-Cobrm_-8.js +2 -0
  214. package/dist/renderer/assets/qsharp-DUKSQoR1.js +2 -0
  215. package/dist/renderer/assets/r-D-QApv87.js +2 -0
  216. package/dist/renderer/assets/razor-BEUIQFNJ.js +2 -0
  217. package/dist/renderer/assets/redis-SXdDyWR9.js +2 -0
  218. package/dist/renderer/assets/redshift-Y6lsCryn.js +2 -0
  219. package/dist/renderer/assets/restructuredtext-edObr9a8.js +2 -0
  220. package/dist/renderer/assets/ruby-CNnUfF-8.js +2 -0
  221. package/dist/renderer/assets/rust-IHUZWzBr.js +2 -0
  222. package/dist/renderer/assets/sb-DrUvY44N.js +2 -0
  223. package/dist/renderer/assets/scala-B4hbXGLM.js +2 -0
  224. package/dist/renderer/assets/scheme-BGrd12j3.js +2 -0
  225. package/dist/renderer/assets/scss-x5G1ES4U.js +4 -0
  226. package/dist/renderer/assets/select-C7JQ8G5N.js +2 -0
  227. package/dist/renderer/assets/settings-DpAbTJyF.js +2 -0
  228. package/dist/renderer/assets/{settings-api-BXCw9vOZ.js → settings-api-RD2IZF53.js} +2 -2
  229. package/dist/renderer/assets/shell-DOehe2Y8.js +2 -0
  230. package/dist/renderer/assets/solidity-BeRvcwWV.js +2 -0
  231. package/dist/renderer/assets/sophia-DZbkUNjy.js +2 -0
  232. package/dist/renderer/assets/sparql-B7_oi5-h.js +2 -0
  233. package/dist/renderer/assets/sql-CTlsFWVE.js +2 -0
  234. package/dist/renderer/assets/st-DJVEJdPE.js +2 -0
  235. package/dist/renderer/assets/swift-CwhT3fYa.js +2 -0
  236. package/dist/renderer/assets/systemverilog-BQN63pkN.js +2 -0
  237. package/dist/renderer/assets/tcl-DqwfpskA.js +2 -0
  238. package/dist/renderer/assets/ts.worker-BwM5Ha3L.js +67720 -0
  239. package/dist/renderer/assets/tsMode-BHa7dl9v.js +12 -0
  240. package/dist/renderer/assets/twig-BiyenUgc.js +2 -0
  241. package/dist/renderer/assets/typescript-15aT0Yj8.js +2 -0
  242. package/dist/renderer/assets/typespec-CWOJribt.js +2 -0
  243. package/dist/renderer/assets/vb-Cq5F87m3.js +2 -0
  244. package/dist/renderer/assets/wgsl-BAvW2lVr.js +299 -0
  245. package/dist/renderer/assets/workbenchSettings-CNJX4Qna.js +8 -0
  246. package/dist/renderer/assets/workers-CRBS0W-v.js +2 -0
  247. package/dist/renderer/assets/xml-bR2Zh-HV.js +2 -0
  248. package/dist/renderer/assets/yaml-Bdk54Qrb.js +2 -0
  249. package/dist/renderer/entries/main/index.html +29 -6
  250. package/dist/renderer/entries/popover/index.html +7 -6
  251. package/dist/renderer/entries/settings/index.html +6 -5
  252. package/dist/renderer/entries/workbench-settings/index.html +6 -5
  253. package/dist/service-host/preload.cjs +254 -0
  254. package/dist/service-host/service.html +10 -0
  255. package/dist/service-host/sourcemap-rewrite.cjs +58 -0
  256. package/dist/service-host/sync-api-patch.js +20 -0
  257. package/dist/service-host/sync-impls/menu-button.js +16 -0
  258. package/dist/service-host/sync-impls/storage.js +50 -0
  259. package/dist/service-host/sync-impls/system-info.js +54 -0
  260. package/dist/shared/appdata-accumulator.d.ts +95 -0
  261. package/dist/shared/appdata-accumulator.js +213 -0
  262. package/dist/shared/bridge-channels.d.ts +364 -0
  263. package/dist/shared/bridge-channels.js +54 -0
  264. package/dist/shared/constants.d.ts +0 -4
  265. package/dist/shared/constants.js +0 -4
  266. package/dist/shared/ipc-channels.d.ts +108 -1
  267. package/dist/shared/ipc-channels.js +127 -10
  268. package/dist/shared/ipc-schemas.d.ts +65 -2
  269. package/dist/shared/ipc-schemas.js +79 -3
  270. package/dist/shared/open-in-editor.d.ts +71 -0
  271. package/dist/shared/open-in-editor.js +138 -0
  272. package/dist/shared/simulator-api-metadata.d.ts +21 -0
  273. package/dist/shared/simulator-api-metadata.js +23 -0
  274. package/dist/shared/types.d.ts +2 -2
  275. package/dist/shared/vpath.d.ts +42 -0
  276. package/dist/shared/vpath.js +105 -0
  277. package/dist/simulator/assets/device-shell-DsdcNEkt.css +1 -0
  278. package/dist/simulator/assets/device-shell-vwYSOVrh.js +2 -0
  279. package/dist/simulator/assets/jsx-runtime-P6ZegaOf.js +2 -0
  280. package/dist/simulator/assets/simulator-DddliUL5.js +10 -0
  281. package/dist/simulator/assets/simulator-mini-app-BDNu5n26.js +2 -0
  282. package/dist/simulator/device-shell/menu-button-geometry.js +8 -0
  283. package/dist/simulator/simulator.html +2 -112
  284. package/package.json +9 -9
  285. package/dist/main/utils/disposable.d.ts +0 -18
  286. package/dist/main/utils/disposable.js +0 -67
  287. package/dist/renderer/assets/constants-DI382mTP.js +0 -2
  288. package/dist/renderer/assets/index-4lkyF644.js +0 -46
  289. package/dist/renderer/assets/input-D4byFOLS.js +0 -2
  290. package/dist/renderer/assets/ipc-transport-DqbRdZNO.css +0 -1
  291. package/dist/renderer/assets/popover-cxKrg_os.js +0 -2
  292. package/dist/renderer/assets/select-BgSkkdHW.js +0 -2
  293. package/dist/renderer/assets/settings-oD2K1jdT.js +0 -2
  294. package/dist/renderer/assets/workbenchSettings-CTNBpTft.js +0 -8
  295. package/dist/simulator/assets/simulator-CVOFTpSj.js +0 -9
@@ -1,6 +1,11 @@
1
1
  import type { BrowserWindow } from 'electron';
2
2
  import type { CompilationAdapter, WorkbenchConfig } from '../../shared/types.js';
3
- import { DisposableRegistry } from '../utils/disposable.js';
3
+ import type { BridgeRouterHandle } from '../ipc/bridge-router.js';
4
+ import type { ConsoleForwarder } from './console-forward/index.js';
5
+ import type { NetworkForwarder } from './network-forward/index.js';
6
+ import type { AppDataTap } from './simulator-appdata/index.js';
7
+ import type { StorageApi } from './simulator-storage/index.js';
8
+ import { DisposableRegistry, type ConnectionRegistry } from '@dimina-kit/electron-deck/main';
4
9
  import type { SenderPolicy } from '../utils/ipc-registry.js';
5
10
  import { type RendererNotifier } from './notifications/renderer-notifier.js';
6
11
  import { type ViewManager } from './views/view-manager.js';
@@ -97,6 +102,66 @@ export interface WorkbenchContext {
97
102
  toolbar: ToolbarStore;
98
103
  /** Aggregates dispose handlers for every IPC handler, listener, watcher, and CDP session registered by the workbench. */
99
104
  registry: DisposableRegistry;
105
+ /**
106
+ * Per-webContents connection registry. Each trusted webContents (main window,
107
+ * overlay views, native simulator/render guests) is one `Connection` that
108
+ * owns the resources tied to its lifetime and tears them down deterministically
109
+ * on `webContents.once('destroyed')` (hard) or `reset(id)` (soft pool reuse).
110
+ * The substrate for connection-scoped resource ownership — see
111
+ * packages/electron-deck/docs/foundation.md §4. Domain services consume it by
112
+ * `own()`-ing their per-endpoint resources and observing `reset`/`closed`.
113
+ */
114
+ connections: ConnectionRegistry;
115
+ /**
116
+ * Accessor over the bridge-router's private state, set by `installBridgeRouter`.
117
+ * Lets other main services (simulator-storage, automation, appdata) resolve
118
+ * live render/service WebContents and the native-host flag without owning
119
+ * router state. Undefined until the bridge router is installed.
120
+ */
121
+ bridge?: BridgeRouterHandle;
122
+ /**
123
+ * Native-host AppData tap, set by `setupSimulatorAppData` (app.ts) when
124
+ * native-host is on. bridge-router feeds it the service→render setData stream
125
+ * + page evictions so the AppData panel can be sourced from main. Undefined on
126
+ * the default dimina-fe path (which sniffs setData via a Worker hook).
127
+ */
128
+ appData?: AppDataTap;
129
+ /**
130
+ * Native-host async-storage runtime hook, set by `setupSimulatorStorage` when
131
+ * native-host is on. bridge-router routes async `wx.setStorage`/etc. here so
132
+ * they hit the same service-host `file://` store as the sync APIs (one origin).
133
+ * Undefined on the default dimina-fe path (storage handled in the guest).
134
+ */
135
+ storageApi?: StorageApi;
136
+ /**
137
+ * Native-host console sink. The render-host / service-host guest preloads
138
+ * monkeypatch `console.*` and post each entry to main as a `consoleLog`
139
+ * container message; bridge-router routes those here. Owned by the
140
+ * `ConsoleForwarder` (set in `installBridgeRouter`), whose `emit` fans every
141
+ * entry out to subscribers (automation WS) AND mirrors render-layer entries
142
+ * into the service host's own console for the embedded DevTools.
143
+ */
144
+ guestConsole?: {
145
+ emit(entry: unknown): void;
146
+ };
147
+ /**
148
+ * Always-on console fan-out, set by `installBridgeRouter`. Other services
149
+ * (automation) call `subscribe` to receive every guest console entry instead
150
+ * of each clobbering `ctx.guestConsole`. Undefined until the bridge router is
151
+ * installed.
152
+ */
153
+ consoleForwarder?: ConsoleForwarder;
154
+ /**
155
+ * Native-host network forwarder, set in app bootstrap. Attaches the CDP
156
+ * debugger to the simulator WCV (where `wx.request`/`downloadFile`/`uploadFile`
157
+ * run) and injects its raw Network.* CDP events into the DevTools FRONT-END wc
158
+ * (`window.DevToolsAPI.dispatchMessage`) so the native Network tab renders them;
159
+ * falls back to a `[网络]` service-host console line when the front-end is
160
+ * unavailable. The ViewManager calls `attachSimulator` + `setDevtoolsHost` from
161
+ * `attachNativeSimulator` once the simulator WCV + DevTools host exist.
162
+ * Undefined until bootstrap wires it.
163
+ */
164
+ networkForward?: NetworkForwarder;
100
165
  }
101
166
  /**
102
167
  * Inputs for `createWorkbenchContext`. The scalar config fields it shares with
@@ -1,4 +1,4 @@
1
- import { DisposableRegistry } from '../utils/disposable.js';
1
+ import { createConnectionRegistry, DisposableRegistry, } from '@dimina-kit/electron-deck/main';
2
2
  import { createWorkbenchSenderPolicy } from '../utils/sender-policy.js';
3
3
  import { defaultAdapter } from './default-adapter.js';
4
4
  import { createRendererNotifier, } from './notifications/renderer-notifier.js';
@@ -32,6 +32,11 @@ export function createWorkbenchContext(opts) {
32
32
  brandingProvider: opts.brandingProvider,
33
33
  };
34
34
  ctx.registry = new DisposableRegistry();
35
+ // Empty connection registry as a first-class context field. Connections are
36
+ // acquired by real wiring points (app bootstrap, view-manager endpoints),
37
+ // NOT here — the constructor stays side-effect-free so focused unit tests can
38
+ // build a context with a minimal mainWindow fake.
39
+ ctx.connections = createConnectionRegistry();
35
40
  ctx.trustedWindowSenderIds = new Map();
36
41
  ctx.simulatorApis = createSimulatorApiRegistry();
37
42
  ctx.toolbar = createToolbarStore();
@@ -38,6 +38,14 @@ export interface WorkspaceService {
38
38
  appInfo: unknown;
39
39
  } | null;
40
40
  getProjectPath(): string;
41
+ /**
42
+ * The project path most recently torn down by `closeProject`, or '' if none
43
+ * since the last `openProject`. Lets the project-fs sandbox accept an
44
+ * in-flight write (debounced/teardown flush) that targets the just-closed
45
+ * project even though `getProjectPath()` has already been cleared. Reset to
46
+ * '' on the next `openProject` so it never accumulates stale roots.
47
+ */
48
+ getLastClosedProjectPath(): string;
41
49
  hasActiveSession(): boolean;
42
50
  captureThumbnail(projectPath: string): Promise<string | null>;
43
51
  getThumbnail(projectPath: string): Promise<string | null>;
@@ -6,6 +6,10 @@ import { loadWorkbenchSettings } from '../settings/index.js';
6
6
  export function createWorkspaceService(ctx) {
7
7
  let currentSession = null;
8
8
  let currentProjectPath = '';
9
+ // The last project path cleared by `closeProject`; consumed by project-fs to
10
+ // accept an in-flight write that targets the just-closed project. Reset at
11
+ // the start of every `openProject` so it never accumulates a stale root.
12
+ let lastClosedProjectPath = '';
9
13
  function sendStatus(status, message, hotReload) {
10
14
  ctx.notify.projectStatus(hotReload ? { status, message, hotReload: true } : { status, message });
11
15
  }
@@ -61,6 +65,9 @@ export function createWorkspaceService(ctx) {
61
65
  clearSimulatorServicewechatReferer();
62
66
  await disposeSession();
63
67
  currentProjectPath = '';
68
+ // A fresh open starts a clean sandbox window — drop any previously
69
+ // recorded last-closed root so it can't accept writes after this point.
70
+ lastClosedProjectPath = '';
64
71
  // Reject obviously broken projects up front so we never spin up a
65
72
  // compile/server that the simulator will then fetch asset-by-asset.
66
73
  // Without this guard, deleted recent-list entries and typo'd CLI paths
@@ -109,11 +116,16 @@ export function createWorkspaceService(ctx) {
109
116
  async closeProject() {
110
117
  clearSimulatorServicewechatReferer();
111
118
  await disposeSession();
119
+ // Record the root being torn down BEFORE clearing it, so a teardown/
120
+ // debounced write already in flight can still be accepted against it.
121
+ if (currentProjectPath !== '')
122
+ lastClosedProjectPath = currentProjectPath;
112
123
  currentProjectPath = '';
113
124
  ctx.views.disposeAll();
114
125
  },
115
126
  getSession: () => currentSession,
116
127
  getProjectPath: () => currentProjectPath,
128
+ getLastClosedProjectPath: () => lastClosedProjectPath,
117
129
  hasActiveSession: () => currentSession !== null,
118
130
  async captureThumbnail(projectPath) {
119
131
  const wc = ctx.views.getSimulatorWebContents();
@@ -1,6 +1,6 @@
1
- import type { WebContents } from 'electron';
1
+ import type { IpcMainEvent, WebContents } from 'electron';
2
2
  import { ipcMain } from 'electron';
3
- import { type Disposable } from './disposable.js';
3
+ import { type Disposable } from '@dimina-kit/electron-deck/main';
4
4
  type HandleFn = Parameters<typeof ipcMain.handle>[1];
5
5
  type ListenerFn = Parameters<typeof ipcMain.on>[1];
6
6
  /**
@@ -32,6 +32,15 @@ export declare class IpcRegistry implements Disposable {
32
32
  private registry;
33
33
  constructor(policy?: SenderPolicy | undefined);
34
34
  handle(channel: string, fn: HandleFn): this;
35
+ /**
36
+ * Register a SYNCHRONOUS `ipcRenderer.sendSync` handler. Unlike {@link on}
37
+ * (fire-and-forget), the renderer is blocked until we set `event.returnValue`,
38
+ * so `fn` MUST be synchronous and return the value to hand back. The sender
39
+ * policy gates it like {@link handle}; a rejected sender or a thrown error
40
+ * yields a structured `{ ok: false, code, message }` returnValue instead of
41
+ * the silent drop `on` uses, so the blocked renderer always gets an answer.
42
+ */
43
+ handleSync(channel: string, fn: (event: IpcMainEvent, ...args: unknown[]) => unknown): this;
35
44
  on(channel: string, fn: ListenerFn): this;
36
45
  dispose(): Promise<void>;
37
46
  }
@@ -1,5 +1,5 @@
1
1
  import { ipcMain } from 'electron';
2
- import { DisposableRegistry } from './disposable.js';
2
+ import { DisposableRegistry } from '@dimina-kit/electron-deck/main';
3
3
  import { IpcValidationError } from './ipc-schema.js';
4
4
  import { createLogger } from './logger.js';
5
5
  const log = createLogger('ipc');
@@ -30,6 +30,23 @@ function summarizeSender(sender) {
30
30
  const url = sender.getURL();
31
31
  return `id=${sender.id} ${url.slice(0, 120)}`;
32
32
  }
33
+ function isMainFrameSender(event) {
34
+ // Read via loose casts: the Electron types declare these always-present, but
35
+ // unit-test stubs legitimately omit them — and real events can carry a null
36
+ // senderFrame after navigation/destruction.
37
+ const frame = event.senderFrame;
38
+ const main = event.sender.mainFrame;
39
+ // Frame-unaware stub (NEITHER field modeled) → not a real frame boundary; the
40
+ // sender-id white-list is the gate. Real events always have both, so they fall
41
+ // through to the strict check; a partial/malformed event (only one field) also
42
+ // falls through and fail-closes below rather than escaping here.
43
+ if (frame === undefined && main === undefined)
44
+ return true;
45
+ // Real event, unresolvable frame (navigate-after-send / destroyed) → reject.
46
+ if (frame == null || main == null)
47
+ return false;
48
+ return frame.routingId === main.routingId && frame.processId === main.processId;
49
+ }
33
50
  /**
34
51
  * Tiny fluent helper that wraps every `ipcMain.handle` / `ipcMain.on` with a
35
52
  * matching removeHandler/removeListener registered into an internal registry.
@@ -62,7 +79,7 @@ export class IpcRegistry {
62
79
  const guarded = policy
63
80
  ? async (event, ...args) => {
64
81
  const sender = event.sender;
65
- if (!policy(sender)) {
82
+ if (!policy(sender) || !isMainFrameSender(event)) {
66
83
  console.warn(`[ipc] sender rejected for channel '${channel}' (${summarizeSender(sender)})`);
67
84
  throw new Error(`IPC sender rejected for channel ${channel}`);
68
85
  }
@@ -73,6 +90,49 @@ export class IpcRegistry {
73
90
  this.registry.add(() => ipcMain.removeHandler(channel));
74
91
  return this;
75
92
  }
93
+ /**
94
+ * Register a SYNCHRONOUS `ipcRenderer.sendSync` handler. Unlike {@link on}
95
+ * (fire-and-forget), the renderer is blocked until we set `event.returnValue`,
96
+ * so `fn` MUST be synchronous and return the value to hand back. The sender
97
+ * policy gates it like {@link handle}; a rejected sender or a thrown error
98
+ * yields a structured `{ ok: false, code, message }` returnValue instead of
99
+ * the silent drop `on` uses, so the blocked renderer always gets an answer.
100
+ */
101
+ handleSync(channel, fn) {
102
+ const policy = this.policy;
103
+ const listener = (event, ...args) => {
104
+ // Everything — including the policy check — runs inside the try so EVERY
105
+ // path sets `event.returnValue`. sendSync blocks the renderer until it is
106
+ // set, so an unset value (e.g. a throwing policy fn) would hang the
107
+ // renderer forever; the catch guarantees a sentinel instead.
108
+ try {
109
+ if (policy && (!policy(event.sender) || !isMainFrameSender(event))) {
110
+ console.warn(`[ipc] sender rejected for channel '${channel}' (${summarizeSender(event.sender)})`);
111
+ event.returnValue = {
112
+ ok: false,
113
+ code: 'EREJECTED',
114
+ message: `IPC sender rejected for channel ${channel}`,
115
+ };
116
+ return;
117
+ }
118
+ event.returnValue = fn(event, ...args);
119
+ }
120
+ catch (err) {
121
+ reportListenerError(channel, err);
122
+ const code = err?.code;
123
+ event.returnValue = {
124
+ ok: false,
125
+ code: typeof code === 'string' ? code : 'EUNKNOWN',
126
+ message: err instanceof Error ? err.message : String(err),
127
+ };
128
+ }
129
+ };
130
+ ipcMain.on(channel, listener);
131
+ this.registry.add(() => {
132
+ ipcMain.removeListener(channel, listener);
133
+ });
134
+ return this;
135
+ }
76
136
  on(channel, fn) {
77
137
  const policy = this.policy;
78
138
  const raw = fn;
@@ -93,7 +153,7 @@ export class IpcRegistry {
93
153
  const guarded = policy
94
154
  ? (event, ...args) => {
95
155
  const sender = event.sender;
96
- if (!policy(sender)) {
156
+ if (!policy(sender) || !isMainFrameSender(event)) {
97
157
  console.warn(`[ipc] sender rejected for channel '${channel}' (${summarizeSender(sender)})`);
98
158
  return;
99
159
  }
@@ -1,12 +1,27 @@
1
1
  export declare const devtoolsPackageRoot: string;
2
2
  export declare const rendererDir: string;
3
3
  export declare const defaultPreloadPath: string;
4
+ /**
5
+ * Resolve the CommonJS sibling (`*.cjs`) of a simulator preload bundle.
6
+ *
7
+ * A `<webview>`/session-frame preload is always loaded as CommonJS by Electron.
8
+ * The native-host simulator (the sole runtime) instead runs in a top-level
9
+ * WebContentsView whose `webPreferences.preload` obeys the `.js` +
10
+ * `"type":"module"` ESM rule — so the `.js` bundle would fail with
11
+ * `require is not defined`. We ship a byte-identical `.cjs` copy
12
+ * (build:preload emits both) and hand the WCV the `.cjs` sibling. If a host
13
+ * supplies a custom `.js` preload, we swap the extension; an already-`.cjs`
14
+ * path (or any non-`.js`) is returned unchanged.
15
+ */
16
+ export declare function cjsSiblingPreloadPath(preloadPath: string): string;
4
17
  /**
5
18
  * Preload bundle for the main window, settings window, and the settings /
6
19
  * popover overlay WebContentsViews. Exposes `window.devtools.ipc` via
7
20
  * contextBridge so the renderer never needs `window.require('electron')`.
8
21
  */
9
22
  export declare const mainPreloadPath: string;
23
+ /** Preload for the host-controllable toolbar WCV — runs the reverse size-advertiser. */
24
+ export declare const hostToolbarPreloadPath: string;
10
25
  export declare const simulatorDir: string;
11
26
  export declare function getRendererDir(): string;
12
27
  export declare function getPreloadDir(): string;
@@ -25,12 +25,31 @@ function resolveDevtoolsPackageRoot() {
25
25
  export const devtoolsPackageRoot = resolveDevtoolsPackageRoot();
26
26
  export const rendererDir = path.join(devtoolsPackageRoot, 'dist/renderer');
27
27
  export const defaultPreloadPath = path.join(devtoolsPackageRoot, 'dist/preload/windows/simulator.js');
28
+ /**
29
+ * Resolve the CommonJS sibling (`*.cjs`) of a simulator preload bundle.
30
+ *
31
+ * A `<webview>`/session-frame preload is always loaded as CommonJS by Electron.
32
+ * The native-host simulator (the sole runtime) instead runs in a top-level
33
+ * WebContentsView whose `webPreferences.preload` obeys the `.js` +
34
+ * `"type":"module"` ESM rule — so the `.js` bundle would fail with
35
+ * `require is not defined`. We ship a byte-identical `.cjs` copy
36
+ * (build:preload emits both) and hand the WCV the `.cjs` sibling. If a host
37
+ * supplies a custom `.js` preload, we swap the extension; an already-`.cjs`
38
+ * path (or any non-`.js`) is returned unchanged.
39
+ */
40
+ export function cjsSiblingPreloadPath(preloadPath) {
41
+ return preloadPath.endsWith('.js')
42
+ ? preloadPath.slice(0, -'.js'.length) + '.cjs'
43
+ : preloadPath;
44
+ }
28
45
  /**
29
46
  * Preload bundle for the main window, settings window, and the settings /
30
47
  * popover overlay WebContentsViews. Exposes `window.devtools.ipc` via
31
48
  * contextBridge so the renderer never needs `window.require('electron')`.
32
49
  */
33
50
  export const mainPreloadPath = path.join(devtoolsPackageRoot, 'dist/preload/windows/main.cjs');
51
+ /** Preload for the host-controllable toolbar WCV — runs the reverse size-advertiser. */
52
+ export const hostToolbarPreloadPath = path.join(devtoolsPackageRoot, 'dist/preload/windows/host-toolbar.cjs');
34
53
  export const simulatorDir = path.join(devtoolsPackageRoot, 'dist/simulator');
35
54
  export function getRendererDir() {
36
55
  return rendererDir;
@@ -12,9 +12,15 @@ import type { SenderPolicy } from './ipc-registry.js';
12
12
  *
13
13
  * The simulator webview is intentionally NOT on this list. Anything it
14
14
  * needs from main (currently just the custom-apis bridge — see
15
- * `installCustomApisBridge` in `src/preload/runtime/custom-apis.ts` and the
16
- * matching `useCustomApiProxy` host hook) proxies through the trusted
17
- * main-window renderer via `ipcRenderer.sendToHost` + `<webview>.send`.
15
+ * `installCustomApisBridge` in `src/preload/runtime/custom-apis.ts`) reaches
16
+ * the host without being white-listed here via the native-host path:
17
+ * the simulator is a top-level WebContentsView (no embedder), and its
18
+ * custom-api traffic is dispatched by a `ctx.simulatorApis`-backed
19
+ * `ipcMain.on` listener bound to that exact simWc in view-manager
20
+ * `attachNativeCustomApiBridge` — it gates on the precise sender id rather
21
+ * than this white-list. (Historically a `<webview>` simulator proxied through
22
+ * the trusted main-window renderer via `ipcRenderer.sendToHost` + `<webview>.send`;
23
+ * that renderer-proxied path no longer exists — native-host is the sole runtime.)
18
24
  * Keeping the guest off this list contains the blast radius if the
19
25
  * simulator content is ever compromised.
20
26
  *
@@ -10,9 +10,15 @@
10
10
  *
11
11
  * The simulator webview is intentionally NOT on this list. Anything it
12
12
  * needs from main (currently just the custom-apis bridge — see
13
- * `installCustomApisBridge` in `src/preload/runtime/custom-apis.ts` and the
14
- * matching `useCustomApiProxy` host hook) proxies through the trusted
15
- * main-window renderer via `ipcRenderer.sendToHost` + `<webview>.send`.
13
+ * `installCustomApisBridge` in `src/preload/runtime/custom-apis.ts`) reaches
14
+ * the host without being white-listed here via the native-host path:
15
+ * the simulator is a top-level WebContentsView (no embedder), and its
16
+ * custom-api traffic is dispatched by a `ctx.simulatorApis`-backed
17
+ * `ipcMain.on` listener bound to that exact simWc in view-manager
18
+ * `attachNativeCustomApiBridge` — it gates on the precise sender id rather
19
+ * than this white-list. (Historically a `<webview>` simulator proxied through
20
+ * the trusted main-window renderer via `ipcRenderer.sendToHost` + `<webview>.send`;
21
+ * that renderer-proxied path no longer exists — native-host is the sole runtime.)
16
22
  * Keeping the guest off this list contains the blast radius if the
17
23
  * simulator content is ever compromised.
18
24
  *
@@ -43,7 +49,15 @@ export function createWorkbenchSenderPolicy(ctx) {
43
49
  const popoverViewId = ctx.views.getPopoverWebContentsId();
44
50
  if (popoverViewId != null && sender.id === popoverViewId)
45
51
  return true;
46
- // simulator <webview> proxies through main-window renderer (see file header).
52
+ // The host-toolbar overlay is DELIBERATELY NOT trusted here. The host loads
53
+ // arbitrary content into it, so granting it the global white-list would open
54
+ // all ~72 IpcRegistry channels to that content. Its one channel (the reverse
55
+ // size-advertiser) is instead a raw `ipcMain.on` gated on its exact wc id in
56
+ // `registerViewsIpc` — same blast-radius containment as the simulator guest.
57
+ // The simulator (a top-level WebContentsView under native-host) is also
58
+ // DELIBERATELY off this white-list; its custom-api traffic is gated on the
59
+ // exact simWc id elsewhere (see file header). There is no longer a
60
+ // renderer-proxied <webview> simulator path.
47
61
  return false;
48
62
  };
49
63
  }
@@ -1,4 +1,4 @@
1
- import { type Disposable } from './disposable.js';
1
+ import { type Disposable } from '@dimina-kit/electron-deck/main';
2
2
  /**
3
3
  * Background color that matches the current system color scheme.
4
4
  * Pass as `backgroundColor` when creating BrowserWindows to prevent
@@ -1,5 +1,5 @@
1
1
  import { BrowserWindow, nativeTheme } from 'electron';
2
- import { toDisposable } from './disposable.js';
2
+ import { toDisposable } from '@dimina-kit/electron-deck/main';
3
3
  /**
4
4
  * Background color that matches the current system color scheme.
5
5
  * Pass as `backgroundColor` when creating BrowserWindows to prevent
@@ -6,12 +6,6 @@ export interface WindowOptions {
6
6
  minWidth?: number;
7
7
  minHeight?: number;
8
8
  indexHtml: string;
9
- /**
10
- * Absolute path to the simulator preload bundle. Registered at the session
11
- * level so every frame inside the simulator <webview> gets the preload that
12
- * exposes the `wx` runtime to the mini-program.
13
- */
14
- simulatorPreloadPath: string;
15
9
  }
16
10
  export declare function createMainWindow(opts: WindowOptions): BrowserWindow;
17
11
  //# sourceMappingURL=create.d.ts.map
@@ -1,21 +1,15 @@
1
- import { app, BrowserWindow, View, session, shell } from 'electron';
1
+ import { app, BrowserWindow, View, session } from 'electron';
2
2
  import path from 'path';
3
3
  import { getSimulatorServicewechatReferer } from '../../services/simulator/referer.js';
4
4
  import { mainPreloadPath } from '../../utils/paths.js';
5
5
  import { themeBg } from '../../utils/theme.js';
6
- import { applyNavigationHardening, handleWindowOpenExternal, } from '../navigation-hardening.js';
6
+ import { applyNavigationHardening } from '../navigation-hardening.js';
7
7
  let simulatorSessionConfigured = false;
8
- function configureSimulatorSession(simulatorPreloadPath) {
8
+ function configureSimulatorSession() {
9
9
  if (simulatorSessionConfigured)
10
10
  return;
11
11
  simulatorSessionConfigured = true;
12
12
  const simulatorSession = session.fromPartition('persist:simulator');
13
- // Inject the simulator preload on every frame in this session. This is the
14
- // mini-program runtime entry point (exposes `wx`, page registers, etc.).
15
- simulatorSession.registerPreloadScript({
16
- type: 'frame',
17
- filePath: simulatorPreloadPath,
18
- });
19
13
  simulatorSession.webRequest.onBeforeSendHeaders((details, callback) => {
20
14
  const forcedReferer = getSimulatorServicewechatReferer();
21
15
  if (forcedReferer) {
@@ -25,16 +19,17 @@ function configureSimulatorSession(simulatorPreloadPath) {
25
19
  });
26
20
  simulatorSession.webRequest.onHeadersReceived((details, callback) => {
27
21
  const headers = details.responseHeaders ?? {};
22
+ // CORS for the native render/service hosts to fetch compiled app resources
23
+ // cross-origin. (The COOP/COEP cross-origin-isolation headers were only for
24
+ // the removed default-path SharedArrayBuffer sync Worker — dropped.)
28
25
  headers['access-control-allow-origin'] = ['*'];
29
26
  headers['access-control-allow-headers'] = ['*'];
30
27
  headers['access-control-allow-methods'] = ['*'];
31
- headers['Cross-Origin-Opener-Policy'] = ['same-origin'];
32
- headers['Cross-Origin-Embedder-Policy'] = ['credentialless'];
33
28
  callback({ responseHeaders: headers });
34
29
  });
35
30
  }
36
31
  export function createMainWindow(opts) {
37
- configureSimulatorSession(opts.simulatorPreloadPath);
32
+ configureSimulatorSession();
38
33
  const mainWindow = new BrowserWindow({
39
34
  width: opts.width ?? 1280,
40
35
  height: opts.height ?? 980,
@@ -50,8 +45,6 @@ export function createMainWindow(opts) {
50
45
  // to access contextBridge/ipcRenderer. The renderer itself runs isolated.
51
46
  sandbox: false,
52
47
  preload: mainPreloadPath,
53
- // The simulator <webview> still relies on the webview tag; keep it enabled.
54
- webviewTag: true,
55
48
  },
56
49
  });
57
50
  mainWindow.once('ready-to-show', () => {
@@ -60,7 +53,10 @@ export function createMainWindow(opts) {
60
53
  }
61
54
  else {
62
55
  mainWindow.show();
63
- if (!app.isPackaged) {
56
+ // Don't auto-open a detached DevTools for the devtools UI shell itself —
57
+ // it's noise for normal use (the mini-app's Console lives in the embedded
58
+ // right-panel DevTools, not here). Opt in via env for debugging the shell.
59
+ if (!app.isPackaged && process.env.DIMINA_DEVTOOLS_MAIN_INSPECTOR === '1') {
64
60
  mainWindow.webContents.openDevTools({ mode: 'detach' });
65
61
  }
66
62
  }
@@ -69,50 +65,6 @@ export function createMainWindow(opts) {
69
65
  // Restrict the main renderer to file:// URLs under the renderer bundle and
70
66
  // route every popup through the OS browser. See navigation-hardening.ts.
71
67
  applyNavigationHardening(mainWindow.webContents, rendererDir);
72
- mainWindow.webContents.on('will-attach-webview', (event, webPreferences, params) => {
73
- // Pin the simulator <webview> onto `persist:simulator` so it shares storage
74
- // with the rest of the session and picks up the session-registered preload.
75
- // Empirically (Electron 41) `webPreferences.partition` is the field the
76
- // guest session actually consults; `params.partition` alone is a no-op,
77
- // so we write both belt-and-braces.
78
- ;
79
- webPreferences.partition = 'persist:simulator';
80
- params.partition = 'persist:simulator';
81
- // The simulator <webview> intentionally runs with `contextIsolation: false`
82
- // because the dimina runtime and the user-authored preload scripts share
83
- // the same JavaScript realm as the page — the mini-program SDK reaches
84
- // into the page's globals (e.g. AudioContext, custom registers) and
85
- // attaches helpers via window-level injection. Flipping isolation on
86
- // would break that contract.
87
- webPreferences.contextIsolation = false;
88
- void event;
89
- });
90
- // The simulator webview's webContents only exists once attached; wire its
91
- // window-open / will-navigate handlers here so popups + redirects don't
92
- // pivot to file:// or arbitrary origins.
93
- mainWindow.webContents.on('did-attach-webview', (_event, webviewWebContents) => {
94
- webviewWebContents.setWindowOpenHandler(({ url }) => handleWindowOpenExternal(url));
95
- webviewWebContents.on('will-navigate', (e, url) => {
96
- try {
97
- const u = new URL(url);
98
- // Allow the simulator's own host (localhost dev server) plus the
99
- // initial about:blank that Chromium uses before src loads.
100
- if (u.protocol === 'about:')
101
- return;
102
- if ((u.protocol === 'http:' || u.protocol === 'https:') &&
103
- (u.hostname === 'localhost' || u.hostname === '127.0.0.1')) {
104
- return;
105
- }
106
- e.preventDefault();
107
- if (u.protocol === 'http:' || u.protocol === 'https:') {
108
- void shell.openExternal(url);
109
- }
110
- }
111
- catch {
112
- e.preventDefault();
113
- }
114
- });
115
- });
116
68
  mainWindow.loadFile(opts.indexHtml);
117
69
  const container = new View();
118
70
  const mainWebView = mainWindow.contentView;
@@ -1,6 +1,6 @@
1
1
  import type { BrowserWindow } from 'electron';
2
2
  import type { WorkbenchContext } from '../../services/workbench-context.js';
3
- import { type Disposable } from '../../utils/disposable.js';
3
+ import { type Disposable } from '@dimina-kit/electron-deck/main';
4
4
  export interface MainWindowEventState {
5
5
  context?: WorkbenchContext;
6
6
  onResize?: () => void;
@@ -1,5 +1,5 @@
1
1
  import { globalShortcut } from 'electron';
2
- import { DisposableRegistry, toDisposable } from '../../utils/disposable.js';
2
+ import { DisposableRegistry, toDisposable } from '@dimina-kit/electron-deck/main';
3
3
  export function wireMainWindowEvents(win, state = {}) {
4
4
  const registry = new DisposableRegistry();
5
5
  const mainWebView = win.contentView.children[0];
@@ -0,0 +1,52 @@
1
+ import { BrowserWindow } from 'electron';
2
+ import type { ServiceHostSpec } from '../../services/service-host-pool/pool.js';
3
+ /** Session partition the service host shares with the simulator `<webview>`. */
4
+ export declare const SERVICE_HOST_PARTITION = "persist:simulator";
5
+ /** Absolute path to the service-host preload (loaded at runtime by path). */
6
+ export declare const serviceHostPreloadPath: string;
7
+ export interface ServiceHostWindowOptions {
8
+ bridgeId: string;
9
+ appId: string;
10
+ pagePath: string;
11
+ pkgRoot: string;
12
+ resourceBaseUrl: string;
13
+ hostEnvSnapshot?: Record<string, unknown>;
14
+ }
15
+ /**
16
+ * Construct an (un-navigated) service-host BrowserWindow. Split out from
17
+ * `createServiceHostWindow` so a pre-warm pool can build the window once and
18
+ * navigate it per spawn (the spawn context lives in the URL — see
19
+ * `buildServiceHostSpawnUrl`). The process-model flags here are the contract
20
+ * the service-host preload depends on (it `require('electron')` and writes
21
+ * globals onto the page realm).
22
+ */
23
+ export declare function constructServiceHostWindow(opts?: {
24
+ appId?: string;
25
+ partition?: string;
26
+ }): BrowserWindow;
27
+ /**
28
+ * Build the file:// spawn URL carrying the per-spawn context the preload reads
29
+ * from `location.search` at eval time (bridgeId/appId/pagePath/pkgRoot/
30
+ * resourceBaseUrl/hostEnv).
31
+ */
32
+ export declare function buildServiceHostSpawnUrl(opts: ServiceHostWindowOptions): string;
33
+ /**
34
+ * Navigate a (constructed or pooled) service-host window to its spawn URL. The
35
+ * preload re-evaluates on this navigation, rebuilding `__diminaSpawnContext`.
36
+ * Returns the load promise (resolves on did-finish-load). Attaches the dev-only
37
+ * detached-DevTools hook, matching the original behavior.
38
+ */
39
+ export declare function navigateServiceHost(win: BrowserWindow, url: string): Promise<void>;
40
+ /**
41
+ * The spec a `ServiceHostPool` uses to pre-warm service-host windows. Keeps the
42
+ * pooled window byte-equivalent to `constructServiceHostWindow`'s output, and
43
+ * opts out of the reset storage-clear because the service host shares the
44
+ * `persist:simulator` session with live projects (see ServiceHostSpec docs).
45
+ */
46
+ export declare function serviceHostSpec(): ServiceHostSpec;
47
+ /**
48
+ * Construct + navigate a fresh service-host window (the non-pool path).
49
+ * Behavior-identical to the pre-refactor implementation.
50
+ */
51
+ export declare function createServiceHostWindow(opts: ServiceHostWindowOptions): BrowserWindow;
52
+ //# sourceMappingURL=create.d.ts.map