@dimina-kit/devtools 0.4.0-dev.20260729062524 → 0.4.0-dev.20260801163345

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 (104) hide show
  1. package/dist/main/app/app.js +7 -0
  2. package/dist/main/app/bootstrap.d.ts +8 -5
  3. package/dist/main/app/bootstrap.js +15 -15
  4. package/dist/main/index.bundle.js +2207 -5152
  5. package/dist/main/ipc/app-lifecycle.d.ts +1 -31
  6. package/dist/main/ipc/app-lifecycle.js +1 -53
  7. package/dist/main/ipc/bridge-router.d.ts +19 -152
  8. package/dist/main/ipc/bridge-router.js +28 -2186
  9. package/dist/main/ipc/page-scroll.d.ts +1 -13
  10. package/dist/main/ipc/page-scroll.js +1 -16
  11. package/dist/main/ipc/session-listener-bag.d.ts +1 -40
  12. package/dist/main/ipc/session-listener-bag.js +1 -39
  13. package/dist/main/services/console-forward/index.d.ts +1 -60
  14. package/dist/main/services/console-forward/index.js +1 -225
  15. package/dist/main/services/console-forward/internal-log.d.ts +1 -10
  16. package/dist/main/services/console-forward/internal-log.js +1 -22
  17. package/dist/main/services/diagnostics/index.d.ts +1 -58
  18. package/dist/main/services/diagnostics/index.js +1 -60
  19. package/dist/main/services/dimina-resource-server.d.ts +1 -6
  20. package/dist/main/services/dimina-resource-server.js +1 -98
  21. package/dist/main/services/mcp/target-manager.js +5 -1
  22. package/dist/main/services/network-forward/index.d.ts +15 -3
  23. package/dist/main/services/network-forward/index.js +30 -4
  24. package/dist/main/services/network-forward/websocket.d.ts +36 -0
  25. package/dist/main/services/network-forward/websocket.js +120 -0
  26. package/dist/main/services/service-host-pool/pool.d.ts +1 -196
  27. package/dist/main/services/service-host-pool/pool.js +1 -363
  28. package/dist/main/services/simulator/custom-apis.d.ts +1 -42
  29. package/dist/main/services/simulator/custom-apis.js +1 -46
  30. package/dist/main/services/simulator/referer.d.ts +1 -9
  31. package/dist/main/services/simulator/referer.js +1 -19
  32. package/dist/main/services/simulator-storage/service-storage-ops.d.ts +1 -39
  33. package/dist/main/services/simulator-storage/service-storage-ops.js +1 -66
  34. package/dist/main/services/simulator-temp-files/disk.d.ts +1 -54
  35. package/dist/main/services/simulator-temp-files/disk.js +1 -237
  36. package/dist/main/services/simulator-temp-files/fs-channels.d.ts +1 -68
  37. package/dist/main/services/simulator-temp-files/fs-channels.js +1 -107
  38. package/dist/main/services/simulator-temp-files/index.d.ts +1 -32
  39. package/dist/main/services/simulator-temp-files/index.js +1 -181
  40. package/dist/main/services/simulator-temp-files/request-handler.d.ts +1 -29
  41. package/dist/main/services/simulator-temp-files/request-handler.js +1 -177
  42. package/dist/main/services/simulator-temp-files/resolver.d.ts +1 -21
  43. package/dist/main/services/simulator-temp-files/resolver.js +1 -21
  44. package/dist/main/services/simulator-temp-files/store.d.ts +1 -13
  45. package/dist/main/services/simulator-temp-files/store.js +1 -23
  46. package/dist/main/services/views/miniapp-partition.d.ts +1 -89
  47. package/dist/main/services/views/miniapp-partition.js +1 -158
  48. package/dist/main/services/views/simulator-session-policy.d.ts +1 -27
  49. package/dist/main/services/views/simulator-session-policy.js +1 -98
  50. package/dist/main/services/workbench-context.d.ts +4 -1
  51. package/dist/main/services/workbench-context.js +17 -0
  52. package/dist/main/utils/ipc-registry.d.ts +21 -3
  53. package/dist/main/utils/ipc-registry.js +26 -23
  54. package/dist/main/utils/paths.d.ts +14 -0
  55. package/dist/main/utils/paths.js +14 -0
  56. package/dist/main/windows/service-host-window/create.d.ts +1 -92
  57. package/dist/main/windows/service-host-window/create.js +1 -154
  58. package/dist/native-host/common/common.js +154 -58
  59. package/dist/native-host/container/pageFrame.css +1 -1
  60. package/dist/native-host/render/render.js +6611 -3312
  61. package/dist/native-host/service/service.js +2 -2
  62. package/dist/preload/index.d.ts +2 -0
  63. package/dist/preload/index.js +1 -0
  64. package/dist/preload/runtime/clipboard.d.ts +6 -0
  65. package/dist/preload/runtime/clipboard.js +12 -0
  66. package/dist/preload/runtime/native-host.d.ts +2 -0
  67. package/dist/preload/runtime/native-host.js +5 -10
  68. package/dist/preload/runtime/node-bindings.d.ts +18 -0
  69. package/dist/preload/runtime/node-bindings.js +44 -0
  70. package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
  71. package/dist/preload/windows/main.cjs +1195 -897
  72. package/dist/preload/windows/main.cjs.map +4 -4
  73. package/dist/preload/windows/simulator.cjs +149 -60
  74. package/dist/preload/windows/simulator.cjs.map +4 -4
  75. package/dist/preload/windows/simulator.js +149 -60
  76. package/dist/render-host/pageFrame.html +3 -3
  77. package/dist/shared/bridge-channels.d.ts +1 -419
  78. package/dist/shared/bridge-channels.js +1 -89
  79. package/dist/shared/dmb-resource-url.d.ts +2 -0
  80. package/dist/shared/dmb-resource-url.js +2 -0
  81. package/dist/shared/ipc-channels.d.ts +2 -32
  82. package/dist/shared/ipc-channels.js +2 -5
  83. package/dist/shared/node-bindings.d.ts +2 -0
  84. package/dist/shared/node-bindings.js +2 -0
  85. package/dist/shared/request-core.d.ts +1 -83
  86. package/dist/shared/request-core.js +1 -167
  87. package/dist/simulator/assets/device-shell-Cw7c-IkG.js +2 -0
  88. package/dist/simulator/assets/{device-shell-BHz1v3Yo.css → device-shell-DbC5ccs8.css} +1 -1
  89. package/dist/simulator/assets/{jsx-runtime-hBv-rHqQ.js → jsx-runtime-DkKmJyBb.js} +2 -2
  90. package/dist/simulator/assets/simulator-COIE6R49.js +10 -0
  91. package/dist/simulator/assets/simulator-mini-app-BLn7XV8e.js +2 -0
  92. package/dist/simulator/simulator.html +2 -2
  93. package/dist/simulator/temp-files.d.ts +29 -0
  94. package/dist/simulator/temp-files.js +79 -0
  95. package/dist/simulator/types.d.ts +43 -0
  96. package/dist/simulator/types.js +2 -0
  97. package/package.json +6 -5
  98. package/dist/shared/simulator-api-metadata.d.ts +0 -26
  99. package/dist/shared/simulator-api-metadata.js +0 -59
  100. package/dist/shared/vpath.d.ts +0 -42
  101. package/dist/shared/vpath.js +0 -105
  102. package/dist/simulator/assets/device-shell-CH_DMYaz.js +0 -2
  103. package/dist/simulator/assets/simulator-DXraYerh.js +0 -10
  104. package/dist/simulator/assets/simulator-mini-app-w1Bhwkld.js +0 -2
