sublyzer-snapshot 0.3.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 (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +306 -0
  3. package/dist/api/sublyzer.d.ts +29 -0
  4. package/dist/api/sublyzer.d.ts.map +1 -0
  5. package/dist/api/sublyzer.js +61 -0
  6. package/dist/api/sublyzer.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +199 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/commands/ci.d.ts +9 -0
  12. package/dist/commands/ci.d.ts.map +1 -0
  13. package/dist/commands/ci.js +65 -0
  14. package/dist/commands/ci.js.map +1 -0
  15. package/dist/commands/compare.d.ts +7 -0
  16. package/dist/commands/compare.d.ts.map +1 -0
  17. package/dist/commands/compare.js +60 -0
  18. package/dist/commands/compare.js.map +1 -0
  19. package/dist/commands/doctor.d.ts +13 -0
  20. package/dist/commands/doctor.d.ts.map +1 -0
  21. package/dist/commands/doctor.js +100 -0
  22. package/dist/commands/doctor.js.map +1 -0
  23. package/dist/commands/init.d.ts +10 -0
  24. package/dist/commands/init.d.ts.map +1 -0
  25. package/dist/commands/init.js +88 -0
  26. package/dist/commands/init.js.map +1 -0
  27. package/dist/commands/open.d.ts +2 -0
  28. package/dist/commands/open.d.ts.map +1 -0
  29. package/dist/commands/open.js +16 -0
  30. package/dist/commands/open.js.map +1 -0
  31. package/dist/commands/pull.d.ts +9 -0
  32. package/dist/commands/pull.d.ts.map +1 -0
  33. package/dist/commands/pull.js +34 -0
  34. package/dist/commands/pull.js.map +1 -0
  35. package/dist/commands/report.d.ts +8 -0
  36. package/dist/commands/report.d.ts.map +1 -0
  37. package/dist/commands/report.js +47 -0
  38. package/dist/commands/report.js.map +1 -0
  39. package/dist/commands/run.d.ts +21 -0
  40. package/dist/commands/run.d.ts.map +1 -0
  41. package/dist/commands/run.js +96 -0
  42. package/dist/commands/run.js.map +1 -0
  43. package/dist/commands/status.d.ts +5 -0
  44. package/dist/commands/status.d.ts.map +1 -0
  45. package/dist/commands/status.js +52 -0
  46. package/dist/commands/status.js.map +1 -0
  47. package/dist/config.d.ts +36 -0
  48. package/dist/config.d.ts.map +1 -0
  49. package/dist/config.js +58 -0
  50. package/dist/config.js.map +1 -0
  51. package/dist/constants.d.ts +13 -0
  52. package/dist/constants.d.ts.map +1 -0
  53. package/dist/constants.js +12 -0
  54. package/dist/constants.js.map +1 -0
  55. package/dist/detect/git.d.ts +9 -0
  56. package/dist/detect/git.d.ts.map +1 -0
  57. package/dist/detect/git.js +25 -0
  58. package/dist/detect/git.js.map +1 -0
  59. package/dist/detect/meta.d.ts +8 -0
  60. package/dist/detect/meta.d.ts.map +1 -0
  61. package/dist/detect/meta.js +42 -0
  62. package/dist/detect/meta.js.map +1 -0
  63. package/dist/detect/routes.d.ts +2 -0
  64. package/dist/detect/routes.d.ts.map +1 -0
  65. package/dist/detect/routes.js +104 -0
  66. package/dist/detect/routes.js.map +1 -0
  67. package/dist/detect/stack.d.ts +15 -0
  68. package/dist/detect/stack.d.ts.map +1 -0
  69. package/dist/detect/stack.js +114 -0
  70. package/dist/detect/stack.js.map +1 -0
  71. package/dist/detect/workspaces.d.ts +6 -0
  72. package/dist/detect/workspaces.d.ts.map +1 -0
  73. package/dist/detect/workspaces.js +54 -0
  74. package/dist/detect/workspaces.js.map +1 -0
  75. package/dist/report/markdown.d.ts +5 -0
  76. package/dist/report/markdown.d.ts.map +1 -0
  77. package/dist/report/markdown.js +81 -0
  78. package/dist/report/markdown.js.map +1 -0
  79. package/dist/scan/audit.d.ts +16 -0
  80. package/dist/scan/audit.d.ts.map +1 -0
  81. package/dist/scan/audit.js +53 -0
  82. package/dist/scan/audit.js.map +1 -0
  83. package/dist/scan/health-score.d.ts +13 -0
  84. package/dist/scan/health-score.d.ts.map +1 -0
  85. package/dist/scan/health-score.js +60 -0
  86. package/dist/scan/health-score.js.map +1 -0
  87. package/dist/scan/history.d.ts +21 -0
  88. package/dist/scan/history.d.ts.map +1 -0
  89. package/dist/scan/history.js +82 -0
  90. package/dist/scan/history.js.map +1 -0
  91. package/dist/scan/outdated.d.ts +15 -0
  92. package/dist/scan/outdated.d.ts.map +1 -0
  93. package/dist/scan/outdated.js +54 -0
  94. package/dist/scan/outdated.js.map +1 -0
  95. package/dist/scan/policy.d.ts +5 -0
  96. package/dist/scan/policy.d.ts.map +1 -0
  97. package/dist/scan/policy.js +20 -0
  98. package/dist/scan/policy.js.map +1 -0
  99. package/dist/scan/snapshot.d.ts +47 -0
  100. package/dist/scan/snapshot.d.ts.map +1 -0
  101. package/dist/scan/snapshot.js +176 -0
  102. package/dist/scan/snapshot.js.map +1 -0
  103. package/dist/utils/gitignore.d.ts +3 -0
  104. package/dist/utils/gitignore.d.ts.map +1 -0
  105. package/dist/utils/gitignore.js +34 -0
  106. package/dist/utils/gitignore.js.map +1 -0
  107. package/dist/utils/log.d.ts +6 -0
  108. package/dist/utils/log.d.ts.map +1 -0
  109. package/dist/utils/log.js +17 -0
  110. package/dist/utils/log.js.map +1 -0
  111. package/dist/utils/prompt.d.ts +4 -0
  112. package/dist/utils/prompt.d.ts.map +1 -0
  113. package/dist/utils/prompt.js +35 -0
  114. package/dist/utils/prompt.js.map +1 -0
  115. package/package.json +51 -0
@@ -0,0 +1,114 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ const VERSION_KEYS = [
4
+ 'next',
5
+ 'react',
6
+ 'react-dom',
7
+ 'vue',
8
+ 'nuxt',
9
+ '@nestjs/core',
10
+ 'express',
11
+ 'fastify',
12
+ '@remix-run/react',
13
+ '@sveltejs/kit',
14
+ 'typescript',
15
+ ];
16
+ function readPackageJson(root) {
17
+ const file = path.join(root, 'package.json');
18
+ if (!fs.existsSync(file))
19
+ return null;
20
+ try {
21
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ function allDeps(pkg) {
28
+ if (!pkg)
29
+ return {};
30
+ return { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
31
+ }
32
+ function exists(root, rel) {
33
+ return fs.existsSync(path.join(root, rel));
34
+ }
35
+ function frameworkVersions(deps) {
36
+ const out = {};
37
+ for (const key of VERSION_KEYS) {
38
+ if (deps[key])
39
+ out[key] = deps[key];
40
+ }
41
+ return out;
42
+ }
43
+ export function detectStack(root = process.cwd()) {
44
+ const pkg = readPackageJson(root);
45
+ const deps = allDeps(pkg);
46
+ const hints = [];
47
+ const versions = frameworkVersions(deps);
48
+ if (deps.next) {
49
+ hints.push('package.json → next');
50
+ if (exists(root, 'app') || exists(root, 'pages'))
51
+ hints.push('app/ or pages/ directory');
52
+ return { id: 'nextjs', label: 'Next.js', confidence: 'high', hints, frameworkVersions: versions };
53
+ }
54
+ if (deps.nuxt || deps['nuxt3']) {
55
+ hints.push('package.json → nuxt');
56
+ return { id: 'nuxt', label: 'Nuxt', confidence: 'high', hints, frameworkVersions: versions };
57
+ }
58
+ if (deps['@sveltejs/kit']) {
59
+ hints.push('package.json → @sveltejs/kit');
60
+ return { id: 'sveltekit', label: 'SvelteKit', confidence: 'high', hints, frameworkVersions: versions };
61
+ }
62
+ if (deps['@nestjs/core']) {
63
+ hints.push('package.json → @nestjs/core');
64
+ if (exists(root, 'nest-cli.json'))
65
+ hints.push('nest-cli.json');
66
+ return { id: 'nestjs', label: 'NestJS', confidence: 'high', hints, frameworkVersions: versions };
67
+ }
68
+ if (deps.fastify) {
69
+ hints.push('package.json → fastify');
70
+ return { id: 'fastify', label: 'Fastify', confidence: 'high', hints, frameworkVersions: versions };
71
+ }
72
+ if (deps.express) {
73
+ hints.push('package.json → express');
74
+ return { id: 'express', label: 'Express', confidence: 'high', hints, frameworkVersions: versions };
75
+ }
76
+ if (deps['@remix-run/react'] || deps['@remix-run/node']) {
77
+ hints.push('package.json → remix');
78
+ return { id: 'remix', label: 'Remix', confidence: 'high', hints, frameworkVersions: versions };
79
+ }
80
+ if (deps.react && !deps.next) {
81
+ hints.push('package.json → react');
82
+ return { id: 'react', label: 'React', confidence: 'medium', hints, frameworkVersions: versions };
83
+ }
84
+ if (deps.vue) {
85
+ hints.push('package.json → vue');
86
+ return { id: 'vue', label: 'Vue', confidence: 'medium', hints, frameworkVersions: versions };
87
+ }
88
+ if (pkg?.name)
89
+ hints.push(`package.json name: ${pkg.name}`);
90
+ if (exists(root, 'package.json')) {
91
+ return { id: 'node', label: 'Node.js', confidence: 'low', hints, frameworkVersions: versions };
92
+ }
93
+ return { id: 'unknown', label: 'Unknown', confidence: 'low', hints: ['No package.json found'], frameworkVersions: versions };
94
+ }
95
+ export function readProjectName(root = process.cwd()) {
96
+ const pkg = readPackageJson(root);
97
+ if (pkg?.name)
98
+ return pkg.name;
99
+ return path.basename(root);
100
+ }
101
+ export function listDependencies(root = process.cwd()) {
102
+ const pkg = readPackageJson(root);
103
+ if (!pkg)
104
+ return [];
105
+ const out = [];
106
+ for (const [name, version] of Object.entries(pkg.dependencies || {})) {
107
+ out.push({ name, version, dev: false });
108
+ }
109
+ for (const [name, version] of Object.entries(pkg.devDependencies || {})) {
110
+ out.push({ name, version, dev: true });
111
+ }
112
+ return out.sort((a, b) => a.name.localeCompare(b.name));
113
+ }
114
+ //# sourceMappingURL=stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack.js","sourceRoot":"","sources":["../../src/detect/stack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export type WorkspaceInfo = {
2
+ type: 'npm' | 'pnpm' | 'yarn' | 'none';
3
+ packages: string[];
4
+ };
5
+ export declare function detectWorkspaces(root?: string): WorkspaceInfo;
6
+ //# sourceMappingURL=workspaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/detect/workspaces.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAmCF,wBAAgB,gBAAgB,CAAC,IAAI,SAAgB,GAAG,aAAa,CAgBpE"}
@@ -0,0 +1,54 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ function readPackageJson(root) {
4
+ const file = path.join(root, 'package.json');
5
+ if (!fs.existsSync(file))
6
+ return null;
7
+ try {
8
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
9
+ }
10
+ catch {
11
+ return null;
12
+ }
13
+ }
14
+ function expandWorkspaceGlobs(root, patterns) {
15
+ const found = new Set();
16
+ for (const pattern of patterns) {
17
+ const base = pattern.replace(/\*.*$/, '').replace(/\/$/, '');
18
+ const dir = path.join(root, base);
19
+ if (fs.existsSync(path.join(dir, 'package.json'))) {
20
+ found.add(base || '.');
21
+ }
22
+ if (pattern.includes('*') && fs.existsSync(dir)) {
23
+ try {
24
+ for (const ent of fs.readdirSync(dir, { withFileTypes: true })) {
25
+ if (!ent.isDirectory())
26
+ continue;
27
+ const rel = path.join(base, ent.name).replace(/\\/g, '/');
28
+ if (fs.existsSync(path.join(root, rel, 'package.json')))
29
+ found.add(rel);
30
+ }
31
+ }
32
+ catch {
33
+ /* ignore */
34
+ }
35
+ }
36
+ }
37
+ return [...found].sort();
38
+ }
39
+ export function detectWorkspaces(root = process.cwd()) {
40
+ if (fs.existsSync(path.join(root, 'pnpm-workspace.yaml'))) {
41
+ const pkgs = expandWorkspaceGlobs(root, ['packages/*', 'apps/*', 'projects/*']);
42
+ return { type: 'pnpm', packages: pkgs.length ? pkgs : ['.'] };
43
+ }
44
+ const pkg = readPackageJson(root);
45
+ const workspaces = pkg?.workspaces;
46
+ if (Array.isArray(workspaces)) {
47
+ return { type: 'npm', packages: expandWorkspaceGlobs(root, workspaces) };
48
+ }
49
+ if (workspaces && typeof workspaces === 'object' && Array.isArray(workspaces.packages)) {
50
+ return { type: 'npm', packages: expandWorkspaceGlobs(root, workspaces.packages) };
51
+ }
52
+ return { type: 'none', packages: ['.'] };
53
+ }
54
+ //# sourceMappingURL=workspaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../../src/detect/workspaces.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { SnapshotDiff } from '../scan/history.js';
2
+ import { type HealthScore } from '../scan/health-score.js';
3
+ import type { ProjectSnapshot } from '../scan/snapshot.js';
4
+ export declare function renderMarkdownReport(snapshot: ProjectSnapshot, health: HealthScore, diff?: SnapshotDiff | null, dashboardUrl?: string): string;
5
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/report/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,WAAW,EACnB,IAAI,CAAC,EAAE,YAAY,GAAG,IAAI,EAC1B,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,CAsFR"}
@@ -0,0 +1,81 @@
1
+ export function renderMarkdownReport(snapshot, health, diff, dashboardUrl) {
2
+ const lines = [];
3
+ const s = snapshot.summary;
4
+ lines.push(`# Sublyzer Snapshot — ${snapshot.projectName}`);
5
+ lines.push('');
6
+ lines.push(`**Generated:** ${snapshot.scannedAt} `);
7
+ lines.push(`**Stack:** ${snapshot.stack.label} `);
8
+ lines.push(`**Health:** ${health.score}/100 (grade ${health.grade}) `);
9
+ if (dashboardUrl)
10
+ lines.push(`**Dashboard:** ${dashboardUrl} `);
11
+ lines.push('');
12
+ lines.push('## Summary');
13
+ lines.push('');
14
+ lines.push('| Metric | Value |');
15
+ lines.push('|--------|-------|');
16
+ lines.push(`| Routes | ${s.routeCount} |`);
17
+ lines.push(`| Dependencies | ${s.productionDeps} prod / ${s.devDeps} dev |`);
18
+ lines.push(`| Vulnerabilities | ${s.vulnerablePackages} (C:${s.criticalVulns} H:${s.highVulns}) |`);
19
+ if (snapshot.outdated?.ran) {
20
+ lines.push(`| Outdated packages | ${snapshot.outdated.total} (${snapshot.outdated.majorCount} major) |`);
21
+ }
22
+ if (snapshot.git.available) {
23
+ lines.push(`| Git | \`${snapshot.git.branch}@${snapshot.git.commit}\`${snapshot.git.dirty ? ' *(dirty)*' : ''} |`);
24
+ }
25
+ lines.push('');
26
+ if (health.factors.length) {
27
+ lines.push('## Health factors');
28
+ lines.push('');
29
+ for (const f of health.factors) {
30
+ const sign = f.impact >= 0 ? '+' : '';
31
+ lines.push(`- ${f.label} (${sign}${f.impact})`);
32
+ }
33
+ lines.push('');
34
+ }
35
+ if (diff && diff.previousAt) {
36
+ lines.push('## Changes since last scan');
37
+ lines.push('');
38
+ lines.push(`Previous scan: ${diff.previousAt}`);
39
+ lines.push('');
40
+ if (diff.healthDelta != null) {
41
+ const arrow = diff.healthDelta >= 0 ? '↑' : '↓';
42
+ lines.push(`- Health score: ${arrow} ${Math.abs(diff.healthDelta)} points`);
43
+ }
44
+ if (diff.vulnDelta.total !== 0) {
45
+ lines.push(`- Vulnerabilities: ${diff.vulnDelta.total >= 0 ? '+' : ''}${diff.vulnDelta.total}`);
46
+ }
47
+ if (diff.routesAdded.length) {
48
+ lines.push(`- Routes added (${diff.routesAdded.length}): ${diff.routesAdded.slice(0, 10).join(', ')}`);
49
+ }
50
+ if (diff.routesRemoved.length) {
51
+ lines.push(`- Routes removed (${diff.routesRemoved.length}): ${diff.routesRemoved.slice(0, 10).join(', ')}`);
52
+ }
53
+ lines.push('');
54
+ }
55
+ if (snapshot.audit.advisories.length) {
56
+ lines.push('## Top vulnerabilities');
57
+ lines.push('');
58
+ lines.push('| Severity | Package | Title |');
59
+ lines.push('|----------|---------|-------|');
60
+ for (const a of snapshot.audit.advisories.slice(0, 10)) {
61
+ lines.push(`| ${a.severity} | ${a.name} | ${a.title.replace(/\|/g, '/')} |`);
62
+ }
63
+ lines.push('');
64
+ }
65
+ if (snapshot.routes.length) {
66
+ lines.push('## Routes');
67
+ lines.push('');
68
+ for (const r of snapshot.routes.slice(0, 50)) {
69
+ lines.push(`- \`${r}\``);
70
+ }
71
+ if (snapshot.routes.length > 50) {
72
+ lines.push(`- … +${snapshot.routes.length - 50} more`);
73
+ }
74
+ lines.push('');
75
+ }
76
+ lines.push('---');
77
+ lines.push('*Generated by [sublyzer-snapshot](https://github.com/sublyzer-one/sublyzer-snapshot)*');
78
+ lines.push('');
79
+ return lines.join('\n');
80
+ }
81
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/report/markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export type AuditSummary = {
2
+ ran: boolean;
3
+ total: number;
4
+ critical: number;
5
+ high: number;
6
+ moderate: number;
7
+ low: number;
8
+ advisories: {
9
+ name: string;
10
+ severity: string;
11
+ title: string;
12
+ }[];
13
+ error?: string;
14
+ };
15
+ export declare function runNpmAudit(root?: string): AuditSummary;
16
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/scan/audit.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,WAAW,CAAC,IAAI,SAAgB,GAAG,YAAY,CAwD9D"}
@@ -0,0 +1,53 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ export function runNpmAudit(root = process.cwd()) {
3
+ const empty = {
4
+ ran: false,
5
+ total: 0,
6
+ critical: 0,
7
+ high: 0,
8
+ moderate: 0,
9
+ low: 0,
10
+ advisories: [],
11
+ };
12
+ const res = spawnSync(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['audit', '--json'], {
13
+ cwd: root,
14
+ encoding: 'utf8',
15
+ timeout: 120_000,
16
+ maxBuffer: 10 * 1024 * 1024,
17
+ });
18
+ const stdout = res.stdout || '';
19
+ if (!stdout.trim()) {
20
+ return { ...empty, error: res.stderr?.slice(0, 200) || 'npm audit produced no output' };
21
+ }
22
+ let parsed;
23
+ try {
24
+ parsed = JSON.parse(stdout);
25
+ }
26
+ catch {
27
+ return { ...empty, error: 'Failed to parse npm audit JSON' };
28
+ }
29
+ const meta = parsed.metadata?.vulnerabilities || {};
30
+ const advisories = [];
31
+ const vulns = parsed.vulnerabilities || parsed.advisories || {};
32
+ if (typeof vulns === 'object') {
33
+ for (const [name, entry] of Object.entries(vulns)) {
34
+ const severity = String(entry?.severity || entry?.via?.[0]?.severity || 'unknown').toLowerCase();
35
+ const title = String(entry?.via?.[0]?.title || entry?.title || name).slice(0, 200);
36
+ advisories.push({ name, severity, title });
37
+ }
38
+ }
39
+ advisories.sort((a, b) => {
40
+ const rank = (s) => ({ critical: 0, high: 1, moderate: 2, low: 3 }[s] ?? 4);
41
+ return rank(a.severity) - rank(b.severity);
42
+ });
43
+ return {
44
+ ran: true,
45
+ total: Number(meta.total ?? advisories.length) || advisories.length,
46
+ critical: Number(meta.critical ?? 0),
47
+ high: Number(meta.high ?? 0),
48
+ moderate: Number(meta.moderate ?? 0),
49
+ low: Number(meta.low ?? 0),
50
+ advisories: advisories.slice(0, 25),
51
+ };
52
+ }
53
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/scan/audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ProjectSnapshot } from './snapshot.js';
2
+ export type HealthGrade = 'A' | 'B' | 'C' | 'D' | 'F';
3
+ export type HealthScore = {
4
+ score: number;
5
+ grade: HealthGrade;
6
+ factors: {
7
+ label: string;
8
+ impact: number;
9
+ }[];
10
+ };
11
+ export declare function computeHealthScore(snapshot: ProjectSnapshot): HealthScore;
12
+ export declare function formatHealthBar(score: number): string;
13
+ //# sourceMappingURL=health-score.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health-score.d.ts","sourceRoot":"","sources":["../../src/scan/health-score.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,MAAM,WAAW,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9C,CAAC;AAUF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,eAAe,GAAG,WAAW,CAiDzE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIrD"}
@@ -0,0 +1,60 @@
1
+ function gradeFromScore(score) {
2
+ if (score >= 90)
3
+ return 'A';
4
+ if (score >= 80)
5
+ return 'B';
6
+ if (score >= 70)
7
+ return 'C';
8
+ if (score >= 60)
9
+ return 'D';
10
+ return 'F';
11
+ }
12
+ export function computeHealthScore(snapshot) {
13
+ let score = 100;
14
+ const factors = [];
15
+ const s = snapshot.summary;
16
+ if (s.criticalVulns > 0) {
17
+ const impact = Math.min(50, s.criticalVulns * 25);
18
+ score -= impact;
19
+ factors.push({ label: `${s.criticalVulns} critical CVE(s)`, impact: -impact });
20
+ }
21
+ if (s.highVulns > 0) {
22
+ const impact = Math.min(30, s.highVulns * 10);
23
+ score -= impact;
24
+ factors.push({ label: `${s.highVulns} high CVE(s)`, impact: -impact });
25
+ }
26
+ if (snapshot.audit.moderate > 0) {
27
+ const impact = Math.min(15, snapshot.audit.moderate * 3);
28
+ score -= impact;
29
+ factors.push({ label: `${snapshot.audit.moderate} moderate CVE(s)`, impact: -impact });
30
+ }
31
+ const webStacks = new Set(['nextjs', 'nestjs', 'express', 'fastify', 'remix', 'nuxt', 'sveltekit', 'react']);
32
+ if (webStacks.has(snapshot.stack.id) && s.routeCount === 0) {
33
+ score -= 8;
34
+ factors.push({ label: 'No routes detected', impact: -8 });
35
+ }
36
+ if (snapshot.git.available && snapshot.git.dirty) {
37
+ score -= 3;
38
+ factors.push({ label: 'Uncommitted changes (dirty git)', impact: -3 });
39
+ }
40
+ if (snapshot.env.found.length === 0 && snapshot.dependencyCount > 0) {
41
+ score -= 2;
42
+ factors.push({ label: 'No .env.example found', impact: -2 });
43
+ }
44
+ if (snapshot.outdated?.majorCount && snapshot.outdated.majorCount > 0) {
45
+ const impact = Math.min(12, snapshot.outdated.majorCount * 3);
46
+ score -= impact;
47
+ factors.push({ label: `${snapshot.outdated.majorCount} major outdated package(s)`, impact: -impact });
48
+ }
49
+ if (snapshot.workspaces?.packages && snapshot.workspaces.packages.length > 1) {
50
+ factors.push({ label: `Monorepo (${snapshot.workspaces.packages.length} packages)`, impact: 0 });
51
+ }
52
+ score = Math.max(0, Math.min(100, Math.round(score)));
53
+ return { score, grade: gradeFromScore(score), factors };
54
+ }
55
+ export function formatHealthBar(score) {
56
+ const filled = Math.round(score / 10);
57
+ const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);
58
+ return `[${bar}] ${score}/100`;
59
+ }
60
+ //# sourceMappingURL=health-score.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health-score.js","sourceRoot":"","sources":["../../src/scan/health-score.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { ProjectSnapshot } from './snapshot.js';
2
+ export declare function lastSnapshotPath(root: string): string;
3
+ export declare function historyDir(root: string): string;
4
+ export declare function saveScanHistory(snapshot: ProjectSnapshot, root?: string): void;
5
+ export declare function loadLastSnapshot(root?: string): ProjectSnapshot | null;
6
+ export declare function loadPreviousSnapshot(root?: string): ProjectSnapshot | null;
7
+ export type SnapshotDiff = {
8
+ routesAdded: string[];
9
+ routesRemoved: string[];
10
+ vulnDelta: {
11
+ critical: number;
12
+ high: number;
13
+ total: number;
14
+ };
15
+ depDelta: number;
16
+ healthDelta: number | null;
17
+ previousAt: string | null;
18
+ currentAt: string;
19
+ };
20
+ export declare function diffSnapshots(previous: ProjectSnapshot | null, current: ProjectSnapshot, healthDelta?: number | null): SnapshotDiff;
21
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/scan/history.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAMrD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,SAAgB,GAAG,IAAI,CAyBrF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,SAAgB,GAAG,eAAe,GAAG,IAAI,CAQ7E;AAED,wBAAgB,oBAAoB,CAAC,IAAI,SAAgB,GAAG,eAAe,GAAG,IAAI,CAcjF;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,eAAe,GAAG,IAAI,EAChC,OAAO,EAAE,eAAe,EACxB,WAAW,GAAE,MAAM,GAAG,IAAW,GAChC,YAAY,CAiBd"}
@@ -0,0 +1,82 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { CONFIG_DIR, HISTORY_DIR, LAST_SNAPSHOT_FILE, MAX_HISTORY_FILES, } from '../constants.js';
4
+ function sublyzerDir(root) {
5
+ return path.join(root, CONFIG_DIR);
6
+ }
7
+ export function lastSnapshotPath(root) {
8
+ return path.join(sublyzerDir(root), LAST_SNAPSHOT_FILE);
9
+ }
10
+ export function historyDir(root) {
11
+ return path.join(sublyzerDir(root), HISTORY_DIR);
12
+ }
13
+ export function saveScanHistory(snapshot, root = process.cwd()) {
14
+ const dir = sublyzerDir(root);
15
+ fs.mkdirSync(dir, { recursive: true });
16
+ const payload = JSON.stringify(snapshot, null, 2);
17
+ fs.writeFileSync(lastSnapshotPath(root), `${payload}\n`, 'utf8');
18
+ const hist = historyDir(root);
19
+ fs.mkdirSync(hist, { recursive: true });
20
+ const stamp = snapshot.scannedAt.replace(/[:.]/g, '-');
21
+ fs.writeFileSync(path.join(hist, `${stamp}.json`), `${payload}\n`, 'utf8');
22
+ const files = fs
23
+ .readdirSync(hist)
24
+ .filter((f) => f.endsWith('.json'))
25
+ .sort()
26
+ .reverse();
27
+ for (const old of files.slice(MAX_HISTORY_FILES)) {
28
+ try {
29
+ fs.unlinkSync(path.join(hist, old));
30
+ }
31
+ catch {
32
+ /* ignore */
33
+ }
34
+ }
35
+ }
36
+ export function loadLastSnapshot(root = process.cwd()) {
37
+ const file = lastSnapshotPath(root);
38
+ if (!fs.existsSync(file))
39
+ return null;
40
+ try {
41
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ }
47
+ export function loadPreviousSnapshot(root = process.cwd()) {
48
+ const hist = historyDir(root);
49
+ if (!fs.existsSync(hist))
50
+ return null;
51
+ const files = fs
52
+ .readdirSync(hist)
53
+ .filter((f) => f.endsWith('.json'))
54
+ .sort()
55
+ .reverse();
56
+ if (files.length < 2)
57
+ return null;
58
+ try {
59
+ return JSON.parse(fs.readFileSync(path.join(hist, files[1]), 'utf8'));
60
+ }
61
+ catch {
62
+ return null;
63
+ }
64
+ }
65
+ export function diffSnapshots(previous, current, healthDelta = null) {
66
+ const prevRoutes = new Set(previous?.routes || []);
67
+ const curRoutes = new Set(current.routes);
68
+ return {
69
+ routesAdded: current.routes.filter((r) => !prevRoutes.has(r)),
70
+ routesRemoved: (previous?.routes || []).filter((r) => !curRoutes.has(r)),
71
+ vulnDelta: {
72
+ critical: current.summary.criticalVulns - (previous?.summary.criticalVulns ?? 0),
73
+ high: current.summary.highVulns - (previous?.summary.highVulns ?? 0),
74
+ total: current.summary.vulnerablePackages - (previous?.summary.vulnerablePackages ?? 0),
75
+ },
76
+ depDelta: current.dependencyCount - (previous?.dependencyCount ?? 0),
77
+ healthDelta,
78
+ previousAt: previous?.scannedAt ?? null,
79
+ currentAt: current.scannedAt,
80
+ };
81
+ }
82
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/scan/history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EACL,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AAGzB,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAyB,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IAC7E,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC9B,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEvC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAClD,EAAE,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,IAAI,EAAE,MAAM,CAAC,CAAC;IAEjE,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACvD,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,EAAE,GAAG,OAAO,IAAI,EAAE,MAAM,CAAC,CAAC;IAE3E,MAAM,KAAK,GAAG,EAAE;SACb,WAAW,CAAC,IAAI,CAAC;SACjB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;SAClC,IAAI,EAAE;SACN,OAAO,EAAE,CAAC;IAEb,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IACnD,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAoB,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IACvD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,KAAK,GAAG,EAAE;SACb,WAAW,CAAC,IAAI,CAAC;SACjB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;SAClC,IAAI,EAAE;SACN,OAAO,EAAE,CAAC;IACb,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAoB,CAAC;IAC3F,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAYD,MAAM,UAAU,aAAa,CAC3B,QAAgC,EAChC,OAAwB,EACxB,cAA6B,IAAI;IAEjC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAE1C,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC7D,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACxE,SAAS,EAAE;YACT,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,aAAa,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC;YAChF,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC;YACpE,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,kBAAkB,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,kBAAkB,IAAI,CAAC,CAAC;SACxF;QACD,QAAQ,EAAE,OAAO,CAAC,eAAe,GAAG,CAAC,QAAQ,EAAE,eAAe,IAAI,CAAC,CAAC;QACpE,WAAW;QACX,UAAU,EAAE,QAAQ,EAAE,SAAS,IAAI,IAAI;QACvC,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ export type OutdatedSummary = {
2
+ ran: boolean;
3
+ total: number;
4
+ majorCount: number;
5
+ packages: {
6
+ name: string;
7
+ current: string;
8
+ wanted: string;
9
+ latest: string;
10
+ kind: 'major' | 'minor' | 'patch';
11
+ }[];
12
+ error?: string;
13
+ };
14
+ export declare function runNpmOutdated(root?: string): OutdatedSummary;
15
+ //# sourceMappingURL=outdated.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outdated.d.ts","sourceRoot":"","sources":["../../src/scan/outdated.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAA;KAAE,EAAE,CAAC;IACjH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAUF,wBAAgB,cAAc,CAAC,IAAI,SAAgB,GAAG,eAAe,CA8CpE"}