svelte-vitals 0.4.0 → 0.5.1

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 CHANGED
@@ -5,6 +5,8 @@
5
5
 
6
6
  > **A SvelteKit SEO checker — not a runtime Web Vitals reporter.**
7
7
  > Diagnose your project's SEO health by statically analyzing your source code, before it ships. No browser, no build server, no headless Chrome.
8
+ >
9
+ > **ESM-only** (Node 18+). Ships ES modules only; `require()` is unsupported by design.
8
10
 
9
11
  ```bash
10
12
  npx svelte-vitals
package/dist/bin.js CHANGED
@@ -1,32 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ buildRulesConfig,
4
+ findUnknownRuleIds,
3
5
  isReporterName,
6
+ knownRuleIds,
4
7
  readPackageVersion,
5
8
  run
6
- } from "./chunk-XOPYXOAE.js";
9
+ } from "./chunk-RI6LBHFR.js";
7
10
 
8
11
  // src/bin.ts
9
12
  import mri from "mri";
10
-
11
- // src/rules-config.ts
12
- import { allRules } from "@svelte-vitals/core";
13
- var KNOWN_IDS = new Set(allRules.map((r) => r.id));
14
- function findUnknownRuleIds(ids) {
15
- return [...new Set(ids.filter((id) => !KNOWN_IDS.has(id)))];
16
- }
17
- function knownRuleIds() {
18
- return [...KNOWN_IDS].sort();
19
- }
20
- function buildRulesConfig(allow, ignore) {
21
- const rules = {};
22
- if (allow.length > 0) {
23
- for (const r of allRules) if (!allow.includes(r.id)) rules[r.id] = "off";
24
- }
25
- for (const id of ignore) rules[id] = "off";
26
- return rules;
27
- }
28
-
29
- // src/bin.ts
30
13
  var HELP = `svelte-vitals \u2014 a SvelteKit SEO checker (static mode)
31
14
 
32
15
  Usage:
@@ -1,6 +1,6 @@
1
1
  // src/index.ts