@@ -1,14 +1,2 @@
1
- /**
2
- * Build the script that `wx.pageScrollTo` runs inside the page's render guest.
3
- *
4
- * The mini-program page scrolls the whole render document (the native iOS impl
5
- * scrolls the WKWebView's scrollView; Android scrolls the page view), so the
6
- * simulator scrolls `window`. `duration` is best-effort: a positive duration
7
- * maps to smooth scrolling (the browser owns the easing — the exact ms is not
8
- * controllable), and `0` jumps instantly.
9
- */
10
- export declare function buildPageScrollScript(params: {
11
- scrollTop?: unknown;
12
- duration?: unknown;
13
- }): string;
1
+ export * from '@dimina-kit/electron-runtime/main/page-scroll';
14
2
  //# sourceMappingURL=page-scroll.d.ts.map
@@ -1,17 +1,2 @@
1
- /**
2
- * Build the script that `wx.pageScrollTo` runs inside the page's render guest.
3
- *
4
- * The mini-program page scrolls the whole render document (the native iOS impl
5
- * scrolls the WKWebView's scrollView; Android scrolls the page view), so the
6
- * simulator scrolls `window`. `duration` is best-effort: a positive duration
7
- * maps to smooth scrolling (the browser owns the easing — the exact ms is not
8
- * controllable), and `0` jumps instantly.
9
- */
10
- export function buildPageScrollScript(params) {
11
- const rawTop = Number(params.scrollTop);
12
- const top = Number.isFinite(rawTop) ? rawTop : 0;
13
- const duration = params.duration === undefined ? 300 : Number(params.duration);
14
- const behavior = Number.isFinite(duration) && duration > 0 ? 'smooth' : 'auto';
15
- return `window.scrollTo({ top: ${top}, left: 0, behavior: ${JSON.stringify(behavior)} })`;
16
- }
1
+ export * from '@dimina-kit/electron-runtime/main/page-scroll';
17
2
  //# sourceMappingURL=page-scroll.js.map
