@svelte-vitals/vite 0.9.2 → 0.11.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/dist/{chunk-LIC7DE52.js → chunk-4LXPHVAW.js} +21 -1
- package/dist/hooks/index.js +2 -9
- package/dist/index.js +55 -10
- package/package.json +10 -10
|
@@ -108,6 +108,26 @@ function parseHtmlHead(html) {
|
|
|
108
108
|
return { tags, htmlLang, headings, images };
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
// src/loopback.ts
|
|
112
|
+
function isLoopbackOrigin(origin) {
|
|
113
|
+
try {
|
|
114
|
+
const host = new URL(origin).hostname;
|
|
115
|
+
return host === "localhost" || host === "127.0.0.1" || host === "[::1]";
|
|
116
|
+
} catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function isLoopbackHost(host) {
|
|
121
|
+
if (host === void 0) return false;
|
|
122
|
+
try {
|
|
123
|
+
return isLoopbackOrigin(`http://${host}`);
|
|
124
|
+
} catch {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
111
129
|
export {
|
|
112
|
-
parseHtmlHead
|
|
130
|
+
parseHtmlHead,
|
|
131
|
+
isLoopbackOrigin,
|
|
132
|
+
isLoopbackHost
|
|
113
133
|
};
|
package/dist/hooks/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
isLoopbackOrigin,
|
|
2
3
|
parseHtmlHead
|
|
3
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-4LXPHVAW.js";
|
|
4
5
|
|
|
5
6
|
// src/hooks/handle.ts
|
|
6
7
|
import { DEV } from "esm-env";
|
|
@@ -35,14 +36,6 @@ function findingSignature(results, config) {
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
// src/hooks/handle.ts
|
|
38
|
-
function isLoopbackOrigin(origin) {
|
|
39
|
-
try {
|
|
40
|
-
const host = new URL(origin).hostname;
|
|
41
|
-
return host === "localhost" || host === "127.0.0.1" || host === "[::1]" || host === "::1";
|
|
42
|
-
} catch {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
39
|
async function postIngest(origin, route, results) {
|
|
47
40
|
if (!isLoopbackOrigin(origin)) {
|
|
48
41
|
if (globalThis.process?.env?.SVELTE_VITALS_DEBUG) {
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
isLoopbackHost,
|
|
3
|
+
isLoopbackOrigin,
|
|
2
4
|
parseHtmlHead
|
|
3
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-4LXPHVAW.js";
|
|
4
6
|
|
|
5
7
|
// src/plugin.ts
|
|
6
8
|
import { existsSync } from "fs";
|
|
7
9
|
import { writeFile, mkdir } from "fs/promises";
|
|
8
|
-
import { join as
|
|
10
|
+
import { join as join4, isAbsolute, dirname } from "path";
|
|
9
11
|
import { defineConfig as defineConfig2 } from "@svelte-vitals/core";
|
|
10
12
|
|
|
11
13
|
// src/analyze.ts
|
|
@@ -97,6 +99,28 @@ async function collectRenderedProject(cwd, htmlLang) {
|
|
|
97
99
|
};
|
|
98
100
|
}
|
|
99
101
|
|
|
102
|
+
// src/providers/source/components.ts
|
|
103
|
+
import { readFile as readFile3, access as access2 } from "fs/promises";
|
|
104
|
+
import { join as join3 } from "path";
|
|
105
|
+
import { glob as glob2 } from "tinyglobby";
|
|
106
|
+
import { collectComponentFacts as collect } from "@svelte-vitals/core";
|
|
107
|
+
var nodeRuntime = {
|
|
108
|
+
readFile: (path) => readFile3(path, "utf8"),
|
|
109
|
+
async exists(path) {
|
|
110
|
+
try {
|
|
111
|
+
await access2(path);
|
|
112
|
+
return true;
|
|
113
|
+
} catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
glob: (pattern, cwd) => glob2(pattern, { cwd, dot: false }),
|
|
118
|
+
join: (...parts) => join3(...parts)
|
|
119
|
+
};
|
|
120
|
+
function collectComponentFacts(root) {
|
|
121
|
+
return collect(nodeRuntime, root);
|
|
122
|
+
}
|
|
123
|
+
|
|
100
124
|
// src/version.ts
|
|
101
125
|
import { readFileSync } from "fs";
|
|
102
126
|
function readPackageVersion() {
|
|
@@ -118,14 +142,16 @@ async function analyze(prerenderPagesDir, cwd, options) {
|
|
|
118
142
|
});
|
|
119
143
|
const { heads, headings, images, htmlLang } = await collectRenderedHeads(prerenderPagesDir);
|
|
120
144
|
const project = await collectRenderedProject(cwd, htmlLang);
|
|
145
|
+
const components = await collectComponentFacts(cwd);
|
|
121
146
|
const results = applyRuleSeverities(
|
|
122
|
-
await runRules(selectRules(allRules, config), { heads, headings, images, project, config }),
|
|
147
|
+
await runRules(selectRules(allRules, config), { heads, headings, images, project, components, config }),
|
|
123
148
|
config
|
|
124
149
|
);
|
|
125
150
|
const { score } = computeScore(results, config);
|
|
126
151
|
const summary = summarize(results, config);
|
|
127
152
|
const failed = hasFailureAtOrAbove(summary, config.failOn);
|
|
128
|
-
const coverageNote = `Analyzed ${heads.length} prerendered route(s). SSR/dynamic routes are not covered \u2014 run \`npx svelte-vitals\` for those
|
|
153
|
+
const coverageNote = `Analyzed ${heads.length} prerendered route(s). SSR/dynamic routes are not covered \u2014 run \`npx svelte-vitals\` for those.
|
|
154
|
+
Scanned ${components.length} component(s) under src/ for Correctness/Security/Architecture/Bundle findings.`;
|
|
129
155
|
const consoleReport = formatConsoleReport(results, config, { mode: "rendered / plugin" }) + "\n" + coverageNote + "\n";
|
|
130
156
|
const jsonReport = formatJsonReport(results, config, { version: readPackageVersion() });
|
|
131
157
|
return {
|
|
@@ -186,11 +212,16 @@ function renderDashboard(results, config, meta) {
|
|
|
186
212
|
|
|
187
213
|
// src/ui/middleware.ts
|
|
188
214
|
var SEVERITIES = /* @__PURE__ */ new Set(["critical", "warning", "info"]);
|
|
215
|
+
var CATEGORIES = /* @__PURE__ */ new Set(["seo", "performance", "correctness", "security", "architecture"]);
|
|
216
|
+
function isOptionalString(v) {
|
|
217
|
+
return v === void 0 || typeof v === "string";
|
|
218
|
+
}
|
|
189
219
|
function isResultLike(x) {
|
|
190
220
|
if (typeof x !== "object" || x === null) return false;
|
|
191
221
|
const r = x;
|
|
192
222
|
const d = r.detection;
|
|
193
|
-
|
|
223
|
+
const f = r.fix;
|
|
224
|
+
return typeof r.id === "string" && typeof r.message === "string" && typeof r.severity === "string" && SEVERITIES.has(r.severity) && typeof d === "object" && d !== null && typeof d.presence === "string" && typeof d.value === "string" && (r.category === void 0 || typeof r.category === "string" && CATEGORIES.has(r.category)) && isOptionalString(r.location) && isOptionalString(r.recommendation) && isOptionalString(r.docsUrl) && (f === void 0 || typeof f === "object" && f !== null && typeof f.description === "string" && isOptionalString(f.snippet) && isOptionalString(f.lang)) && (r.line === void 0 || typeof r.line === "number") && isOptionalString(r.route);
|
|
194
225
|
}
|
|
195
226
|
function installUiMiddleware(server, config, version) {
|
|
196
227
|
const store = createStore();
|
|
@@ -210,6 +241,14 @@ function installUiMiddleware(server, config, version) {
|
|
|
210
241
|
});
|
|
211
242
|
server.middlewares.use("/__svelte-vitals", (req, res) => {
|
|
212
243
|
const url = req.url ?? "/";
|
|
244
|
+
const origin = req.headers.origin;
|
|
245
|
+
const host = req.headers.host;
|
|
246
|
+
if (typeof origin === "string" && !isLoopbackOrigin(origin) || !isLoopbackHost(host)) {
|
|
247
|
+
req.resume();
|
|
248
|
+
res.statusCode = 403;
|
|
249
|
+
res.end("svelte-vitals dev UI is only available from localhost");
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
213
252
|
if (req.method === "POST" && url.startsWith("/ingest")) {
|
|
214
253
|
const chunks = [];
|
|
215
254
|
req.on("data", (c) => chunks.push(c));
|
|
@@ -237,8 +276,14 @@ function installUiMiddleware(server, config, version) {
|
|
|
237
276
|
req.on("close", () => clients.delete(res));
|
|
238
277
|
return;
|
|
239
278
|
}
|
|
240
|
-
|
|
241
|
-
|
|
279
|
+
try {
|
|
280
|
+
const html = renderDashboard(store.snapshot(), config, { version });
|
|
281
|
+
res.setHeader("Content-Type", "text/html");
|
|
282
|
+
res.end(html);
|
|
283
|
+
} catch {
|
|
284
|
+
res.statusCode = 500;
|
|
285
|
+
res.end("svelte-vitals dashboard failed to render");
|
|
286
|
+
}
|
|
242
287
|
});
|
|
243
288
|
}
|
|
244
289
|
|
|
@@ -254,8 +299,8 @@ function svelteVitals(options = {}) {
|
|
|
254
299
|
if (!options.cwd) root = config.root;
|
|
255
300
|
},
|
|
256
301
|
async closeBundle() {
|
|
257
|
-
const pagesDir = options.prerenderDir ? options.prerenderDir :
|
|
258
|
-
const resolved = isAbsolute(pagesDir) ? pagesDir :
|
|
302
|
+
const pagesDir = options.prerenderDir ? options.prerenderDir : join4(root, DEFAULT_PRERENDER_DIR);
|
|
303
|
+
const resolved = isAbsolute(pagesDir) ? pagesDir : join4(root, pagesDir);
|
|
259
304
|
if (!existsSync(resolved)) return;
|
|
260
305
|
let result;
|
|
261
306
|
try {
|
|
@@ -270,7 +315,7 @@ function svelteVitals(options = {}) {
|
|
|
270
315
|
console.log(out);
|
|
271
316
|
}
|
|
272
317
|
if (options.outFile) {
|
|
273
|
-
const outPath = isAbsolute(options.outFile) ? options.outFile :
|
|
318
|
+
const outPath = isAbsolute(options.outFile) ? options.outFile : join4(root, options.outFile);
|
|
274
319
|
await mkdir(dirname(outPath), { recursive: true });
|
|
275
320
|
await writeFile(outPath, result.jsonReport);
|
|
276
321
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svelte-vitals/vite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Vite/SvelteKit plugin for svelte-vitals — analyzes prerendered HTML during vite build.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"homepage": "https://github.com/oekazuma/svelte-vitals#readme",
|
|
24
24
|
"engines": {
|
|
25
|
-
"node": ">=
|
|
25
|
+
"node": ">=22.13.0"
|
|
26
26
|
},
|
|
27
27
|
"sideEffects": false,
|
|
28
28
|
"exports": {
|
|
@@ -40,13 +40,13 @@
|
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"esm-env": "^1.2.2",
|
|
43
|
-
"node-html-parser": "^
|
|
43
|
+
"node-html-parser": "^8.0.4",
|
|
44
44
|
"tinyglobby": "^0.2.17",
|
|
45
|
-
"@svelte-vitals/core": "0.
|
|
45
|
+
"@svelte-vitals/core": "0.20.0"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"@sveltejs/kit": "^2.
|
|
49
|
-
"vite": "^8.1.
|
|
48
|
+
"@sveltejs/kit": "^2.69.1",
|
|
49
|
+
"vite": "^8.1.3"
|
|
50
50
|
},
|
|
51
51
|
"peerDependenciesMeta": {
|
|
52
52
|
"@sveltejs/kit": {
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@sveltejs/kit": "^2.
|
|
58
|
-
"@types/node": "^24.
|
|
59
|
-
"svelte": "^5.56.
|
|
60
|
-
"vite": "^8.1.
|
|
57
|
+
"@sveltejs/kit": "^2.69.1",
|
|
58
|
+
"@types/node": "^24.13.2",
|
|
59
|
+
"svelte": "^5.56.4",
|
|
60
|
+
"vite": "^8.1.3"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "tsup",
|