@proteus-vue/devtools 0.1.0
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/README.md +114 -0
- package/dist/component-trace.d.ts +35 -0
- package/dist/device-info.d.ts +5 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +3323 -0
- package/dist/install.d.ts +76 -0
- package/dist/ownership-info.d.ts +77 -0
- package/dist/panel.d.ts +39 -0
- package/dist/panel.js +9172 -0
- package/dist/plugins/network.d.ts +2 -0
- package/dist/plugins.d.ts +64 -0
- package/dist/session-io.d.ts +35 -0
- package/dist/snapshot-io.d.ts +37 -0
- package/dist/source.d.ts +22 -0
- package/dist/tooltip.d.ts +21 -0
- package/dist/views/components.d.ts +26 -0
- package/dist/views/device.d.ts +43 -0
- package/dist/views/errors.d.ts +5 -0
- package/dist/views/flamegraph.d.ts +20 -0
- package/dist/views/graph.d.ts +5 -0
- package/dist/views/inspector.d.ts +9 -0
- package/dist/views/ownership.d.ts +4 -0
- package/dist/views/pages.d.ts +18 -0
- package/dist/views/route.d.ts +5 -0
- package/dist/views/state.d.ts +26 -0
- package/dist/views/timeline-interaction.d.ts +12 -0
- package/dist/views/timeline.d.ts +16 -0
- package/dist/vue-devtools.d.ts +133 -0
- package/dist/ws-bridge.d.ts +21 -0
- package/package.json +43 -0
- package/panel.html +26 -0
- package/style.css +1248 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { TraceEvent } from '@proteus-vue/devtools-runtime';
|
|
2
|
+
export interface DevToolsPlugin {
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
/** 依赖插件(激活拓扑排序;循环依赖 → activate 报错并给出环路径) */
|
|
6
|
+
peerDependencies?: string[];
|
|
7
|
+
setup(ctx: PluginContext): void | Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface PluginBus {
|
|
10
|
+
/** 订阅事件流;回调抛错 → 自动卸载 + 插件标记 crashed(核心不崩) */
|
|
11
|
+
on(cb: (e: TraceEvent) => void): () => void;
|
|
12
|
+
}
|
|
13
|
+
export interface PanelAPI {
|
|
14
|
+
/** 注册自定义视图(侧栏导航项 + 内容容器);render 由面板 16ms 节流 rerender 调用 */
|
|
15
|
+
addView(id: string, opts: {
|
|
16
|
+
label: string;
|
|
17
|
+
icon?: string;
|
|
18
|
+
render: (container: HTMLElement) => void;
|
|
19
|
+
}): void;
|
|
20
|
+
}
|
|
21
|
+
export interface CommandRegistry {
|
|
22
|
+
register(id: string, run: () => void): void;
|
|
23
|
+
run(id: string): void;
|
|
24
|
+
/** 已注册命令 id 列表(命令面板展示用) */
|
|
25
|
+
list(): string[];
|
|
26
|
+
}
|
|
27
|
+
export interface KVStorage {
|
|
28
|
+
get(key: string): unknown | undefined;
|
|
29
|
+
set(key: string, value: unknown): void;
|
|
30
|
+
}
|
|
31
|
+
export interface PluginContext {
|
|
32
|
+
name: string;
|
|
33
|
+
bus: PluginBus;
|
|
34
|
+
panel: PanelAPI;
|
|
35
|
+
commands: CommandRegistry;
|
|
36
|
+
storage: KVStorage;
|
|
37
|
+
}
|
|
38
|
+
export type PluginStatus = 'registered' | 'active' | 'crashed';
|
|
39
|
+
export interface PluginEntry {
|
|
40
|
+
name: string;
|
|
41
|
+
version: string;
|
|
42
|
+
status: PluginStatus;
|
|
43
|
+
error?: string;
|
|
44
|
+
}
|
|
45
|
+
/** 内存 KV(缺省存储;业务可注入 localStorage/IndexedDB 持久化) */
|
|
46
|
+
export declare function createMemoryStorage(): KVStorage;
|
|
47
|
+
export declare function createCommandRegistry(): CommandRegistry;
|
|
48
|
+
/**
|
|
49
|
+
* 拓扑排序(Kahn)+ 循环依赖检测:按 peerDependencies 求激活顺序。
|
|
50
|
+
* 存在环 → 返回剩余节点的依赖环路径(用于报错提示);无环 → cycle = null。
|
|
51
|
+
*/
|
|
52
|
+
export declare function resolveActivationOrder(plugins: DevToolsPlugin[]): {
|
|
53
|
+
order: string[];
|
|
54
|
+
cycle: string[] | null;
|
|
55
|
+
};
|
|
56
|
+
export interface PluginRegistry {
|
|
57
|
+
register(plugin: DevToolsPlugin): void;
|
|
58
|
+
unregister(name: string): void;
|
|
59
|
+
/** 拓扑序激活全部已注册插件(含依赖先激活);插件崩溃不影响其余 */
|
|
60
|
+
activateAll(ctx: (plugin: DevToolsPlugin) => PluginContext): Promise<PluginEntry[]>;
|
|
61
|
+
list(): PluginEntry[];
|
|
62
|
+
get(name: string): DevToolsPlugin | undefined;
|
|
63
|
+
}
|
|
64
|
+
export declare function createPluginRegistry(initial?: DevToolsPlugin[]): PluginRegistry;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { TraceEvent } from '@proteus-vue/devtools-runtime';
|
|
2
|
+
import type { StoreStepIO, StoreRestoreEntry } from './snapshot-io';
|
|
3
|
+
import type { DeviceInfo } from './views/device';
|
|
4
|
+
export interface SessionBundle {
|
|
5
|
+
kind: 'proteus-session';
|
|
6
|
+
version: 1;
|
|
7
|
+
exportedAt: number;
|
|
8
|
+
meta: {
|
|
9
|
+
eventCount: number;
|
|
10
|
+
platform?: string;
|
|
11
|
+
userAgent?: string;
|
|
12
|
+
};
|
|
13
|
+
/** 可重放事件日志(重建 timeline/flame/errors/router-nav/store/component 聚合的唯一真相源) */
|
|
14
|
+
events: TraceEvent[];
|
|
15
|
+
/** 设备面板数据(环境/能力/内存基线) */
|
|
16
|
+
device?: DeviceInfo;
|
|
17
|
+
/** store 最新快照 + 步骤(应用侧恢复用;与快照导入同形态) */
|
|
18
|
+
stores: StoreRestoreEntry[];
|
|
19
|
+
steps: StoreStepIO[];
|
|
20
|
+
}
|
|
21
|
+
export interface ParsedSession {
|
|
22
|
+
events: TraceEvent[];
|
|
23
|
+
device?: DeviceInfo;
|
|
24
|
+
stores: StoreRestoreEntry[];
|
|
25
|
+
steps: StoreStepIO[];
|
|
26
|
+
}
|
|
27
|
+
/** 序列化会话(面板导出:事件日志 + 设备 + store 快照) */
|
|
28
|
+
export declare function serializeSession(input: {
|
|
29
|
+
events: TraceEvent[];
|
|
30
|
+
device?: DeviceInfo;
|
|
31
|
+
stores: StoreRestoreEntry[];
|
|
32
|
+
steps: StoreStepIO[];
|
|
33
|
+
}): string;
|
|
34
|
+
/** 解析并校验会话(非法 → null;坏事件行过滤保留合法行) */
|
|
35
|
+
export declare function parseSession(json: string): ParsedSession | null;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface StoreRestoreEntry {
|
|
2
|
+
id: string;
|
|
3
|
+
state: Record<string, unknown>;
|
|
4
|
+
}
|
|
5
|
+
export interface StoreStepIO {
|
|
6
|
+
index: number;
|
|
7
|
+
storeId: string;
|
|
8
|
+
type: 'patch' | 'action';
|
|
9
|
+
name: string;
|
|
10
|
+
payload: unknown;
|
|
11
|
+
timestamp: number;
|
|
12
|
+
}
|
|
13
|
+
export interface StoreSnapshotIO {
|
|
14
|
+
kind: 'proteus-store-snapshot';
|
|
15
|
+
version: 1;
|
|
16
|
+
exportedAt: number;
|
|
17
|
+
stores: StoreRestoreEntry[];
|
|
18
|
+
steps: StoreStepIO[];
|
|
19
|
+
}
|
|
20
|
+
export interface ParsedStoreSnapshot {
|
|
21
|
+
stores: StoreRestoreEntry[];
|
|
22
|
+
steps: StoreStepIO[];
|
|
23
|
+
}
|
|
24
|
+
/** 敏感键检测结果(导出二次确认用;对齐 TraceBus 脱敏键规则) */
|
|
25
|
+
export interface SensitiveKeyHit {
|
|
26
|
+
storeId: string;
|
|
27
|
+
keys: string[];
|
|
28
|
+
}
|
|
29
|
+
/** 递归扫描 state 树命中的敏感键(嵌套对象/数组;★M10 权限最小化 M7.3——导出前列出将导出的敏感字段) */
|
|
30
|
+
export declare function findSensitiveKeys(stores: StoreRestoreEntry[]): SensitiveKeyHit[];
|
|
31
|
+
/** 序列化快照(面板导出 / 测试 roundtrip) */
|
|
32
|
+
export declare function serializeStoreSnapshot(input: {
|
|
33
|
+
stores: StoreRestoreEntry[];
|
|
34
|
+
steps: StoreStepIO[];
|
|
35
|
+
}): string;
|
|
36
|
+
/** 解析并校验快照 JSON(非法 → null) */
|
|
37
|
+
export declare function parseStoreSnapshot(json: string): ParsedStoreSnapshot | null;
|
package/dist/source.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TraceEvent } from '@proteus-vue/devtools-runtime';
|
|
2
|
+
import type { TraceBus } from '@proteus-vue/devtools-runtime';
|
|
3
|
+
export interface DevtoolsSource {
|
|
4
|
+
/** 订阅事件流,返回取消函数 */
|
|
5
|
+
onEvent(cb: (e: TraceEvent) => void): () => void;
|
|
6
|
+
/** 订阅连接状态(可选):WS 源连上即通知——面板「已连接」不再等首个事件(避免「连上了但暂无事件」误显示连接中) */
|
|
7
|
+
onStatus?(cb: (s: DevtoolsSourceStatus) => void): () => void;
|
|
8
|
+
/** 应用信息(Proteus.appInfo:pages/依赖图数据源;WS 源请求缓存,TraceBus 源缺省) */
|
|
9
|
+
appInfo?(): unknown;
|
|
10
|
+
/** ★M8 设备信息(Proteus.deviceInfo:环境/能力数据源;WS 源请求缓存,TraceBus 源缺省) */
|
|
11
|
+
deviceInfo?(): unknown;
|
|
12
|
+
/** ★G-43 B4 所有权图(Proteus.ownership:视图数据源;WS 源请求缓存,TraceBus 源缺省) */
|
|
13
|
+
ownership?(): unknown;
|
|
14
|
+
/** ★远程命令下发(WS 源:面板 → relay → 应用侧执行;如 Proteus.restoreStores 时间旅行恢复) */
|
|
15
|
+
sendCommand?(method: string, params?: Record<string, unknown>): void;
|
|
16
|
+
close(): void;
|
|
17
|
+
}
|
|
18
|
+
export type DevtoolsSourceStatus = 'connecting' | 'connected' | 'closed';
|
|
19
|
+
/** TraceBus 直连源:进程内 TraceBus 事件 → DevtoolsSource(Web 端运行时接入用) */
|
|
20
|
+
export declare function createTraceBusSource(bus: TraceBus): DevtoolsSource;
|
|
21
|
+
/** WS 数据源:连接 dev server → Proteus.enable → 接收 Proteus.event 重组 TraceEvent(断线 1s 重连) */
|
|
22
|
+
export declare function createDevtoolsWsSource(url: string, createSocket?: (url: string) => WebSocket): DevtoolsSource;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface TooltipData {
|
|
2
|
+
title: string;
|
|
3
|
+
/** 详情行(如 耗时 / 时间戳 / 阶段) */
|
|
4
|
+
lines: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function attachTip(el: HTMLElement, data: TooltipData): void;
|
|
7
|
+
export declare function resolveTipData(target: HTMLElement): TooltipData | null;
|
|
8
|
+
export interface TooltipLayer {
|
|
9
|
+
/** 显示浮层(position 相对 viewport) */
|
|
10
|
+
show(data: TooltipData, x: number, y: number): void;
|
|
11
|
+
hide(): void;
|
|
12
|
+
/** 销毁:从 document.body 移除浮层元素(面板 destroy 时调用) */
|
|
13
|
+
dispose(): void;
|
|
14
|
+
readonly visible: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function createTooltipLayer(): TooltipLayer;
|
|
17
|
+
/**
|
|
18
|
+
* 给容器绑定 tooltip:元素带 `data-tip` 且 resolve 返回数据 → hover 显示。
|
|
19
|
+
* 返回解绑函数。resolve 返回 null → 不显示(但隐藏当前)。
|
|
20
|
+
*/
|
|
21
|
+
export declare function bindTooltip(root: HTMLElement, layer: TooltipLayer, resolve: (target: HTMLElement) => TooltipData | null): () => void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { DomTreeNode } from '../component-trace';
|
|
2
|
+
export interface ComponentNodeData {
|
|
3
|
+
id: number;
|
|
4
|
+
name: string;
|
|
5
|
+
parentId?: number;
|
|
6
|
+
/** 挂载时间戳 */
|
|
7
|
+
ts: number;
|
|
8
|
+
/** 同 id 重复挂载计数(组件复用场景) */
|
|
9
|
+
count: number;
|
|
10
|
+
/** mount 时刻 props 快照(serializeState 序列化,JSON-safe) */
|
|
11
|
+
props?: unknown;
|
|
12
|
+
/** mount 时刻 state 快照(options data / setupState) */
|
|
13
|
+
state?: unknown;
|
|
14
|
+
}
|
|
15
|
+
export interface ComponentsViewData {
|
|
16
|
+
nodes: ComponentNodeData[];
|
|
17
|
+
/** 选中组件 id(详情面板展示;缺省不选中) */
|
|
18
|
+
selectedId?: number;
|
|
19
|
+
/** ★P1.5:选中组件的渲染元素 DOM 树(component.inspect 事件下发) */
|
|
20
|
+
dom?: DomTreeNode;
|
|
21
|
+
}
|
|
22
|
+
export interface ComponentsViewHooks {
|
|
23
|
+
/** 选中组件 → 页面元素高亮(install 侧 scrollIntoView + flash;同 id 再点由调用方取消) */
|
|
24
|
+
onSelect?: (id: number) => void;
|
|
25
|
+
}
|
|
26
|
+
export declare function renderComponents(container: HTMLElement, data: ComponentsViewData, hooks?: ComponentsViewHooks): void;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface DeviceScreenInfo {
|
|
2
|
+
dpr: number;
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
/** 安全区(CSS env(safe-area-inset-*);刘海屏;无则 undefined) */
|
|
6
|
+
safeTop?: number;
|
|
7
|
+
safeBottom?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface DeviceMemoryInfo {
|
|
10
|
+
jsHeapLimit: number;
|
|
11
|
+
totalJSHeapSize: number;
|
|
12
|
+
usedJSHeapSize: number;
|
|
13
|
+
}
|
|
14
|
+
export interface DeviceCapabilityInfo {
|
|
15
|
+
capability: string;
|
|
16
|
+
platform: string;
|
|
17
|
+
priority: number;
|
|
18
|
+
required: boolean;
|
|
19
|
+
fallback?: string;
|
|
20
|
+
supported: boolean;
|
|
21
|
+
runsInWorklet?: boolean;
|
|
22
|
+
platforms: string[];
|
|
23
|
+
}
|
|
24
|
+
export interface DeviceInfo {
|
|
25
|
+
platform: string;
|
|
26
|
+
userAgent?: string;
|
|
27
|
+
/** 基础库版本(小程序;web 缺省) */
|
|
28
|
+
libVersion?: string;
|
|
29
|
+
screen?: DeviceScreenInfo;
|
|
30
|
+
memory?: DeviceMemoryInfo;
|
|
31
|
+
capabilities: DeviceCapabilityInfo[];
|
|
32
|
+
}
|
|
33
|
+
export interface DeviceMemorySample {
|
|
34
|
+
t: number;
|
|
35
|
+
used: number;
|
|
36
|
+
total: number;
|
|
37
|
+
limit: number;
|
|
38
|
+
}
|
|
39
|
+
export interface DeviceViewData {
|
|
40
|
+
info?: DeviceInfo;
|
|
41
|
+
memory: DeviceMemorySample[];
|
|
42
|
+
}
|
|
43
|
+
export declare function renderDevice(container: HTMLElement, data: DeviceViewData): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FlameNode, FlameCompareEntry } from '@proteus-vue/devtools-runtime';
|
|
2
|
+
export interface FlamegraphViewData {
|
|
3
|
+
nodes: FlameNode[];
|
|
4
|
+
/** 对比数据(与 baseline 录制 diff;缺省单录制无高亮) */
|
|
5
|
+
compare?: FlameCompareEntry[];
|
|
6
|
+
/** ★聚焦(zoom):渲染该节点子树;缺省渲染全部根 */
|
|
7
|
+
focus?: FlameNode;
|
|
8
|
+
/** 面包屑(焦点祖先链,含焦点自身) */
|
|
9
|
+
breadcrumb?: Array<{
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export interface FlamegraphViewHooks {
|
|
15
|
+
/** 点击块 → 聚焦该节点(zoom 到其子树) */
|
|
16
|
+
onFocus?: (id: string) => void;
|
|
17
|
+
/** 返回上级(面包屑最后一项 / 退出 zoom 到根) */
|
|
18
|
+
onFocusUp?: () => void;
|
|
19
|
+
}
|
|
20
|
+
export declare function renderFlamegraph(container: HTMLElement, data: FlamegraphViewData, hooks?: FlamegraphViewHooks): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** 值编辑钩子(state 视图双向调试;components 视图不传则只读) */
|
|
2
|
+
export interface InspectorEditHooks {
|
|
3
|
+
/** 原始值编辑提交(path 相对渲染根;非法输入不回调) */
|
|
4
|
+
onEdit?: (path: Array<string | number>, value: unknown) => void;
|
|
5
|
+
}
|
|
6
|
+
/** 单行摘要(object/array 折叠态显示) */
|
|
7
|
+
export declare function summarize(value: unknown): string;
|
|
8
|
+
/** 递归渲染 key-value 树(可折叠:object/array 行点击展开/收起;★path + hooks 支持原始值编辑双向调试) */
|
|
9
|
+
export declare function renderKeyValue(container: HTMLElement, key: string, value: unknown, depth: number, initiallyOpen?: boolean, path?: Array<string | number>, hooks?: InspectorEditHooks): void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface PageRouteData {
|
|
2
|
+
name: string;
|
|
3
|
+
path: string;
|
|
4
|
+
parent?: string;
|
|
5
|
+
meta?: {
|
|
6
|
+
title?: string;
|
|
7
|
+
isTab?: boolean;
|
|
8
|
+
};
|
|
9
|
+
subPackage?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface PagesViewData {
|
|
12
|
+
routes: PageRouteData[];
|
|
13
|
+
/** 当前页面栈(MP 真实栈;Web 恒 1 项) */
|
|
14
|
+
stack?: Array<{
|
|
15
|
+
route?: string;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
export declare function renderPages(container: HTMLElement, data: PagesViewData): void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { StateSnapshot, PatchStep } from '@proteus-vue/devtools-runtime';
|
|
2
|
+
export interface StateViewHooks {
|
|
3
|
+
/** 时间旅行回放到第 index 步(index = -1 表示初始快照) */
|
|
4
|
+
onTimeTravel?: (index: number) => void;
|
|
5
|
+
/** 选中 store(Pinia 面板布局:单选详情) */
|
|
6
|
+
onSelectStore?: (id: string) => void;
|
|
7
|
+
/** 导出快照(面板侧 Blob 下载) */
|
|
8
|
+
onExport?: () => void;
|
|
9
|
+
/** 导入快照 JSON(view 读文件 → 面板解析校验 + 数据重建 + 应用) */
|
|
10
|
+
onImport?: (json: string) => void;
|
|
11
|
+
/** ★M11 可观测性(M8.2):导出 SessionBundle(可重放事件日志 + 设备 + store 快照) */
|
|
12
|
+
onExportSession?: () => void;
|
|
13
|
+
/** ★M11 可观测性(M8.2):导入 SessionBundle(完整还原另一环境) */
|
|
14
|
+
onImportSession?: (json: string) => void;
|
|
15
|
+
/** ★双向调试:值编辑提交(点值改 → 应用侧 $patch 写回真实状态) */
|
|
16
|
+
onEditValue?: (storeId: string, path: Array<string | number>, value: unknown) => void;
|
|
17
|
+
}
|
|
18
|
+
export interface StateViewData {
|
|
19
|
+
snapshot: StateSnapshot;
|
|
20
|
+
steps: PatchStep[];
|
|
21
|
+
/** 当前选中 store(缺省第一个有快照的 store) */
|
|
22
|
+
selectedStore?: string;
|
|
23
|
+
/** ★当前时间旅行回放位置(rerender 后滑块保持;缺省最新) */
|
|
24
|
+
travelIndex?: number;
|
|
25
|
+
}
|
|
26
|
+
export declare function renderState(container: HTMLElement, data: StateViewData, hooks?: StateViewHooks): void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TimelineSpan } from '@proteus-vue/devtools-runtime';
|
|
2
|
+
import type { TimelineWindow } from './timeline';
|
|
3
|
+
export interface TimelineZoomOptions {
|
|
4
|
+
/** 窗口变更回调(panel 触发节流 rerender) */
|
|
5
|
+
onWindowChange?: (w: TimelineWindow) => void;
|
|
6
|
+
}
|
|
7
|
+
export interface TimelineZoom {
|
|
8
|
+
/** 当前窗口(未交互过 → null,panel 传 undefined 让渲染函数自算全窗) */
|
|
9
|
+
getWindow(): TimelineWindow | null;
|
|
10
|
+
destroy(): void;
|
|
11
|
+
}
|
|
12
|
+
export declare function createTimelineZoom(container: HTMLElement, getSpans: () => TimelineSpan[], opts?: TimelineZoomOptions): TimelineZoom;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TimelineSpan } from '@proteus-vue/devtools-runtime';
|
|
2
|
+
export interface TimelineWindow {
|
|
3
|
+
start: number;
|
|
4
|
+
end: number;
|
|
5
|
+
}
|
|
6
|
+
export interface TimelineViewData {
|
|
7
|
+
spans: TimelineSpan[];
|
|
8
|
+
/** 时间轴窗口(缺省自动取 min start ~ max end) */
|
|
9
|
+
window?: TimelineWindow;
|
|
10
|
+
/** 虚拟滚动(万级 span 分块渲染):仅渲染视口内泳道;容器由调用方设为 overflow-y 滚动 */
|
|
11
|
+
virtual?: {
|
|
12
|
+
scrollTop: number;
|
|
13
|
+
viewHeight: number;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export declare function renderTimeline(container: HTMLElement, data: TimelineViewData): void;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { DevtoolsSource } from './source';
|
|
2
|
+
/** @vue/devtools-api DevtoolsApi 的结构类型(只取 Timeline 能力面) */
|
|
3
|
+
export interface VueDevtoolsApiLike {
|
|
4
|
+
addTimelineLayer(options: {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
color?: number;
|
|
8
|
+
}): void;
|
|
9
|
+
addTimelineEvent(options: {
|
|
10
|
+
layerId: string;
|
|
11
|
+
event: unknown;
|
|
12
|
+
}): void;
|
|
13
|
+
}
|
|
14
|
+
export interface VueDevtoolsTimelineOptions {
|
|
15
|
+
/** Proteus 事件源(TraceBus 直连 / WS-CDP / mock) */
|
|
16
|
+
source: DevtoolsSource;
|
|
17
|
+
/** layer 颜色(Vue DevTools Timeline 色板,缺省紫蓝) */
|
|
18
|
+
color?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface VueDevtoolsTimeline {
|
|
21
|
+
/** 卸载:取消事件订阅 */
|
|
22
|
+
dispose(): void;
|
|
23
|
+
/** 已注册的 layer id */
|
|
24
|
+
readonly layerId: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 接入 Vue 官方 DevTools:注册 'proteus' Timeline layer,把事件流推送为 Timeline 事件。
|
|
28
|
+
* 用法(应用侧):setupDevtoolsPlugin({ id: 'proteus', label: 'Proteus', app }, (api) => {
|
|
29
|
+
* installProteusTimeline(api, { source })
|
|
30
|
+
* })
|
|
31
|
+
*/
|
|
32
|
+
export declare function installProteusTimeline(api: VueDevtoolsApiLike, options: VueDevtoolsTimelineOptions): VueDevtoolsTimeline;
|
|
33
|
+
/** 自定义 Inspector 所需的 @vue/devtools-api 形状(结构类型注入,可 mock 单测)
|
|
34
|
+
* ★state 是「分组名 → 状态行数组」对象(CustomInspectorState:`{ 分组: [{key, value}] }`)——
|
|
35
|
+
* 传数组会让 Vue DevTools 渲染不出分组详情(2026-09 实测根因) */
|
|
36
|
+
export interface VueDevtoolsInspectorApiLike {
|
|
37
|
+
addInspector(options: {
|
|
38
|
+
id: string;
|
|
39
|
+
label: string;
|
|
40
|
+
icon?: string;
|
|
41
|
+
}): void;
|
|
42
|
+
on: {
|
|
43
|
+
getInspectorTree(cb: (payload: {
|
|
44
|
+
inspectorId: string;
|
|
45
|
+
rootNodes?: unknown[];
|
|
46
|
+
}) => void): void;
|
|
47
|
+
getInspectorState(cb: (payload: {
|
|
48
|
+
inspectorId: string;
|
|
49
|
+
nodeId: string;
|
|
50
|
+
state?: Record<string, Array<{
|
|
51
|
+
key: string;
|
|
52
|
+
value: unknown;
|
|
53
|
+
}>>;
|
|
54
|
+
}) => void): void;
|
|
55
|
+
editInspectorState(cb: (payload: {
|
|
56
|
+
inspectorId: string;
|
|
57
|
+
nodeId: string;
|
|
58
|
+
path: string[];
|
|
59
|
+
state: {
|
|
60
|
+
value: unknown;
|
|
61
|
+
};
|
|
62
|
+
}) => void): void;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export interface ProteusInspectorsOptions {
|
|
66
|
+
/** 应用配置读取(缺省空对象;业务侧传 getConfig) */
|
|
67
|
+
getConfig?: () => Record<string, unknown>;
|
|
68
|
+
/** 配置更新(编辑回写——Web 端响应式更新白给;缺省 no-op) */
|
|
69
|
+
setConfig?: (patch: Record<string, unknown>) => void;
|
|
70
|
+
/**
|
|
71
|
+
* style-safety 拦截记录读取(G-31 runtime guard.records();提供则注册 proteus-style-safety inspector)
|
|
72
|
+
* 对齐 vue-devtools-plan §3:`p.state = [{ key: 'rejected', value: getRejectedRecords() }]`
|
|
73
|
+
*/
|
|
74
|
+
getStyleSafetyRecords?: () => Array<{
|
|
75
|
+
prop: string;
|
|
76
|
+
value: unknown;
|
|
77
|
+
reason: string;
|
|
78
|
+
ts: number;
|
|
79
|
+
}>;
|
|
80
|
+
/**
|
|
81
|
+
* 路由表(父引用嵌套树 → proteus-router Inspector:Vue DevTools 内置 Router 面板只认 vue-router,
|
|
82
|
+
* 我们用自己的路由 → 自定义 Inspector 展示路由树 + 详情)
|
|
83
|
+
*/
|
|
84
|
+
pages?: {
|
|
85
|
+
routes: Array<{
|
|
86
|
+
name: string;
|
|
87
|
+
path: string;
|
|
88
|
+
parent?: string;
|
|
89
|
+
subPackage?: string;
|
|
90
|
+
meta?: Record<string, unknown>;
|
|
91
|
+
}>;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* 导航记录(动态数据 → proteus-router Inspector 的「导航记录」节点:当前路由 + 最近导航历史,
|
|
95
|
+
* 对齐 vue-router 面板的 Router 记录形态;由 install 侧聚合 router 事件提供)
|
|
96
|
+
* 记录含完整导航状态:from/to/耗时/时间/traceId/守卫链
|
|
97
|
+
*/
|
|
98
|
+
getRouterState?: () => {
|
|
99
|
+
currentRoute?: string;
|
|
100
|
+
records: Array<{
|
|
101
|
+
from: string;
|
|
102
|
+
to: string;
|
|
103
|
+
query?: Record<string, string>;
|
|
104
|
+
durationMs: number;
|
|
105
|
+
timestamp: number;
|
|
106
|
+
traceId?: string;
|
|
107
|
+
guards: Array<{
|
|
108
|
+
name: string;
|
|
109
|
+
result: 'next' | 'cancel' | 'redirect' | 'error';
|
|
110
|
+
}>;
|
|
111
|
+
}>;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
export interface ProteusInspectors {
|
|
115
|
+
dispose(): void;
|
|
116
|
+
}
|
|
117
|
+
export declare const PROTEUS_DEVTOOLS_PLUGIN_DESCRIPTOR: {
|
|
118
|
+
readonly id: "proteus";
|
|
119
|
+
readonly label: "Proteus";
|
|
120
|
+
/** ★触发 fallback 的占位 logo(根相对路径:扩展/独立/dev server 下 404 或图片解码失败 → img error)
|
|
121
|
+
* 不能传 undefined(三个 inspector 全默认图标),也不能传真实图片 URL(会直接显示图片而非字典图标) */
|
|
122
|
+
readonly logo: "/__proteus-inspector-icons__.svg";
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* 注册自定义 Inspector(vue-devtools-plan §3 可落地项):
|
|
126
|
+
* `proteus-app-config`——App Config 当前生效值 + 编辑回写(对齐规划 §6 双向调试的 Web 形态)
|
|
127
|
+
* `proteus-style-safety`——运行时拦截记录(G-31 guard.records(),需提供 getStyleSafetyRecords)
|
|
128
|
+
* `proteus-router`——路由嵌套树 + 详情(★Vue DevTools 内置 Router 面板只认 vue-router,自研路由需自定义 Inspector)
|
|
129
|
+
* 用法(应用侧):setupDevtoolsPlugin({ id: 'proteus', label: 'Proteus', app }, (api) => {
|
|
130
|
+
* installProteusInspectors(api, { getConfig, setConfig, getStyleSafetyRecords, pages })
|
|
131
|
+
* })
|
|
132
|
+
*/
|
|
133
|
+
export declare function installProteusInspectors(api: VueDevtoolsInspectorApiLike, options?: ProteusInspectorsOptions): ProteusInspectors;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { TraceBus } from '@proteus-vue/devtools-runtime';
|
|
2
|
+
export interface TraceBusWsBridgeOptions {
|
|
3
|
+
/** WS 地址(如 ws://host/proteus-source——由 devtoolsRelayPlugin 提供端点) */
|
|
4
|
+
url: string;
|
|
5
|
+
/** Proteus.appInfo 响应(面板 pages/依赖图数据;缺省空对象) */
|
|
6
|
+
appInfo?: () => unknown;
|
|
7
|
+
/** ★M8 设备面板:Proteus.deviceInfo 响应(环境/能力上报;缺省空对象) */
|
|
8
|
+
deviceInfo?: () => unknown;
|
|
9
|
+
/** ★G-43 B4 所有权面板:Proteus.ownership 响应(视图数据上报;缺省空对象) */
|
|
10
|
+
ownership?: () => unknown;
|
|
11
|
+
/** ★远程时间旅行:面板 Proteus.restoreStores 命令 → 应用侧恢复(install 传 pinia.$patch 闭包) */
|
|
12
|
+
onRestoreStores?: (stores: Array<{
|
|
13
|
+
id: string;
|
|
14
|
+
state: Record<string, unknown>;
|
|
15
|
+
}>) => void;
|
|
16
|
+
}
|
|
17
|
+
export interface TraceBusWsBridge {
|
|
18
|
+
close(): void;
|
|
19
|
+
}
|
|
20
|
+
/** 创建 TraceBus → WS 桥(业务侧 installProteusDevtools remote 选项内部使用;也可独立接入) */
|
|
21
|
+
export declare function createTraceBusWsBridge(bus: TraceBus, options: TraceBusWsBridgeOptions): TraceBusWsBridge;
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@proteus-vue/devtools",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Proteus DevTools 面板(devtools-plan UI 层):十视图(时间轴/火焰图/状态·时间旅行·值编辑/路由/根因/组件/页面/依赖图/设备/所有权)+ 一键接入 + Vue DevTools 插件(Timeline/Inspectors)+ 开放数据源(WS/CDP 协议)——浏览器端 dev 工具,不随业务产物发布",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./panel": "./panel.html",
|
|
16
|
+
"./style": "./style.css",
|
|
17
|
+
"./style.css": "./style.css",
|
|
18
|
+
"./package.json": "./package.json"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"panel.html",
|
|
23
|
+
"style.css",
|
|
24
|
+
"README.md"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc -p tsconfig.build.json --emitDeclarationOnly && esbuild src/index.ts --bundle --format=esm --platform=browser --outfile=dist/index.js --external:@proteus-vue/capabilities --external:@proteus-vue/devtools-runtime --external:@proteus-vue/render-backend --external:@vue/devtools-api && esbuild src/index.ts --bundle --format=iife --global-name=ProteusDevtools --platform=browser --outfile=dist/panel.js"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@proteus-vue/capabilities": "0.1.0",
|
|
31
|
+
"@proteus-vue/devtools-runtime": "0.1.0",
|
|
32
|
+
"@proteus-vue/render-backend": "0.1.0"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@vue/devtools-api": "^8.0.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^20.0.0",
|
|
39
|
+
"@vue/devtools-api": "^8.0.0",
|
|
40
|
+
"pinia": "^4.0.0",
|
|
41
|
+
"vue": "^3.4.0"
|
|
42
|
+
}
|
|
43
|
+
}
|
package/panel.html
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Proteus DevTools</title>
|
|
7
|
+
<!-- Vue DevTools 质感主题(style.css;file:// 双击可直接打开——普通样式表无 CORS 限制) -->
|
|
8
|
+
<link rel="stylesheet" href="./style.css" />
|
|
9
|
+
</head>
|
|
10
|
+
<body class="pd-body">
|
|
11
|
+
<div id="proteus-devtools"></div>
|
|
12
|
+
<!-- ★IIFE bundle:file:// 双击可直接打开(module 脚本在 file:// 下被浏览器 CORS 拦截 → 黑屏) -->
|
|
13
|
+
<script src="./dist/panel.js"></script>
|
|
14
|
+
<script>
|
|
15
|
+
// 数据源:?ws= 覆盖连接地址
|
|
16
|
+
// ① dev-mp HMR/CDP 通道:缺省 ws://127.0.0.1:5174/(小程序开发;PROTEUS_DEVTOOLS_URL 可覆盖)
|
|
17
|
+
// ② ★Web 远程查看(移动端/真机):vite dev 起 devtoolsRelayPlugin 后,
|
|
18
|
+
// 连 ws://<vite-host>/proteus-panel——手机跑应用(installProteusDevtools remote: true 上行),电脑开本页查看
|
|
19
|
+
// ③ /proteus-devtools 页面端点注入时把默认 WS 占位符替换为当前 host 的 ws://host/proteus-panel;
|
|
20
|
+
// file:// 双击未注入时回退 5174(dev-mp 场景)
|
|
21
|
+
var url = new URLSearchParams(location.search).get('ws') || (typeof __PROTEUS_DEFAULT_WS__ === 'string' ? __PROTEUS_DEFAULT_WS__ : 'ws://127.0.0.1:5174/')
|
|
22
|
+
var source = ProteusDevtools.createDevtoolsWsSource(url)
|
|
23
|
+
ProteusDevtools.createDevtoolsPanel(document.getElementById('proteus-devtools'), { source: source })
|
|
24
|
+
</script>
|
|
25
|
+
</body>
|
|
26
|
+
</html>
|