@@ -1,41 +1,2 @@
1
- /**
2
- * Session-scoped listener bookkeeping. An app session hangs lifecycle hooks on
3
- * emitters it does NOT own — the shared simulator WebContentsView, a pooled
4
- * service-host window — and those emitters outlive the session (one simulator
5
- * wc soft-reloads through many sessions). Every such hook is registered
6
- * through this bag so the session's single teardown chokepoint can detach them
7
- * all with one `dispose()`; a hook left behind survives as a dead listener on
8
- * the shared emitter, growing by one per soft reload until Node's MaxListeners
9
- * warning fires.
10
- */
11
- type Listener = (...args: unknown[]) => void;
12
- /**
13
- * Structural surface of the Node/Electron emitters the bag manages.
14
- * `removeListener(event, fn)` also detaches a `once(event, fn)` registration:
15
- * Node's once wrapper keeps a `.listener` back-reference to `fn` and
16
- * removeListener matches through it. `isDestroyed` covers Electron objects
17
- * (WebContents / BrowserWindow) whose methods throw once destroyed.
18
- */
19
- export interface BagEmitter {
20
- on(event: string, listener: Listener): unknown;
21
- once(event: string, listener: Listener): unknown;
22
- removeListener(event: string, listener: Listener): unknown;
23
- isDestroyed?(): boolean;
24
- }
25
- export interface SessionListenerBag {
26
- /** Attach `fn` via `emitter.on` and track it for dispose. No-op after dispose. */
27
- on(emitter: BagEmitter, event: string, fn: Listener): void;
28
- /** Attach `fn` via `emitter.once` and track it for dispose. No-op after dispose. */
29
- once(emitter: BagEmitter, event: string, fn: Listener): void;
30
- /**
31
- * Detach every tracked listener that may still be attached. Emitters that
32
- * report `isDestroyed()` are skipped — their listeners died with them, and
33
- * touching a destroyed Electron object throws. Removing a `once` that
34
- * already fired is a no-op, so dispose is safe to call FROM one of the
35
- * bag's own hooks (teardown triggered by the hook itself). Idempotent.
36
- */
37
- dispose(): void;
38
- }
39
- export declare function createSessionListenerBag(): SessionListenerBag;
40
- export {};
1
+ export * from '@dimina-kit/electron-runtime/main/session-listener-bag';
41
2
  //# sourceMappingURL=session-listener-bag.d.ts.map
@@ -1,40 +1,2 @@
1
- /**
2
- * Session-scoped listener bookkeeping. An app session hangs lifecycle hooks on
3
- * emitters it does NOT own — the shared simulator WebContentsView, a pooled
4
- * service-host window — and those emitters outlive the session (one simulator
5
- * wc soft-reloads through many sessions). Every such hook is registered
6
- * through this bag so the session's single teardown chokepoint can detach them
7
- * all with one `dispose()`; a hook left behind survives as a dead listener on
8
- * the shared emitter, growing by one per soft reload until Node's MaxListeners
9
- * warning fires.
10
- */
11
- export function createSessionListenerBag() {
12
- const records = [];
13
- let disposed = false;
14
- return {
15
- on(emitter, event, fn) {
16
- if (disposed)
17
- return;
18
- emitter.on(event, fn);
19
- records.push({ emitter, event, fn });
20
- },
21
- once(emitter, event, fn) {
22
- if (disposed)
23
- return;
24
- emitter.once(event, fn);
25
- records.push({ emitter, event, fn });
26
- },
27
- dispose() {
28
- if (disposed)
29
- return;
30
- disposed = true;
31
- for (const { emitter, event, fn } of records) {
32
- if (emitter.isDestroyed?.())
33
- continue;
34
- emitter.removeListener(event, fn);
35
- }
36
- records.length = 0;
37
- },
38
- };
39
- }
1
+ export * from '@dimina-kit/electron-runtime/main/session-listener-bag';
40
2
  //# sourceMappingURL=session-listener-bag.js.map
