@vibecodeqa/cli 0.17.0 → 0.18.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.
Files changed (42) hide show
  1. package/README.md +73 -63
  2. package/dist/check-meta.d.ts +1 -0
  3. package/dist/check-meta.js +34 -2
  4. package/dist/cli.js +35 -10
  5. package/dist/detect.js +24 -2
  6. package/dist/fs-utils.d.ts +4 -0
  7. package/dist/fs-utils.js +12 -6
  8. package/dist/report/html.d.ts +17 -10
  9. package/dist/report/html.js +106 -73
  10. package/dist/report/pages.d.ts +2 -1
  11. package/dist/report/pages.js +88 -82
  12. package/dist/report/sarif.d.ts +3 -0
  13. package/dist/report/sarif.js +67 -0
  14. package/dist/report/styles.d.ts +1 -1
  15. package/dist/report/styles.js +82 -36
  16. package/dist/runners/architecture.d.ts +2 -0
  17. package/dist/runners/architecture.js +232 -20
  18. package/dist/runners/code-coherence.d.ts +17 -0
  19. package/dist/runners/code-coherence.js +39 -0
  20. package/dist/runners/complexity.js +7 -37
  21. package/dist/runners/confusion.js +3 -31
  22. package/dist/runners/context.js +9 -40
  23. package/dist/runners/dependencies.js +28 -0
  24. package/dist/runners/doc-coherence.d.ts +14 -0
  25. package/dist/runners/doc-coherence.js +48 -0
  26. package/dist/runners/docs.js +7 -32
  27. package/dist/runners/duplication.js +9 -37
  28. package/dist/runners/lint.js +17 -0
  29. package/dist/runners/performance.d.ts +10 -0
  30. package/dist/runners/performance.js +174 -0
  31. package/dist/runners/react.js +15 -10
  32. package/dist/runners/secrets.js +8 -29
  33. package/dist/runners/security.js +15 -38
  34. package/dist/runners/standards.js +3 -36
  35. package/dist/runners/structure.js +35 -55
  36. package/dist/runners/testing.js +2 -36
  37. package/dist/runners/type-safety.d.ts +1 -1
  38. package/dist/runners/type-safety.js +19 -37
  39. package/dist/runners/types-check.d.ts +1 -1
  40. package/dist/runners/types-check.js +38 -20
  41. package/dist/types.d.ts +5 -5
  42. package/package.json +11 -10
@@ -1,8 +1,8 @@
1
1
  /** Type safety check — count unsafe patterns: `as any`, explicit `any`, non-null assertions. */
2
- import { readdirSync, readFileSync, statSync } from "node:fs";
3
- import { extname, join } from "node:path";
2
+ import { getProductionFiles } from "../fs-utils.js";
4
3
  import { gradeFromScore } from "../types.js";
