nuxt-devtools-observatory 0.1.7 → 0.1.9
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/client/dist/assets/index-CVI-arV5.js +17 -0
- package/client/dist/assets/{index-mu192QeW.css → index-RdqCF5ft.css} +1 -1
- package/client/dist/index.html +2 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +63 -69
- package/dist/runtime/composables/composable-registry.js +10 -4
- package/dist/runtime/composables/fetch-registry.d.ts +21 -5
- package/dist/runtime/composables/fetch-registry.js +84 -112
- package/dist/runtime/composables/provide-inject-registry.d.ts +4 -0
- package/dist/runtime/composables/provide-inject-registry.js +4 -0
- package/dist/runtime/composables/render-registry.d.ts +1 -2
- package/dist/runtime/composables/render-registry.js +24 -57
- package/dist/runtime/nitro/fetch-capture.d.ts +8 -0
- package/dist/runtime/nitro/fetch-capture.js +14 -0
- package/dist/runtime/plugin.js +49 -21
- package/package.json +2 -1
- package/client/dist/assets/index-CgZM5MBX.js +0 -17
- package/dist/nitro/fetch-capture.d.mts +0 -3
- package/dist/nitro/fetch-capture.mjs +0 -16
package/dist/module.mjs
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { defineNuxtModule, createResolver, addVitePlugin, addPlugin } from '@nuxt/kit';
|
|
1
|
+
import { defineNuxtModule, createResolver, addVitePlugin, addPlugin, addServerPlugin } from '@nuxt/kit';
|
|
2
2
|
import { parse } from '@babel/parser';
|
|
3
3
|
import _traverse from '@babel/traverse';
|
|
4
4
|
import _generate from '@babel/generator';
|
|
5
5
|
import * as t from '@babel/types';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
const generate$2 = _generate.default ?? _generate;
|
|
9
|
-
function extractScriptBlock$2(code) {
|
|
7
|
+
function extractScriptBlock(code) {
|
|
10
8
|
const openTagRE = /<script(\s[^>]*)?>/i;
|
|
11
9
|
const openMatch = openTagRE.exec(code);
|
|
12
10
|
if (!openMatch) {
|
|
@@ -19,7 +17,13 @@ function extractScriptBlock$2(code) {
|
|
|
19
17
|
}
|
|
20
18
|
return { content: code.slice(start, end), start, end };
|
|
21
19
|
}
|
|
20
|
+
|
|
21
|
+
const traverse$2 = _traverse.default ?? _traverse;
|
|
22
|
+
const generate$2 = _generate.default ?? _generate;
|
|
22
23
|
const FETCH_FNS = /* @__PURE__ */ new Set(["useFetch", "useAsyncData", "useLazyFetch", "useLazyAsyncData"]);
|
|
24
|
+
function isHandlerExpression(node) {
|
|
25
|
+
return Boolean(node && (t.isIdentifier(node) || t.isArrowFunctionExpression(node) || t.isFunctionExpression(node)));
|
|
26
|
+
}
|
|
23
27
|
function fetchInstrumentPlugin() {
|
|
24
28
|
return {
|
|
25
29
|
name: "vite-plugin-observatory-fetch",
|
|
@@ -29,13 +33,13 @@ function fetchInstrumentPlugin() {
|
|
|
29
33
|
if (!isVue && !id.endsWith(".ts") && !id.endsWith(".js")) {
|
|
30
34
|
return;
|
|
31
35
|
}
|
|
32
|
-
if (id.includes("node_modules")) {
|
|
36
|
+
if (id.includes("node_modules") || id.includes("composable-registry") || id.includes("provide-inject-registry") || id.includes("fetch-registry")) {
|
|
33
37
|
return;
|
|
34
38
|
}
|
|
35
39
|
let scriptCode = code;
|
|
36
40
|
let scriptStart = 0;
|
|
37
41
|
if (isVue) {
|
|
38
|
-
const block = extractScriptBlock
|
|
42
|
+
const block = extractScriptBlock(code);
|
|
39
43
|
if (!block) {
|
|
40
44
|
return null;
|
|
41
45
|
}
|
|
@@ -51,7 +55,10 @@ function fetchInstrumentPlugin() {
|
|
|
51
55
|
plugins: ["typescript"]
|
|
52
56
|
});
|
|
53
57
|
let modified = false;
|
|
54
|
-
|
|
58
|
+
let needsFetchCallHelper = false;
|
|
59
|
+
let needsFetchHandlerHelper = false;
|
|
60
|
+
const hasFetchCallImport = scriptCode.includes("__devFetchCall");
|
|
61
|
+
const hasFetchHandlerImport = scriptCode.includes("__devFetchHandler");
|
|
55
62
|
traverse$2(ast, {
|
|
56
63
|
CallExpression(path) {
|
|
57
64
|
if (path.node.__observatoryTransformed) {
|
|
@@ -64,7 +71,7 @@ function fetchInstrumentPlugin() {
|
|
|
64
71
|
if (!FETCH_FNS.has(callee.name)) {
|
|
65
72
|
return;
|
|
66
73
|
}
|
|
67
|
-
if (path.parent && t.isCallExpression(path.parent) && t.isIdentifier(path.parent.callee) && path.parent.callee.name
|
|
74
|
+
if (path.parent && t.isCallExpression(path.parent) && t.isIdentifier(path.parent.callee) && ["__devFetchCall", "__devFetchHandler"].includes(path.parent.callee.name)) {
|
|
68
75
|
return;
|
|
69
76
|
}
|
|
70
77
|
const originalName = callee.name;
|
|
@@ -76,22 +83,35 @@ function fetchInstrumentPlugin() {
|
|
|
76
83
|
return t.isExpression(node) ? node : void 0;
|
|
77
84
|
}
|
|
78
85
|
if (originalName === "useAsyncData" || originalName === "useLazyAsyncData") {
|
|
79
|
-
if (args.length === 1 && getExpr(args[0])) {
|
|
86
|
+
if (args.length === 1 && isHandlerExpression(getExpr(args[0]))) {
|
|
80
87
|
handlerArg = getExpr(args[0]);
|
|
81
|
-
} else if (args.length >= 2 && getExpr(args[0]) && getExpr(args[1])) {
|
|
88
|
+
} else if (args.length >= 2 && getExpr(args[0]) && isHandlerExpression(getExpr(args[1]))) {
|
|
82
89
|
keyArg = getExpr(args[0]);
|
|
83
90
|
handlerArg = getExpr(args[1]);
|
|
84
91
|
optsArg = getExpr(args[2]) ?? t.objectExpression([]);
|
|
85
92
|
} else {
|
|
86
|
-
|
|
93
|
+
keyArg = getExpr(args[0]) ?? t.stringLiteral("");
|
|
94
|
+
optsArg = getExpr(args[1]) ?? t.objectExpression([]);
|
|
95
|
+
handlerArg = void 0;
|
|
87
96
|
}
|
|
88
97
|
} else {
|
|
89
98
|
keyArg = getExpr(args[0]) ?? t.stringLiteral("");
|
|
90
99
|
optsArg = getExpr(args[1]) ?? t.objectExpression([]);
|
|
91
100
|
}
|
|
92
101
|
let key = originalName;
|
|
93
|
-
if (
|
|
94
|
-
|
|
102
|
+
if (originalName === "useFetch" || originalName === "useLazyFetch") {
|
|
103
|
+
if (optsArg && t.isObjectExpression(optsArg)) {
|
|
104
|
+
const keyProp = optsArg.properties.find(
|
|
105
|
+
(property) => t.isObjectProperty(property) && t.isIdentifier(property.key) && property.key.name === "key" && t.isStringLiteral(property.value)
|
|
106
|
+
);
|
|
107
|
+
if (keyProp && t.isStringLiteral(keyProp.value)) {
|
|
108
|
+
key = keyProp.value.value;
|
|
109
|
+
} else if (keyArg && t.isStringLiteral(keyArg)) {
|
|
110
|
+
key = keyArg.value.replace(/[^a-z0-9]/gi, "-").replace(/^-+|-+$/g, "");
|
|
111
|
+
}
|
|
112
|
+
} else if (keyArg && t.isStringLiteral(keyArg)) {
|
|
113
|
+
key = keyArg.value.replace(/[^a-z0-9]/gi, "-").replace(/^-+|-+$/g, "");
|
|
114
|
+
}
|
|
95
115
|
}
|
|
96
116
|
const loc = path.node.loc;
|
|
97
117
|
const meta = t.objectExpression([
|
|
@@ -100,9 +120,9 @@ function fetchInstrumentPlugin() {
|
|
|
100
120
|
t.objectProperty(t.identifier("line"), t.numericLiteral(loc?.start.line ?? 0)),
|
|
101
121
|
t.objectProperty(t.identifier("originalFn"), t.stringLiteral(originalName))
|
|
102
122
|
]);
|
|
103
|
-
if (originalName === "useAsyncData" || originalName === "useLazyAsyncData") {
|
|
123
|
+
if ((originalName === "useAsyncData" || originalName === "useLazyAsyncData") && handlerArg) {
|
|
104
124
|
if (handlerArg) {
|
|
105
|
-
const
|
|
125
|
+
const wrappedHandler = t.arrowFunctionExpression(
|
|
106
126
|
[t.restElement(t.identifier("args"))],
|
|
107
127
|
t.conditionalExpression(
|
|
108
128
|
t.logicalExpression(
|
|
@@ -111,41 +131,38 @@ function fetchInstrumentPlugin() {
|
|
|
111
131
|
t.memberExpression(t.identifier("process"), t.identifier("client"))
|
|
112
132
|
),
|
|
113
133
|
t.callExpression(
|
|
114
|
-
t.callExpression(
|
|
115
|
-
t.identifier("__devFetch"),
|
|
116
|
-
[handlerArg, keyArg ?? t.stringLiteral(key), meta]
|
|
117
|
-
),
|
|
134
|
+
t.callExpression(t.identifier("__devFetchHandler"), [handlerArg, keyArg ?? t.stringLiteral(key), meta]),
|
|
118
135
|
[t.spreadElement(t.identifier("args"))]
|
|
119
136
|
),
|
|
120
|
-
t.callExpression(
|
|
121
|
-
handlerArg,
|
|
122
|
-
[t.spreadElement(t.identifier("args"))]
|
|
123
|
-
)
|
|
137
|
+
t.callExpression(handlerArg, [t.spreadElement(t.identifier("args"))])
|
|
124
138
|
)
|
|
125
139
|
);
|
|
126
|
-
|
|
127
|
-
|
|
140
|
+
wrappedHandler.__observatoryTransformed = true;
|
|
141
|
+
needsFetchHandlerHelper = true;
|
|
128
142
|
if (keyArg) {
|
|
129
|
-
newCall = t.callExpression(t.identifier(originalName), [
|
|
143
|
+
const newCall = t.callExpression(t.identifier(originalName), [
|
|
130
144
|
keyArg,
|
|
131
|
-
|
|
145
|
+
wrappedHandler,
|
|
132
146
|
optsArg ?? t.objectExpression([])
|
|
133
147
|
]);
|
|
148
|
+
newCall.__observatoryTransformed = true;
|
|
149
|
+
path.replaceWith(newCall);
|
|
134
150
|
} else {
|
|
135
|
-
newCall = t.callExpression(t.identifier(originalName), [
|
|
151
|
+
const newCall = t.callExpression(t.identifier(originalName), [wrappedHandler]);
|
|
152
|
+
newCall.__observatoryTransformed = true;
|
|
153
|
+
path.replaceWith(newCall);
|
|
136
154
|
}
|
|
137
|
-
newCall.__observatoryTransformed = true;
|
|
138
|
-
path.replaceWith(newCall);
|
|
139
155
|
modified = true;
|
|
140
156
|
}
|
|
141
157
|
} else {
|
|
142
|
-
const newCall = t.callExpression(t.identifier("
|
|
158
|
+
const newCall = t.callExpression(t.identifier("__devFetchCall"), [
|
|
143
159
|
t.identifier(originalName),
|
|
144
160
|
keyArg ?? t.stringLiteral(""),
|
|
145
161
|
optsArg ?? t.objectExpression([]),
|
|
146
162
|
meta
|
|
147
163
|
]);
|
|
148
164
|
newCall.__observatoryTransformed = true;
|
|
165
|
+
needsFetchCallHelper = true;
|
|
149
166
|
path.replaceWith(newCall);
|
|
150
167
|
modified = true;
|
|
151
168
|
}
|
|
@@ -154,8 +171,12 @@ function fetchInstrumentPlugin() {
|
|
|
154
171
|
if (!modified) {
|
|
155
172
|
return null;
|
|
156
173
|
}
|
|
157
|
-
const
|
|
158
|
-
|
|
174
|
+
const importNames = [
|
|
175
|
+
needsFetchCallHelper && !hasFetchCallImport ? "__devFetchCall" : "",
|
|
176
|
+
needsFetchHandlerHelper && !hasFetchHandlerImport ? "__devFetchHandler" : ""
|
|
177
|
+
].filter(Boolean);
|
|
178
|
+
const importStatement = importNames.length ? `import { ${importNames.join(", ")} } from 'nuxt-devtools-observatory/runtime/fetch-registry';
|
|
179
|
+
` : "";
|
|
159
180
|
const output = generate$2(ast, { retainLines: true }, scriptCode);
|
|
160
181
|
let finalCode;
|
|
161
182
|
if (isVue) {
|
|
@@ -177,26 +198,13 @@ function fetchInstrumentPlugin() {
|
|
|
177
198
|
|
|
178
199
|
const traverse$1 = _traverse.default ?? _traverse;
|
|
179
200
|
const generate$1 = _generate.default ?? _generate;
|
|
180
|
-
function extractScriptBlock$1(code) {
|
|
181
|
-
const openTagRE = /<script(\s[^>]*)?>/i;
|
|
182
|
-
const openMatch = openTagRE.exec(code);
|
|
183
|
-
if (!openMatch) {
|
|
184
|
-
return null;
|
|
185
|
-
}
|
|
186
|
-
const start = openMatch.index + openMatch[0].length;
|
|
187
|
-
const end = code.indexOf("<\/script>", start);
|
|
188
|
-
if (end === -1) {
|
|
189
|
-
return null;
|
|
190
|
-
}
|
|
191
|
-
return { content: code.slice(start, end), start, end };
|
|
192
|
-
}
|
|
193
201
|
function provideInjectPlugin() {
|
|
194
202
|
return {
|
|
195
203
|
name: "vite-plugin-observatory-provide-inject",
|
|
196
204
|
enforce: "pre",
|
|
197
205
|
transform(code, id) {
|
|
198
206
|
const isVue = id.endsWith(".vue");
|
|
199
|
-
if (!isVue && !id.endsWith(".ts")) {
|
|
207
|
+
if (!isVue && !id.endsWith(".ts") && !id.endsWith(".js")) {
|
|
200
208
|
return;
|
|
201
209
|
}
|
|
202
210
|
if (id.includes("node_modules") || id.includes("composable-registry") || id.includes("provide-inject-registry") || id.includes("fetch-registry")) {
|
|
@@ -205,7 +213,7 @@ function provideInjectPlugin() {
|
|
|
205
213
|
let scriptCode = code;
|
|
206
214
|
let scriptStart = 0;
|
|
207
215
|
if (isVue) {
|
|
208
|
-
const block = extractScriptBlock
|
|
216
|
+
const block = extractScriptBlock(code);
|
|
209
217
|
if (!block) {
|
|
210
218
|
return null;
|
|
211
219
|
}
|
|
@@ -272,19 +280,6 @@ function provideInjectPlugin() {
|
|
|
272
280
|
|
|
273
281
|
const traverse = _traverse.default ?? _traverse;
|
|
274
282
|
const generate = _generate.default ?? _generate;
|
|
275
|
-
function extractScriptBlock(code) {
|
|
276
|
-
const openTagRE = /<script(\s[^>]*)?>/i;
|
|
277
|
-
const openMatch = openTagRE.exec(code);
|
|
278
|
-
if (!openMatch) {
|
|
279
|
-
return null;
|
|
280
|
-
}
|
|
281
|
-
const start = openMatch.index + openMatch[0].length;
|
|
282
|
-
const end = code.indexOf("<\/script>", start);
|
|
283
|
-
if (end === -1) {
|
|
284
|
-
return null;
|
|
285
|
-
}
|
|
286
|
-
return { content: code.slice(start, end), start, end };
|
|
287
|
-
}
|
|
288
283
|
const COMPOSABLE_RE = /\buse[A-Z]/;
|
|
289
284
|
const SKIP_LIST = /* @__PURE__ */ new Set([
|
|
290
285
|
"useFetch",
|
|
@@ -309,7 +304,7 @@ function composableTrackerPlugin() {
|
|
|
309
304
|
enforce: "pre",
|
|
310
305
|
transform(code, id) {
|
|
311
306
|
const isVue = id.endsWith(".vue");
|
|
312
|
-
if (!isVue && !id.endsWith(".ts")) {
|
|
307
|
+
if (!isVue && !id.endsWith(".ts") && !id.endsWith(".js")) {
|
|
313
308
|
return;
|
|
314
309
|
}
|
|
315
310
|
if (id.includes("node_modules") || id.includes("composable-registry") || id.includes("provide-inject-registry") || id.includes("fetch-registry")) {
|
|
@@ -551,12 +546,10 @@ const module$1 = defineNuxtModule({
|
|
|
551
546
|
}
|
|
552
547
|
addPlugin(resolver.resolve("./runtime/plugin"));
|
|
553
548
|
if (options.fetchDashboard) {
|
|
554
|
-
|
|
555
|
-
nitroConfig.plugins = nitroConfig.plugins || [];
|
|
556
|
-
nitroConfig.plugins.push(resolver.resolve("./nitro/fetch-capture"));
|
|
557
|
-
});
|
|
549
|
+
addServerPlugin(resolver.resolve("./runtime/nitro/fetch-capture"));
|
|
558
550
|
}
|
|
559
551
|
const CLIENT_PORT = 4949;
|
|
552
|
+
const clientOrigin = `http://localhost:${CLIENT_PORT}`;
|
|
560
553
|
nuxt.hook("vite:serverCreated", async (_viteServer, env) => {
|
|
561
554
|
if (!env.isClient) {
|
|
562
555
|
return;
|
|
@@ -566,7 +559,7 @@ const module$1 = defineNuxtModule({
|
|
|
566
559
|
const inner = await createServer({
|
|
567
560
|
root: resolver.resolve("../client"),
|
|
568
561
|
base: "/",
|
|
569
|
-
server: { port: CLIENT_PORT, strictPort:
|
|
562
|
+
server: { port: CLIENT_PORT, strictPort: true, cors: true },
|
|
570
563
|
appType: "spa",
|
|
571
564
|
configFile: false,
|
|
572
565
|
plugins: [vue()],
|
|
@@ -575,7 +568,7 @@ const module$1 = defineNuxtModule({
|
|
|
575
568
|
await inner.listen();
|
|
576
569
|
nuxt.hook("close", () => inner.close());
|
|
577
570
|
});
|
|
578
|
-
const base =
|
|
571
|
+
const base = clientOrigin;
|
|
579
572
|
nuxt.hook("devtools:customTabs", (tabs) => {
|
|
580
573
|
if (options.fetchDashboard) {
|
|
581
574
|
tabs.push({
|
|
@@ -619,7 +612,8 @@ const module$1 = defineNuxtModule({
|
|
|
619
612
|
}
|
|
620
613
|
});
|
|
621
614
|
nuxt.options.runtimeConfig.public.observatory = {
|
|
622
|
-
heatmapThreshold: options.heatmapThreshold ?? 5
|
|
615
|
+
heatmapThreshold: options.heatmapThreshold ?? 5,
|
|
616
|
+
clientOrigin
|
|
623
617
|
};
|
|
624
618
|
}
|
|
625
619
|
});
|
|
@@ -95,10 +95,16 @@ export function __trackComposable(name, callFn, meta) {
|
|
|
95
95
|
}
|
|
96
96
|
originalClearInterval(id2);
|
|
97
97
|
});
|
|
98
|
-
const
|
|
98
|
+
const effectsBefore = new Set(instance?.scope?.effects ?? []);
|
|
99
|
+
const mountedHooksBefore = instance?.bm?.length ?? 0;
|
|
100
|
+
const unmountedHooksBefore = instance?.um?.length ?? 0;
|
|
99
101
|
const result = callFn();
|
|
100
102
|
window.setInterval = originalSetInterval;
|
|
101
103
|
window.clearInterval = originalClearInterval;
|
|
104
|
+
const trackedWatchers = (instance?.scope?.effects ?? []).filter((effect) => !effectsBefore.has(effect)).map((effect) => ({
|
|
105
|
+
effect,
|
|
106
|
+
stop: () => effect.stop?.()
|
|
107
|
+
}));
|
|
102
108
|
const refs = {};
|
|
103
109
|
if (result && typeof result === "object") {
|
|
104
110
|
for (const [key, val] of Object.entries(result)) {
|
|
@@ -121,8 +127,8 @@ export function __trackComposable(name, callFn, meta) {
|
|
|
121
127
|
watcherCount: trackedWatchers.length,
|
|
122
128
|
intervalCount: trackedIntervals.length,
|
|
123
129
|
lifecycle: {
|
|
124
|
-
hasOnMounted:
|
|
125
|
-
hasOnUnmounted:
|
|
130
|
+
hasOnMounted: (instance?.bm?.length ?? 0) > mountedHooksBefore,
|
|
131
|
+
hasOnUnmounted: (instance?.um?.length ?? 0) > unmountedHooksBefore,
|
|
126
132
|
watchersCleaned: true,
|
|
127
133
|
intervalsCleaned: true
|
|
128
134
|
},
|
|
@@ -131,7 +137,7 @@ export function __trackComposable(name, callFn, meta) {
|
|
|
131
137
|
};
|
|
132
138
|
registry.register(entry);
|
|
133
139
|
onUnmounted(() => {
|
|
134
|
-
const leakedWatchers = trackedWatchers.filter((w) =>
|
|
140
|
+
const leakedWatchers = trackedWatchers.filter((w) => w.effect.active);
|
|
135
141
|
const leakedIntervals = trackedIntervals.filter((id2) => !clearedIntervals.has(id2));
|
|
136
142
|
const leak = leakedWatchers.length > 0 || leakedIntervals.length > 0;
|
|
137
143
|
const reasons = [];
|
|
@@ -14,6 +14,24 @@ export interface FetchEntry {
|
|
|
14
14
|
file?: string;
|
|
15
15
|
line?: number;
|
|
16
16
|
}
|
|
17
|
+
interface FetchResponse extends Response {
|
|
18
|
+
_data?: unknown;
|
|
19
|
+
}
|
|
20
|
+
interface FetchOptions {
|
|
21
|
+
server?: boolean;
|
|
22
|
+
onResponse?: (ctx: {
|
|
23
|
+
response: FetchResponse;
|
|
24
|
+
}) => void;
|
|
25
|
+
onResponseError?: (ctx: {
|
|
26
|
+
response: FetchResponse;
|
|
27
|
+
}) => void;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
interface FetchMeta {
|
|
31
|
+
key: string;
|
|
32
|
+
file: string;
|
|
33
|
+
line: number;
|
|
34
|
+
}
|
|
17
35
|
/**
|
|
18
36
|
* Sets up the fetch registry, which tracks all fetch requests and their
|
|
19
37
|
* associated metadata (e.g. duration, size, origin).
|
|
@@ -56,8 +74,6 @@ export declare function setupFetchRegistry(): {
|
|
|
56
74
|
readonly line?: number | undefined;
|
|
57
75
|
}>>>;
|
|
58
76
|
};
|
|
59
|
-
export declare function
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
line: number;
|
|
63
|
-
}): unknown;
|
|
77
|
+
export declare function __devFetchHandler(handler: (...args: unknown[]) => unknown, key: unknown, meta: FetchMeta): (...args: unknown[]) => Promise<unknown>;
|
|
78
|
+
export declare function __devFetchCall(originalFn: (url: string, opts: FetchOptions) => Promise<unknown>, url: string, opts: FetchOptions, meta: FetchMeta): Promise<unknown>;
|
|
79
|
+
export {};
|
|
@@ -14,42 +14,8 @@ export function setupFetchRegistry() {
|
|
|
14
14
|
entries.value.set(id, updated);
|
|
15
15
|
emit("fetch:update", updated);
|
|
16
16
|
}
|
|
17
|
-
function safeValue(val) {
|
|
18
|
-
if (val === void 0 || val === null) {
|
|
19
|
-
return val;
|
|
20
|
-
}
|
|
21
|
-
if (typeof val === "function") {
|
|
22
|
-
return void 0;
|
|
23
|
-
}
|
|
24
|
-
if (typeof val === "object") {
|
|
25
|
-
try {
|
|
26
|
-
return JSON.parse(JSON.stringify(val));
|
|
27
|
-
} catch {
|
|
28
|
-
return String(val);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return val;
|
|
32
|
-
}
|
|
33
|
-
function sanitize(entry) {
|
|
34
|
-
return {
|
|
35
|
-
id: entry.id,
|
|
36
|
-
key: entry.key,
|
|
37
|
-
url: entry.url,
|
|
38
|
-
status: entry.status,
|
|
39
|
-
origin: entry.origin,
|
|
40
|
-
startTime: entry.startTime,
|
|
41
|
-
endTime: entry.endTime,
|
|
42
|
-
ms: entry.ms,
|
|
43
|
-
size: entry.size,
|
|
44
|
-
cached: entry.cached,
|
|
45
|
-
payload: safeValue(entry.payload),
|
|
46
|
-
error: safeValue(entry.error),
|
|
47
|
-
file: entry.file,
|
|
48
|
-
line: entry.line
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
17
|
function getAll() {
|
|
52
|
-
return [...entries.value.values()]
|
|
18
|
+
return [...entries.value.values()];
|
|
53
19
|
}
|
|
54
20
|
function clear() {
|
|
55
21
|
entries.value.clear();
|
|
@@ -64,97 +30,103 @@ export function setupFetchRegistry() {
|
|
|
64
30
|
}
|
|
65
31
|
return { register, update, getAll, clear, entries: readonly(entries) };
|
|
66
32
|
}
|
|
67
|
-
export function
|
|
33
|
+
export function __devFetchHandler(handler, key, meta) {
|
|
68
34
|
if (!import.meta.dev || !import.meta.client) {
|
|
69
|
-
|
|
70
|
-
return (...args) => arg1(...args);
|
|
71
|
-
}
|
|
72
|
-
return originalFn(arg1, arg2);
|
|
35
|
+
return (...args) => Promise.resolve(handler(...args));
|
|
73
36
|
}
|
|
74
37
|
const registry = window.__observatory__?.fetch;
|
|
75
38
|
if (!registry) {
|
|
76
|
-
return
|
|
39
|
+
return (...args) => Promise.resolve(handler(...args));
|
|
77
40
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const id = `${meta.key}::${Date.now()}`;
|
|
82
|
-
const startTime = performance.now();
|
|
83
|
-
const origin = import.meta.server ? "ssr" : "csr";
|
|
84
|
-
registry.register({
|
|
85
|
-
id,
|
|
86
|
-
key: meta.key,
|
|
87
|
-
url: meta.key,
|
|
88
|
-
// No URL in useAsyncData, use key as identifier
|
|
89
|
-
status: "pending",
|
|
90
|
-
origin,
|
|
91
|
-
startTime,
|
|
92
|
-
cached: false,
|
|
93
|
-
file: meta.file,
|
|
94
|
-
line: meta.line
|
|
95
|
-
});
|
|
96
|
-
return Promise.resolve(handler(...handlerArgs)).then((result) => {
|
|
97
|
-
registry.update(id, {
|
|
98
|
-
status: "ok",
|
|
99
|
-
endTime: performance.now(),
|
|
100
|
-
ms: Math.round(performance.now() - startTime),
|
|
101
|
-
payload: result
|
|
102
|
-
});
|
|
103
|
-
return result;
|
|
104
|
-
}).catch((error) => {
|
|
105
|
-
registry.update(id, {
|
|
106
|
-
status: "error",
|
|
107
|
-
endTime: performance.now(),
|
|
108
|
-
ms: Math.round(performance.now() - startTime),
|
|
109
|
-
error
|
|
110
|
-
});
|
|
111
|
-
throw error;
|
|
112
|
-
});
|
|
113
|
-
};
|
|
114
|
-
} else {
|
|
115
|
-
const url = arg1;
|
|
116
|
-
const opts = arg2 || {};
|
|
117
|
-
const id = `${meta.key}::${Date.now()}`;
|
|
41
|
+
const normalizedKey = typeof key === "string" ? key : "useAsyncData";
|
|
42
|
+
return (...args) => {
|
|
43
|
+
const id = `${normalizedKey}::${Date.now()}`;
|
|
118
44
|
const startTime = performance.now();
|
|
119
|
-
const origin = import.meta.server ? "ssr" : "csr";
|
|
120
45
|
registry.register({
|
|
121
46
|
id,
|
|
122
|
-
key:
|
|
123
|
-
url:
|
|
47
|
+
key: normalizedKey,
|
|
48
|
+
url: normalizedKey,
|
|
124
49
|
status: "pending",
|
|
125
|
-
origin,
|
|
50
|
+
origin: "csr",
|
|
126
51
|
startTime,
|
|
127
52
|
cached: false,
|
|
128
53
|
file: meta.file,
|
|
129
54
|
line: meta.line
|
|
130
55
|
});
|
|
131
|
-
return
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
},
|
|
148
|
-
onResponseError({ response }) {
|
|
149
|
-
registry.update(id, {
|
|
150
|
-
status: "error",
|
|
151
|
-
endTime: performance.now(),
|
|
152
|
-
ms: Math.round(performance.now() - startTime)
|
|
153
|
-
});
|
|
154
|
-
if (typeof opts.onResponseError === "function") {
|
|
155
|
-
opts.onResponseError({ response });
|
|
156
|
-
}
|
|
157
|
-
}
|
|
56
|
+
return Promise.resolve(handler(...args)).then((result) => {
|
|
57
|
+
registry.update(id, {
|
|
58
|
+
status: "ok",
|
|
59
|
+
endTime: performance.now(),
|
|
60
|
+
ms: Math.round(performance.now() - startTime),
|
|
61
|
+
payload: result
|
|
62
|
+
});
|
|
63
|
+
return result;
|
|
64
|
+
}).catch((error) => {
|
|
65
|
+
registry.update(id, {
|
|
66
|
+
status: "error",
|
|
67
|
+
endTime: performance.now(),
|
|
68
|
+
ms: Math.round(performance.now() - startTime),
|
|
69
|
+
error
|
|
70
|
+
});
|
|
71
|
+
throw error;
|
|
158
72
|
});
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export function __devFetchCall(originalFn, url, opts, meta) {
|
|
76
|
+
if (!import.meta.dev || !import.meta.client) {
|
|
77
|
+
return originalFn(url, opts);
|
|
78
|
+
}
|
|
79
|
+
const registry = window.__observatory__?.fetch;
|
|
80
|
+
if (!registry) {
|
|
81
|
+
return originalFn(url, opts);
|
|
82
|
+
}
|
|
83
|
+
const id = `${meta.key}::${Date.now()}`;
|
|
84
|
+
const startTime = performance.now();
|
|
85
|
+
const payload = window.__NUXT__?.data ?? {};
|
|
86
|
+
const fromPayload = Object.prototype.hasOwnProperty.call(payload, meta.key);
|
|
87
|
+
const origin = fromPayload ? "ssr" : "csr";
|
|
88
|
+
registry.register({
|
|
89
|
+
id,
|
|
90
|
+
key: meta.key,
|
|
91
|
+
url: typeof url === "string" ? url : String(url),
|
|
92
|
+
status: fromPayload ? "cached" : "pending",
|
|
93
|
+
origin,
|
|
94
|
+
startTime,
|
|
95
|
+
cached: fromPayload,
|
|
96
|
+
payload: fromPayload ? payload[meta.key] : void 0,
|
|
97
|
+
file: meta.file,
|
|
98
|
+
line: meta.line
|
|
99
|
+
});
|
|
100
|
+
if (fromPayload) {
|
|
101
|
+
return originalFn(url, opts);
|
|
159
102
|
}
|
|
103
|
+
return originalFn(url, {
|
|
104
|
+
...opts,
|
|
105
|
+
onResponse({ response }) {
|
|
106
|
+
const ms = Math.round(performance.now() - startTime);
|
|
107
|
+
const size = Number(response.headers?.get("content-length")) || void 0;
|
|
108
|
+
const cached = response.headers?.get("x-nuxt-cache") === "HIT";
|
|
109
|
+
registry.update(id, {
|
|
110
|
+
status: cached ? "cached" : response.ok ? "ok" : "error",
|
|
111
|
+
endTime: performance.now(),
|
|
112
|
+
ms,
|
|
113
|
+
size,
|
|
114
|
+
cached,
|
|
115
|
+
payload: response._data
|
|
116
|
+
});
|
|
117
|
+
if (typeof opts.onResponse === "function") {
|
|
118
|
+
opts.onResponse({ response });
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
onResponseError({ response }) {
|
|
122
|
+
registry.update(id, {
|
|
123
|
+
status: "error",
|
|
124
|
+
endTime: performance.now(),
|
|
125
|
+
ms: Math.round(performance.now() - startTime)
|
|
126
|
+
});
|
|
127
|
+
if (typeof opts.onResponseError === "function") {
|
|
128
|
+
opts.onResponseError({ response });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
});
|
|
160
132
|
}
|
|
@@ -3,6 +3,8 @@ export interface ProvideEntry {
|
|
|
3
3
|
componentName: string;
|
|
4
4
|
componentFile: string;
|
|
5
5
|
componentUid: number;
|
|
6
|
+
parentUid?: number;
|
|
7
|
+
parentFile?: string;
|
|
6
8
|
isReactive: boolean;
|
|
7
9
|
valueSnapshot: unknown;
|
|
8
10
|
line: number;
|
|
@@ -12,6 +14,8 @@ export interface InjectEntry {
|
|
|
12
14
|
componentName: string;
|
|
13
15
|
componentFile: string;
|
|
14
16
|
componentUid: number;
|
|
17
|
+
parentUid?: number;
|
|
18
|
+
parentFile?: string;
|
|
15
19
|
resolved: boolean;
|
|
16
20
|
resolvedFromFile?: string;
|
|
17
21
|
resolvedFromUid?: number;
|
|
@@ -79,6 +79,8 @@ export function __devProvide(key, value, meta) {
|
|
|
79
79
|
componentName: instance?.type?.__name ?? "unknown",
|
|
80
80
|
componentFile: meta.file,
|
|
81
81
|
componentUid: instance?.uid ?? -1,
|
|
82
|
+
parentUid: instance?.parent?.uid,
|
|
83
|
+
parentFile: instance?.parent?.type?.__file,
|
|
82
84
|
isReactive: isRef(value) || isReactive(value),
|
|
83
85
|
valueSnapshot: safeSnapshot(unref(value)),
|
|
84
86
|
line: meta.line
|
|
@@ -100,6 +102,8 @@ export function __devInject(key, defaultValue, meta) {
|
|
|
100
102
|
componentName: instance?.type?.__name ?? "unknown",
|
|
101
103
|
componentFile: meta.file,
|
|
102
104
|
componentUid: instance?.uid ?? -1,
|
|
105
|
+
parentUid: instance?.parent?.uid,
|
|
106
|
+
parentFile: instance?.parent?.type?.__file,
|
|
103
107
|
resolved: resolved !== void 0,
|
|
104
108
|
resolvedFromFile: providerInfo?.file,
|
|
105
109
|
resolvedFromUid: providerInfo?.uid,
|
|
@@ -25,12 +25,11 @@ export interface RenderEntry {
|
|
|
25
25
|
* Sets up a render registry for the given Nuxt app.
|
|
26
26
|
* @param {{ vueApp: import('vue').App }} nuxtApp - The Nuxt app object.
|
|
27
27
|
* @param {object} nuxtApp.vueApp - The Vue app instance.
|
|
28
|
-
* @param {number} threshold - The minimum number of renders required for a component to be tracked.
|
|
29
28
|
* @returns {object} The render registry object.
|
|
30
29
|
*/
|
|
31
30
|
export declare function setupRenderRegistry(nuxtApp: {
|
|
32
31
|
vueApp: import('vue').App;
|
|
33
|
-
}
|
|
32
|
+
}): {
|
|
34
33
|
getAll: () => RenderEntry[];
|
|
35
34
|
snapshot: () => RenderEntry[];
|
|
36
35
|
};
|