@@ -1,61 +1,2 @@
1
- import { type Disposable } from '@dimina-kit/electron-deck/main';
2
- import type { BridgeRouterHandle } from '../../ipc/bridge-router.js';
3
- import type { DiagnosticsBus } from '../diagnostics/index.js';
4
- /**
5
- * One console entry posted by a guest preload. Shape mirrors
6
- * render-host/preload.cjs + service-host/preload.cjs `emitConsoleLog`:
7
- * - `source` which layer it came from ('render' | 'service'); ONLY 'render'
8
- * is forwarded into the service host (see loop-safety above).
9
- * - `bridgeId` present for render entries; identifies the owning page so we
10
- * can target the matching app's service host (multi-app safe).
11
- * - `level` console method name ('log' | 'warn' | 'error' | 'info' | 'debug').
12
- * - `args` already-`safeSerialize`d arguments (structured-cloneable).
13
- */
14
- export interface GuestConsoleEntry {
15
- source?: string;
16
- bridgeId?: string;
17
- level?: string;
18
- args?: unknown[];
19
- ts?: number;
20
- }
21
- /** A consumer of every guest console entry (render AND service). */
22
- export type ConsoleSink = (entry: GuestConsoleEntry) => void;
23
- export interface ConsoleForwarder extends Disposable {
24
- /**
25
- * The single sink bridge-router invokes (wired onto `ctx.guestConsole.emit`).
26
- * Fans every entry out to subscribers, then runs the render→service forward.
27
- */
28
- emit(entry: unknown): void;
29
- /**
30
- * Register an external sink (e.g. automation WS broadcast). Returns a
31
- * Disposable that unregisters it. Sinks see EVERY entry (both layers) — the
32
- * render→service forward is internal and not exposed as a sink.
33
- *
34
- * A bounded history buffer (200 entries, oldest dropped first — mirrors
35
- * `DiagnosticsBus`'s `DEFAULT_BUFFER_CAP` ring-buffer style) records every
36
- * entry regardless of whether anyone is subscribed. `opts.replay` (default
37
- * `false`, UNLIKE `DiagnosticsBus` whose default is `true`) opts a new
38
- * subscriber into draining that buffer, in order, before receiving live
39
- * entries. Default stays non-replaying because the existing automation
40
- * subscriber (`services/automation/index.ts`) wants only entries from the
41
- * moment it subscribes — a history dump on an existing WS connection would
42
- * be a surprise duplicate broadcast. `{replay:true}` exists for the global
43
- * console mirror, whose whole point is to catch up a standalone debug
44
- * window opened well after boot.
45
- */
46
- subscribe(sink: ConsoleSink, opts?: {
47
- replay?: boolean;
48
- }): Disposable;
49
- /**
50
- * Flush any diagnostic queued for `appSessionId` (plus the global,
51
- * session-less queue) into that session's now-ready service-host wc.
52
- * Idempotent: entries are removed from their bucket as they flush, so a
53
- * repeat call for the same session injects nothing further. Call once the
54
- * session's service-host webContents has actually navigated/loaded (e.g.
55
- * from `bootServiceHost`, after `did-finish-load`) — calling it earlier just
56
- * finds nothing resolvable and leaves the queue intact for a later call.
57
- */
58
- notifyServiceHostReady(appSessionId: string): void;
59
- }
60
- export declare function createConsoleForwarder(bridge: Pick<BridgeRouterHandle, 'getServiceWc' | 'getServiceWcForBridge'>, diagnostics?: DiagnosticsBus): ConsoleForwarder;
1
+ export * from '@dimina-kit/electron-runtime/main/console-forward';
61
2
  //# sourceMappingURL=index.d.ts.map
