nuxt-devtools-observatory 0.1.28 → 0.1.31
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 +93 -11
- package/client/.env +2 -1
- package/client/.env.example +2 -1
- package/client/dist/assets/index-BuMXDBO9.js +17 -0
- package/client/dist/assets/index-CwcspZ6w.css +1 -0
- package/client/dist/index.html +2 -2
- package/client/src/App.vue +4 -0
- package/client/src/components/Flamegraph.vue +443 -0
- package/client/src/components/SpanInspector.vue +446 -0
- package/client/src/components/TraceFilter.vue +344 -0
- package/client/src/components/WaterfallView.vue +443 -0
- package/client/src/composables/useResizablePane.ts +65 -0
- package/client/src/composables/useTraceFilter.ts +164 -0
- package/client/src/stores/observatory.ts +16 -2
- package/client/src/style.css +203 -28
- package/client/src/views/ComposableTracker.vue +324 -259
- package/client/src/views/FetchDashboard.vue +104 -133
- package/client/src/views/ProvideInjectGraph.vue +99 -109
- package/client/src/views/RenderHeatmap.vue +191 -147
- package/client/src/views/TraceViewer.vue +599 -0
- package/client/src/views/TransitionTimeline.vue +167 -137
- package/client/tsconfig.json +3 -1
- package/client/vite.config.ts +8 -0
- package/dist/module.d.mts +5 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +186 -200
- package/dist/runtime/composables/render-registry.js +66 -110
- package/dist/runtime/composables/transition-registry.js +103 -28
- package/dist/runtime/instrumentation/asyncData.d.ts +9 -0
- package/dist/runtime/instrumentation/asyncData.js +49 -0
- package/dist/runtime/instrumentation/component.d.ts +2 -0
- package/dist/runtime/instrumentation/component.js +126 -0
- package/dist/runtime/instrumentation/fetch.d.ts +2 -0
- package/dist/runtime/instrumentation/fetch.js +89 -0
- package/dist/runtime/instrumentation/route.d.ts +6 -0
- package/dist/runtime/instrumentation/route.js +41 -0
- package/dist/runtime/plugin.js +39 -3
- package/dist/runtime/tracing/context.d.ts +9 -0
- package/dist/runtime/tracing/context.js +15 -0
- package/dist/runtime/tracing/trace.d.ts +25 -0
- package/dist/runtime/tracing/trace.js +0 -0
- package/dist/runtime/tracing/traceStore.d.ts +39 -0
- package/dist/runtime/tracing/traceStore.js +101 -0
- package/dist/runtime/tracing/tracing.d.ts +27 -0
- package/dist/runtime/tracing/tracing.js +48 -0
- package/package.json +9 -6
- package/client/dist/assets/index-DXCGQOSF.js +0 -17
- package/client/dist/assets/index-htI4WwBU.css +0 -1
package/dist/module.mjs
CHANGED
|
@@ -24,6 +24,156 @@ function extractScriptBlock(code) {
|
|
|
24
24
|
|
|
25
25
|
const traverse$2 = _traverse.default ?? _traverse;
|
|
26
26
|
const generate$2 = _generate.default ?? _generate;
|
|
27
|
+
const COMPOSABLE_RE = /\buse[A-Z]/;
|
|
28
|
+
const SKIP_LIST = /* @__PURE__ */ new Set([
|
|
29
|
+
// useFetch family — tracked by the fetch dashboard
|
|
30
|
+
"useFetch",
|
|
31
|
+
"useAsyncData",
|
|
32
|
+
"useLazyFetch",
|
|
33
|
+
"useLazyAsyncData",
|
|
34
|
+
// Nuxt auto-imports
|
|
35
|
+
"useCookie",
|
|
36
|
+
"useRequestEvent",
|
|
37
|
+
"useRequestHeaders",
|
|
38
|
+
"useRequestURL",
|
|
39
|
+
"useResponseHeader",
|
|
40
|
+
"useNuxtApp",
|
|
41
|
+
"useRuntimeConfig",
|
|
42
|
+
"useRoute",
|
|
43
|
+
"useRouter",
|
|
44
|
+
"useNuxtData",
|
|
45
|
+
"useError",
|
|
46
|
+
"useState",
|
|
47
|
+
"useAppConfig",
|
|
48
|
+
// Nuxt head
|
|
49
|
+
"useHead",
|
|
50
|
+
"useSeoMeta",
|
|
51
|
+
"useServerSeoMeta",
|
|
52
|
+
"useHeadSafe",
|
|
53
|
+
// Nuxt i18n (common plugin)
|
|
54
|
+
"useI18n",
|
|
55
|
+
"useLocalePath",
|
|
56
|
+
"useLocaleRoute",
|
|
57
|
+
// Vue built-ins
|
|
58
|
+
"useSlots",
|
|
59
|
+
"useAttrs",
|
|
60
|
+
"useModel",
|
|
61
|
+
"useTemplateRef",
|
|
62
|
+
"useId",
|
|
63
|
+
"useCssModule",
|
|
64
|
+
"useCssVars"
|
|
65
|
+
]);
|
|
66
|
+
function composableTrackerPlugin() {
|
|
67
|
+
return {
|
|
68
|
+
name: "vite-plugin-observatory-composables",
|
|
69
|
+
enforce: "pre",
|
|
70
|
+
transform(code, id) {
|
|
71
|
+
const isVue = id.endsWith(".vue");
|
|
72
|
+
if (!isVue && !id.endsWith(".ts") && !id.endsWith(".js")) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (id.includes("node_modules") || id.includes("composable-registry") || id.includes("provide-inject-registry") || id.includes("fetch-registry")) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
let scriptCode = code;
|
|
79
|
+
let scriptStart = 0;
|
|
80
|
+
if (isVue) {
|
|
81
|
+
const block = extractScriptBlock(code);
|
|
82
|
+
if (!block) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
scriptCode = block.content;
|
|
86
|
+
scriptStart = block.start;
|
|
87
|
+
}
|
|
88
|
+
if (!COMPOSABLE_RE.test(scriptCode)) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
const ast = parse(scriptCode, {
|
|
93
|
+
sourceType: "module",
|
|
94
|
+
plugins: ["typescript"]
|
|
95
|
+
});
|
|
96
|
+
let modified = false;
|
|
97
|
+
traverse$2(ast, {
|
|
98
|
+
CallExpression(path) {
|
|
99
|
+
const callee = path.node.callee;
|
|
100
|
+
if (!t.isIdentifier(callee)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const name = callee.name;
|
|
104
|
+
if (!COMPOSABLE_RE.test(name)) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (SKIP_LIST.has(name)) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const binding = path.scope.getBinding(name);
|
|
111
|
+
if (binding?.path.isImportSpecifier() || binding?.path.isImportDefaultSpecifier()) {
|
|
112
|
+
const importDecl = binding.path.parentPath?.node;
|
|
113
|
+
const source = importDecl?.source?.value ?? "";
|
|
114
|
+
if (source && !source.startsWith(".") && !source.startsWith("/")) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
let parent = path.parentPath;
|
|
119
|
+
let isWrapped = false;
|
|
120
|
+
while (parent) {
|
|
121
|
+
if (t.isCallExpression(parent.node) && t.isIdentifier(parent.node.callee) && parent.node.callee.name === "__trackComposable") {
|
|
122
|
+
isWrapped = true;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
parent = parent.parentPath ?? null;
|
|
126
|
+
}
|
|
127
|
+
if (isWrapped) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const comments = (path.node.leadingComments ?? []).concat(path.parentPath?.node?.leadingComments ?? []);
|
|
131
|
+
const ignored = comments.some((c) => c.value.includes("@devtools-ignore"));
|
|
132
|
+
if (ignored) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const args = path.node.arguments;
|
|
136
|
+
const loc = path.node.loc;
|
|
137
|
+
const fileName = id.split(/[\\/]/).pop() || id;
|
|
138
|
+
const meta = t.objectExpression([
|
|
139
|
+
t.objectProperty(t.identifier("file"), t.stringLiteral(fileName)),
|
|
140
|
+
t.objectProperty(t.identifier("line"), t.numericLiteral(loc?.start.line ?? 0))
|
|
141
|
+
]);
|
|
142
|
+
path.replaceWith(
|
|
143
|
+
t.callExpression(t.identifier("__trackComposable"), [
|
|
144
|
+
t.stringLiteral(name),
|
|
145
|
+
t.arrowFunctionExpression([], t.callExpression(t.identifier(name), args)),
|
|
146
|
+
meta
|
|
147
|
+
])
|
|
148
|
+
);
|
|
149
|
+
modified = true;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
if (!modified) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
const importLine = `import { __trackComposable } from 'nuxt-devtools-observatory/runtime/composable-registry';
|
|
156
|
+
`;
|
|
157
|
+
const output = generate$2(ast, { retainLines: true }, scriptCode);
|
|
158
|
+
const alreadyImported = output.code.includes("nuxt-devtools-observatory/runtime/composable-registry");
|
|
159
|
+
const prefix = alreadyImported ? "" : importLine;
|
|
160
|
+
let finalCode;
|
|
161
|
+
if (isVue) {
|
|
162
|
+
finalCode = code.slice(0, scriptStart) + prefix + output.code + code.slice(scriptStart + scriptCode.length);
|
|
163
|
+
} else {
|
|
164
|
+
finalCode = prefix + output.code;
|
|
165
|
+
}
|
|
166
|
+
return { code: finalCode, map: output.map };
|
|
167
|
+
} catch (err) {
|
|
168
|
+
console.warn("[observatory] composable transform error:", err);
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const traverse$1 = _traverse.default ?? _traverse;
|
|
176
|
+
const generate$1 = _generate.default ?? _generate;
|
|
27
177
|
const FETCH_FNS = /* @__PURE__ */ new Set(["useFetch", "useAsyncData", "useLazyFetch", "useLazyAsyncData"]);
|
|
28
178
|
function isHandlerExpression(node) {
|
|
29
179
|
return Boolean(node && (t.isIdentifier(node) || t.isArrowFunctionExpression(node) || t.isFunctionExpression(node)));
|
|
@@ -37,7 +187,7 @@ function fetchInstrumentPlugin() {
|
|
|
37
187
|
if (!isVue && !id.endsWith(".ts") && !id.endsWith(".js")) {
|
|
38
188
|
return;
|
|
39
189
|
}
|
|
40
|
-
if (id.includes("node_modules") || id.includes("composable-registry") || id.includes("provide-inject-registry") || id.includes("fetch-registry")) {
|
|
190
|
+
if (id.includes("node_modules") || id.includes("composable-registry") || id.includes("provide-inject-registry") || id.includes("fetch-registry") || id.includes("instrumentation/asyncData")) {
|
|
41
191
|
return;
|
|
42
192
|
}
|
|
43
193
|
let scriptCode = code;
|
|
@@ -60,10 +210,10 @@ function fetchInstrumentPlugin() {
|
|
|
60
210
|
});
|
|
61
211
|
let modified = false;
|
|
62
212
|
let needsFetchCallHelper = false;
|
|
63
|
-
let
|
|
213
|
+
let needsTracedAsyncDataHelper = false;
|
|
64
214
|
const hasFetchCallImport = scriptCode.includes("__devFetchCall");
|
|
65
|
-
const
|
|
66
|
-
traverse$
|
|
215
|
+
const hasTracedAsyncDataImport = scriptCode.includes("useTracedAsyncData");
|
|
216
|
+
traverse$1(ast, {
|
|
67
217
|
CallExpression(path) {
|
|
68
218
|
if (path.node.__observatoryTransformed) {
|
|
69
219
|
return;
|
|
@@ -75,7 +225,7 @@ function fetchInstrumentPlugin() {
|
|
|
75
225
|
if (!FETCH_FNS.has(callee.name)) {
|
|
76
226
|
return;
|
|
77
227
|
}
|
|
78
|
-
if (path.parent && t.isCallExpression(path.parent) && t.isIdentifier(path.parent.callee) && ["__devFetchCall", "
|
|
228
|
+
if (path.parent && t.isCallExpression(path.parent) && t.isIdentifier(path.parent.callee) && ["__devFetchCall", "useTracedAsyncData"].includes(path.parent.callee.name)) {
|
|
79
229
|
return;
|
|
80
230
|
}
|
|
81
231
|
const originalName = callee.name;
|
|
@@ -123,40 +273,18 @@ function fetchInstrumentPlugin() {
|
|
|
123
273
|
t.objectProperty(t.identifier("originalFn"), t.stringLiteral(originalName))
|
|
124
274
|
]);
|
|
125
275
|
if ((originalName === "useAsyncData" || originalName === "useLazyAsyncData") && handlerArg) {
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
meta
|
|
139
|
-
]),
|
|
140
|
-
[t.spreadElement(t.identifier("args"))]
|
|
141
|
-
),
|
|
142
|
-
t.callExpression(handlerArg, [t.spreadElement(t.identifier("args"))])
|
|
143
|
-
)
|
|
144
|
-
);
|
|
145
|
-
wrappedHandler.__observatoryTransformed = true;
|
|
146
|
-
needsFetchHandlerHelper = true;
|
|
147
|
-
if (keyArg) {
|
|
148
|
-
const newCall = t.callExpression(t.identifier(originalName), [
|
|
149
|
-
keyArg,
|
|
150
|
-
wrappedHandler,
|
|
151
|
-
optsArg ?? t.objectExpression([])
|
|
152
|
-
]);
|
|
153
|
-
newCall.__observatoryTransformed = true;
|
|
154
|
-
path.replaceWith(newCall);
|
|
155
|
-
} else {
|
|
156
|
-
const newCall = t.callExpression(t.identifier(originalName), [wrappedHandler]);
|
|
157
|
-
newCall.__observatoryTransformed = true;
|
|
158
|
-
path.replaceWith(newCall);
|
|
159
|
-
}
|
|
276
|
+
const rewrittenArgs = keyArg ? [keyArg, handlerArg, optsArg ?? t.objectExpression([])] : [handlerArg];
|
|
277
|
+
const handlerIndex = keyArg ? 1 : 0;
|
|
278
|
+
const newCall = t.callExpression(t.identifier("useTracedAsyncData"), [
|
|
279
|
+
t.identifier(originalName),
|
|
280
|
+
t.arrayExpression(rewrittenArgs),
|
|
281
|
+
t.numericLiteral(handlerIndex),
|
|
282
|
+
keyArg ?? t.stringLiteral(key),
|
|
283
|
+
meta
|
|
284
|
+
]);
|
|
285
|
+
newCall.__observatoryTransformed = true;
|
|
286
|
+
path.replaceWith(newCall);
|
|
287
|
+
needsTracedAsyncDataHelper = true;
|
|
160
288
|
modified = true;
|
|
161
289
|
} else {
|
|
162
290
|
const newCall = t.callExpression(t.identifier("__devFetchCall"), [
|
|
@@ -175,13 +303,13 @@ function fetchInstrumentPlugin() {
|
|
|
175
303
|
if (!modified) {
|
|
176
304
|
return null;
|
|
177
305
|
}
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
needsFetchHandlerHelper && !hasFetchHandlerImport ? "__devFetchHandler" : ""
|
|
181
|
-
].filter(Boolean);
|
|
182
|
-
const importStatement = importNames.length ? `import { ${importNames.join(", ")} } from 'nuxt-devtools-observatory/runtime/fetch-registry';
|
|
306
|
+
const fetchImportNames = [needsFetchCallHelper && !hasFetchCallImport ? "__devFetchCall" : ""].filter(Boolean);
|
|
307
|
+
const fetchImportStatement = fetchImportNames.length ? `import { ${fetchImportNames.join(", ")} } from 'nuxt-devtools-observatory/runtime/fetch-registry';
|
|
183
308
|
` : "";
|
|
184
|
-
const
|
|
309
|
+
const asyncDataImportStatement = needsTracedAsyncDataHelper && !hasTracedAsyncDataImport ? `import { useTracedAsyncData } from 'nuxt-devtools-observatory/runtime/async-data-instrumentation';
|
|
310
|
+
` : "";
|
|
311
|
+
const importStatement = fetchImportStatement + asyncDataImportStatement;
|
|
312
|
+
const output = generate$1(ast, { retainLines: true }, scriptCode);
|
|
185
313
|
let finalCode;
|
|
186
314
|
if (isVue) {
|
|
187
315
|
finalCode = code.slice(0, scriptStart) + importStatement + output.code + code.slice(scriptStart + scriptCode.length);
|
|
@@ -200,8 +328,8 @@ function fetchInstrumentPlugin() {
|
|
|
200
328
|
};
|
|
201
329
|
}
|
|
202
330
|
|
|
203
|
-
const traverse
|
|
204
|
-
const generate
|
|
331
|
+
const traverse = _traverse.default ?? _traverse;
|
|
332
|
+
const generate = _generate.default ?? _generate;
|
|
205
333
|
function provideInjectPlugin() {
|
|
206
334
|
return {
|
|
207
335
|
name: "vite-plugin-observatory-provide-inject",
|
|
@@ -233,7 +361,7 @@ function provideInjectPlugin() {
|
|
|
233
361
|
plugins: ["typescript"]
|
|
234
362
|
});
|
|
235
363
|
let modified = false;
|
|
236
|
-
traverse
|
|
364
|
+
traverse(ast, {
|
|
237
365
|
CallExpression(path) {
|
|
238
366
|
const callee = path.node.callee;
|
|
239
367
|
if (!t.isIdentifier(callee)) {
|
|
@@ -267,7 +395,7 @@ function provideInjectPlugin() {
|
|
|
267
395
|
}
|
|
268
396
|
const importLine = `import { __devProvide, __devInject } from 'nuxt-devtools-observatory/runtime/provide-inject-registry';
|
|
269
397
|
`;
|
|
270
|
-
const output = generate
|
|
398
|
+
const output = generate(ast, { retainLines: true }, scriptCode);
|
|
271
399
|
let finalCode;
|
|
272
400
|
if (isVue) {
|
|
273
401
|
finalCode = code.slice(0, scriptStart) + (scriptCode.includes("__devProvide") ? "" : importLine) + output.code + code.slice(scriptStart + scriptCode.length);
|
|
@@ -283,156 +411,6 @@ function provideInjectPlugin() {
|
|
|
283
411
|
};
|
|
284
412
|
}
|
|
285
413
|
|
|
286
|
-
const traverse = _traverse.default ?? _traverse;
|
|
287
|
-
const generate = _generate.default ?? _generate;
|
|
288
|
-
const COMPOSABLE_RE = /\buse[A-Z]/;
|
|
289
|
-
const SKIP_LIST = /* @__PURE__ */ new Set([
|
|
290
|
-
// useFetch family — tracked by the fetch dashboard
|
|
291
|
-
"useFetch",
|
|
292
|
-
"useAsyncData",
|
|
293
|
-
"useLazyFetch",
|
|
294
|
-
"useLazyAsyncData",
|
|
295
|
-
// Nuxt auto-imports
|
|
296
|
-
"useCookie",
|
|
297
|
-
"useRequestEvent",
|
|
298
|
-
"useRequestHeaders",
|
|
299
|
-
"useRequestURL",
|
|
300
|
-
"useResponseHeader",
|
|
301
|
-
"useNuxtApp",
|
|
302
|
-
"useRuntimeConfig",
|
|
303
|
-
"useRoute",
|
|
304
|
-
"useRouter",
|
|
305
|
-
"useNuxtData",
|
|
306
|
-
"useError",
|
|
307
|
-
"useState",
|
|
308
|
-
"useAppConfig",
|
|
309
|
-
// Nuxt head
|
|
310
|
-
"useHead",
|
|
311
|
-
"useSeoMeta",
|
|
312
|
-
"useServerSeoMeta",
|
|
313
|
-
"useHeadSafe",
|
|
314
|
-
// Nuxt i18n (common plugin)
|
|
315
|
-
"useI18n",
|
|
316
|
-
"useLocalePath",
|
|
317
|
-
"useLocaleRoute",
|
|
318
|
-
// Vue built-ins
|
|
319
|
-
"useSlots",
|
|
320
|
-
"useAttrs",
|
|
321
|
-
"useModel",
|
|
322
|
-
"useTemplateRef",
|
|
323
|
-
"useId",
|
|
324
|
-
"useCssModule",
|
|
325
|
-
"useCssVars"
|
|
326
|
-
]);
|
|
327
|
-
function composableTrackerPlugin() {
|
|
328
|
-
return {
|
|
329
|
-
name: "vite-plugin-observatory-composables",
|
|
330
|
-
enforce: "pre",
|
|
331
|
-
transform(code, id) {
|
|
332
|
-
const isVue = id.endsWith(".vue");
|
|
333
|
-
if (!isVue && !id.endsWith(".ts") && !id.endsWith(".js")) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
if (id.includes("node_modules") || id.includes("composable-registry") || id.includes("provide-inject-registry") || id.includes("fetch-registry")) {
|
|
337
|
-
return;
|
|
338
|
-
}
|
|
339
|
-
let scriptCode = code;
|
|
340
|
-
let scriptStart = 0;
|
|
341
|
-
if (isVue) {
|
|
342
|
-
const block = extractScriptBlock(code);
|
|
343
|
-
if (!block) {
|
|
344
|
-
return null;
|
|
345
|
-
}
|
|
346
|
-
scriptCode = block.content;
|
|
347
|
-
scriptStart = block.start;
|
|
348
|
-
}
|
|
349
|
-
if (!COMPOSABLE_RE.test(scriptCode)) {
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
try {
|
|
353
|
-
const ast = parse(scriptCode, {
|
|
354
|
-
sourceType: "module",
|
|
355
|
-
plugins: ["typescript"]
|
|
356
|
-
});
|
|
357
|
-
let modified = false;
|
|
358
|
-
traverse(ast, {
|
|
359
|
-
CallExpression(path) {
|
|
360
|
-
const callee = path.node.callee;
|
|
361
|
-
if (!t.isIdentifier(callee)) {
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
const name = callee.name;
|
|
365
|
-
if (!COMPOSABLE_RE.test(name)) {
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
if (SKIP_LIST.has(name)) {
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
const binding = path.scope.getBinding(name);
|
|
372
|
-
if (binding?.path.isImportSpecifier() || binding?.path.isImportDefaultSpecifier()) {
|
|
373
|
-
const importDecl = binding.path.parentPath?.node;
|
|
374
|
-
const source = importDecl?.source?.value ?? "";
|
|
375
|
-
if (source && !source.startsWith(".") && !source.startsWith("/")) {
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
let parent = path.parentPath;
|
|
380
|
-
let isWrapped = false;
|
|
381
|
-
while (parent) {
|
|
382
|
-
if (t.isCallExpression(parent.node) && t.isIdentifier(parent.node.callee) && parent.node.callee.name === "__trackComposable") {
|
|
383
|
-
isWrapped = true;
|
|
384
|
-
break;
|
|
385
|
-
}
|
|
386
|
-
parent = parent.parentPath ?? null;
|
|
387
|
-
}
|
|
388
|
-
if (isWrapped) {
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
const comments = (path.node.leadingComments ?? []).concat(path.parentPath?.node?.leadingComments ?? []);
|
|
392
|
-
const ignored = comments.some((c) => c.value.includes("@devtools-ignore"));
|
|
393
|
-
if (ignored) {
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
const args = path.node.arguments;
|
|
397
|
-
const loc = path.node.loc;
|
|
398
|
-
const fileName = id.split(/[\\/]/).pop() || id;
|
|
399
|
-
const meta = t.objectExpression([
|
|
400
|
-
t.objectProperty(t.identifier("file"), t.stringLiteral(fileName)),
|
|
401
|
-
t.objectProperty(t.identifier("line"), t.numericLiteral(loc?.start.line ?? 0))
|
|
402
|
-
]);
|
|
403
|
-
path.replaceWith(
|
|
404
|
-
t.callExpression(t.identifier("__trackComposable"), [
|
|
405
|
-
t.stringLiteral(name),
|
|
406
|
-
t.arrowFunctionExpression([], t.callExpression(t.identifier(name), args)),
|
|
407
|
-
meta
|
|
408
|
-
])
|
|
409
|
-
);
|
|
410
|
-
modified = true;
|
|
411
|
-
}
|
|
412
|
-
});
|
|
413
|
-
if (!modified) {
|
|
414
|
-
return null;
|
|
415
|
-
}
|
|
416
|
-
const importLine = `import { __trackComposable } from 'nuxt-devtools-observatory/runtime/composable-registry';
|
|
417
|
-
`;
|
|
418
|
-
const output = generate(ast, { retainLines: true }, scriptCode);
|
|
419
|
-
const alreadyImported = output.code.includes("nuxt-devtools-observatory/runtime/composable-registry");
|
|
420
|
-
const prefix = alreadyImported ? "" : importLine;
|
|
421
|
-
let finalCode;
|
|
422
|
-
if (isVue) {
|
|
423
|
-
finalCode = code.slice(0, scriptStart) + prefix + output.code + code.slice(scriptStart + scriptCode.length);
|
|
424
|
-
} else {
|
|
425
|
-
finalCode = prefix + output.code;
|
|
426
|
-
}
|
|
427
|
-
return { code: finalCode, map: output.map };
|
|
428
|
-
} catch (err) {
|
|
429
|
-
console.warn("[observatory] composable transform error:", err);
|
|
430
|
-
return null;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
|
|
436
414
|
const VIRTUAL_ID = "\0obs:vue-proxy";
|
|
437
415
|
const PROXY_MODULE = `
|
|
438
416
|
import {
|
|
@@ -554,6 +532,7 @@ const defaults = {
|
|
|
554
532
|
composableTracker: process.env.OBSERVATORY_COMPOSABLE_TRACKER === "true",
|
|
555
533
|
renderHeatmap: process.env.OBSERVATORY_RENDER_HEATMAP === "true",
|
|
556
534
|
transitionTracker: process.env.OBSERVATORY_TRANSITION_TRACKER === "true",
|
|
535
|
+
traceViewer: process.env.OBSERVATORY_TRACE_VIEWER === "true",
|
|
557
536
|
heatmapThresholdCount: process.env.OBSERVATORY_HEATMAP_THRESHOLD_COUNT ? Number(process.env.OBSERVATORY_HEATMAP_THRESHOLD_COUNT) : 3,
|
|
558
537
|
heatmapThresholdTime: process.env.OBSERVATORY_HEATMAP_THRESHOLD_TIME ? Number(process.env.OBSERVATORY_HEATMAP_THRESHOLD_TIME) : 1600,
|
|
559
538
|
maxFetchEntries: process.env.OBSERVATORY_MAX_FETCH_ENTRIES ? Number(process.env.OBSERVATORY_MAX_FETCH_ENTRIES) : 200,
|
|
@@ -591,6 +570,7 @@ const module$1 = defineNuxtModule({
|
|
|
591
570
|
composableTracker: options.composableTracker ?? (process.env.OBSERVATORY_COMPOSABLE_TRACKER ? process.env.OBSERVATORY_COMPOSABLE_TRACKER === "true" : true),
|
|
592
571
|
renderHeatmap: options.renderHeatmap ?? (process.env.OBSERVATORY_RENDER_HEATMAP ? process.env.OBSERVATORY_RENDER_HEATMAP === "true" : true),
|
|
593
572
|
transitionTracker: options.transitionTracker ?? (process.env.OBSERVATORY_TRANSITION_TRACKER ? process.env.OBSERVATORY_TRANSITION_TRACKER === "true" : true),
|
|
573
|
+
traceViewer: options.traceViewer ?? (process.env.OBSERVATORY_TRACE_VIEWER ? process.env.OBSERVATORY_TRACE_VIEWER === "true" : true),
|
|
594
574
|
instrumentServer: options.instrumentServer ?? (process.env.OBSERVATORY_INSTRUMENT_SERVER ? process.env.OBSERVATORY_INSTRUMENT_SERVER === "true" : nuxt.options.ssr !== false),
|
|
595
575
|
heatmapThresholdCount: options.heatmapThresholdCount ?? (process.env.OBSERVATORY_HEATMAP_THRESHOLD_COUNT ? Number(process.env.OBSERVATORY_HEATMAP_THRESHOLD_COUNT) : 3),
|
|
596
576
|
heatmapThresholdTime: options.heatmapThresholdTime ?? (process.env.OBSERVATORY_HEATMAP_THRESHOLD_TIME ? Number(process.env.OBSERVATORY_HEATMAP_THRESHOLD_TIME) : 1600),
|
|
@@ -611,6 +591,9 @@ const module$1 = defineNuxtModule({
|
|
|
611
591
|
"./runtime/composables/provide-inject-registry"
|
|
612
592
|
);
|
|
613
593
|
aliases["nuxt-devtools-observatory/runtime/fetch-registry"] = resolver.resolve("./runtime/composables/fetch-registry");
|
|
594
|
+
aliases["nuxt-devtools-observatory/runtime/async-data-instrumentation"] = resolver.resolve(
|
|
595
|
+
"./runtime/instrumentation/asyncData"
|
|
596
|
+
);
|
|
614
597
|
config.resolve = { ...config.resolve, alias: aliases };
|
|
615
598
|
});
|
|
616
599
|
const vitePluginScope = resolved.instrumentServer ? { server: true, client: true } : { server: false, client: true };
|
|
@@ -645,13 +628,15 @@ const module$1 = defineNuxtModule({
|
|
|
645
628
|
composables: [],
|
|
646
629
|
renders: [],
|
|
647
630
|
transitions: [],
|
|
631
|
+
traces: [],
|
|
648
632
|
features: {
|
|
649
633
|
fetchDashboard: !!resolved.fetchDashboard,
|
|
650
634
|
provideInjectGraph: !!resolved.provideInjectGraph,
|
|
651
635
|
composableTracker: !!resolved.composableTracker,
|
|
652
636
|
composableNavigationMode: resolved.composableNavigationMode,
|
|
653
637
|
renderHeatmap: !!resolved.renderHeatmap,
|
|
654
|
-
transitionTracker: !!resolved.transitionTracker
|
|
638
|
+
transitionTracker: !!resolved.transitionTracker,
|
|
639
|
+
traceViewer: !!resolved.traceViewer
|
|
655
640
|
}
|
|
656
641
|
};
|
|
657
642
|
let rpc = null;
|
|
@@ -730,6 +715,7 @@ ${configScript}`);
|
|
|
730
715
|
composableTracker: resolved.composableTracker,
|
|
731
716
|
renderHeatmap: resolved.renderHeatmap,
|
|
732
717
|
transitionTracker: resolved.transitionTracker,
|
|
718
|
+
traceViewer: resolved.traceViewer,
|
|
733
719
|
maxFetchEntries: resolved.maxFetchEntries,
|
|
734
720
|
maxPayloadBytes: resolved.maxPayloadBytes,
|
|
735
721
|
maxTransitions: resolved.maxTransitions,
|