@dimina-kit/devtools 0.4.0-dev.20260803105710 → 0.4.0-dev.20260828092243
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main/api.d.ts +1 -1
- package/dist/main/app/app.js +66 -2
- package/dist/main/index.bundle.js +1454 -540
- package/dist/main/ipc/index.d.ts +3 -0
- package/dist/main/ipc/index.js +3 -0
- package/dist/main/ipc/popover.js +1 -1
- package/dist/main/ipc/project-create.d.ts +15 -0
- package/dist/main/ipc/project-create.js +26 -0
- package/dist/main/ipc/projects.d.ts +1 -1
- package/dist/main/ipc/projects.js +11 -0
- package/dist/main/ipc/session.js +11 -0
- package/dist/main/ipc/settings.js +2 -1
- package/dist/main/ipc/simulator-module.d.ts +4 -3
- package/dist/main/ipc/simulator-module.js +4 -5
- package/dist/main/ipc/tooltip.d.ts +13 -0
- package/dist/main/ipc/tooltip.js +28 -0
- package/dist/main/ipc/views.d.ts +15 -1
- package/dist/main/ipc/views.js +61 -4
- package/dist/main/runtime/miniapp-runtime.d.ts +87 -19
- package/dist/main/services/layout/index.d.ts +11 -0
- package/dist/main/services/layout/index.js +23 -0
- package/dist/main/services/network-forward/frontend-dispatch.js +2 -1
- package/dist/main/services/notifications/renderer-notifier.d.ts +32 -1
- package/dist/main/services/notifications/renderer-notifier.js +29 -1
- package/dist/main/services/projects/project-repository.d.ts +4 -1
- package/dist/main/services/projects/project-repository.js +63 -5
- package/dist/main/services/simulator-current-page/index.d.ts +5 -3
- package/dist/main/services/simulator-current-page/index.js +8 -1
- package/dist/main/services/update/update-manager.d.ts +17 -3
- package/dist/main/services/update/update-manager.js +25 -6
- package/dist/main/services/views/clear-console-filter.d.ts +44 -0
- package/dist/main/services/views/clear-console-filter.js +86 -0
- package/dist/main/services/views/console-filter-test-fixtures.d.ts +94 -0
- package/dist/main/services/views/console-filter-test-fixtures.js +82 -0
- package/dist/main/services/views/console-filter.d.ts +79 -130
- package/dist/main/services/views/console-filter.js +140 -183
- package/dist/main/services/views/devtools-tabs.d.ts +24 -4
- package/dist/main/services/views/devtools-tabs.js +40 -21
- package/dist/main/services/views/host-dialog-port-channel.d.ts +18 -0
- package/dist/main/services/views/host-dialog-port-channel.js +15 -0
- package/dist/main/services/views/host-dialog-session-runtime.d.ts +10 -0
- package/dist/main/services/views/host-dialog-session-runtime.js +17 -0
- package/dist/main/services/views/host-dialog-view.d.ts +95 -0
- package/dist/main/services/views/host-dialog-view.js +147 -0
- package/dist/main/services/views/host-sidebar-port-channel.d.ts +18 -0
- package/dist/main/services/views/host-sidebar-port-channel.js +15 -0
- package/dist/main/services/views/host-sidebar-session-runtime.d.ts +10 -0
- package/dist/main/services/views/host-sidebar-session-runtime.js +17 -0
- package/dist/main/services/views/host-sidebar-view.d.ts +59 -0
- package/dist/main/services/views/host-sidebar-view.js +44 -0
- package/dist/main/services/views/host-slot-port-channel.d.ts +107 -0
- package/dist/main/services/views/host-slot-port-channel.js +261 -0
- package/dist/main/services/views/host-slot-session-runtime.d.ts +40 -0
- package/dist/main/services/views/host-slot-session-runtime.js +50 -0
- package/dist/main/services/views/host-slot-view.d.ts +109 -0
- package/dist/main/services/views/host-slot-view.js +147 -0
- package/dist/main/services/views/host-toolbar-port-channel.d.ts +6 -91
- package/dist/main/services/views/host-toolbar-port-channel.js +10 -243
- package/dist/main/services/views/host-toolbar-session-runtime.d.ts +5 -30
- package/dist/main/services/views/host-toolbar-session-runtime.js +9 -47
- package/dist/main/services/views/host-toolbar-view.d.ts +34 -7
- package/dist/main/services/views/host-toolbar-view.js +30 -237
- package/dist/main/services/views/managed-web-contents-view.d.ts +48 -0
- package/dist/main/services/views/managed-web-contents-view.js +123 -0
- package/dist/main/services/views/native-simulator-devtools-host.js +64 -45
- package/dist/main/services/views/native-simulator-view.js +6 -24
- package/dist/main/services/views/native-view-tree.d.ts +25 -0
- package/dist/main/services/views/native-view-tree.js +69 -0
- package/dist/main/services/views/overlay-panels-view.d.ts +50 -4
- package/dist/main/services/views/overlay-panels-view.js +226 -108
- package/dist/main/services/views/placement-reconciler.d.ts +18 -18
- package/dist/main/services/views/placement-reconciler.js +91 -29
- package/dist/main/services/views/placement-test-driver.d.ts +27 -0
- package/dist/main/services/views/placement-test-driver.js +29 -0
- package/dist/main/services/views/view-manager-devtools-host-test-fixtures.js +3 -1
- package/dist/main/services/views/view-manager.d.ts +14 -86
- package/dist/main/services/views/view-manager.js +41 -4
- package/dist/main/services/views/workbench-view.js +27 -20
- package/dist/main/services/workbench-coi-server.d.ts +11 -0
- package/dist/main/services/workbench-coi-server.js +32 -0
- package/dist/main/services/workspace/rebuild-status.d.ts +21 -8
- package/dist/main/services/workspace/rebuild-status.js +24 -8
- package/dist/main/utils/paths.d.ts +4 -0
- package/dist/main/utils/paths.js +4 -0
- package/dist/main/utils/sender-policy.d.ts +1 -1
- package/dist/main/utils/sender-policy.js +16 -1
- package/dist/main/utils/theme.d.ts +7 -2
- package/dist/main/utils/theme.js +8 -3
- package/dist/native-host/common/common.js +65 -62
- package/dist/native-host/container/pageFrame.css +1 -1
- package/dist/native-host/render/render.js +3226 -2898
- package/dist/native-host/service/service.js +2 -2
- package/dist/preload/runtime/host-dialog-advertiser.d.ts +22 -0
- package/dist/preload/runtime/host-dialog-advertiser.js +37 -0
- package/dist/preload/runtime/host-dialog-port.d.ts +44 -0
- package/dist/preload/runtime/host-dialog-port.js +53 -0
- package/dist/preload/runtime/host-dialog-runtime.d.ts +28 -0
- package/dist/preload/runtime/host-dialog-runtime.js +36 -0
- package/dist/preload/runtime/host-sidebar-advertiser.d.ts +19 -0
- package/dist/preload/runtime/host-sidebar-advertiser.js +35 -0
- package/dist/preload/runtime/host-sidebar-port.d.ts +44 -0
- package/dist/preload/runtime/host-sidebar-port.js +53 -0
- package/dist/preload/runtime/host-sidebar-runtime.d.ts +28 -0
- package/dist/preload/runtime/host-sidebar-runtime.js +36 -0
- package/dist/preload/runtime/host-slot-port-bridge.d.ts +18 -0
- package/dist/preload/runtime/host-slot-port-bridge.js +112 -0
- package/dist/preload/runtime/host-toolbar-advertiser.d.ts +5 -13
- package/dist/preload/runtime/host-toolbar-advertiser.js +18 -38
- package/dist/preload/runtime/host-toolbar-port.d.ts +9 -0
- package/dist/preload/runtime/host-toolbar-port.js +11 -95
- package/dist/preload/runtime/wait-for-slot-root.d.ts +20 -0
- package/dist/preload/runtime/wait-for-slot-root.js +52 -0
- package/dist/preload/windows/host-dialog-runtime.cjs +353 -0
- package/dist/preload/windows/host-dialog-runtime.cjs.map +7 -0
- package/dist/preload/windows/host-dialog-runtime.d.ts +2 -0
- package/dist/preload/windows/host-dialog-runtime.js +13 -0
- package/dist/preload/windows/host-sidebar-runtime.cjs +354 -0
- package/dist/preload/windows/host-sidebar-runtime.cjs.map +7 -0
- package/dist/preload/windows/host-sidebar-runtime.d.ts +2 -0
- package/dist/preload/windows/host-sidebar-runtime.js +13 -0
- package/dist/preload/windows/host-toolbar-runtime.cjs +134 -51
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +3 -3
- package/dist/preload/windows/main.cjs +3176 -14
- package/dist/preload/windows/main.cjs.map +4 -4
- package/dist/preload/windows/main.css +428 -0
- package/dist/preload/windows/main.css.map +7 -0
- package/dist/preload/windows/simulator.cjs +5 -2
- package/dist/preload/windows/simulator.cjs.map +2 -2
- package/dist/preload/windows/simulator.js +5 -2
- package/dist/renderer/assets/button-DsNqZm7o.js +2 -0
- package/dist/renderer/assets/constants-D7DfVqMp.js +2 -0
- package/dist/renderer/assets/constants-D8zsejFq.js +2 -0
- package/dist/renderer/assets/createLucideIcon-CYJeT1ji.js +2 -0
- package/dist/renderer/assets/dialog-pT4qWmka.js +46 -0
- package/dist/renderer/assets/dist-o70xmpc1.js +2 -0
- package/dist/renderer/assets/hostSidebarDefault-NvGZlE9O.js +2 -0
- package/dist/renderer/assets/index-zErhG3ta.js +5 -0
- package/dist/renderer/assets/input-4QxTXMZN.js +2 -0
- package/dist/renderer/assets/ipc-channels-overlays-Blr5TNoB.js +2 -0
- package/dist/renderer/assets/jsx-runtime-B-3rq1y5.css +1 -0
- package/dist/renderer/assets/jsx-runtime-CqVdW3eg.js +9 -0
- package/dist/renderer/assets/popover-CJiSWwuE.js +2 -0
- package/dist/renderer/assets/project-api-DZ1Zi6EC.js +2 -0
- package/dist/renderer/assets/projectCreateDialog-DMWNhw_1.js +2 -0
- package/dist/renderer/assets/select-C86pNcsu.js +2 -0
- package/dist/renderer/assets/settings-BoI8mLT1.js +2 -0
- package/dist/renderer/assets/settings-api-Bs_g4NHs.js +2 -0
- package/dist/renderer/assets/settings-tab-bar-DHLLygqv.js +2 -0
- package/dist/renderer/assets/tooltip-BhAyY0T4.js +2 -0
- package/dist/renderer/assets/types-YYjkvane.js +2 -0
- package/dist/renderer/assets/updateDialog-DPum3wx1.js +2 -0
- package/dist/renderer/assets/utils-kfQov6Pa.js +2 -0
- package/dist/renderer/assets/view-api-DFhb2R8-.js +2 -0
- package/dist/renderer/assets/workbenchSettings-DrajRQUk.js +8 -0
- package/dist/renderer/entries/host-sidebar-default/index.html +21 -0
- package/dist/renderer/entries/main/index.html +15 -7
- package/dist/renderer/entries/popover/index.html +10 -6
- package/dist/renderer/entries/project-create-dialog/index.html +27 -0
- package/dist/renderer/entries/settings/index.html +10 -5
- package/dist/renderer/entries/tooltip/index.html +21 -0
- package/dist/renderer/entries/update-dialog/index.html +25 -0
- package/dist/renderer/entries/workbench-settings/index.html +11 -5
- package/dist/service-host/preload.cjs +10 -0
- package/dist/service-host/sync-impls/menu-button-geometry.js +1 -0
- package/dist/shared/constants.d.ts +22 -0
- package/dist/shared/constants.js +22 -0
- package/dist/shared/ipc-channels-overlays.d.ts +156 -0
- package/dist/shared/ipc-channels-overlays.js +186 -0
- package/dist/shared/ipc-channels.d.ts +1 -67
- package/dist/shared/ipc-channels.js +9 -81
- package/dist/shared/ipc-schemas.d.ts +52 -0
- package/dist/shared/ipc-schemas.js +64 -0
- package/dist/shared/simulator-route.d.ts +8 -0
- package/dist/shared/simulator-route.js +15 -0
- package/dist/shared/types.d.ts +17 -0
- package/dist/shared/view-ids.d.ts +9 -0
- package/dist/shared/view-ids.js +21 -0
- package/dist/simulator/assets/device-shell-CmtM1QxP.js +2 -0
- package/dist/simulator/assets/device-shell-iFZo1igL.css +1 -0
- package/dist/simulator/assets/{simulator-COIE6R49.js → simulator-CIobn3Mh.js} +6 -6
- package/dist/simulator/assets/{simulator-mini-app-BLn7XV8e.js → simulator-mini-app-CRe6n9br.js} +2 -2
- package/dist/simulator/assets/simulator-ui-BupATgKo.css +1 -0
- package/dist/simulator/assets/simulator-ui-C_cP602X.js +2 -0
- package/dist/simulator/simulator.html +3 -2
- package/dist/vscode-workbench/assets/__vite-browser-external-Bc1vizTf.js +1 -0
- package/dist/vscode-workbench/assets/{dist-oHcwN53f.js → dist-CMfmHflW.js} +3 -3
- package/dist/vscode-workbench/assets/{iconv-lite-umd-CLMLpdGm.js → iconv-lite-umd-Bx8CgaZq.js} +1 -1
- package/dist/vscode-workbench/assets/{index-BE3UJdoH.js → index-CdG6YWhW.js} +436 -436
- package/dist/vscode-workbench/assets/{jschardet-BICW8PLJ.js → jschardet-M0qgd2lN.js} +1 -1
- package/dist/vscode-workbench/index.html +21 -1
- package/package.json +9 -8
- package/dist/main/services/views/destroy-child-view.d.ts +0 -9
- package/dist/main/services/views/destroy-child-view.js +0 -23
- package/dist/renderer/assets/constants-EAMiwL9_.js +0 -2
- package/dist/renderer/assets/index-BBg3YI5b.js +0 -49
- package/dist/renderer/assets/input-xdmfv-eH.js +0 -2
- package/dist/renderer/assets/ipc-transport-B3EpmfNS.js +0 -9
- package/dist/renderer/assets/ipc-transport-Blac3sOj.css +0 -1
- package/dist/renderer/assets/popover-B88e2hkg.js +0 -2
- package/dist/renderer/assets/select-CD9CJyhI.js +0 -2
- package/dist/renderer/assets/settings-44hf0QtO.js +0 -2
- package/dist/renderer/assets/settings-api-pJKPuP1M.js +0 -2
- package/dist/renderer/assets/workbenchSettings-DKD5U1Ql.js +0 -8
- package/dist/simulator/assets/device-shell-Cw7c-IkG.js +0 -2
- package/dist/simulator/assets/device-shell-DbC5ccs8.css +0 -1
- package/dist/simulator/assets/jsx-runtime-DkKmJyBb.js +0 -2
- package/dist/simulator/device-shell/menu-button-geometry.js +0 -18
- package/dist/vscode-workbench/assets/__vite-browser-external-BON7qP59.js +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ProjectChannel, SessionChannel, WindowChannel,
|
|
1
|
+
import { ProjectChannel, SessionChannel, WindowChannel, WorkbenchSettingsChannel, EditorChannel, } from '../../../shared/ipc-channels.js';
|
|
2
|
+
import { SettingsChannel, PopoverChannel, TooltipChannel, ProjectCreateChannel, UpdateChannel, ViewChannel, } from '../../../shared/ipc-channels-overlays.js';
|
|
2
3
|
/** Safely resolve a WebContents, skipping destroyed / missing targets. */
|
|
3
4
|
function liveWebContents(wc) {
|
|
4
5
|
if (!wc)
|
|
@@ -45,15 +46,42 @@ export function createRendererNotifier(ctx) {
|
|
|
45
46
|
hostToolbarHeightChanged(height) {
|
|
46
47
|
sendToMain(ViewChannel.HostToolbarHeightChanged, height);
|
|
47
48
|
},
|
|
49
|
+
hostSidebarWidthChanged(width) {
|
|
50
|
+
sendToMain(ViewChannel.HostSidebarWidthChanged, width);
|
|
51
|
+
},
|
|
52
|
+
hostSidebarCategorySelected(category) {
|
|
53
|
+
sendToMain(ViewChannel.HostSidebarCategorySelected, category);
|
|
54
|
+
},
|
|
48
55
|
editorOpenFile(payload) {
|
|
49
56
|
sendToMain(EditorChannel.OpenFile, payload);
|
|
50
57
|
},
|
|
58
|
+
projectCreateSubmitted(payload) {
|
|
59
|
+
sendToMain(ProjectCreateChannel.Submitted, payload);
|
|
60
|
+
},
|
|
51
61
|
popoverInit(popoverView, payload) {
|
|
52
62
|
const wc = liveWebContents(popoverView.webContents);
|
|
53
63
|
if (!wc)
|
|
54
64
|
return;
|
|
55
65
|
wc.send(PopoverChannel.Init, payload);
|
|
56
66
|
},
|
|
67
|
+
tooltipInit(tooltipView, payload) {
|
|
68
|
+
const wc = liveWebContents(tooltipView.webContents);
|
|
69
|
+
if (!wc)
|
|
70
|
+
return;
|
|
71
|
+
wc.send(TooltipChannel.Init, payload);
|
|
72
|
+
},
|
|
73
|
+
projectCreateInit(dialogView, payload) {
|
|
74
|
+
const wc = liveWebContents(dialogView.webContents);
|
|
75
|
+
if (!wc)
|
|
76
|
+
return;
|
|
77
|
+
wc.send(ProjectCreateChannel.Init, payload);
|
|
78
|
+
},
|
|
79
|
+
updateAvailable(dialogView, payload) {
|
|
80
|
+
const wc = liveWebContents(dialogView.webContents);
|
|
81
|
+
if (!wc)
|
|
82
|
+
return;
|
|
83
|
+
wc.send(UpdateChannel.Available, payload);
|
|
84
|
+
},
|
|
57
85
|
settingsInit(payload) {
|
|
58
86
|
const wc = liveWebContents(ctx.views.getSettingsWebContents());
|
|
59
87
|
if (!wc)
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import type { CompileConfig } from '../../../shared/types.js';
|
|
1
|
+
import type { CompileConfig, ProjectType } from '../../../shared/types.js';
|
|
2
|
+
export type { ProjectType };
|
|
2
3
|
export interface Project {
|
|
3
4
|
name: string;
|
|
4
5
|
path: string;
|
|
5
6
|
lastOpened?: string | null;
|
|
6
7
|
compileConfig?: CompileConfig;
|
|
8
|
+
/** Absent on projects added before mini-game support — treat as 'miniprogram'. */
|
|
9
|
+
type?: ProjectType;
|
|
7
10
|
}
|
|
8
11
|
export interface ProjectPages {
|
|
9
12
|
pages: string[];
|
|
@@ -4,6 +4,44 @@ import fs from 'fs';
|
|
|
4
4
|
import { DEFAULT_SCENE } from '../../../shared/constants.js';
|
|
5
5
|
import { createLogger } from '../../utils/logger.js';
|
|
6
6
|
const log = createLogger('projects');
|
|
7
|
+
/**
|
|
8
|
+
* Merge project.config.json + project.private.config.json (private wins),
|
|
9
|
+
* mirroring `dimina/fe/packages/compiler/src/env.js`'s `storeInfo`.
|
|
10
|
+
*/
|
|
11
|
+
function readProjectConfig(dirPath) {
|
|
12
|
+
let merged = {};
|
|
13
|
+
for (const fileName of ['project.config.json', 'project.private.config.json']) {
|
|
14
|
+
const configPath = path.join(dirPath, fileName);
|
|
15
|
+
if (!fs.existsSync(configPath))
|
|
16
|
+
continue;
|
|
17
|
+
try {
|
|
18
|
+
merged = { ...merged, ...JSON.parse(fs.readFileSync(configPath, 'utf-8')) };
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
log.warn(`Failed to parse ${configPath}`, err);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return merged;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Mirrors `dimina/fe/packages/compiler/src/env.js`'s `detectRuntimeType` —
|
|
28
|
+
* an explicit `compileType` wins, else a mini-game is inferred from
|
|
29
|
+
* game.json + game.js/.ts with no app.json present.
|
|
30
|
+
*/
|
|
31
|
+
function detectRuntimeType(dirPath) {
|
|
32
|
+
const compileType = readProjectConfig(dirPath).compileType;
|
|
33
|
+
if (compileType === 'game')
|
|
34
|
+
return 'minigame';
|
|
35
|
+
if (compileType === 'miniprogram')
|
|
36
|
+
return 'miniprogram';
|
|
37
|
+
const hasMiniProgramConfig = fs.existsSync(path.join(dirPath, 'app.json'));
|
|
38
|
+
const hasMiniGameConfig = fs.existsSync(path.join(dirPath, 'game.json'));
|
|
39
|
+
const hasMiniGameEntry = ['game.js', 'game.ts']
|
|
40
|
+
.some((fileName) => fs.existsSync(path.join(dirPath, fileName)));
|
|
41
|
+
if (!hasMiniProgramConfig && hasMiniGameConfig && hasMiniGameEntry)
|
|
42
|
+
return 'minigame';
|
|
43
|
+
return 'miniprogram';
|
|
44
|
+
}
|
|
7
45
|
function getProjectsFile() {
|
|
8
46
|
return path.join(app.getPath('userData'), 'dimina-projects.json');
|
|
9
47
|
}
|
|
@@ -28,6 +66,12 @@ export function validateProjectDir(dirPath) {
|
|
|
28
66
|
if (!fs.existsSync(dirPath)) {
|
|
29
67
|
return `小程序目录不存在:${dirPath}`;
|
|
30
68
|
}
|
|
69
|
+
if (detectRuntimeType(dirPath) === 'minigame') {
|
|
70
|
+
if (!fs.existsSync(path.join(dirPath, 'game.json'))) {
|
|
71
|
+
return '该目录缺少 game.json,请选择包含小游戏源码的目录';
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
31
75
|
if (!fs.existsSync(path.join(dirPath, 'app.json'))) {
|
|
32
76
|
const configPath = path.join(dirPath, 'project.config.json');
|
|
33
77
|
if (fs.existsSync(configPath)) {
|
|
@@ -63,10 +107,11 @@ export function addProject(dirPath) {
|
|
|
63
107
|
catch (err) {
|
|
64
108
|
log.warn('Failed to read project name from config', err);
|
|
65
109
|
}
|
|
66
|
-
const
|
|
110
|
+
const type = detectRuntimeType(dirPath);
|
|
111
|
+
const project = { name, path: dirPath, lastOpened: null, type };
|
|
67
112
|
const idx = projects.findIndex((p) => p.path === dirPath);
|
|
68
113
|
if (idx >= 0) {
|
|
69
|
-
projects[idx] = { ...projects[idx], name };
|
|
114
|
+
projects[idx] = { ...projects[idx], name, type };
|
|
70
115
|
}
|
|
71
116
|
else {
|
|
72
117
|
projects.unshift(project);
|
|
@@ -88,13 +133,26 @@ export function updateLastOpened(dirPath) {
|
|
|
88
133
|
export function getCompileConfig(dirPath) {
|
|
89
134
|
const projects = load();
|
|
90
135
|
const project = projects.find((p) => p.path === dirPath);
|
|
91
|
-
|
|
92
|
-
|
|
136
|
+
if (project?.compileConfig)
|
|
137
|
+
return project.compileConfig;
|
|
138
|
+
// Default startPage to the project's real entry page (mirrors
|
|
139
|
+
// getProjectPages: 'game' for mini-games, app.json's entryPagePath for
|
|
140
|
+
// mini-programs) rather than a mini-program-only literal — the simulator
|
|
141
|
+
// URL builders' own 'pages/index/index' fallback only fires when this is
|
|
142
|
+
// still empty (unreadable/malformed manifest).
|
|
143
|
+
return {
|
|
144
|
+
startPage: getProjectPages(dirPath).entryPagePath,
|
|
93
145
|
scene: DEFAULT_SCENE,
|
|
94
146
|
queryParams: [],
|
|
95
|
-
}
|
|
147
|
+
};
|
|
96
148
|
}
|
|
97
149
|
export function getProjectPages(dirPath) {
|
|
150
|
+
if (detectRuntimeType(dirPath) === 'minigame') {
|
|
151
|
+
// Mini-games have no page router — the compiler always emits a single
|
|
152
|
+
// synthetic 'game' entry (dimina/fe/packages/compiler/src/env.js
|
|
153
|
+
// storeAppConfig), mirrored here rather than reading a nonexistent app.json.
|
|
154
|
+
return { pages: ['game'], entryPagePath: 'game' };
|
|
155
|
+
}
|
|
98
156
|
const appJsonPath = path.join(dirPath, 'app.json');
|
|
99
157
|
try {
|
|
100
158
|
const appJson = JSON.parse(fs.readFileSync(appJsonPath, 'utf-8'));
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* page a nested render-host `<webview>`), not a renderer `<webview>` the main
|
|
7
7
|
* window can observe — so in-app navigation (navigateTo / switchTab / back)
|
|
8
8
|
* never reaches the renderer's `<webview>` did-navigate events. This service
|
|
9
|
-
* taps the bridge's active-page signal and pushes the
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* taps the bridge's active-page signal and pushes the route — page path plus
|
|
10
|
+
* its launch query, so the simulator's page-path bar shows params just like
|
|
11
|
+
* WeChat DevTools and a recompile can restore them — to the main-window
|
|
12
|
+
* renderer (`SimulatorChannel.CurrentPage`), keeping the toolbar in sync
|
|
13
|
+
* without polling.
|
|
12
14
|
*
|
|
13
15
|
* Inert on the default dimina-fe path (which derives the current page from the
|
|
14
16
|
* simulator `<webview>`'s navigation events); app.ts gates the call on
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SimulatorChannel } from '../../../shared/ipc-channels.js';
|
|
2
|
+
import { encodePageSpec } from '../../../shared/simulator-route.js';
|
|
2
3
|
import { DisposableRegistry } from '@dimina-kit/electron-deck/main';
|
|
3
4
|
export function setupSimulatorCurrentPage(host, options) {
|
|
4
5
|
const registry = new DisposableRegistry();
|
|
@@ -11,7 +12,13 @@ export function setupSimulatorCurrentPage(host, options) {
|
|
|
11
12
|
return;
|
|
12
13
|
if (host.isDestroyed())
|
|
13
14
|
return;
|
|
14
|
-
|
|
15
|
+
// Bridge queries are `Record<string, unknown>` (they may hold numbers from
|
|
16
|
+
// the URL); the route format wants strings. encodePageSpec re-encodes with
|
|
17
|
+
// `?k=v&…` so the renderer can decode it back into { pagePath, query }.
|
|
18
|
+
const query = {};
|
|
19
|
+
for (const [k, v] of Object.entries(ev.query ?? {}))
|
|
20
|
+
query[k] = String(v);
|
|
21
|
+
host.send(SimulatorChannel.CurrentPage, encodePageSpec({ pagePath: ev.pagePath, query }));
|
|
15
22
|
});
|
|
16
23
|
registry.add(off);
|
|
17
24
|
return registry;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { BrowserWindow } from 'electron';
|
|
2
1
|
import type { UpdateChecker, UpdateInfo } from '../../../shared/types.js';
|
|
3
2
|
import { type SenderPolicy } from '../../utils/ipc-registry.js';
|
|
4
3
|
export interface UpdateManagerOptions {
|
|
5
4
|
checker: UpdateChecker;
|
|
6
|
-
|
|
5
|
+
/** Show the update-available overlay panel, fed the discovered update's info. */
|
|
6
|
+
showUpdatePanel: (info: UpdateInfo) => void;
|
|
7
|
+
/** Forward a download-progress tick into the (already-shown) update overlay. */
|
|
8
|
+
notifyDownloadProgress: (percent: number) => void;
|
|
9
|
+
/** Hide the update overlay panel — the renderer's close (any path) forwards here. */
|
|
10
|
+
hideUpdatePanel: () => void;
|
|
7
11
|
/** Check interval in milliseconds. Default: 1 hour */
|
|
8
12
|
checkInterval?: number;
|
|
9
13
|
/** Delay before the first check after startup in ms. Default: 5000 */
|
|
@@ -20,7 +24,9 @@ export interface UpdateManagerOptions {
|
|
|
20
24
|
}
|
|
21
25
|
export declare class UpdateManager {
|
|
22
26
|
private checker;
|
|
23
|
-
private
|
|
27
|
+
private showUpdatePanel;
|
|
28
|
+
private notifyDownloadProgress;
|
|
29
|
+
private hideUpdatePanel;
|
|
24
30
|
private getCurrentVersion;
|
|
25
31
|
private latestUpdate;
|
|
26
32
|
private downloadedPath;
|
|
@@ -37,6 +43,14 @@ export declare class UpdateManager {
|
|
|
37
43
|
private timer;
|
|
38
44
|
private initialTimer;
|
|
39
45
|
private ipc;
|
|
46
|
+
/**
|
|
47
|
+
* Set by `dispose()`. Clearing the timers only stops FUTURE ticks — an
|
|
48
|
+
* in-flight `checkAndNotify()` invocation (already past its `await
|
|
49
|
+
* this.check()`) has no timer left to cancel it, and would otherwise call
|
|
50
|
+
* `showUpdatePanel` after dispose has torn down the overlay panel that
|
|
51
|
+
* owns (e.g. `views.disposeAll()` destroying its WebContentsView).
|
|
52
|
+
*/
|
|
53
|
+
private disposed;
|
|
40
54
|
constructor(opts: UpdateManagerOptions);
|
|
41
55
|
private registerIpc;
|
|
42
56
|
check(): Promise<{
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { app, shell } from 'electron';
|
|
2
|
-
import { UpdateChannel } from '../../../shared/ipc-channels.js';
|
|
2
|
+
import { UpdateChannel } from '../../../shared/ipc-channels-overlays.js';
|
|
3
3
|
import { IpcRegistry } from '../../utils/ipc-registry.js';
|
|
4
4
|
export class UpdateManager {
|
|
5
5
|
checker;
|
|
6
|
-
|
|
6
|
+
showUpdatePanel;
|
|
7
|
+
notifyDownloadProgress;
|
|
8
|
+
hideUpdatePanel;
|
|
7
9
|
getCurrentVersion;
|
|
8
10
|
latestUpdate = null;
|
|
9
11
|
downloadedPath = null;
|
|
@@ -20,9 +22,19 @@ export class UpdateManager {
|
|
|
20
22
|
timer = null;
|
|
21
23
|
initialTimer = null;
|
|
22
24
|
ipc;
|
|
25
|
+
/**
|
|
26
|
+
* Set by `dispose()`. Clearing the timers only stops FUTURE ticks — an
|
|
27
|
+
* in-flight `checkAndNotify()` invocation (already past its `await
|
|
28
|
+
* this.check()`) has no timer left to cancel it, and would otherwise call
|
|
29
|
+
* `showUpdatePanel` after dispose has torn down the overlay panel that
|
|
30
|
+
* owns (e.g. `views.disposeAll()` destroying its WebContentsView).
|
|
31
|
+
*/
|
|
32
|
+
disposed = false;
|
|
23
33
|
constructor(opts) {
|
|
24
34
|
this.checker = opts.checker;
|
|
25
|
-
this.
|
|
35
|
+
this.showUpdatePanel = opts.showUpdatePanel;
|
|
36
|
+
this.notifyDownloadProgress = opts.notifyDownloadProgress;
|
|
37
|
+
this.hideUpdatePanel = opts.hideUpdatePanel;
|
|
26
38
|
this.getCurrentVersion = opts.getCurrentVersion ?? (() => app.getVersion());
|
|
27
39
|
this.ipc = new IpcRegistry(opts.senderPolicy);
|
|
28
40
|
this.registerIpc();
|
|
@@ -32,7 +44,8 @@ export class UpdateManager {
|
|
|
32
44
|
this.ipc
|
|
33
45
|
.handle(UpdateChannel.Check, async () => this.check())
|
|
34
46
|
.handle(UpdateChannel.Download, async () => this.download())
|
|
35
|
-
.handle(UpdateChannel.Install, async () => this.install())
|
|
47
|
+
.handle(UpdateChannel.Install, async () => this.install())
|
|
48
|
+
.on(UpdateChannel.Close, () => this.hideUpdatePanel());
|
|
36
49
|
}
|
|
37
50
|
async check() {
|
|
38
51
|
try {
|
|
@@ -69,7 +82,7 @@ export class UpdateManager {
|
|
|
69
82
|
}
|
|
70
83
|
try {
|
|
71
84
|
const filePath = await this.checker.downloadUpdate(this.latestUpdate, (percent) => {
|
|
72
|
-
this.
|
|
85
|
+
this.notifyDownloadProgress(percent);
|
|
73
86
|
});
|
|
74
87
|
this.downloadedPath = filePath;
|
|
75
88
|
return { success: true, filePath };
|
|
@@ -104,6 +117,7 @@ export class UpdateManager {
|
|
|
104
117
|
* the timer clears + handler removals are scheduled synchronously.
|
|
105
118
|
*/
|
|
106
119
|
dispose() {
|
|
120
|
+
this.disposed = true;
|
|
107
121
|
if (this.timer) {
|
|
108
122
|
clearInterval(this.timer);
|
|
109
123
|
this.timer = null;
|
|
@@ -120,12 +134,17 @@ export class UpdateManager {
|
|
|
120
134
|
}
|
|
121
135
|
async checkAndNotify() {
|
|
122
136
|
const result = await this.check();
|
|
137
|
+
// dispose() only cancels the timers that SCHEDULE future ticks — a tick
|
|
138
|
+
// already in flight (past this await) has nothing left to cancel it, and
|
|
139
|
+
// must not call into a torn-down panel/registry after the fact.
|
|
140
|
+
if (this.disposed)
|
|
141
|
+
return;
|
|
123
142
|
if (!result.hasUpdate || !result.info)
|
|
124
143
|
return;
|
|
125
144
|
if (this.hasNotified)
|
|
126
145
|
return;
|
|
127
146
|
this.hasNotified = true;
|
|
128
|
-
this.
|
|
147
|
+
this.showUpdatePanel(result.info);
|
|
129
148
|
}
|
|
130
149
|
}
|
|
131
150
|
//# sourceMappingURL=update-manager.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clears the right-panel Console panel's text-filter box on a FRESH project
|
|
3
|
+
* open, together with the stale persisted keys behind it.
|
|
4
|
+
*
|
|
5
|
+
* ── Why this exists ──────────────────────────────────────────────────────
|
|
6
|
+
* The Console filter text is a DevTools-owned setting that DevTools itself
|
|
7
|
+
* persists: it lives on the `devtools://` origin's localStorage, backed by the
|
|
8
|
+
* default session's on-disk storage (verified on disk:
|
|
9
|
+
* `~/Library/Application Support/Dimina DevTools/Local Storage/leveldb` holds a
|
|
10
|
+
* `console.textFilter` entry). An earlier implementation of the internal-log
|
|
11
|
+
* hiding wrote `-/^\[service\]/`-style negative filters straight into the box
|
|
12
|
+
* (see console-filter.ts's header for that history); that value still sits in
|
|
13
|
+
* localStorage and is restored on every project reopen / app restart. We do NOT
|
|
14
|
+
* fight DevTools' persistence mechanism here — instead, on each fresh project
|
|
15
|
+
* open we remove the stale keys and reset the visible box, so a project starts
|
|
16
|
+
* with the developer's own filter surface genuinely empty.
|
|
17
|
+
*
|
|
18
|
+
* ── When it runs ─────────────────────────────────────────────────────────
|
|
19
|
+
* Only the PROJECT-OPEN path arms this (see native-simulator-devtools-host.ts:
|
|
20
|
+
* `attach()` sets the flag; the injection consumes it once). Service-host pool
|
|
21
|
+
* swaps (hot-reload respawn) rebuild the front-end host too, but deliberately do
|
|
22
|
+
* NOT clear — the developer may legitimately have typed a filter during the
|
|
23
|
+
* session and a respawn must not drop in-flight work.
|
|
24
|
+
*
|
|
25
|
+
* ── Discipline (mirrors console-filter.ts) ────────────────────────────────
|
|
26
|
+
* In-realm bootstrap probe before touching `Console.ConsoleView.instance()` (an
|
|
27
|
+
* early construction transitively creates IssuesManager and permanently kills
|
|
28
|
+
* the front-end's own bootstrap — see frontend-bootstrap-gate.ts); bounded
|
|
29
|
+
* retry; silent degradation on any failure. The main process additionally holds
|
|
30
|
+
* this whole injection behind `whenFrontendBootstrapped`.
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* Build the `executeJavaScript` source that clears the Console filter box.
|
|
34
|
+
*
|
|
35
|
+
* Two levers, belt-and-suspenders:
|
|
36
|
+
* 1. remove the stale persisted keys (`console.textFilter` — the on-disk
|
|
37
|
+
* leftover we actually observed, and its kebab-case sibling) so a Console
|
|
38
|
+
* view constructed after this script reads an empty setting;
|
|
39
|
+
* 2. reset the already-constructed panel's visible box via
|
|
40
|
+
* `filter.textFilterUI.setValue('')`, which persists the empty value back
|
|
41
|
+
* through the panel's own setting path.
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildClearConsoleFilterScript(): string;
|
|
44
|
+
//# sourceMappingURL=clear-console-filter.d.ts.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clears the right-panel Console panel's text-filter box on a FRESH project
|
|
3
|
+
* open, together with the stale persisted keys behind it.
|
|
4
|
+
*
|
|
5
|
+
* ── Why this exists ──────────────────────────────────────────────────────
|
|
6
|
+
* The Console filter text is a DevTools-owned setting that DevTools itself
|
|
7
|
+
* persists: it lives on the `devtools://` origin's localStorage, backed by the
|
|
8
|
+
* default session's on-disk storage (verified on disk:
|
|
9
|
+
* `~/Library/Application Support/Dimina DevTools/Local Storage/leveldb` holds a
|
|
10
|
+
* `console.textFilter` entry). An earlier implementation of the internal-log
|
|
11
|
+
* hiding wrote `-/^\[service\]/`-style negative filters straight into the box
|
|
12
|
+
* (see console-filter.ts's header for that history); that value still sits in
|
|
13
|
+
* localStorage and is restored on every project reopen / app restart. We do NOT
|
|
14
|
+
* fight DevTools' persistence mechanism here — instead, on each fresh project
|
|
15
|
+
* open we remove the stale keys and reset the visible box, so a project starts
|
|
16
|
+
* with the developer's own filter surface genuinely empty.
|
|
17
|
+
*
|
|
18
|
+
* ── When it runs ─────────────────────────────────────────────────────────
|
|
19
|
+
* Only the PROJECT-OPEN path arms this (see native-simulator-devtools-host.ts:
|
|
20
|
+
* `attach()` sets the flag; the injection consumes it once). Service-host pool
|
|
21
|
+
* swaps (hot-reload respawn) rebuild the front-end host too, but deliberately do
|
|
22
|
+
* NOT clear — the developer may legitimately have typed a filter during the
|
|
23
|
+
* session and a respawn must not drop in-flight work.
|
|
24
|
+
*
|
|
25
|
+
* ── Discipline (mirrors console-filter.ts) ────────────────────────────────
|
|
26
|
+
* In-realm bootstrap probe before touching `Console.ConsoleView.instance()` (an
|
|
27
|
+
* early construction transitively creates IssuesManager and permanently kills
|
|
28
|
+
* the front-end's own bootstrap — see frontend-bootstrap-gate.ts); bounded
|
|
29
|
+
* retry; silent degradation on any failure. The main process additionally holds
|
|
30
|
+
* this whole injection behind `whenFrontendBootstrapped`.
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* Build the `executeJavaScript` source that clears the Console filter box.
|
|
34
|
+
*
|
|
35
|
+
* Two levers, belt-and-suspenders:
|
|
36
|
+
* 1. remove the stale persisted keys (`console.textFilter` — the on-disk
|
|
37
|
+
* leftover we actually observed, and its kebab-case sibling) so a Console
|
|
38
|
+
* view constructed after this script reads an empty setting;
|
|
39
|
+
* 2. reset the already-constructed panel's visible box via
|
|
40
|
+
* `filter.textFilterUI.setValue('')`, which persists the empty value back
|
|
41
|
+
* through the panel's own setting path.
|
|
42
|
+
*/
|
|
43
|
+
export function buildClearConsoleFilterScript() {
|
|
44
|
+
return `(function(){
|
|
45
|
+
var attempts = 0;
|
|
46
|
+
var MAX = 100;
|
|
47
|
+
function bootstrapReady() {
|
|
48
|
+
try {
|
|
49
|
+
var eui = globalThis.EUI;
|
|
50
|
+
if (!eui || !eui.ShortcutRegistry || !eui.ShortcutRegistry.ShortcutRegistry) return false;
|
|
51
|
+
eui.ShortcutRegistry.ShortcutRegistry.instance();
|
|
52
|
+
return true;
|
|
53
|
+
} catch (_) { return false; }
|
|
54
|
+
}
|
|
55
|
+
function tryClear() {
|
|
56
|
+
attempts++;
|
|
57
|
+
var scheduleRetry = attempts < MAX;
|
|
58
|
+
if (!bootstrapReady()) {
|
|
59
|
+
if (scheduleRetry) { setTimeout(tryClear, 100); return; }
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
try { localStorage.removeItem('console.textFilter'); } catch(_) {}
|
|
64
|
+
try { localStorage.removeItem('console.text-filter'); } catch(_) {}
|
|
65
|
+
var ConsoleNS = globalThis.Console;
|
|
66
|
+
var view = ConsoleNS && ConsoleNS.ConsoleView ? ConsoleNS.ConsoleView.instance() : null;
|
|
67
|
+
var f = view ? view.filter : null;
|
|
68
|
+
var box = f && f.textFilterUI;
|
|
69
|
+
if (!box || typeof box.setValue !== 'function' || typeof box.value !== 'function') {
|
|
70
|
+
if (scheduleRetry) { setTimeout(tryClear, 100); return; }
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
var current = box.value();
|
|
74
|
+
if (current) {
|
|
75
|
+
box.setValue('');
|
|
76
|
+
if (typeof f.updateCurrentFilter === 'function') f.updateCurrentFilter();
|
|
77
|
+
if (typeof f.onFilterChanged === 'function') f.onFilterChanged();
|
|
78
|
+
}
|
|
79
|
+
} catch(_) {
|
|
80
|
+
if (scheduleRetry) setTimeout(tryClear, 100);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
tryClear();
|
|
84
|
+
})()`;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=clear-console-filter.js.map
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fakes shaped like the Chrome DevTools front-end objects
|
|
3
|
+
* `buildInternalLogHideScript()`'s generated source talks to, shared by
|
|
4
|
+
* console-filter.test.ts (what the hook does) and
|
|
5
|
+
* console-filter-degradation.test.ts (what happens when the panel is not there
|
|
6
|
+
* or the front-end API has moved).
|
|
7
|
+
*
|
|
8
|
+
* These are STUBS OF A FOREIGN API, not a second implementation: every test
|
|
9
|
+
* runs the real generated script string through `new Function`, so the fakes
|
|
10
|
+
* only have to expose the handful of members the script reaches for. What they
|
|
11
|
+
* cannot prove is that the real front-end still has those members — that is
|
|
12
|
+
* e2e/console-filter-live.spec.ts's job.
|
|
13
|
+
*/
|
|
14
|
+
import { type Mock } from 'vitest';
|
|
15
|
+
export interface FakeViewMessage {
|
|
16
|
+
consoleMessage: () => {
|
|
17
|
+
messageText: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export type ShouldBeVisible = (this: unknown, viewMessage: FakeViewMessage) => boolean;
|
|
21
|
+
export interface FakeConsoleFilterClass {
|
|
22
|
+
original: Mock<ShouldBeVisible>;
|
|
23
|
+
prototype: {
|
|
24
|
+
shouldBeVisible?: ShouldBeVisible;
|
|
25
|
+
};
|
|
26
|
+
newInstance: () => {
|
|
27
|
+
shouldBeVisible: ShouldBeVisible;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface FakeConsoleView {
|
|
31
|
+
view: {
|
|
32
|
+
filter: {
|
|
33
|
+
currentFilter: object;
|
|
34
|
+
textFilterUI: {
|
|
35
|
+
value: () => string;
|
|
36
|
+
setValue: Mock<(next: string) => void>;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
onFilterChanged: Mock<() => void>;
|
|
40
|
+
};
|
|
41
|
+
setValue: Mock<(next: string) => void>;
|
|
42
|
+
onFilterChanged: Mock<() => void>;
|
|
43
|
+
filterText: () => string;
|
|
44
|
+
}
|
|
45
|
+
/** A ConsoleViewMessage stub exposing the single field the hook inspects. */
|
|
46
|
+
export declare function createViewMessage(messageText: string): FakeViewMessage;
|
|
47
|
+
/**
|
|
48
|
+
* A ConsoleFilter "class": one shared prototype carrying `shouldBeVisible`,
|
|
49
|
+
* plus a factory for further instances off that same prototype — what
|
|
50
|
+
* `ConsoleFilter.clone()` produces. `original` is the pre-existing
|
|
51
|
+
* implementation the hook must delegate to.
|
|
52
|
+
*/
|
|
53
|
+
export declare function createConsoleFilterClass(verdict?: boolean | ShouldBeVisible): FakeConsoleFilterClass;
|
|
54
|
+
/** A ConsoleFilter whose prototype chain carries no `shouldBeVisible` at all. */
|
|
55
|
+
export declare function createConsoleFilterClassWithoutHook(): {
|
|
56
|
+
prototype: Record<string, unknown>;
|
|
57
|
+
newInstance: () => object;
|
|
58
|
+
};
|
|
59
|
+
/** The ConsoleView surface the script reaches through: filter + refresh entry point. */
|
|
60
|
+
export declare function createConsoleView(currentFilter: object, initialFilterText?: string): FakeConsoleView;
|
|
61
|
+
/** A front end whose bootstrap has finished: the probe returns instead of throwing. */
|
|
62
|
+
export declare function createReadyEui(): {
|
|
63
|
+
ShortcutRegistry: {
|
|
64
|
+
ShortcutRegistry: {
|
|
65
|
+
instance: () => {};
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
export declare function createGlobalThis(view: unknown): {
|
|
70
|
+
EUI: {
|
|
71
|
+
ShortcutRegistry: {
|
|
72
|
+
ShortcutRegistry: {
|
|
73
|
+
instance: () => {};
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
Console: {
|
|
78
|
+
ConsoleView: {
|
|
79
|
+
instance: () => unknown;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
export declare function run(script: string, fakeGlobalThis: object): void;
|
|
84
|
+
/**
|
|
85
|
+
* Collect `console.warn` output as plain strings for the whole test file.
|
|
86
|
+
*
|
|
87
|
+
* Reading `warnSpy.mock.calls` instead would hand every assertion an untyped
|
|
88
|
+
* `any[]`; the degradation tests care about WHICH warning was emitted, so the
|
|
89
|
+
* text has to survive into the assertion with its type intact.
|
|
90
|
+
*/
|
|
91
|
+
export declare function recordWarnings(): {
|
|
92
|
+
messages: string[];
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=console-filter-test-fixtures.d.ts.map
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fakes shaped like the Chrome DevTools front-end objects
|
|
3
|
+
* `buildInternalLogHideScript()`'s generated source talks to, shared by
|
|
4
|
+
* console-filter.test.ts (what the hook does) and
|
|
5
|
+
* console-filter-degradation.test.ts (what happens when the panel is not there
|
|
6
|
+
* or the front-end API has moved).
|
|
7
|
+
*
|
|
8
|
+
* These are STUBS OF A FOREIGN API, not a second implementation: every test
|
|
9
|
+
* runs the real generated script string through `new Function`, so the fakes
|
|
10
|
+
* only have to expose the handful of members the script reaches for. What they
|
|
11
|
+
* cannot prove is that the real front-end still has those members — that is
|
|
12
|
+
* e2e/console-filter-live.spec.ts's job.
|
|
13
|
+
*/
|
|
14
|
+
import { vi } from 'vitest';
|
|
15
|
+
/** A ConsoleViewMessage stub exposing the single field the hook inspects. */
|
|
16
|
+
export function createViewMessage(messageText) {
|
|
17
|
+
return { consoleMessage: () => ({ messageText }) };
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A ConsoleFilter "class": one shared prototype carrying `shouldBeVisible`,
|
|
21
|
+
* plus a factory for further instances off that same prototype — what
|
|
22
|
+
* `ConsoleFilter.clone()` produces. `original` is the pre-existing
|
|
23
|
+
* implementation the hook must delegate to.
|
|
24
|
+
*/
|
|
25
|
+
export function createConsoleFilterClass(verdict = true) {
|
|
26
|
+
const impl = typeof verdict === 'function' ? verdict : () => verdict;
|
|
27
|
+
const original = vi.fn(impl);
|
|
28
|
+
const prototype = { shouldBeVisible: original };
|
|
29
|
+
return {
|
|
30
|
+
original,
|
|
31
|
+
prototype,
|
|
32
|
+
newInstance: () => Object.create(prototype),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** A ConsoleFilter whose prototype chain carries no `shouldBeVisible` at all. */
|
|
36
|
+
export function createConsoleFilterClassWithoutHook() {
|
|
37
|
+
const prototype = Object.create(null);
|
|
38
|
+
return { prototype, newInstance: () => Object.create(prototype) };
|
|
39
|
+
}
|
|
40
|
+
/** The ConsoleView surface the script reaches through: filter + refresh entry point. */
|
|
41
|
+
export function createConsoleView(currentFilter, initialFilterText = '') {
|
|
42
|
+
let filterText = initialFilterText;
|
|
43
|
+
const setValue = vi.fn((next) => { filterText = next; });
|
|
44
|
+
const onFilterChanged = vi.fn();
|
|
45
|
+
return {
|
|
46
|
+
view: {
|
|
47
|
+
filter: {
|
|
48
|
+
currentFilter,
|
|
49
|
+
textFilterUI: { value: () => filterText, setValue },
|
|
50
|
+
},
|
|
51
|
+
onFilterChanged,
|
|
52
|
+
},
|
|
53
|
+
setValue,
|
|
54
|
+
onFilterChanged,
|
|
55
|
+
filterText: () => filterText,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** A front end whose bootstrap has finished: the probe returns instead of throwing. */
|
|
59
|
+
export function createReadyEui() {
|
|
60
|
+
return { ShortcutRegistry: { ShortcutRegistry: { instance: () => ({}) } } };
|
|
61
|
+
}
|
|
62
|
+
export function createGlobalThis(view) {
|
|
63
|
+
return { EUI: createReadyEui(), Console: { ConsoleView: { instance: () => view } } };
|
|
64
|
+
}
|
|
65
|
+
export function run(script, fakeGlobalThis) {
|
|
66
|
+
new Function('globalThis', script)(fakeGlobalThis);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Collect `console.warn` output as plain strings for the whole test file.
|
|
70
|
+
*
|
|
71
|
+
* Reading `warnSpy.mock.calls` instead would hand every assertion an untyped
|
|
72
|
+
* `any[]`; the degradation tests care about WHICH warning was emitted, so the
|
|
73
|
+
* text has to survive into the assertion with its type intact.
|
|
74
|
+
*/
|
|
75
|
+
export function recordWarnings() {
|
|
76
|
+
const record = { messages: [] };
|
|
77
|
+
vi.spyOn(console, 'warn').mockImplementation((...args) => {
|
|
78
|
+
record.messages.push(args.map((arg) => String(arg)).join(' '));
|
|
79
|
+
});
|
|
80
|
+
return record;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=console-filter-test-fixtures.js.map
|