@@ -1,226 +1,2 @@
1
- import { DisposableRegistry, toDisposable } from '@dimina-kit/electron-deck/main';
2
- import { RENDER_FORWARD_SOURCE_URL } from '../service-console/console-api.js';
3
- import { isInternalLogMessage } from './internal-log.js';
4
- /** Console levels we re-emit into the service host. Anything else maps to 'log'. */
5
- const FORWARDABLE_LEVELS = new Set(['log', 'warn', 'error', 'info', 'debug']);
6
- /**
7
- * Build the `executeJavaScript` source that re-emits a render entry inside the
8
- * service host. Args are carried as a JSON string and parsed service-side, so no
9
- * guest-controlled value is ever interpolated into executable JS — the only
10
- * thing that reaches the parser is a JSON literal. The `[视图]` prefix lets the
11
- * DevTools console filter isolate the render layer.
12
- */
13
- function buildForwardScript(level, args) {
14
- const method = FORWARDABLE_LEVELS.has(level) ? level : 'log';
15
- // JSON.stringify('…') yields a valid JS string literal; embedding it and
16
- // re-parsing keeps args as data, never code. JSON.stringify can throw on a
17
- // value that slipped past safeSerialize (e.g. a BigInt) — caller guards.
18
- const argsJson = JSON.stringify(args ?? []);
19
- // `console[method]` (not `console.log`) preserves the original level so the
20
- // DevTools severity filter still works on the forwarded line.
21
- //
22
- // The trailing `//# sourceURL` stamps this injected line with a sentinel URL.
23
- // The service-console CDP capture (services/service-console) attached to THIS
24
- // service host would otherwise re-capture this `console[...]` call as a fresh
25
- // service entry and re-broadcast it to automation (duplicate). It skips any
26
- // `consoleAPICalled` whose top frame URL === RENDER_FORWARD_SOURCE_URL.
27
- return `(()=>{try{const a=JSON.parse(${JSON.stringify(argsJson)});console[${JSON.stringify(method)}]('[视图]',...a)}catch(_){}})()\n//# sourceURL=${RENDER_FORWARD_SOURCE_URL}`;
28
- }
29
- /** `Diagnostic.severity` → the literal `console.<method>` call to emit (dot form, not computed — kept greppable/CDP-attributable like a hand-written call site). */
30
- const DIAGNOSTIC_CONSOLE_CALL = {
31
- error: 'console.error',
32
- warn: 'console.warn',
33
- info: 'console.info',
34
- };
35
- /**
36
- * Build the `executeJavaScript` source that injects one diagnostic into the
37
- * service host's console, prefixed `[dimina-kit]`. Args ride as a JSON string
38
- * (same anti-injection shape as `buildForwardScript`) and the sourceURL is the
39
- * SAME sentinel the render mirror uses, so this line is exempt from
40
- * service-console's loop-safety skip too.
41
- */
42
- function buildDiagnosticScript(severity, message) {
43
- const call = DIAGNOSTIC_CONSOLE_CALL[severity];
44
- const argsJson = JSON.stringify([`[dimina-kit] ${message}`]);
45
- return `(()=>{try{const a=JSON.parse(${JSON.stringify(argsJson)});${call}(...a)}catch(_){}})()\n//# sourceURL=${RENDER_FORWARD_SOURCE_URL}`;
46
- }
47
- export function createConsoleForwarder(bridge, diagnostics) {
48
- const sinks = new Set();
49
- const registry = new DisposableRegistry();
50
- // Bounded history ring buffer backing `subscribe(sink, {replay:true})` —
51
- // see the interface doc comment above. Every entry is recorded regardless
52
- // of whether anyone is subscribed, so a replaying subscriber that arrives
53
- // long after boot (the standalone global debug window) still catches up.
54
- const CONSOLE_BUFFER_CAP = 200;
55
- const buffer = [];
56
- // Diagnostics queued because no live service-host wc could be resolved yet,
57
- // bucketed by the owning appSessionId; diagnostics with no appSessionId land
58
- // in `pendingGlobal` instead. `notifyServiceHostReady` drains both into the
59
- // session that just became ready.
60
- const pendingBySession = new Map();
61
- const pendingGlobal = [];
62
- // Sessions whose service host has finished loading service.html (the caller
63
- // signals this via `notifyServiceHostReady`). A resolvable wc alone is NOT
64
- // readiness: the window exists (and is bound) before its spawn navigation
65
- // lands, and anything injected into that pre-load document is wiped by the
66
- // navigation — the diagnostic would silently vanish from the Console panel.
67
- const readySessions = new Set();
68
- function injectDiagnostic(wc, d) {
69
- wc.executeJavaScript(buildDiagnosticScript(d.severity, d.message), true).catch(() => { });
70
- }
71
- /**
72
- * Inject a diagnostic into its owning session's service-host console, or
73
- * queue it until that host is READY (not merely constructed — see
74
- * `readySessions`). Ownership is strict: a session-owned diagnostic NEVER
75
- * falls back to the currently-active host — while `handleSpawn` is still
76
- * running, the new session's host doesn't exist yet and the "active" host
77
- * is the OUTGOING session's window, so a fallback would land the message in
78
- * a console about to be destroyed instead of the session it explains. Only
79
- * session-less diagnostics may use the active host. Never throws — a
80
- * missing/destroyed/not-yet-ready host is a normal state, not an error.
81
- */
82
- function handleDiagnostic(d) {
83
- // Internal-audience diagnostics (e.g. compile-standby's warm-pool
84
- // lifecycle) are devtools-tooling-only state — never inject them into a
85
- // project's service host (the right-panel CDP is natively attached
86
- // there), and never queue them either: queuing exists so a diagnostic
87
- // survives until ITS session's host becomes resolvable, which is
88
- // meaningless for something that must never reach any service host.
89
- // (See global-diagnostics-mirror.ts for where these actually surface —
90
- // the independent, unfiltered "debug the whole app" panel.)
91
- if (d.audience === 'internal')
92
- return;
93
- if (d.appSessionId) {
94
- const wc = readySessions.has(d.appSessionId) && bridge.getServiceWcForBridge
95
- ? bridge.getServiceWcForBridge(d.appSessionId)
96
- : null;
97
- if (wc && !wc.isDestroyed()) {
98
- injectDiagnostic(wc, d);
99
- return;
100
- }
101
- const bucket = pendingBySession.get(d.appSessionId);
102
- if (bucket)
103
- bucket.push(d);
104
- else
105
- pendingBySession.set(d.appSessionId, [d]);
106
- return;
107
- }
108
- const wc = bridge.getServiceWc();
109
- if (wc && !wc.isDestroyed()) {
110
- injectDiagnostic(wc, d);
111
- return;
112
- }
113
- pendingGlobal.push(d);
114
- }
115
- if (diagnostics) {
116
- // replay:true so diagnostics reported before this forwarder existed (early
117
- // boot, buffered on the bus) are queued/injected here too.
118
- registry.add(diagnostics.subscribe(handleDiagnostic, { replay: true }));
119
- }
120
- /**
121
- * Render→service forward. Resolves the service host for the entry's owning
122
- * page (multi-app safe), falling back to the active app's service host when
123
- * the bridgeId is unknown — that's the host the embedded DevTools inspects.
124
- * No-op on a destroyed/missing host so we never write to a torn-down wc (pool
125
- * reuse / session swap can swap the host out under us). Skips dimina
126
- * framework-internal render-layer log lines (`isInternalLogMessage`) —
127
- * those must never reach the project's right-panel console at all (the
128
- * global console mirror still sees them via the `sinks` broadcast in
129
- * `emit()`, which runs before this function). This is the source-level fix
130
- * for the render half of the noise console-filter.ts's front-end text
131
- * filter used to paper over; the service-layer half (`[service]` lines,
132
- * native CDP-observed, no interception point available — see
133
- * service-host/preload.cjs's "console.* is deliberately NOT patched"
134
- * comment) still needs that filter.
135
- */
136
- function forwardRenderToServiceHost(entry) {
137
- if (isInternalLogMessage(entry))
138
- return;
139
- let wc = null;
140
- if (entry.bridgeId && bridge.getServiceWcForBridge) {
141
- wc = bridge.getServiceWcForBridge(entry.bridgeId);
142
- }
143
- if (!wc)
144
- wc = bridge.getServiceWc();
145
- if (!wc || wc.isDestroyed())
146
- return;
147
- let script;
148
- try {
149
- script = buildForwardScript(entry.level ?? 'log', entry.args ?? []);
150
- }
151
- catch {
152
- // Args that escaped safeSerialize and aren't JSON-stringifiable — drop
153
- // rather than break the forward. Console capture must never throw.
154
- return;
155
- }
156
- // executeJavaScript rejects if the host navigates/teardowns mid-call; the
157
- // injected body is itself try/caught. Swallow either — best-effort mirror.
158
- wc.executeJavaScript(script, true).catch(() => { });
159
- }
160
- return {
161
- // The single sink bridge-router calls (`ctx.guestConsole.emit`). Fans out
162
- // to external subscribers (both layers) then runs the render→service forward
163
- // (render only — see loop-safety invariant in the module header).
164
- emit(raw) {
165
- const entry = (raw ?? {});
166
- buffer.push(entry);
167
- if (buffer.length > CONSOLE_BUFFER_CAP)
168
- buffer.shift();
169
- for (const sink of sinks) {
170
- try {
171
- sink(entry);
172
- }
173
- catch { /* a sink must never break the others */ }
174
- }
175
- // Forward ONLY the render layer. Service entries are already shown
176
- // natively in the attached DevTools, and forwarding them would loop
177
- // (see header).
178
- if (entry.source === 'render')
179
- forwardRenderToServiceHost(entry);
180
- },
181
- subscribe(sink, opts) {
182
- if (opts?.replay) {
183
- for (const entry of buffer) {
184
- try {
185
- sink(entry);
186
- }
187
- catch { /* isolate a replay throw same as a live one */ }
188
- }
189
- }
190
- sinks.add(sink);
191
- return registry.add(toDisposable(() => { sinks.delete(sink); }));
192
- },
193
- notifyServiceHostReady(appSessionId) {
194
- // Readiness is sticky per session: from here on, session-owned
195
- // diagnostics inject directly instead of queueing.
196
- readySessions.add(appSessionId);
197
- // Re-resolve fresh rather than trusting whatever `handleDiagnostic` saw at
198
- // report time — the caller invokes this exactly when it knows the wc just
199
- // became live, so that resolution wins even if an earlier snapshot was
200
- // destroyed/missing.
201
- const wc = bridge.getServiceWcForBridge ? bridge.getServiceWcForBridge(appSessionId) : null;
202
- if (!wc)
203
- return;
204
- const sessionEntries = pendingBySession.get(appSessionId);
205
- if (sessionEntries) {
206
- for (const d of sessionEntries)
207
- injectDiagnostic(wc, d);
208
- pendingBySession.delete(appSessionId);
209
- }
210
- if (pendingGlobal.length) {
211
- for (const d of pendingGlobal)
212
- injectDiagnostic(wc, d);
213
- pendingGlobal.length = 0;
214
- }
215
- },
216
- dispose() {
217
- sinks.clear();
218
- buffer.length = 0;
219
- pendingBySession.clear();
220
- pendingGlobal.length = 0;
221
- readySessions.clear();
222
- return registry.disposeAll();
223
- },
224
- };
225
- }
1
+ export * from '@dimina-kit/electron-runtime/main/console-forward';
226
2
  //# sourceMappingURL=index.js.map
