svelte-vitals 0.20.0 → 0.22.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/bin.js +30 -49
- package/dist/{chunk-AAM2A7D7.js → chunk-KSJZLF5U.js} +59 -37
- package/dist/index.d.ts +16 -1
- package/dist/index.js +3 -1
- package/package.json +5 -5
package/dist/bin.js
CHANGED
|
@@ -4,9 +4,10 @@ import {
|
|
|
4
4
|
findUnknownRuleIds,
|
|
5
5
|
isReporterName,
|
|
6
6
|
knownRuleIds,
|
|
7
|
+
readCoreVersion,
|
|
7
8
|
readPackageVersion,
|
|
8
9
|
run
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-KSJZLF5U.js";
|
|
10
11
|
|
|
11
12
|
// src/bin.ts
|
|
12
13
|
import mri3 from "mri";
|
|
@@ -496,6 +497,15 @@ function installCommand(pm) {
|
|
|
496
497
|
const action = pm === "npm" ? "install" : "add";
|
|
497
498
|
return { command: pm, args: [action, "-D", "@svelte-vitals/vite"] };
|
|
498
499
|
}
|
|
500
|
+
function readInstalledViteVersion(io) {
|
|
501
|
+
const raw = io.readFile(join2(io.cwd, "node_modules/@svelte-vitals/vite/package.json"));
|
|
502
|
+
if (raw === void 0) return void 0;
|
|
503
|
+
try {
|
|
504
|
+
return JSON.parse(raw).version;
|
|
505
|
+
} catch {
|
|
506
|
+
return void 0;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
499
509
|
|
|
500
510
|
// src/install/index.ts
|
|
501
511
|
function planForClient(client, scope, io, force) {
|
|
@@ -669,6 +679,11 @@ ${indent(r.snippet ?? "")}`);
|
|
|
669
679
|
io.errorLog(
|
|
670
680
|
`svelte-vitals: failed to install @svelte-vitals/vite (${command} ${args.join(" ")} exited ${code}). Install it manually.`
|
|
671
681
|
);
|
|
682
|
+
} else {
|
|
683
|
+
const installedVersion = readInstalledViteVersion(io);
|
|
684
|
+
io.log(
|
|
685
|
+
installedVersion ? `svelte-vitals: installed @svelte-vitals/vite@${installedVersion} \u2014 compare against \`svelte-vitals --version\`'s core number if findings ever seem out of sync.` : "svelte-vitals: installed @svelte-vitals/vite (could not read the installed version from node_modules)."
|
|
686
|
+
);
|
|
672
687
|
}
|
|
673
688
|
}
|
|
674
689
|
if (hadFailure) return 2;
|
|
@@ -834,9 +849,9 @@ function planWorkflowWrite(existing, force) {
|
|
|
834
849
|
return { status: "updated" };
|
|
835
850
|
}
|
|
836
851
|
function buildWorkflowYaml(opts) {
|
|
837
|
-
const
|
|
852
|
+
const { actionSha, actionVersion } = opts;
|
|
838
853
|
return [
|
|
839
|
-
|
|
854
|
+
"# Generated by `svelte-vitals ci install`.",
|
|
840
855
|
"# Re-run with --force to regenerate.",
|
|
841
856
|
"name: svelte-vitals",
|
|
842
857
|
"",
|
|
@@ -854,60 +869,27 @@ function buildWorkflowYaml(opts) {
|
|
|
854
869
|
" - uses: actions/checkout@v4",
|
|
855
870
|
" with:",
|
|
856
871
|
" fetch-depth: 0",
|
|
857
|
-
|
|
872
|
+
` - uses: oekazuma/svelte-vitals/packages/action@${actionSha} # @svelte-vitals/action@${actionVersion}`,
|
|
858
873
|
" with:",
|
|
859
|
-
"
|
|
860
|
-
"
|
|
861
|
-
" id: scan",
|
|
862
|
-
" continue-on-error: true",
|
|
863
|
-
" run: >",
|
|
864
|
-
` npx -y svelte-vitals@${v} .`,
|
|
865
|
-
" --diff origin/${{ github.base_ref }}",
|
|
866
|
-
" --baseline origin/${{ github.base_ref }}",
|
|
867
|
-
" --reporter github",
|
|
868
|
-
" - name: Markdown summary",
|
|
869
|
-
" run: >",
|
|
870
|
-
` npx -y svelte-vitals@${v} .`,
|
|
871
|
-
" --diff origin/${{ github.base_ref }}",
|
|
872
|
-
" --baseline origin/${{ github.base_ref }}",
|
|
873
|
-
" --reporter md > svelte-vitals-report.md || true",
|
|
874
|
-
" - name: Job summary",
|
|
875
|
-
' run: cat svelte-vitals-report.md >> "$GITHUB_STEP_SUMMARY"',
|
|
876
|
-
" - name: PR comment (sticky)",
|
|
877
|
-
" if: github.event.pull_request.head.repo.full_name == github.repository",
|
|
878
|
-
" continue-on-error: true",
|
|
879
|
-
" uses: actions/github-script@v7",
|
|
880
|
-
" with:",
|
|
881
|
-
" script: |",
|
|
882
|
-
" const fs = require('fs');",
|
|
883
|
-
" const marker = '<!-- svelte-vitals-report -->';",
|
|
884
|
-
" const body = marker + '\\n' + fs.readFileSync('svelte-vitals-report.md', 'utf8');",
|
|
885
|
-
" const { data: comments } = await github.rest.issues.listComments({",
|
|
886
|
-
" ...context.repo, issue_number: context.issue.number, per_page: 100",
|
|
887
|
-
" });",
|
|
888
|
-
" const mine = comments.find(c => c.body && c.body.startsWith(marker));",
|
|
889
|
-
" if (mine) {",
|
|
890
|
-
" await github.rest.issues.updateComment({ ...context.repo, comment_id: mine.id, body });",
|
|
891
|
-
" } else {",
|
|
892
|
-
" await github.rest.issues.createComment({ ...context.repo, issue_number: context.issue.number, body });",
|
|
893
|
-
" }",
|
|
894
|
-
" - name: Gate",
|
|
895
|
-
" if: steps.scan.outcome == 'failure'",
|
|
896
|
-
" run: |",
|
|
897
|
-
' echo "svelte-vitals found blocking issues (see annotations above)."',
|
|
898
|
-
" exit 1",
|
|
874
|
+
" diff: origin/${{ github.base_ref }}",
|
|
875
|
+
" baseline: origin/${{ github.base_ref }}",
|
|
899
876
|
""
|
|
900
877
|
].join("\n");
|
|
901
878
|
}
|
|
902
879
|
|
|
880
|
+
// src/ci/action-pin.generated.ts
|
|
881
|
+
var ACTION_SHA = "86e84073bddea99530d2d6831378a68836443ee4";
|
|
882
|
+
var ACTION_VERSION = "0.2.0";
|
|
883
|
+
|
|
903
884
|
// src/ci/cli.ts
|
|
904
885
|
var CI_HELP = `svelte-vitals ci \u2014 scaffold CI integration
|
|
905
886
|
|
|
906
887
|
Usage:
|
|
907
888
|
svelte-vitals ci install [options]
|
|
908
889
|
|
|
909
|
-
Adds a GitHub Actions workflow (${WORKFLOW_PATH}) that
|
|
910
|
-
annotations
|
|
890
|
+
Adds a GitHub Actions workflow (${WORKFLOW_PATH}) that calls the \`@svelte-vitals/action\`
|
|
891
|
+
GitHub Action on pull requests: inline annotations, a job summary, and a sticky PR
|
|
892
|
+
comment with the findings.
|
|
911
893
|
|
|
912
894
|
Options:
|
|
913
895
|
--force Overwrite an existing workflow file
|
|
@@ -943,9 +925,8 @@ async function runCiCli(args, io = realIO()) {
|
|
|
943
925
|
if (plan.status === "exists") {
|
|
944
926
|
io.log(`= already installed (${WORKFLOW_PATH}) \u2014 use --force to regenerate.`);
|
|
945
927
|
} else {
|
|
946
|
-
const version = readPackageVersion();
|
|
947
928
|
try {
|
|
948
|
-
io.writeFile(path, buildWorkflowYaml({
|
|
929
|
+
io.writeFile(path, buildWorkflowYaml({ actionSha: ACTION_SHA, actionVersion: ACTION_VERSION }));
|
|
949
930
|
io.log(`\u2713 ${plan.status} ${WORKFLOW_PATH}`);
|
|
950
931
|
} catch (err) {
|
|
951
932
|
io.errorLog(
|
|
@@ -1038,7 +1019,7 @@ async function main() {
|
|
|
1038
1019
|
process.exit(0);
|
|
1039
1020
|
}
|
|
1040
1021
|
if (argv.version) {
|
|
1041
|
-
console.log(VERSION);
|
|
1022
|
+
console.log(`${VERSION} (core ${readCoreVersion()})`);
|
|
1042
1023
|
process.exit(0);
|
|
1043
1024
|
}
|
|
1044
1025
|
const { options, warnings, errors } = resolveArgs(argv);
|
|
@@ -678,6 +678,15 @@ function readPackageVersion() {
|
|
|
678
678
|
return "0.0.0";
|
|
679
679
|
}
|
|
680
680
|
}
|
|
681
|
+
function readCoreVersion() {
|
|
682
|
+
try {
|
|
683
|
+
const entry = import.meta.resolve("@svelte-vitals/core");
|
|
684
|
+
const pkg = JSON.parse(readFileSync(new URL("../package.json", entry), "utf8"));
|
|
685
|
+
return pkg.version ?? "0.0.0";
|
|
686
|
+
} catch {
|
|
687
|
+
return "0.0.0";
|
|
688
|
+
}
|
|
689
|
+
}
|
|
681
690
|
|
|
682
691
|
// src/reporter-resolve.ts
|
|
683
692
|
var AGENT_ENV_VARS = ["CLAUDECODE", "SVELTE_VITALS_AGENT"];
|
|
@@ -985,6 +994,38 @@ async function analyzeProject(opts = {}) {
|
|
|
985
994
|
);
|
|
986
995
|
return { results, config, version: readPackageVersion(), warnings };
|
|
987
996
|
}
|
|
997
|
+
async function applyScope(results, opts) {
|
|
998
|
+
const errorLog = opts.errorLog ?? ((line) => console.error(line));
|
|
999
|
+
let scoped = results;
|
|
1000
|
+
if (opts.staged || opts.diffBase !== void 0) {
|
|
1001
|
+
const changed = opts.staged ? getChangedFiles(opts.cwd, { staged: true }) : getChangedFiles(opts.cwd, { base: opts.diffBase });
|
|
1002
|
+
if (changed === void 0) {
|
|
1003
|
+
errorLog(
|
|
1004
|
+
"svelte-vitals: could not determine changed files (not a git repo, git unavailable, or bad ref); analyzing all."
|
|
1005
|
+
);
|
|
1006
|
+
} else {
|
|
1007
|
+
scoped = filterToChangedFiles(scoped, changed);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
if (opts.baseline !== void 0) {
|
|
1011
|
+
const checkout = checkoutBaseline(opts.cwd, opts.baseline);
|
|
1012
|
+
if (checkout === void 0) {
|
|
1013
|
+
errorLog(
|
|
1014
|
+
`svelte-vitals: could not analyze baseline '${opts.baseline}' (not a git repo, git unavailable, or bad ref); reporting all findings.`
|
|
1015
|
+
);
|
|
1016
|
+
} else {
|
|
1017
|
+
try {
|
|
1018
|
+
const base = await analyzeProject({ ...opts.analyzeOpts, cwd: checkout.analyzeCwd });
|
|
1019
|
+
scoped = filterToNewFindings(scoped, base.results);
|
|
1020
|
+
} catch {
|
|
1021
|
+
errorLog(`svelte-vitals: baseline analysis of '${opts.baseline}' failed; reporting all findings.`);
|
|
1022
|
+
} finally {
|
|
1023
|
+
checkout.cleanup();
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
return scoped;
|
|
1028
|
+
}
|
|
988
1029
|
async function run(opts = {}) {
|
|
989
1030
|
const log = opts.log ?? ((line) => console.log(line));
|
|
990
1031
|
const errorLog = opts.errorLog ?? ((line) => console.error(line));
|
|
@@ -1077,43 +1118,22 @@ async function run(opts = {}) {
|
|
|
1077
1118
|
for (const w of analysis.warnings) errorLog(`svelte-vitals: ${w}`);
|
|
1078
1119
|
try {
|
|
1079
1120
|
const { config, version } = analysis;
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
errorLog(
|
|
1095
|
-
`svelte-vitals: could not analyze baseline '${opts.baseline}' (not a git repo, git unavailable, or bad ref); reporting all findings.`
|
|
1096
|
-
);
|
|
1097
|
-
} else {
|
|
1098
|
-
try {
|
|
1099
|
-
const base = await analyzeProject({
|
|
1100
|
-
cwd: checkout.analyzeCwd,
|
|
1101
|
-
metaComponents: opts.metaComponents,
|
|
1102
|
-
treatDynamicAs: opts.treatDynamicAs,
|
|
1103
|
-
route: opts.route,
|
|
1104
|
-
failOn: opts.failOn,
|
|
1105
|
-
rules: opts.rules,
|
|
1106
|
-
weights: opts.weights,
|
|
1107
|
-
categories: opts.categories
|
|
1108
|
-
});
|
|
1109
|
-
results = filterToNewFindings(results, base.results);
|
|
1110
|
-
} catch {
|
|
1111
|
-
errorLog(`svelte-vitals: baseline analysis of '${opts.baseline}' failed; reporting all findings.`);
|
|
1112
|
-
} finally {
|
|
1113
|
-
checkout.cleanup();
|
|
1114
|
-
}
|
|
1121
|
+
const results = await applyScope(analysis.results, {
|
|
1122
|
+
cwd,
|
|
1123
|
+
staged: opts.staged,
|
|
1124
|
+
diffBase: opts.diffBase,
|
|
1125
|
+
baseline: opts.baseline,
|
|
1126
|
+
errorLog,
|
|
1127
|
+
analyzeOpts: {
|
|
1128
|
+
metaComponents: opts.metaComponents,
|
|
1129
|
+
treatDynamicAs: opts.treatDynamicAs,
|
|
1130
|
+
route: opts.route,
|
|
1131
|
+
failOn: opts.failOn,
|
|
1132
|
+
rules: opts.rules,
|
|
1133
|
+
weights: opts.weights,
|
|
1134
|
+
categories: opts.categories
|
|
1115
1135
|
}
|
|
1116
|
-
}
|
|
1136
|
+
});
|
|
1117
1137
|
if (opts.score) {
|
|
1118
1138
|
log(String(computeHealth(results, config).health));
|
|
1119
1139
|
} else {
|
|
@@ -1137,7 +1157,7 @@ async function run(opts = {}) {
|
|
|
1137
1157
|
const output = formatGithubReport(results, config);
|
|
1138
1158
|
if (output) log(output);
|
|
1139
1159
|
} else if (reporter === "html") {
|
|
1140
|
-
const html = formatHtmlReport(results, config, { version });
|
|
1160
|
+
const html = formatHtmlReport(results, config, { version, coreVersion: readCoreVersion() });
|
|
1141
1161
|
if (opts.outFile === "-") {
|
|
1142
1162
|
log(html);
|
|
1143
1163
|
} else {
|
|
@@ -1174,6 +1194,7 @@ async function run(opts = {}) {
|
|
|
1174
1194
|
export {
|
|
1175
1195
|
ProjectError,
|
|
1176
1196
|
readPackageVersion,
|
|
1197
|
+
readCoreVersion,
|
|
1177
1198
|
isReporterName,
|
|
1178
1199
|
findUnknownRuleIds,
|
|
1179
1200
|
knownRuleIds,
|
|
@@ -1182,6 +1203,7 @@ export {
|
|
|
1182
1203
|
spinnerEnabled,
|
|
1183
1204
|
routeMatcher,
|
|
1184
1205
|
analyzeProject,
|
|
1206
|
+
applyScope,
|
|
1185
1207
|
run,
|
|
1186
1208
|
defineConfig2 as defineConfig
|
|
1187
1209
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -137,10 +137,25 @@ interface AnalyzeResult {
|
|
|
137
137
|
* 2026-07-05-config-file-design.md §3).
|
|
138
138
|
*/
|
|
139
139
|
declare function analyzeProject(opts?: AnalyzeOptions): Promise<AnalyzeResult>;
|
|
140
|
+
interface ApplyScopeOptions {
|
|
141
|
+
cwd: string;
|
|
142
|
+
staged?: boolean;
|
|
143
|
+
diffBase?: string;
|
|
144
|
+
baseline?: string;
|
|
145
|
+
errorLog?: (line: string) => void;
|
|
146
|
+
analyzeOpts?: AnalyzeOptions;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Narrow `results` to what a PR gate cares about: `--staged`/`--diff` restrict to
|
|
150
|
+
* changed files, `--baseline` drops findings that already existed at that ref. Shared
|
|
151
|
+
* by `run()` and `@svelte-vitals/action` (issue #154) so the git-diff/baseline
|
|
152
|
+
* orchestration lives in exactly one place.
|
|
153
|
+
*/
|
|
154
|
+
declare function applyScope(results: Result[], opts: ApplyScopeOptions): Promise<Result[]>;
|
|
140
155
|
/**
|
|
141
156
|
* Run static-mode analysis once and return the process exit code (design §6):
|
|
142
157
|
* 0 = no failing findings, 1 = critical finding present, 2 = execution error.
|
|
143
158
|
*/
|
|
144
159
|
declare function run(opts?: RunOptions): Promise<number>;
|
|
145
160
|
|
|
146
|
-
export { type AnalyzeOptions, type AnalyzeResult, type LoadedConfigFile, ProjectError, type RunOptions, analyzeProject, buildRulesConfig, findUnknownRuleIds, knownRuleIds, loadConfigFile, routeMatcher, run, spinnerEnabled };
|
|
161
|
+
export { type AnalyzeOptions, type AnalyzeResult, type ApplyScopeOptions, type LoadedConfigFile, ProjectError, type RunOptions, analyzeProject, applyScope, buildRulesConfig, findUnknownRuleIds, knownRuleIds, loadConfigFile, routeMatcher, run, spinnerEnabled };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ProjectError,
|
|
3
3
|
analyzeProject,
|
|
4
|
+
applyScope,
|
|
4
5
|
buildRulesConfig,
|
|
5
6
|
defineConfig,
|
|
6
7
|
findUnknownRuleIds,
|
|
@@ -9,10 +10,11 @@ import {
|
|
|
9
10
|
routeMatcher,
|
|
10
11
|
run,
|
|
11
12
|
spinnerEnabled
|
|
12
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-KSJZLF5U.js";
|
|
13
14
|
export {
|
|
14
15
|
ProjectError,
|
|
15
16
|
analyzeProject,
|
|
17
|
+
applyScope,
|
|
16
18
|
buildRulesConfig,
|
|
17
19
|
defineConfig,
|
|
18
20
|
findUnknownRuleIds,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-vitals",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "A SvelteKit SEO checker — not a runtime Web Vitals reporter. Static analysis of your routes' head metadata.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
"smol-toml": "^1.7.0",
|
|
46
46
|
"svelte": "^5.56.4",
|
|
47
47
|
"tinyglobby": "^0.2.17",
|
|
48
|
-
"@svelte-vitals/core": "0.
|
|
48
|
+
"@svelte-vitals/core": "0.22.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^24.13.2"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
|
-
"build": "tsup",
|
|
55
|
-
"typecheck": "tsc --noEmit",
|
|
56
|
-
"test": "vitest run"
|
|
54
|
+
"build": "node scripts/gen-action-pin.mjs && tsup",
|
|
55
|
+
"typecheck": "node scripts/gen-action-pin.mjs && tsc --noEmit",
|
|
56
|
+
"test": "node scripts/gen-action-pin.mjs && vitest run"
|
|
57
57
|
}
|
|
58
58
|
}
|