@presto1314w/vite-devtools-browser 0.1.3 → 0.2.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 +238 -65
- package/dist/browser.d.ts +42 -1
- package/dist/browser.js +211 -96
- package/dist/cli.d.ts +13 -1
- package/dist/cli.js +191 -157
- package/dist/client.d.ts +24 -0
- package/dist/client.js +37 -22
- package/dist/correlate.d.ts +20 -0
- package/dist/correlate.js +110 -0
- package/dist/daemon.d.ts +58 -1
- package/dist/daemon.js +183 -128
- package/dist/diagnose.d.ts +19 -0
- package/dist/diagnose.js +88 -0
- package/dist/event-queue.d.ts +22 -0
- package/dist/event-queue.js +32 -0
- package/dist/network.d.ts +2 -0
- package/dist/network.js +19 -1
- package/dist/react/devtools.d.ts +13 -0
- package/dist/react/devtools.js +130 -128
- package/dist/sourcemap.d.ts +7 -1
- package/dist/sourcemap.js +10 -7
- package/dist/svelte/devtools.d.ts +9 -0
- package/dist/svelte/devtools.js +110 -167
- package/dist/vue/devtools.d.ts +4 -0
- package/dist/vue/devtools.js +218 -236
- package/package.json +17 -3
package/dist/vue/devtools.js
CHANGED
|
@@ -3,6 +3,214 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Uses @vue/devtools-kit to access Vue component tree and state
|
|
5
5
|
*/
|
|
6
|
+
export function formatComponentTree(apps) {
|
|
7
|
+
if (apps.length === 0)
|
|
8
|
+
return "No Vue apps found";
|
|
9
|
+
const output = [];
|
|
10
|
+
output.push("# Vue Component Tree");
|
|
11
|
+
output.push(`# ${apps.length} app(s) detected\n`);
|
|
12
|
+
apps.forEach((app, appIndex) => {
|
|
13
|
+
const appName = app._component?.name || app.config?.globalProperties?.$options?.name || `App ${appIndex}`;
|
|
14
|
+
output.push(`## App: ${appName}`);
|
|
15
|
+
const rootInstance = app._instance || app._container?._vnode?.component;
|
|
16
|
+
if (!rootInstance) {
|
|
17
|
+
output.push(" (no root instance)");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const seen = new WeakSet();
|
|
21
|
+
const visit = (instance, depth = 0) => {
|
|
22
|
+
if (!instance || typeof instance !== "object")
|
|
23
|
+
return;
|
|
24
|
+
if (seen.has(instance))
|
|
25
|
+
return;
|
|
26
|
+
seen.add(instance);
|
|
27
|
+
const indent = " ".repeat(depth);
|
|
28
|
+
const name = instance.type?.name || instance.type?.__name || "Anonymous";
|
|
29
|
+
const uid = instance.uid ?? "?";
|
|
30
|
+
output.push(`${indent}[${uid}] ${name}`);
|
|
31
|
+
const subTree = instance.subTree;
|
|
32
|
+
if (subTree?.component)
|
|
33
|
+
visit(subTree.component, depth + 1);
|
|
34
|
+
if (Array.isArray(subTree?.children)) {
|
|
35
|
+
subTree.children.forEach((child) => {
|
|
36
|
+
if (child?.component)
|
|
37
|
+
visit(child.component, depth + 1);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (Array.isArray(instance.children)) {
|
|
41
|
+
instance.children.forEach((child) => visit(child, depth + 1));
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
visit(rootInstance, 1);
|
|
45
|
+
output.push("");
|
|
46
|
+
});
|
|
47
|
+
return output.join("\n");
|
|
48
|
+
}
|
|
49
|
+
export function formatComponentDetails(targetInstance, componentId) {
|
|
50
|
+
if (!targetInstance)
|
|
51
|
+
return `Component ${componentId} not found`;
|
|
52
|
+
const output = [];
|
|
53
|
+
const name = targetInstance.type?.name || targetInstance.type?.__name || "Anonymous";
|
|
54
|
+
output.push(`# Component: ${name}`);
|
|
55
|
+
output.push(`# UID: ${targetInstance.uid}\n`);
|
|
56
|
+
if (targetInstance.props && Object.keys(targetInstance.props).length > 0) {
|
|
57
|
+
output.push("## Props");
|
|
58
|
+
for (const [key, value] of Object.entries(targetInstance.props)) {
|
|
59
|
+
output.push(` ${key}: ${JSON.stringify(value)}`);
|
|
60
|
+
}
|
|
61
|
+
output.push("");
|
|
62
|
+
}
|
|
63
|
+
if (targetInstance.data && Object.keys(targetInstance.data).length > 0) {
|
|
64
|
+
output.push("## Data");
|
|
65
|
+
for (const [key, value] of Object.entries(targetInstance.data)) {
|
|
66
|
+
output.push(` ${key}: ${JSON.stringify(value)}`);
|
|
67
|
+
}
|
|
68
|
+
output.push("");
|
|
69
|
+
}
|
|
70
|
+
const setupState = targetInstance.setupState || targetInstance.devtoolsRawSetupState;
|
|
71
|
+
if (setupState && Object.keys(setupState).length > 0) {
|
|
72
|
+
output.push("## Setup State");
|
|
73
|
+
for (const [key, value] of Object.entries(setupState)) {
|
|
74
|
+
output.push(` ${key}: ${typeof value === "function" ? "[Function]" : JSON.stringify(value)}`);
|
|
75
|
+
}
|
|
76
|
+
output.push("");
|
|
77
|
+
}
|
|
78
|
+
const computed = targetInstance.type?.computed;
|
|
79
|
+
if (computed && Object.keys(computed).length > 0) {
|
|
80
|
+
output.push("## Computed");
|
|
81
|
+
for (const key of Object.keys(computed)) {
|
|
82
|
+
try {
|
|
83
|
+
const value = targetInstance.proxy?.[key];
|
|
84
|
+
output.push(` ${key}: ${JSON.stringify(value)}`);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
output.push(` ${key}: [Error]`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
output.push("");
|
|
91
|
+
}
|
|
92
|
+
const file = targetInstance.type?.__file;
|
|
93
|
+
if (file) {
|
|
94
|
+
output.push("## Source");
|
|
95
|
+
output.push(` ${file}`);
|
|
96
|
+
}
|
|
97
|
+
return output.join("\n");
|
|
98
|
+
}
|
|
99
|
+
export function formatPiniaStores(pinia, storeName, piniaFromWindow = true) {
|
|
100
|
+
if (!pinia && piniaFromWindow)
|
|
101
|
+
return "Pinia not found";
|
|
102
|
+
const safeJson = (value) => {
|
|
103
|
+
if (typeof value === "function")
|
|
104
|
+
return "[Function]";
|
|
105
|
+
if (typeof value === "bigint")
|
|
106
|
+
return value.toString();
|
|
107
|
+
const seen = new WeakSet();
|
|
108
|
+
try {
|
|
109
|
+
return JSON.stringify(value, (_, v) => {
|
|
110
|
+
if (typeof v === "function")
|
|
111
|
+
return "[Function]";
|
|
112
|
+
if (typeof v === "bigint")
|
|
113
|
+
return v.toString();
|
|
114
|
+
if (v && typeof v === "object") {
|
|
115
|
+
if (seen.has(v))
|
|
116
|
+
return "[Circular]";
|
|
117
|
+
seen.add(v);
|
|
118
|
+
}
|
|
119
|
+
return v;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return String(value);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const storesById = {};
|
|
127
|
+
const registry = pinia?._s;
|
|
128
|
+
if (registry instanceof Map) {
|
|
129
|
+
registry.forEach((store, id) => {
|
|
130
|
+
storesById[String(id)] = store;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
else if (registry && typeof registry === "object") {
|
|
134
|
+
for (const [id, store] of Object.entries(registry)) {
|
|
135
|
+
storesById[id] = store;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const stateById = pinia?.state?.value && typeof pinia.state.value === "object" ? pinia.state.value : {};
|
|
139
|
+
const storeKeys = Array.from(new Set([...Object.keys(storesById), ...Object.keys(stateById)]));
|
|
140
|
+
if (storeKeys.length === 0)
|
|
141
|
+
return "No Pinia stores found";
|
|
142
|
+
const output = [];
|
|
143
|
+
if (!storeName) {
|
|
144
|
+
output.push("# Pinia Stores\n");
|
|
145
|
+
storeKeys.forEach((key) => output.push(`- ${key}`));
|
|
146
|
+
output.push("\nUse 'vite-browser vue pinia <store-name>' to inspect a specific store");
|
|
147
|
+
return output.join("\n");
|
|
148
|
+
}
|
|
149
|
+
const store = storesById[storeName] ?? null;
|
|
150
|
+
const stateOnly = stateById[storeName];
|
|
151
|
+
if (!store && !stateOnly)
|
|
152
|
+
return `Store '${storeName}' not found`;
|
|
153
|
+
output.push(`# Pinia Store: ${storeName}\n`);
|
|
154
|
+
const state = store?.$state || store?.state || stateOnly || store;
|
|
155
|
+
if (state && typeof state === "object") {
|
|
156
|
+
output.push("## State");
|
|
157
|
+
for (const [key, value] of Object.entries(state)) {
|
|
158
|
+
if (key.startsWith("$"))
|
|
159
|
+
continue;
|
|
160
|
+
output.push(` ${key}: ${safeJson(value)}`);
|
|
161
|
+
}
|
|
162
|
+
output.push("");
|
|
163
|
+
}
|
|
164
|
+
const getterNames = [];
|
|
165
|
+
const rawGetters = store?._getters;
|
|
166
|
+
if (Array.isArray(rawGetters))
|
|
167
|
+
getterNames.push(...rawGetters.map((g) => String(g)));
|
|
168
|
+
else if (rawGetters instanceof Set)
|
|
169
|
+
getterNames.push(...Array.from(rawGetters).map(String));
|
|
170
|
+
else if (rawGetters && typeof rawGetters === "object")
|
|
171
|
+
getterNames.push(...Object.keys(rawGetters));
|
|
172
|
+
if (getterNames.length > 0) {
|
|
173
|
+
output.push("## Getters");
|
|
174
|
+
for (const key of getterNames) {
|
|
175
|
+
try {
|
|
176
|
+
output.push(` ${key}: ${safeJson(store[key])}`);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
output.push(` ${key}: [Error]`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
output.push("");
|
|
183
|
+
}
|
|
184
|
+
return output.join("\n");
|
|
185
|
+
}
|
|
186
|
+
export function formatRouterInfo(actualRouter) {
|
|
187
|
+
if (!actualRouter)
|
|
188
|
+
return "Vue Router not found";
|
|
189
|
+
const output = [];
|
|
190
|
+
output.push("# Vue Router\n");
|
|
191
|
+
const currentRoute = actualRouter.currentRoute?.value || actualRouter.currentRoute;
|
|
192
|
+
if (currentRoute) {
|
|
193
|
+
output.push("## Current Route");
|
|
194
|
+
output.push(` Path: ${currentRoute.path}`);
|
|
195
|
+
output.push(` Name: ${currentRoute.name || "(unnamed)"}`);
|
|
196
|
+
if (currentRoute.params && Object.keys(currentRoute.params).length > 0) {
|
|
197
|
+
output.push(` Params: ${JSON.stringify(currentRoute.params)}`);
|
|
198
|
+
}
|
|
199
|
+
if (currentRoute.query && Object.keys(currentRoute.query).length > 0) {
|
|
200
|
+
output.push(` Query: ${JSON.stringify(currentRoute.query)}`);
|
|
201
|
+
}
|
|
202
|
+
output.push("");
|
|
203
|
+
}
|
|
204
|
+
const routes = actualRouter.getRoutes?.() || actualRouter.options?.routes || [];
|
|
205
|
+
if (routes.length > 0) {
|
|
206
|
+
output.push("## All Routes");
|
|
207
|
+
routes.forEach((route) => {
|
|
208
|
+
const routeName = route.name ? ` (${route.name})` : "";
|
|
209
|
+
output.push(` ${route.path}${routeName}`);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return output.join("\n");
|
|
213
|
+
}
|
|
6
214
|
/**
|
|
7
215
|
* Get Vue component tree from the page
|
|
8
216
|
*/
|
|
@@ -12,54 +220,9 @@ export async function getComponentTree(page) {
|
|
|
12
220
|
const hook = window.__VUE_DEVTOOLS_GLOBAL_HOOK__;
|
|
13
221
|
if (!hook)
|
|
14
222
|
return "Vue DevTools not found";
|
|
15
|
-
|
|
16
|
-
if (apps.length === 0)
|
|
17
|
-
return "No Vue apps found";
|
|
18
|
-
const output = [];
|
|
19
|
-
output.push("# Vue Component Tree");
|
|
20
|
-
output.push(`# ${apps.length} app(s) detected\n`);
|
|
21
|
-
apps.forEach((app, appIndex) => {
|
|
22
|
-
const appName = app._component?.name || app.config?.globalProperties?.$options?.name || `App ${appIndex}`;
|
|
23
|
-
output.push(`## App: ${appName}`);
|
|
24
|
-
// Get root instance
|
|
25
|
-
const rootInstance = app._instance || app._container?._vnode?.component;
|
|
26
|
-
if (!rootInstance) {
|
|
27
|
-
output.push(" (no root instance)");
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
// Traverse component tree
|
|
31
|
-
const traverse = (instance, depth = 0) => {
|
|
32
|
-
if (!instance)
|
|
33
|
-
return;
|
|
34
|
-
const indent = " ".repeat(depth);
|
|
35
|
-
const name = instance.type?.name || instance.type?.__name || "Anonymous";
|
|
36
|
-
const uid = instance.uid ?? "?";
|
|
37
|
-
output.push(`${indent}[${uid}] ${name}`);
|
|
38
|
-
// Traverse children
|
|
39
|
-
const subTree = instance.subTree;
|
|
40
|
-
if (subTree?.component) {
|
|
41
|
-
traverse(subTree.component, depth + 1);
|
|
42
|
-
}
|
|
43
|
-
if (subTree?.children) {
|
|
44
|
-
subTree.children.forEach((child) => {
|
|
45
|
-
if (child?.component) {
|
|
46
|
-
traverse(child.component, depth + 1);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
// Traverse direct children
|
|
51
|
-
if (instance.children) {
|
|
52
|
-
instance.children.forEach((child) => {
|
|
53
|
-
traverse(child, depth + 1);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
traverse(rootInstance, 1);
|
|
58
|
-
output.push("");
|
|
59
|
-
});
|
|
60
|
-
return output.join("\n");
|
|
223
|
+
return hook.apps || [];
|
|
61
224
|
});
|
|
62
|
-
return result;
|
|
225
|
+
return formatComponentTree(result);
|
|
63
226
|
}
|
|
64
227
|
/**
|
|
65
228
|
* Get component details by ID
|
|
@@ -110,218 +273,37 @@ export async function getComponentDetails(page, id) {
|
|
|
110
273
|
if (targetInstance)
|
|
111
274
|
break;
|
|
112
275
|
}
|
|
113
|
-
|
|
114
|
-
return `Component ${componentId} not found`;
|
|
115
|
-
const output = [];
|
|
116
|
-
const name = targetInstance.type?.name || targetInstance.type?.__name || "Anonymous";
|
|
117
|
-
output.push(`# Component: ${name}`);
|
|
118
|
-
output.push(`# UID: ${targetInstance.uid}\n`);
|
|
119
|
-
// Props
|
|
120
|
-
if (targetInstance.props && Object.keys(targetInstance.props).length > 0) {
|
|
121
|
-
output.push("## Props");
|
|
122
|
-
for (const [key, value] of Object.entries(targetInstance.props)) {
|
|
123
|
-
output.push(` ${key}: ${JSON.stringify(value)}`);
|
|
124
|
-
}
|
|
125
|
-
output.push("");
|
|
126
|
-
}
|
|
127
|
-
// Data
|
|
128
|
-
if (targetInstance.data && Object.keys(targetInstance.data).length > 0) {
|
|
129
|
-
output.push("## Data");
|
|
130
|
-
for (const [key, value] of Object.entries(targetInstance.data)) {
|
|
131
|
-
output.push(` ${key}: ${JSON.stringify(value)}`);
|
|
132
|
-
}
|
|
133
|
-
output.push("");
|
|
134
|
-
}
|
|
135
|
-
// Setup state (Composition API)
|
|
136
|
-
const setupState = targetInstance.setupState || targetInstance.devtoolsRawSetupState;
|
|
137
|
-
if (setupState && Object.keys(setupState).length > 0) {
|
|
138
|
-
output.push("## Setup State");
|
|
139
|
-
for (const [key, value] of Object.entries(setupState)) {
|
|
140
|
-
if (typeof value === 'function') {
|
|
141
|
-
output.push(` ${key}: [Function]`);
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
output.push(` ${key}: ${JSON.stringify(value)}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
output.push("");
|
|
148
|
-
}
|
|
149
|
-
// Computed
|
|
150
|
-
const computed = targetInstance.type?.computed;
|
|
151
|
-
if (computed && Object.keys(computed).length > 0) {
|
|
152
|
-
output.push("## Computed");
|
|
153
|
-
for (const key of Object.keys(computed)) {
|
|
154
|
-
try {
|
|
155
|
-
const value = targetInstance.proxy?.[key];
|
|
156
|
-
output.push(` ${key}: ${JSON.stringify(value)}`);
|
|
157
|
-
}
|
|
158
|
-
catch {
|
|
159
|
-
output.push(` ${key}: [Error]`);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
output.push("");
|
|
163
|
-
}
|
|
164
|
-
// File location
|
|
165
|
-
const file = targetInstance.type?.__file;
|
|
166
|
-
if (file) {
|
|
167
|
-
output.push(`## Source`);
|
|
168
|
-
output.push(` ${file}`);
|
|
169
|
-
}
|
|
170
|
-
return output.join("\n");
|
|
276
|
+
return targetInstance;
|
|
171
277
|
}, id);
|
|
172
|
-
|
|
278
|
+
if (typeof result === "string")
|
|
279
|
+
return result;
|
|
280
|
+
return formatComponentDetails(result, id);
|
|
173
281
|
}
|
|
174
282
|
/**
|
|
175
283
|
* Get Pinia stores
|
|
176
284
|
*/
|
|
177
285
|
export async function getPiniaStores(page, storeName) {
|
|
178
286
|
const result = await page.evaluate((name) => {
|
|
179
|
-
const safeJson = (value) => {
|
|
180
|
-
if (typeof value === "function")
|
|
181
|
-
return "[Function]";
|
|
182
|
-
if (typeof value === "bigint")
|
|
183
|
-
return value.toString();
|
|
184
|
-
const seen = new WeakSet();
|
|
185
|
-
try {
|
|
186
|
-
return JSON.stringify(value, (_, v) => {
|
|
187
|
-
if (typeof v === "function")
|
|
188
|
-
return "[Function]";
|
|
189
|
-
if (typeof v === "bigint")
|
|
190
|
-
return v.toString();
|
|
191
|
-
if (v && typeof v === "object") {
|
|
192
|
-
if (seen.has(v))
|
|
193
|
-
return "[Circular]";
|
|
194
|
-
seen.add(v);
|
|
195
|
-
}
|
|
196
|
-
return v;
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
catch {
|
|
200
|
-
return String(value);
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
287
|
const hook = window.__VUE_DEVTOOLS_GLOBAL_HOOK__;
|
|
204
288
|
const piniaFromApp = hook?.apps?.[0]?.config?.globalProperties?.$pinia;
|
|
205
|
-
// Try to find Pinia instance
|
|
206
289
|
const pinia = window.__PINIA__ || window.pinia || piniaFromApp;
|
|
207
|
-
|
|
208
|
-
return "Pinia not found";
|
|
209
|
-
// Pinia v3 uses Map for _s, older integrations can expose plain objects.
|
|
210
|
-
const storesById = {};
|
|
211
|
-
const registry = pinia._s;
|
|
212
|
-
if (registry instanceof Map) {
|
|
213
|
-
registry.forEach((store, id) => {
|
|
214
|
-
storesById[String(id)] = store;
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
else if (registry && typeof registry === "object") {
|
|
218
|
-
for (const [id, store] of Object.entries(registry)) {
|
|
219
|
-
storesById[id] = store;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
const stateById = pinia.state?.value && typeof pinia.state.value === "object" ? pinia.state.value : {};
|
|
223
|
-
const storeKeys = Array.from(new Set([...Object.keys(storesById), ...Object.keys(stateById)]));
|
|
224
|
-
if (storeKeys.length === 0)
|
|
225
|
-
return "No Pinia stores found";
|
|
226
|
-
const output = [];
|
|
227
|
-
if (!name) {
|
|
228
|
-
// List all stores
|
|
229
|
-
output.push("# Pinia Stores\n");
|
|
230
|
-
storeKeys.forEach((key) => {
|
|
231
|
-
output.push(`- ${key}`);
|
|
232
|
-
});
|
|
233
|
-
output.push("\nUse 'vite-browser vue pinia <store-name>' to inspect a specific store");
|
|
234
|
-
return output.join("\n");
|
|
235
|
-
}
|
|
236
|
-
// Get specific store
|
|
237
|
-
const store = storesById[name] ?? null;
|
|
238
|
-
const stateOnly = stateById[name];
|
|
239
|
-
if (!store && !stateOnly)
|
|
240
|
-
return `Store '${name}' not found`;
|
|
241
|
-
output.push(`# Pinia Store: ${name}\n`);
|
|
242
|
-
// State
|
|
243
|
-
const state = store?.$state || store?.state || stateOnly || store;
|
|
244
|
-
if (state && typeof state === 'object') {
|
|
245
|
-
output.push("## State");
|
|
246
|
-
for (const [key, value] of Object.entries(state)) {
|
|
247
|
-
if (key.startsWith('$'))
|
|
248
|
-
continue; // Skip Pinia internals
|
|
249
|
-
output.push(` ${key}: ${safeJson(value)}`);
|
|
250
|
-
}
|
|
251
|
-
output.push("");
|
|
252
|
-
}
|
|
253
|
-
// Getters
|
|
254
|
-
const getterNames = [];
|
|
255
|
-
const rawGetters = store?._getters;
|
|
256
|
-
if (Array.isArray(rawGetters)) {
|
|
257
|
-
getterNames.push(...rawGetters.map((g) => String(g)));
|
|
258
|
-
}
|
|
259
|
-
else if (rawGetters instanceof Set) {
|
|
260
|
-
getterNames.push(...Array.from(rawGetters).map((g) => String(g)));
|
|
261
|
-
}
|
|
262
|
-
else if (rawGetters && typeof rawGetters === "object") {
|
|
263
|
-
getterNames.push(...Object.keys(rawGetters));
|
|
264
|
-
}
|
|
265
|
-
if (getterNames.length > 0) {
|
|
266
|
-
output.push("## Getters");
|
|
267
|
-
for (const key of getterNames) {
|
|
268
|
-
try {
|
|
269
|
-
const value = store[key];
|
|
270
|
-
output.push(` ${key}: ${safeJson(value)}`);
|
|
271
|
-
}
|
|
272
|
-
catch {
|
|
273
|
-
output.push(` ${key}: [Error]`);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
output.push("");
|
|
277
|
-
}
|
|
278
|
-
return output.join("\n");
|
|
290
|
+
return pinia || null;
|
|
279
291
|
}, storeName);
|
|
280
|
-
return result;
|
|
292
|
+
return formatPiniaStores(result, storeName);
|
|
281
293
|
}
|
|
282
294
|
/**
|
|
283
295
|
* Get Vue Router information
|
|
284
296
|
*/
|
|
285
297
|
export async function getRouterInfo(page) {
|
|
286
298
|
const result = await page.evaluate(() => {
|
|
287
|
-
// Try to find Vue Router instance
|
|
288
299
|
const router = window.$router || window.__VUE_ROUTER__;
|
|
289
|
-
// Also try to get from Vue app
|
|
290
300
|
const hook = window.__VUE_DEVTOOLS_GLOBAL_HOOK__;
|
|
291
301
|
let routerFromApp = null;
|
|
292
302
|
if (hook?.apps?.[0]) {
|
|
293
303
|
const app = hook.apps[0];
|
|
294
304
|
routerFromApp = app.config?.globalProperties?.$router;
|
|
295
305
|
}
|
|
296
|
-
|
|
297
|
-
if (!actualRouter)
|
|
298
|
-
return "Vue Router not found";
|
|
299
|
-
const output = [];
|
|
300
|
-
output.push("# Vue Router\n");
|
|
301
|
-
// Current route
|
|
302
|
-
const currentRoute = actualRouter.currentRoute?.value || actualRouter.currentRoute;
|
|
303
|
-
if (currentRoute) {
|
|
304
|
-
output.push("## Current Route");
|
|
305
|
-
output.push(` Path: ${currentRoute.path}`);
|
|
306
|
-
output.push(` Name: ${currentRoute.name || "(unnamed)"}`);
|
|
307
|
-
if (currentRoute.params && Object.keys(currentRoute.params).length > 0) {
|
|
308
|
-
output.push(` Params: ${JSON.stringify(currentRoute.params)}`);
|
|
309
|
-
}
|
|
310
|
-
if (currentRoute.query && Object.keys(currentRoute.query).length > 0) {
|
|
311
|
-
output.push(` Query: ${JSON.stringify(currentRoute.query)}`);
|
|
312
|
-
}
|
|
313
|
-
output.push("");
|
|
314
|
-
}
|
|
315
|
-
// All routes
|
|
316
|
-
const routes = actualRouter.getRoutes?.() || actualRouter.options?.routes || [];
|
|
317
|
-
if (routes.length > 0) {
|
|
318
|
-
output.push("## All Routes");
|
|
319
|
-
routes.forEach((route) => {
|
|
320
|
-
const name = route.name ? ` (${route.name})` : "";
|
|
321
|
-
output.push(` ${route.path}${name}`);
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
return output.join("\n");
|
|
306
|
+
return router || routerFromApp || null;
|
|
325
307
|
});
|
|
326
|
-
return result;
|
|
308
|
+
return formatRouterInfo(result);
|
|
327
309
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@presto1314w/vite-devtools-browser",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "CLI for
|
|
5
|
-
"license": "MIT",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Runtime diagnostics CLI for Vite apps with event-stream correlation, HMR diagnosis, framework inspection, and mapped errors",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"vite",
|
|
8
|
+
"devtools",
|
|
9
|
+
"debugging",
|
|
10
|
+
"runtime-diagnostics",
|
|
11
|
+
"hmr",
|
|
12
|
+
"module-graph",
|
|
13
|
+
"sourcemap",
|
|
14
|
+
"vue",
|
|
15
|
+
"react",
|
|
16
|
+
"svelte",
|
|
17
|
+
"cli",
|
|
18
|
+
"ai-agents"
|
|
19
|
+
],
|
|
6
20
|
"repository": {
|
|
7
21
|
"type": "git",
|
|
8
22
|
"url": "git+https://github.com/MapleCity1314/vite-browser.git"
|