@@ -1,11 +1,2 @@
1
- import type { GuestConsoleEntry } from './index.js';
2
- /**
3
- * Judges whether a guest console entry is dimina framework-internal output
4
- * (a bridge/lifecycle log the framework itself prints) rather than the
5
- * mini-app author's own business `console.*` call. Only the FIRST arg is
6
- * inspected — framework logs always lead with the literal tag; a
7
- * business log that happens to mention the tag later in its args must not
8
- * be swept up.
9
- */
10
- export declare function isInternalLogMessage(entry: GuestConsoleEntry): boolean;
1
+ export * from '@dimina-kit/electron-runtime/main/internal-log';
11
2
  //# sourceMappingURL=internal-log.d.ts.map
@@ -1,23 +1,2 @@
1
- /** dimina framework internal-log first-arg prefixes, from the framework
2
- * source literals (dimina/fe/packages/service/src/core/message.js:26 and
3
- * siblings use `'[service]'`; dimina/fe/packages/render/src/core/message.js:18
4
- * and siblings use `'[system]'`). */
5
- const SERVICE_PREFIX = '[service]';
6
- const RENDER_PREFIX = '[system]';
7
- /**
8
- * Judges whether a guest console entry is dimina framework-internal output
9
- * (a bridge/lifecycle log the framework itself prints) rather than the
10
- * mini-app author's own business `console.*` call. Only the FIRST arg is
11
- * inspected — framework logs always lead with the literal tag; a
12
- * business log that happens to mention the tag later in its args must not
13
- * be swept up.
14
- */
15
- export function isInternalLogMessage(entry) {
16
- const first = entry.args?.[0];
17
- if (typeof first !== 'string')
18
- return false;
19
- if (first === RENDER_PREFIX)
20
- return true;
21
- return first === SERVICE_PREFIX || first.startsWith(`${SERVICE_PREFIX} `);
22
- }
1
+ export * from '@dimina-kit/electron-runtime/main/internal-log';
23
2
  //# sourceMappingURL=internal-log.js.map