5
- const PATTERNS = [
4
+ // TypeScript unsafe patterns
5
+ const TS_PATTERNS = [
6
6
  { name: "as any", pattern: /\bas any\b/g, severity: "warning", weight: 2 },
7
7
  { name: ": any", pattern: /:\s*any\b/g, severity: "warning", weight: 1 },
8
8
  { name: "non-null assertion (!.)", pattern: /\w+!\./g, severity: "info", weight: 0.5 },
@@ -10,22 +10,22 @@ const PATTERNS = [
10
10
  { name: "@ts-expect-error", pattern: /@ts-expect-error/g, severity: "warning", weight: 2 },
11
11
  { name: "@ts-nocheck", pattern: /@ts-nocheck/g, severity: "error", weight: 10 },
12
12
  ];
13
- export function runTypeSafety(cwd) {
13
+ // Dart unsafe patterns
14
+ const DART_PATTERNS = [
15
+ { name: "dynamic type", pattern: /\bdynamic\b/g, severity: "warning", weight: 1 },
16
+ { name: "as dynamic", pattern: /\bas dynamic\b/g, severity: "warning", weight: 2 },
17
+ { name: "// ignore:", pattern: /\/\/\s*ignore:/g, severity: "error", weight: 5 },
18
+ { name: "// ignore_for_file:", pattern: /\/\/\s*ignore_for_file:/g, severity: "error", weight: 10 },
19
+ { name: "late keyword", pattern: /\blate\s+(?!final)/g, severity: "info", weight: 0.5 },
20
+ ];
21
+ export function runTypeSafety(cwd, isDart = false) {
14
22
  const start = Date.now();
15
23
  const issues = [];
16
24
  const counts = {};
17
25
  let totalPenalty = 0;
18
- const files = [];
19
- const dirs = ["src", "web/src"];
20
- for (const dir of dirs) {
21
- try {
22
- collectFiles(join(cwd, dir), files);
23
- }
24
- catch {
25
- /* dir doesn't exist */
26
- }
27
- }
28
- if (files.length === 0) {
26
+ const PATTERNS = isDart ? DART_PATTERNS : TS_PATTERNS;
27
+ const sourceFiles = getProductionFiles(cwd);
28
+ if (sourceFiles.length === 0) {
29
29
  return {
30
30
  name: "type-safety",
31
31
  score: 100,
@@ -35,10 +35,8 @@ export function runTypeSafety(cwd) {
35
35
  duration: Date.now() - start,
36
36
  };
37
37
  }
38
- for (const file of files) {
39
- const content = readFileSync(file, "utf-8");
40
- const relPath = file.replace(`${cwd}/`, "");
41
- const lines = content.split("\n");
38
+ for (const sf of sourceFiles) {
39
+ const lines = sf.content.split("\n");
42
40
  for (let i = 0; i < lines.length; i++) {
43
41
  const line = lines[i];
44
42
  const trimmed = line.trim();
@@ -53,7 +51,7 @@ export function runTypeSafety(cwd) {
53
51
  counts[p.name] = (counts[p.name] || 0) + matches.length;
54
52
  totalPenalty += p.weight * matches.length;
55
53
  for (const _m of matches) {
56
- issues.push({ severity: p.severity, message: p.name, file: relPath, line: i + 1, rule: "unsafe-type" });
54
+ issues.push({ severity: p.severity, message: p.name, file: sf.path, line: i + 1, rule: "unsafe-type" });
57
55
  }
58
56
  }
59
57
  }
@@ -64,24 +62,8 @@ export function runTypeSafety(cwd) {
64
62
  name: "type-safety",
65
63
  score,
66
64
  grade: gradeFromScore(score),
67
- details: { ...counts, filesScanned: files.length, totalUnsafe: issues.length },
65
+ details: { ...counts, filesScanned: sourceFiles.length, totalUnsafe: issues.length },
68
66
  issues,
69
67
  duration: Date.now() - start,
70
68
  };
71
69
  }
72
- function collectFiles(dir, out) {
73
- for (const entry of readdirSync(dir)) {
74
- if (entry === "node_modules" || entry === "dist")
75
- continue;
76
- const full = join(dir, entry);
77
- if (statSync(full).isDirectory()) {
78
- collectFiles(full, out);
79
- }
80
- else {
81
- const ext = extname(entry);
82
- if ((ext === ".ts" || ext === ".tsx") && !entry.includes(".test.") && !entry.includes(".spec.")) {
83
- out.push(full);
84
- }
85
- }
86
- }
87
- }
@@ -1,3 +1,3 @@
1
1
  /** TypeScript type checking runner. */
2
2
  import type { CheckResult } from "../types.js";
3
- export declare function runTypeCheck(cwd: string): CheckResult;
3
+ export declare function runTypeCheck(cwd: string, isDart?: boolean): CheckResult;
@@ -3,33 +3,51 @@ import { existsSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { gradeFromScore } from "../types.js";
5
5
  import { run } from "./exec.js";
6
- export function runTypeCheck(cwd) {
6
+ export function runTypeCheck(cwd, isDart = false) {
7
7
  const start = Date.now();
8
8
  const issues = [];
9
- if (!existsSync(join(cwd, "tsconfig.json")) && !existsSync(join(cwd, "tsconfig.app.json"))) {
10
- return {
11
- name: "types",
12
- score: 0,
13
- grade: "F",
14
- details: { skipped: true, reason: "no tsconfig.json" },
15
- issues: [],
16
- duration: Date.now() - start,
17
- };
18
- }
19
- const { stdout } = run("npx tsc --noEmit 2>&1 || true", cwd, 30_000);
20
- const lines = stdout.split("\n");
21
- for (const line of lines) {
22
- const match = line.match(/^(.+)\((\d+),\d+\): error (TS\d+): (.+)/);
23
- if (match) {
9
+ if (isDart) {
10
+ // Dart uses dart analyze for type checking — errors are type errors
11
+ const { stdout } = run("dart analyze --format=machine 2>/dev/null || true", cwd, 30_000);
12
+ for (const line of stdout.split("\n")) {
13
+ const parts = line.split("|");
14
+ if (parts.length < 8 || parts[0] !== "ERROR")
15
+ continue;
24
16
  issues.push({
25
17
  severity: "error",
26
- file: match[1],
27
- line: parseInt(match[2], 10),
28
- rule: match[3],
29
- message: match[4],
18
+ file: parts[3],
19
+ line: parseInt(parts[4], 10) || undefined,
20
+ rule: parts[2],
21
+ message: parts[7],
30
22
  });
31
23
  }
32
24
  }
25
+ else {
26
+ if (!existsSync(join(cwd, "tsconfig.json")) && !existsSync(join(cwd, "tsconfig.app.json"))) {
27
+ return {
28
+ name: "types",
29
+ score: 0,
30
+ grade: "F",
31
+ details: { skipped: true, reason: "no tsconfig.json" },
32
+ issues: [],
33
+ duration: Date.now() - start,
34
+ };
35
+ }
36
+ const { stdout } = run("npx tsc --noEmit 2>&1 || true", cwd, 30_000);
37
+ const lines = stdout.split("\n");
38
+ for (const line of lines) {
39
+ const match = line.match(/^(.+)\((\d+),\d+\): error (TS\d+): (.+)/);
40
+ if (match) {
41
+ issues.push({
42
+ severity: "error",
43
+ file: match[1],
44
+ line: parseInt(match[2], 10),
45
+ rule: match[3],
46
+ message: match[4],
47
+ });
48
+ }
49
+ }
50
+ }
33
51
  const errorCount = issues.length;
34
52
  const score = errorCount === 0 ? 100 : Math.max(0, 100 - errorCount * 5);
35
53
  return {
package/dist/types.d.ts CHANGED
@@ -30,11 +30,11 @@ export interface VibeReport {
30
30
  };
31
31
  }
32
32
  export interface StackInfo {
33
- language: "typescript" | "javascript" | "unknown";
34
- framework: "react" | "vue" | "svelte" | "none" | "unknown";
33
+ language: "typescript" | "javascript" | "dart" | "unknown";
34
+ framework: "react" | "vue" | "svelte" | "flutter" | "none" | "unknown";
35
35
  bundler: "vite" | "webpack" | "esbuild" | "none" | "unknown";
36
- testRunner: "vitest" | "jest" | "none" | "unknown";
37
- linter: "biome" | "eslint" | "none" | "unknown";
38
- packageManager: "pnpm" | "npm" | "yarn" | "bun" | "unknown";
36
+ testRunner: "vitest" | "jest" | "flutter_test" | "dart_test" | "none" | "unknown";
37
+ linter: "biome" | "eslint" | "dart_analyze" | "none" | "unknown";
38
+ packageManager: "pnpm" | "npm" | "yarn" | "bun" | "pub" | "unknown";
39
39
  }
40
40
  export declare function gradeFromScore(score: number): "A" | "B" | "C" | "D" | "F";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vibecodeqa/cli",
3
- "version": "0.17.0",
4
- "description": "Code health scanner for the AI coding era. 18 checks, zero config, full report.",
3
+ "version": "0.18.0",
4
+ "description": "Code health scanner for the AI coding era. 21 checks, zero config, full report.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "vcqa": "./dist/cli.js",
@@ -12,6 +12,13 @@
12
12
  "LICENSE",
13
13
  "README.md"
14
14
  ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch",
18
+ "test": "vitest run",
19
+ "lint": "biome check src/",
20
+ "prepublishOnly": "tsc && chmod +x dist/cli.js"
21
+ },
15
22
  "keywords": [
16
23
  "code-quality",
17
24
  "code-health",
@@ -32,7 +39,7 @@
32
39
  "license": "MIT",
33
40
  "repository": {
34
41
  "type": "git",
35
- "url": "https://github.com/freeappstore-online/vibe-check"
42
+ "url": "https://github.com/vibecodeqa/cli"
36
43
  },
37
44
  "homepage": "https://vibecodeqa.online",
38
45
  "engines": {
@@ -43,11 +50,5 @@
43
50
  "@types/node": "^25.8.0",
44
51
  "typescript": "^5.8.3",
45
52
  "vitest": "^4.1.6"
46
- },
47
- "scripts": {
48
- "build": "tsc",
49
- "dev": "tsc --watch",
50
- "test": "vitest run",
51
- "lint": "biome check src/"
52
53
  }
53
- }
54
+ }