2
2
  import {
3
- allRules,
3
+ allRules as allRules2,
4
4
  runRules,
5
5
  formatConsoleReport,
6
6
  formatJsonReport,
@@ -477,6 +477,24 @@ function isAutoDetectedGithub(explicit, env = process.env) {
477
477
  return !explicit && !isReporterName(env.SVELTE_VITALS_REPORTER) && !isAgentEnv(env) && isGithubActionsEnv(env);
478
478
  }
479
479
 
480
+ // src/rules-config.ts
481
+ import { allRules } from "@svelte-vitals/core";
482
+ var KNOWN_IDS = new Set(allRules.map((r) => r.id));
483
+ function findUnknownRuleIds(ids) {
484
+ return [...new Set(ids.filter((id) => !KNOWN_IDS.has(id)))];
485
+ }
486
+ function knownRuleIds() {
487
+ return [...KNOWN_IDS].sort();
488
+ }
489
+ function buildRulesConfig(allow, ignore) {
490
+ const rules = {};
491
+ if (allow.length > 0) {
492
+ for (const r of allRules) if (!allow.includes(r.id)) rules[r.id] = "off";
493
+ }
494
+ for (const id of ignore) rules[id] = "off";
495
+ return rules;
496
+ }
497
+
480
498
  // src/index.ts
481
499
  function routeMatcher(glob) {
482
500
  if (!glob) return () => true;
@@ -484,10 +502,8 @@ function routeMatcher(glob) {
484
502
  const re = new RegExp(`^${body}$`);
485
503
  return (route) => re.test(route.replace(/^\//, ""));
486
504
  }
487
- async function run(opts = {}) {
505
+ async function analyzeProject(opts = {}) {
488
506
  const cwd = opts.cwd ?? process.cwd();
489
- const log = opts.log ?? ((line) => console.log(line));
490
- const errorLog = opts.errorLog ?? ((line) => console.error(line));
491
507
  const rt = createNodeRuntime();
492
508
  const config = defineConfig({
493
509
  treatDynamicAs: opts.treatDynamicAs ?? "pass",
@@ -495,21 +511,37 @@ async function run(opts = {}) {
495
511
  rules: opts.rules ?? {},
496
512
  failOn: opts.failOn ?? "critical"
497
513
  });
514
+ await detectProject(rt, cwd);
515
+ const matches = routeMatcher(opts.route);
516
+ const heads = (await sourceHeadProvider.collect(rt, cwd, config)).filter((h) => matches(h.route));
517
+ const project = await collectProjectFacts(rt, cwd);
518
+ const rules = selectRules(allRules2, config);
519
+ const results = applyRuleSeverities(await runRules(rules, { heads, project, config }), config);
520
+ return { results, config, version: readPackageVersion() };
521
+ }
522
+ async function run(opts = {}) {
523
+ const log = opts.log ?? ((line) => console.log(line));
524
+ const errorLog = opts.errorLog ?? ((line) => console.error(line));
525
+ let analysis;
498
526
  try {
499
- await detectProject(rt, cwd);
527
+ analysis = await analyzeProject({
528
+ cwd: opts.cwd ?? process.cwd(),
529
+ metaComponents: opts.metaComponents,
530
+ treatDynamicAs: opts.treatDynamicAs,
531
+ route: opts.route,
532
+ failOn: opts.failOn,
533
+ rules: opts.rules
534
+ });
500
535
  } catch (err) {
501
536
  if (err instanceof ProjectError) {
502
537
  errorLog(err.message);
503
538
  return 2;
504
539
  }
505
- throw err;
540
+ errorLog(`svelte-vitals: ${err instanceof Error ? err.message : String(err)}`);
541
+ return 2;
506
542
  }
507
543
  try {
508
- const matches = routeMatcher(opts.route);
509
- const heads = (await sourceHeadProvider.collect(rt, cwd, config)).filter((h) => matches(h.route));
510
- const project = await collectProjectFacts(rt, cwd);
511
- const rules = selectRules(allRules, config);
512
- const results = applyRuleSeverities(await runRules(rules, { heads, project, config }), config);
544
+ const { results, config, version } = analysis;
513
545
  const env = opts.env ?? process.env;
514
546
  const reporter = resolveReporter(opts.reporter, env);
515
547
  if (reporter === "agent" && isAutoDetectedAgent(opts.reporter, env)) {
@@ -523,11 +555,11 @@ async function run(opts = {}) {
523
555
  );
524
556
  }
525
557
  if (reporter === "json") {
526
- log(formatJsonReport(results, config, { version: readPackageVersion() }));
558
+ log(formatJsonReport(results, config, { version }));
527
559
  } else if (reporter === "agent") {
528
560
  log(formatAgentReport(results, config));
529
561
  } else if (reporter === "sarif") {
530
- log(formatSarifReport(results, config, { version: readPackageVersion() }));
562
+ log(formatSarifReport(results, config, { version }));
531
563
  } else if (reporter === "github") {
532
564
  const output = formatGithubReport(results, config);
533
565
  if (output) log(output);
@@ -543,8 +575,13 @@ async function run(opts = {}) {
543
575
  }
544
576
 
545
577
  export {
578
+ ProjectError,
546
579
  readPackageVersion,
547
580
  isReporterName,
581
+ findUnknownRuleIds,
582
+ knownRuleIds,
583
+ buildRulesConfig,
548
584
  routeMatcher,
585
+ analyzeProject,
549
586
  run
550
587
  };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,24 @@
1
- import { Severity, RuleSetting } from '@svelte-vitals/core';
1
+ import { RuleSetting, Severity, Result, Config } from '@svelte-vitals/core';
2
2
 
3
3
  type ReporterName = 'console' | 'json' | 'agent' | 'sarif' | 'github';
4
4
 
5
+ /** Thrown when the target directory is not a SvelteKit project (CLI maps to exit 2). */
6
+ declare class ProjectError extends Error {
7
+ constructor(message: string);
8
+ }
9
+
10
+ /** Rule ids passed to --rules/--ignore that aren't part of the built-in registry. */
11
+ declare function findUnknownRuleIds(ids: string[]): string[];
12
+ /** All built-in rule ids, sorted — for help and error messages. */
13
+ declare function knownRuleIds(): string[];
14
+ /**
15
+ * Build the per-rule config map from an allow-list (--rules) and a deny-list
16
+ * (--ignore). An allow-list disables every rule not listed; deny always wins.
17
+ * Callers should reject unknown ids first (see findUnknownRuleIds) so a typo in
18
+ * --rules can't silently disable every rule.
19
+ */
20
+ declare function buildRulesConfig(allow: string[], ignore: string[]): Record<string, RuleSetting>;
21
+
5
22
  interface RunOptions {
6
23
  cwd?: string;
7
24
  log?: (line: string) => void;
@@ -18,10 +35,30 @@ interface RunOptions {
18
35
  env?: NodeJS.ProcessEnv;
19
36
  }
20
37
  declare function routeMatcher(glob: string | undefined): (route: string) => boolean;
38
+ interface AnalyzeOptions {
39
+ cwd?: string;
40
+ metaComponents?: string[];
41
+ treatDynamicAs?: 'pass' | 'warn' | 'fail';
42
+ /** Restrict analysis to routes whose path matches this glob (matched against the route path without leading slash). */
43
+ route?: string;
44
+ failOn?: Severity;
45
+ rules?: Record<string, RuleSetting>;
46
+ }
47
+ interface AnalyzeResult {
48
+ results: Result[];
49
+ config: Config;
50
+ version: string;
51
+ }
52
+ /**
53
+ * Run static-mode analysis and return the structured findings + resolved config.
54
+ * Throws ProjectError when `cwd` is not a SvelteKit project. Shared by the CLI's
55
+ * run() and by @svelte-vitals/mcp (issue #24).
56
+ */
57
+ declare function analyzeProject(opts?: AnalyzeOptions): Promise<AnalyzeResult>;
21
58
  /**
22
59
  * Run static-mode analysis once and return the process exit code (design §6):
23
60
  * 0 = no failing findings, 1 = critical finding present, 2 = execution error.
24
61
  */
25
62
  declare function run(opts?: RunOptions): Promise<number>;
26
63
 
27
- export { type RunOptions, routeMatcher, run };
64
+ export { type AnalyzeOptions, type AnalyzeResult, ProjectError, type RunOptions, analyzeProject, buildRulesConfig, findUnknownRuleIds, knownRuleIds, routeMatcher, run };
package/dist/index.js CHANGED
@@ -1,8 +1,18 @@
1
1
  import {
2
+ ProjectError,
3
+ analyzeProject,
4
+ buildRulesConfig,
5
+ findUnknownRuleIds,
6
+ knownRuleIds,
2
7
  routeMatcher,
3
8
  run
4
- } from "./chunk-XOPYXOAE.js";
9
+ } from "./chunk-RI6LBHFR.js";
5
10
  export {
11
+ ProjectError,
12
+ analyzeProject,
13
+ buildRulesConfig,
14
+ findUnknownRuleIds,
15
+ knownRuleIds,
6
16
  routeMatcher,
7
17
  run
8
18
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-vitals",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
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",
@@ -22,6 +22,10 @@
22
22
  "url": "https://github.com/oekazuma/svelte-vitals/issues"
23
23
  },
24
24
  "homepage": "https://github.com/oekazuma/svelte-vitals#readme",
25
+ "engines": {
26
+ "node": ">=18"
27
+ },
28
+ "sideEffects": false,
25
29
  "bin": {
26
30
  "svelte-vitals": "./dist/bin.js"
27
31
  },
@@ -38,7 +42,7 @@
38
42
  "mri": "^1.2.0",
39
43
  "svelte": "^5.56.3",
40
44
  "tinyglobby": "^0.2.17",
41
- "@svelte-vitals/core": "0.5.0"
45
+ "@svelte-vitals/core": "0.7.0"
42
46
  },
43
47
  "devDependencies": {
44
48
  "@types/node": "^24.7.0"