@@ -1,59 +1,2 @@
1
- /**
2
- * Diagnostics bus: the single authoritative channel for developer-facing
3
- * diagnostics synthesized by main (e.g. "page not found", "logic bundle
4
- * unreachable") that do not originate from a real `console.*` call the
5
- * embedded service-host DevTools' CDP capture could observe on its own.
6
- *
7
- * Main-synthesized diagnostics used to reach only `ctx.guestConsole.emit`,
8
- * which fans out to automation subscribers but — for `source:'service'`
9
- * entries — is never injected into the service host's own console (see
10
- * `console-forward`'s render-only forward invariant), so they never appeared
11
- * in the Console panel. This bus is the fix: `report()` is the one place a
12
- * diagnostic is born, and `console-forward` subscribes to inject each one
13
- * into the owning session's service-host console (queuing until that
14
- * session's window is ready — see `notifyServiceHostReady`).
15
- */
16
- export type DiagnosticSeverity = 'error' | 'warn' | 'info';
17
- export interface Diagnostic {
18
- severity: DiagnosticSeverity;
19
- code: string;
20
- message: string;
21
- appSessionId?: string;
22
- ts: number;
23
- /**
24
- * Who this diagnostic is for. `'internal'` means devtools-tooling-only
25
- * state (e.g. compile-standby's warm-pool lifecycle) that must never reach
26
- * the per-project service-host console the right-panel CDP is attached to
27
- * — see `console-forward/index.ts`'s `handleDiagnostic` gate. `'user'` or
28
- * omitted means the existing behavior: a real diagnostic about the
29
- * inspected mini-program, injected into that project's Console panel.
30
- */
31
- audience?: 'user' | 'internal';
32
- }
33
- export interface DiagnosticsBus {
34
- /** Record one diagnostic: buffers it, mirrors it to the main-process console, and synchronously notifies every live subscriber. No-op after `dispose()`. */
35
- report(d: {
36
- severity: DiagnosticSeverity;
37
- code: string;
38
- message: string;
39
- appSessionId?: string;
40
- audience?: 'user' | 'internal';
41
- }): void;
42
- /**
43
- * Register a sink. With `replay` (default true) the sink is first called,
44
- * in order, for every buffered diagnostic still held, then for every
45
- * diagnostic reported from now on; `replay: false` skips the backlog and
46
- * only delivers diagnostics reported after this call.
47
- */
48
- subscribe(sink: (d: Diagnostic) => void, opts?: {
49
- replay?: boolean;
50
- }): {
51
- dispose(): void;
52
- };
53
- /** Clears subscribers and the buffer. `report()` becomes a no-op afterward (including the console mirror — dispose means fully off, not "log-only"). */
54
- dispose(): void;
55
- }
56
- export declare function createDiagnosticsBus(opts?: {
57
- bufferCap?: number;
58
- }): DiagnosticsBus;
1
+ export * from '@dimina-kit/electron-runtime/main/diagnostics';
59
2
  //# sourceMappingURL=index.d.ts.map
