nuxt-devtools-observatory 0.1.32 → 0.1.33
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 +5 -0
- package/client/.env.example +1 -0
- package/client/dist/assets/index-BqKYgjVB.js +20 -0
- package/client/dist/assets/index-bs1JBJ2u.css +1 -0
- package/client/dist/index.html +2 -2
- package/client/src/App.vue +4 -0
- package/client/src/components/Flamegraph.vue +4 -4
- package/client/src/components/SpanInspector.vue +1 -1
- package/client/src/composables/composable-search.ts +3 -0
- package/client/src/composables/trace-render-aggregation.ts +11 -2
- package/client/src/composables/useVirtualizationConfig.ts +40 -0
- package/client/src/composables/useVirtualizationFlags.ts +129 -0
- package/client/src/views/ComposableTracker.vue +212 -71
- package/client/src/views/FetchDashboard.vue +181 -16
- package/client/src/views/ProvideInjectGraph.vue +41 -18
- package/client/src/views/RenderHeatmap.vue +329 -75
- package/client/src/views/TraceViewer.vue +190 -20
- package/client/src/views/TransitionTimeline.vue +112 -19
- package/dist/module.d.mts +5 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +11 -22
- package/dist/runtime/composables/render-registry.js +6 -4
- package/dist/runtime/instrumentation/asyncData.d.ts +1 -1
- package/dist/runtime/instrumentation/fetch.d.ts +7 -1
- package/dist/runtime/instrumentation/fetch.js +22 -1
- package/dist/runtime/plugin.js +4 -1
- package/dist/runtime/test-bridge.d.ts +18 -0
- package/dist/runtime/test-bridge.js +86 -0
- package/package.json +14 -3
- package/client/dist/assets/index-5Wl1XYRH.js +0 -17
- package/client/dist/assets/index-DT_QUiIh.css +0 -1
package/dist/module.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineNuxtModule, createResolver, addVitePlugin, addPlugin, addServerPlugin } from '@nuxt/kit';
|
|
1
|
+
import { defineNuxtModule, createResolver, addVitePlugin, addImports, addPlugin, addServerPlugin } from '@nuxt/kit';
|
|
2
2
|
import { onDevToolsInitialized, extendServerRpc } from '@nuxt/devtools-kit';
|
|
3
3
|
import sirv from 'sirv';
|
|
4
4
|
import { parse } from '@babel/parser';
|
|
@@ -209,10 +209,6 @@ function fetchInstrumentPlugin() {
|
|
|
209
209
|
plugins: ["typescript"]
|
|
210
210
|
});
|
|
211
211
|
let modified = false;
|
|
212
|
-
let needsFetchCallHelper = false;
|
|
213
|
-
let needsTracedAsyncDataHelper = false;
|
|
214
|
-
const hasFetchCallImport = scriptCode.includes("__devFetchCall");
|
|
215
|
-
const hasTracedAsyncDataImport = scriptCode.includes("useTracedAsyncData");
|
|
216
212
|
traverse$1(ast, {
|
|
217
213
|
CallExpression(path) {
|
|
218
214
|
if (path.node.__observatoryTransformed) {
|
|
@@ -284,7 +280,6 @@ function fetchInstrumentPlugin() {
|
|
|
284
280
|
]);
|
|
285
281
|
newCall.__observatoryTransformed = true;
|
|
286
282
|
path.replaceWith(newCall);
|
|
287
|
-
needsTracedAsyncDataHelper = true;
|
|
288
283
|
modified = true;
|
|
289
284
|
} else {
|
|
290
285
|
const newCall = t.callExpression(t.identifier("__devFetchCall"), [
|
|
@@ -294,7 +289,6 @@ function fetchInstrumentPlugin() {
|
|
|
294
289
|
meta
|
|
295
290
|
]);
|
|
296
291
|
newCall.__observatoryTransformed = true;
|
|
297
|
-
needsFetchCallHelper = true;
|
|
298
292
|
path.replaceWith(newCall);
|
|
299
293
|
modified = true;
|
|
300
294
|
}
|
|
@@ -303,18 +297,12 @@ function fetchInstrumentPlugin() {
|
|
|
303
297
|
if (!modified) {
|
|
304
298
|
return null;
|
|
305
299
|
}
|
|
306
|
-
const fetchImportNames = [needsFetchCallHelper && !hasFetchCallImport ? "__devFetchCall" : ""].filter(Boolean);
|
|
307
|
-
const fetchImportStatement = fetchImportNames.length ? `import { ${fetchImportNames.join(", ")} } from 'nuxt-devtools-observatory/runtime/fetch-registry';
|
|
308
|
-
` : "";
|
|
309
|
-
const asyncDataImportStatement = needsTracedAsyncDataHelper && !hasTracedAsyncDataImport ? `import { useTracedAsyncData } from 'nuxt-devtools-observatory/runtime/async-data-instrumentation';
|
|
310
|
-
` : "";
|
|
311
|
-
const importStatement = fetchImportStatement + asyncDataImportStatement;
|
|
312
300
|
const output = generate$1(ast, { retainLines: true }, scriptCode);
|
|
313
301
|
let finalCode;
|
|
314
302
|
if (isVue) {
|
|
315
|
-
finalCode = code.slice(0, scriptStart) +
|
|
303
|
+
finalCode = code.slice(0, scriptStart) + output.code + code.slice(scriptStart + scriptCode.length);
|
|
316
304
|
} else {
|
|
317
|
-
finalCode =
|
|
305
|
+
finalCode = output.code;
|
|
318
306
|
}
|
|
319
307
|
return {
|
|
320
308
|
code: finalCode,
|
|
@@ -537,6 +525,7 @@ const defaults = {
|
|
|
537
525
|
heatmapThresholdTime: process.env.OBSERVATORY_HEATMAP_THRESHOLD_TIME ? Number(process.env.OBSERVATORY_HEATMAP_THRESHOLD_TIME) : 1600,
|
|
538
526
|
maxFetchEntries: process.env.OBSERVATORY_MAX_FETCH_ENTRIES ? Number(process.env.OBSERVATORY_MAX_FETCH_ENTRIES) : 200,
|
|
539
527
|
maxPayloadBytes: process.env.OBSERVATORY_MAX_PAYLOAD_BYTES ? Number(process.env.OBSERVATORY_MAX_PAYLOAD_BYTES) : 1e4,
|
|
528
|
+
fetchPageSize: process.env.OBSERVATORY_FETCH_PAGE_SIZE ? Number(process.env.OBSERVATORY_FETCH_PAGE_SIZE) : 20,
|
|
540
529
|
maxTransitions: process.env.OBSERVATORY_MAX_TRANSITIONS ? Number(process.env.OBSERVATORY_MAX_TRANSITIONS) : 500,
|
|
541
530
|
maxComposableHistory: process.env.OBSERVATORY_MAX_COMPOSABLE_HISTORY ? Number(process.env.OBSERVATORY_MAX_COMPOSABLE_HISTORY) : 50,
|
|
542
531
|
maxComposableEntries: process.env.OBSERVATORY_MAX_COMPOSABLE_ENTRIES ? Number(process.env.OBSERVATORY_MAX_COMPOSABLE_ENTRIES) : 300,
|
|
@@ -576,6 +565,7 @@ const module$1 = defineNuxtModule({
|
|
|
576
565
|
heatmapThresholdTime: options.heatmapThresholdTime ?? (process.env.OBSERVATORY_HEATMAP_THRESHOLD_TIME ? Number(process.env.OBSERVATORY_HEATMAP_THRESHOLD_TIME) : 1600),
|
|
577
566
|
maxFetchEntries: options.maxFetchEntries ?? (process.env.OBSERVATORY_MAX_FETCH_ENTRIES ? Number(process.env.OBSERVATORY_MAX_FETCH_ENTRIES) : 200),
|
|
578
567
|
maxPayloadBytes: options.maxPayloadBytes ?? (process.env.OBSERVATORY_MAX_PAYLOAD_BYTES ? Number(process.env.OBSERVATORY_MAX_PAYLOAD_BYTES) : 1e4),
|
|
568
|
+
fetchPageSize: options.fetchPageSize ?? (process.env.OBSERVATORY_FETCH_PAGE_SIZE ? Number(process.env.OBSERVATORY_FETCH_PAGE_SIZE) : 20),
|
|
579
569
|
maxTransitions: options.maxTransitions ?? (process.env.OBSERVATORY_MAX_TRANSITIONS ? Number(process.env.OBSERVATORY_MAX_TRANSITIONS) : 500),
|
|
580
570
|
maxComposableHistory: options.maxComposableHistory ?? (process.env.OBSERVATORY_MAX_COMPOSABLE_HISTORY ? Number(process.env.OBSERVATORY_MAX_COMPOSABLE_HISTORY) : 50),
|
|
581
571
|
maxComposableEntries: options.maxComposableEntries ?? (process.env.OBSERVATORY_MAX_COMPOSABLE_ENTRIES ? Number(process.env.OBSERVATORY_MAX_COMPOSABLE_ENTRIES) : 300),
|
|
@@ -599,6 +589,10 @@ const module$1 = defineNuxtModule({
|
|
|
599
589
|
const vitePluginScope = resolved.instrumentServer ? { server: true, client: true } : { server: false, client: true };
|
|
600
590
|
if (resolved.fetchDashboard) {
|
|
601
591
|
addVitePlugin(fetchInstrumentPlugin(), vitePluginScope);
|
|
592
|
+
addImports([
|
|
593
|
+
{ name: "__devFetchCall", from: resolver.resolve("./runtime/composables/fetch-registry") },
|
|
594
|
+
{ name: "useTracedAsyncData", from: resolver.resolve("./runtime/instrumentation/asyncData") }
|
|
595
|
+
]);
|
|
602
596
|
}
|
|
603
597
|
if (resolved.provideInjectGraph) {
|
|
604
598
|
addVitePlugin(provideInjectPlugin(), vitePluginScope);
|
|
@@ -634,6 +628,7 @@ const module$1 = defineNuxtModule({
|
|
|
634
628
|
provideInjectGraph: !!resolved.provideInjectGraph,
|
|
635
629
|
composableTracker: !!resolved.composableTracker,
|
|
636
630
|
composableNavigationMode: resolved.composableNavigationMode,
|
|
631
|
+
fetchPageSize: resolved.fetchPageSize,
|
|
637
632
|
renderHeatmap: !!resolved.renderHeatmap,
|
|
638
633
|
transitionTracker: !!resolved.transitionTracker,
|
|
639
634
|
traceViewer: !!resolved.traceViewer
|
|
@@ -691,13 +686,6 @@ const module$1 = defineNuxtModule({
|
|
|
691
686
|
);
|
|
692
687
|
rpc.broadcast.onSnapshot.asEvent(latestSnapshot);
|
|
693
688
|
}, nuxt);
|
|
694
|
-
nuxt.hook("render:response", (response, { url }) => {
|
|
695
|
-
if (url.startsWith("/trackers") || url === "/" || url.startsWith("/index.html")) {
|
|
696
|
-
const configScript = `<script>window.__observatoryConfig = ${JSON.stringify(nuxt.options.runtimeConfig.public.observatory)};<\/script>`;
|
|
697
|
-
response.body = response.body.replace("<head>", `<head>
|
|
698
|
-
${configScript}`);
|
|
699
|
-
}
|
|
700
|
-
});
|
|
701
689
|
nuxt.hook("devtools:customTabs", (tabs) => {
|
|
702
690
|
if (resolved.fetchDashboard || resolved.provideInjectGraph || resolved.composableTracker || resolved.renderHeatmap || resolved.transitionTracker) {
|
|
703
691
|
tabs.push({
|
|
@@ -718,6 +706,7 @@ ${configScript}`);
|
|
|
718
706
|
traceViewer: resolved.traceViewer,
|
|
719
707
|
maxFetchEntries: resolved.maxFetchEntries,
|
|
720
708
|
maxPayloadBytes: resolved.maxPayloadBytes,
|
|
709
|
+
fetchPageSize: resolved.fetchPageSize,
|
|
721
710
|
maxTransitions: resolved.maxTransitions,
|
|
722
711
|
maxComposableHistory: resolved.maxComposableHistory,
|
|
723
712
|
maxComposableEntries: resolved.maxComposableEntries,
|
|
@@ -74,7 +74,7 @@ export function setupRenderRegistry(nuxtApp, options = {}) {
|
|
|
74
74
|
markDirty();
|
|
75
75
|
}
|
|
76
76
|
function aggregateFromComponentSpans() {
|
|
77
|
-
const componentSpans = traceStore.getAllTraces().flatMap((trace) => trace.spans).filter((span) => span.type === "component");
|
|
77
|
+
const componentSpans = traceStore.getAllTraces().flatMap((trace) => trace.spans).filter((span) => span.type === "render" || span.type === "component");
|
|
78
78
|
const allSpansByUid = /* @__PURE__ */ new Map();
|
|
79
79
|
const postResetSpansByUid = /* @__PURE__ */ new Map();
|
|
80
80
|
for (const span of componentSpans) {
|
|
@@ -96,7 +96,8 @@ export function setupRenderRegistry(nuxtApp, options = {}) {
|
|
|
96
96
|
const allSpans = (allSpansByUid.get(uid) ?? []).sort((a, b) => a.startTime - b.startTime);
|
|
97
97
|
const postResetSpans = (postResetSpansByUid.get(uid) ?? []).sort((a, b) => a.startTime - b.startTime);
|
|
98
98
|
const timeline = postResetSpans.slice(-MAX_TIMELINE).map((span) => {
|
|
99
|
-
const
|
|
99
|
+
const isMountLifecycle = span.metadata?.lifecycle === "render:mount" || span.metadata?.lifecycle === "mounted";
|
|
100
|
+
const lifecycle = isMountLifecycle ? "mount" : "update";
|
|
100
101
|
const routeValue = span.metadata?.route;
|
|
101
102
|
const route = typeof routeValue === "string" && routeValue.length > 0 ? routeValue : entry.route;
|
|
102
103
|
return {
|
|
@@ -106,8 +107,9 @@ export function setupRenderRegistry(nuxtApp, options = {}) {
|
|
|
106
107
|
route
|
|
107
108
|
};
|
|
108
109
|
});
|
|
109
|
-
const
|
|
110
|
-
const
|
|
110
|
+
const isMountSpan = (span) => span.metadata?.lifecycle === "render:mount" || span.metadata?.lifecycle === "mounted";
|
|
111
|
+
const mountCount = allSpans.filter(isMountSpan).length;
|
|
112
|
+
const rerenders = postResetSpans.filter((span) => !isMountSpan(span)).length;
|
|
111
113
|
const totalMs = postResetSpans.reduce((sum, span) => sum + (span.durationMs ?? 0), 0);
|
|
112
114
|
const eventsCount = Math.max(postResetSpans.length, 1);
|
|
113
115
|
entry.mountCount = mountCount;
|
|
@@ -4,6 +4,6 @@ interface AsyncDataMeta {
|
|
|
4
4
|
line: number;
|
|
5
5
|
originalFn?: string;
|
|
6
6
|
}
|
|
7
|
-
type AnyFn = (...args:
|
|
7
|
+
type AnyFn = (...args: unknown[]) => unknown;
|
|
8
8
|
export declare function useTracedAsyncData<TFn extends AnyFn>(originalFn: TFn, args: unknown[], handlerIndex: number, key: unknown, meta: AsyncDataMeta): ReturnType<TFn>;
|
|
9
9
|
export {};
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
import type { NuxtApp } from '#app';
|
|
2
|
-
|
|
2
|
+
import type { FetchEntry } from '../composables/fetch-registry.js';
|
|
3
|
+
type FetchRegistry = {
|
|
4
|
+
register: (entry: FetchEntry) => void;
|
|
5
|
+
update: (id: string, patch: Partial<FetchEntry>) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare function setupFetchInstrumentation(nuxtApp: NuxtApp, fetchRegistry?: FetchRegistry): void;
|
|
8
|
+
export {};
|
|
@@ -27,7 +27,7 @@ function resolveErrorStatus(error) {
|
|
|
27
27
|
return target?.response?.status ?? target?.statusCode ?? target?.status;
|
|
28
28
|
}
|
|
29
29
|
const WRAPPED_FETCH_FLAG = "__observatory_wrapped_fetch__";
|
|
30
|
-
export function setupFetchInstrumentation(nuxtApp) {
|
|
30
|
+
export function setupFetchInstrumentation(nuxtApp, fetchRegistry) {
|
|
31
31
|
const original = nuxtApp.$fetch;
|
|
32
32
|
if (!original) {
|
|
33
33
|
return;
|
|
@@ -39,6 +39,7 @@ export function setupFetchInstrumentation(nuxtApp) {
|
|
|
39
39
|
const url = resolveUrl(request);
|
|
40
40
|
const method = resolveMethod(request, options);
|
|
41
41
|
const startedAt = performance.now();
|
|
42
|
+
const entryId = `$fetch::${Date.now()}::${Math.random().toString(36).slice(2, 7)}`;
|
|
42
43
|
const span = startSpan({
|
|
43
44
|
name: "$fetch",
|
|
44
45
|
type: "fetch",
|
|
@@ -49,6 +50,15 @@ export function setupFetchInstrumentation(nuxtApp) {
|
|
|
49
50
|
status: "pending"
|
|
50
51
|
}
|
|
51
52
|
});
|
|
53
|
+
fetchRegistry?.register({
|
|
54
|
+
id: entryId,
|
|
55
|
+
key: url,
|
|
56
|
+
url,
|
|
57
|
+
status: "pending",
|
|
58
|
+
origin: "csr",
|
|
59
|
+
startTime: startedAt,
|
|
60
|
+
cached: false
|
|
61
|
+
});
|
|
52
62
|
return Promise.resolve(original(request, options)).then((result) => {
|
|
53
63
|
const durationMs = Math.max(performance.now() - startedAt, 0);
|
|
54
64
|
span.end({
|
|
@@ -61,6 +71,11 @@ export function setupFetchInstrumentation(nuxtApp) {
|
|
|
61
71
|
durationMs: Math.round(durationMs * 10) / 10
|
|
62
72
|
}
|
|
63
73
|
});
|
|
74
|
+
fetchRegistry?.update(entryId, {
|
|
75
|
+
status: "ok",
|
|
76
|
+
endTime: performance.now(),
|
|
77
|
+
ms: Math.round(durationMs * 10) / 10
|
|
78
|
+
});
|
|
64
79
|
return result;
|
|
65
80
|
}).catch((error) => {
|
|
66
81
|
const durationMs = Math.max(performance.now() - startedAt, 0);
|
|
@@ -76,6 +91,12 @@ export function setupFetchInstrumentation(nuxtApp) {
|
|
|
76
91
|
durationMs: Math.round(durationMs * 10) / 10
|
|
77
92
|
}
|
|
78
93
|
});
|
|
94
|
+
fetchRegistry?.update(entryId, {
|
|
95
|
+
status: "error",
|
|
96
|
+
endTime: performance.now(),
|
|
97
|
+
ms: Math.round(durationMs * 10) / 10,
|
|
98
|
+
error
|
|
99
|
+
});
|
|
79
100
|
throw error;
|
|
80
101
|
});
|
|
81
102
|
});
|
package/dist/runtime/plugin.js
CHANGED
|
@@ -91,8 +91,10 @@ export default defineNuxtPlugin(() => {
|
|
|
91
91
|
if (import.meta.client) {
|
|
92
92
|
if (config.traceViewer) {
|
|
93
93
|
setupComponentInstrumentation(nuxtApp);
|
|
94
|
-
setupFetchInstrumentation(nuxtApp);
|
|
94
|
+
setupFetchInstrumentation(nuxtApp, registries.fetch);
|
|
95
95
|
mergeSsrSpans();
|
|
96
|
+
} else if (config.fetchDashboard) {
|
|
97
|
+
setupFetchInstrumentation(nuxtApp, registries.fetch);
|
|
96
98
|
}
|
|
97
99
|
delete window.__observatory__;
|
|
98
100
|
window.__observatory__ = registries;
|
|
@@ -291,6 +293,7 @@ export default defineNuxtPlugin(() => {
|
|
|
291
293
|
provideInjectGraph: !!registries.provideInject,
|
|
292
294
|
composableTracker: !!registries.composable,
|
|
293
295
|
composableNavigationMode,
|
|
296
|
+
fetchPageSize: typeof config.fetchPageSize === "number" ? config.fetchPageSize : 20,
|
|
294
297
|
renderHeatmap: !!registries.render,
|
|
295
298
|
transitionTracker: !!registries.transition,
|
|
296
299
|
traceViewer: !!config.traceViewer
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ObservatoryTestAPI } from '../../tests/verification/types/observatory.types.js';
|
|
2
|
+
interface VueApp {
|
|
3
|
+
_context?: {
|
|
4
|
+
app?: {
|
|
5
|
+
_component?: unknown;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
declare global {
|
|
10
|
+
interface Window {
|
|
11
|
+
__NUXT__?: {
|
|
12
|
+
vueApp?: VueApp;
|
|
13
|
+
};
|
|
14
|
+
__OBSERVATORY_TEST_BRIDGE?: ObservatoryTestAPI;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export declare function injectTestBridge(): void;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
function walkComponentTree(instance, counts) {
|
|
2
|
+
if (!instance) {
|
|
3
|
+
return;
|
|
4
|
+
}
|
|
5
|
+
const componentName = instance.type?.name ?? instance.type?.__name ?? "Anonymous";
|
|
6
|
+
if (instance.ctx?.__observatoryMountCount) {
|
|
7
|
+
const currentCount = counts.componentMounts[componentName] ?? 0;
|
|
8
|
+
counts.componentMounts[componentName] = currentCount + instance.ctx.__observatoryMountCount;
|
|
9
|
+
}
|
|
10
|
+
if (instance.subTree?.children) {
|
|
11
|
+
instance.subTree.children.forEach((child) => walkComponentTree(child, counts));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function injectTestBridge() {
|
|
15
|
+
if (!import.meta.dev || typeof window === "undefined") {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const bridge = {
|
|
19
|
+
async getTraces() {
|
|
20
|
+
const { traceStore } = await import("./tracing/traceStore.js");
|
|
21
|
+
return Array.from(traceStore.entries());
|
|
22
|
+
},
|
|
23
|
+
async getHeatmapData() {
|
|
24
|
+
const { renderRegistry } = await import("./composables/render-registry.js");
|
|
25
|
+
return renderRegistry.getData();
|
|
26
|
+
},
|
|
27
|
+
async getComposableEntries() {
|
|
28
|
+
const { composableRegistry } = await import("./composables/composable-registry.js");
|
|
29
|
+
return composableRegistry.getEntries();
|
|
30
|
+
},
|
|
31
|
+
async getFetchEntries() {
|
|
32
|
+
const { fetchRegistry } = await import("./composables/fetch-registry.js");
|
|
33
|
+
return fetchRegistry.getEntries();
|
|
34
|
+
},
|
|
35
|
+
async getProvideInjectGraph() {
|
|
36
|
+
const { provideInjectRegistry } = await import("./composables/provide-inject-registry.js");
|
|
37
|
+
return provideInjectRegistry.getGraph();
|
|
38
|
+
},
|
|
39
|
+
async getTransitionEntries() {
|
|
40
|
+
const { transitionRegistry } = await import("./composables/transition-registry.js");
|
|
41
|
+
return transitionRegistry.getEntries();
|
|
42
|
+
},
|
|
43
|
+
async getInternalCounts() {
|
|
44
|
+
const counts = {
|
|
45
|
+
componentMounts: {},
|
|
46
|
+
renderOperations: {},
|
|
47
|
+
fetchOperations: {}
|
|
48
|
+
};
|
|
49
|
+
const vueApp = window.__NUXT__?.vueApp;
|
|
50
|
+
if (!vueApp) {
|
|
51
|
+
return counts;
|
|
52
|
+
}
|
|
53
|
+
walkComponentTree(vueApp._context?.app?._component, counts);
|
|
54
|
+
return counts;
|
|
55
|
+
},
|
|
56
|
+
async clearAllData() {
|
|
57
|
+
const { traceStore } = await import("./tracing/traceStore.js");
|
|
58
|
+
const { renderRegistry } = await import("./composables/render-registry.js");
|
|
59
|
+
const { composableRegistry } = await import("./composables/composable-registry.js");
|
|
60
|
+
const { fetchRegistry } = await import("./composables/fetch-registry.js");
|
|
61
|
+
traceStore.clear();
|
|
62
|
+
renderRegistry.clear();
|
|
63
|
+
composableRegistry.clear();
|
|
64
|
+
fetchRegistry.clear();
|
|
65
|
+
},
|
|
66
|
+
async startRecording() {
|
|
67
|
+
const { traceStore } = await import("./tracing/traceStore.js");
|
|
68
|
+
traceStore.startRecording();
|
|
69
|
+
},
|
|
70
|
+
async stopRecording() {
|
|
71
|
+
const { traceStore } = await import("./tracing/traceStore.js");
|
|
72
|
+
traceStore.stopRecording();
|
|
73
|
+
},
|
|
74
|
+
async exportSnapshot() {
|
|
75
|
+
const snapshot = {
|
|
76
|
+
traces: await this.getTraces(),
|
|
77
|
+
heatmap: await this.getHeatmapData(),
|
|
78
|
+
composables: await this.getComposableEntries(),
|
|
79
|
+
fetches: await this.getFetchEntries(),
|
|
80
|
+
transitions: await this.getTransitionEntries()
|
|
81
|
+
};
|
|
82
|
+
return JSON.stringify(snapshot, null, 2);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
window.__OBSERVATORY_TEST_BRIDGE = bridge;
|
|
86
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-devtools-observatory",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.33",
|
|
4
4
|
"description": "Nuxt DevTools: useFetch Dashboard, provide/inject Graph, Composable Tracker, Render Heatmap",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -49,14 +49,21 @@
|
|
|
49
49
|
"build": "npm run build:client && nuxt-module-build build",
|
|
50
50
|
"prepack": "npm run build",
|
|
51
51
|
"lint": "eslint .",
|
|
52
|
-
"format": "prettier --write '**/*.{ts,vue,js,json}' --ignore-path .prettierignore && stylelint '**/*.{css,vue}' --ignore-pattern '**/.nuxt/**' --ignore-pattern '**/.output/**' --ignore-pattern 'coverage/**' --ignore-pattern 'client/dist/**' --ignore-pattern 'scripts/**' --fix && eslint --fix '**/*.{ts,vue,js}' --ignore-pattern '**/.nuxt/**' --ignore-pattern '**/.output/**' --ignore-pattern 'coverage/**' --ignore-pattern 'client/dist/**' --ignore-pattern 'scripts/**' --ignore-pattern 'docs/dist/**'",
|
|
52
|
+
"format": "prettier --write '**/*.{ts,vue,js,json}' --ignore-path .prettierignore && stylelint '**/*.{css,vue}' --ignore-pattern '**/.nuxt/**' --ignore-pattern '**/.output/**' --ignore-pattern 'coverage/**' --ignore-pattern 'client/dist/**' --ignore-pattern 'scripts/**' --ignore-pattern 'docs/dist/**' --fix && eslint --fix '**/*.{ts,vue,js}' --ignore-pattern '**/.nuxt/**' --ignore-pattern '**/.output/**' --ignore-pattern 'coverage/**' --ignore-pattern 'client/dist/**' --ignore-pattern 'scripts/**' --ignore-pattern 'docs/dist/**'",
|
|
53
53
|
"typecheck": "vue-tsc --noEmit",
|
|
54
54
|
"test": "vitest run",
|
|
55
55
|
"test:watch": "vitest",
|
|
56
56
|
"test:coverage": "vitest run --coverage",
|
|
57
57
|
"test:screenshots": "playwright test scripts/playwright/screenshot-trackers.spec.ts",
|
|
58
58
|
"test:e2e": "playwright test scripts/playwright/playground-pages.spec.ts",
|
|
59
|
-
"capture:screenshots": "node scripts/playwright/capture-observatory-screenshots.cjs"
|
|
59
|
+
"capture:screenshots": "node scripts/playwright/capture-observatory-screenshots.cjs",
|
|
60
|
+
"verify": "tsx scripts/run-verification.ts",
|
|
61
|
+
"verify:debug": "playwright test --debug",
|
|
62
|
+
"verify:ui": "playwright test --ui",
|
|
63
|
+
"verify:trace": "playwright test --trace on",
|
|
64
|
+
"verify:report": "playwright show-report",
|
|
65
|
+
"test:accuracy": "vitest run tests/verification/accuracy.test.ts",
|
|
66
|
+
"type-check": "tsc --noEmit --project tests/verification/tsconfig.json"
|
|
60
67
|
},
|
|
61
68
|
"dependencies": {
|
|
62
69
|
"@babel/generator": "^7.29.1",
|
|
@@ -73,11 +80,13 @@
|
|
|
73
80
|
"@nuxt/schema": "^3.0.0",
|
|
74
81
|
"@pinia/nuxt": "^0.11.3",
|
|
75
82
|
"@playwright/test": "^1.58.2",
|
|
83
|
+
"@tanstack/vue-virtual": "^3.13.12",
|
|
76
84
|
"@types/babel__generator": "^7.27.0",
|
|
77
85
|
"@types/babel__traverse": "^7.28.0",
|
|
78
86
|
"@types/node": "^25.5.0",
|
|
79
87
|
"@vitejs/plugin-vue": "^6.0.0",
|
|
80
88
|
"@vitest/coverage-v8": "^4.1.0",
|
|
89
|
+
"@vitest/ui": "^4.1.4",
|
|
81
90
|
"concurrently": "^9.2.1",
|
|
82
91
|
"eslint": "^9.39.2",
|
|
83
92
|
"eslint-config-prettier": "^10.1.8",
|
|
@@ -92,10 +101,12 @@
|
|
|
92
101
|
"playwright": "^1.58.2",
|
|
93
102
|
"postcss-html": "^1.8.1",
|
|
94
103
|
"prettier": "^3.8.1",
|
|
104
|
+
"sinon": "^21.1.2",
|
|
95
105
|
"sirv": "^3.0.2",
|
|
96
106
|
"stylelint": "^17.4.0",
|
|
97
107
|
"stylelint-config-standard": "^40.0.0",
|
|
98
108
|
"stylelint-config-standard-vue": "^1.0.0",
|
|
109
|
+
"tsx": "^4.21.0",
|
|
99
110
|
"typescript": "^5.9.3",
|
|
100
111
|
"typescript-eslint": "^8.54.0",
|
|
101
112
|
"unbuild": "^3.6.1",
|