@@ -1,61 +1,2 @@
1
- const DEFAULT_BUFFER_CAP = 200;
2
- const CONSOLE_METHOD = {
3
- error: 'error',
4
- warn: 'warn',
5
- info: 'info',
6
- };
7
- export function createDiagnosticsBus(opts) {
8
- const bufferCap = opts?.bufferCap && opts.bufferCap > 0 ? opts.bufferCap : DEFAULT_BUFFER_CAP;
9
- const buffer = [];
10
- const sinks = new Set();
11
- let disposed = false;
12
- return {
13
- report(d) {
14
- if (disposed)
15
- return;
16
- const entry = { ...d, ts: Date.now() };
17
- buffer.push(entry);
18
- // Ring buffer: drop the oldest once over cap. Bounded at `bufferCap` so a
19
- // burst of synthesized diagnostics can never grow this without limit.
20
- if (buffer.length > bufferCap)
21
- buffer.shift();
22
- // The one guaranteed-visible sink: unlike Console-panel injection (which
23
- // needs a live, ready service-host wc), the main-process terminal is
24
- // always there.
25
- console[CONSOLE_METHOD[entry.severity]](`[dimina-kit:${entry.code}] ${entry.message}`);
26
- for (const sink of sinks) {
27
- try {
28
- sink(entry);
29
- }
30
- catch { /* a sink must never break the others */ }
31
- }
32
- },
33
- subscribe(sink, subOpts) {
34
- const replay = subOpts?.replay ?? true;
35
- if (replay) {
36
- for (const entry of buffer) {
37
- try {
38
- sink(entry);
39
- }
40
- catch { /* isolate a replay throw same as a live one */ }
41
- }
42
- }
43
- sinks.add(sink);
44
- let released = false;
45
- return {
46
- dispose() {
47
- if (released)
48
- return;
49
- released = true;
50
- sinks.delete(sink);
51
- },
52
- };
53
- },
54
- dispose() {
55
- disposed = true;
56
- sinks.clear();
57
- buffer.length = 0;
58
- },
59
- };
60
- }
1
+ export * from '@dimina-kit/electron-runtime/main/diagnostics';
61
2
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,2 @@
1
- export interface DiminaResourceServer {
2
- baseUrl: string;
3
- close(): Promise<void>;
4
- }
5
- export declare function startDiminaResourceServer(rootDir: string): Promise<DiminaResourceServer>;
6
- export declare function toSourceUrl(filePath: string): string;
1
+ export * from '@dimina-kit/electron-runtime/main/dimina-resource-server';
7
2
  //# sourceMappingURL=dimina-resource-server.d.ts.map