@ash-technologia/fathom 0.1.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 (236) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/LICENSE +21 -0
  3. package/README.md +725 -0
  4. package/dist/analyzers/architecture/graph.d.ts +29 -0
  5. package/dist/analyzers/architecture/graph.d.ts.map +1 -0
  6. package/dist/analyzers/architecture/graph.js +347 -0
  7. package/dist/analyzers/architecture/graph.js.map +1 -0
  8. package/dist/analyzers/architecture/imports.d.ts +24 -0
  9. package/dist/analyzers/architecture/imports.d.ts.map +1 -0
  10. package/dist/analyzers/architecture/imports.js +155 -0
  11. package/dist/analyzers/architecture/imports.js.map +1 -0
  12. package/dist/analyzers/architecture/index.d.ts +13 -0
  13. package/dist/analyzers/architecture/index.d.ts.map +1 -0
  14. package/dist/analyzers/architecture/index.js +217 -0
  15. package/dist/analyzers/architecture/index.js.map +1 -0
  16. package/dist/analyzers/architecture/types.d.ts +65 -0
  17. package/dist/analyzers/architecture/types.d.ts.map +1 -0
  18. package/dist/analyzers/architecture/types.js +2 -0
  19. package/dist/analyzers/architecture/types.js.map +1 -0
  20. package/dist/analyzers/cicd/index.d.ts +11 -0
  21. package/dist/analyzers/cicd/index.d.ts.map +1 -0
  22. package/dist/analyzers/cicd/index.js +157 -0
  23. package/dist/analyzers/cicd/index.js.map +1 -0
  24. package/dist/analyzers/dependencies/index.d.ts +11 -0
  25. package/dist/analyzers/dependencies/index.d.ts.map +1 -0
  26. package/dist/analyzers/dependencies/index.js +403 -0
  27. package/dist/analyzers/dependencies/index.js.map +1 -0
  28. package/dist/analyzers/dependencies/lockfiles.d.ts +19 -0
  29. package/dist/analyzers/dependencies/lockfiles.d.ts.map +1 -0
  30. package/dist/analyzers/dependencies/lockfiles.js +172 -0
  31. package/dist/analyzers/dependencies/lockfiles.js.map +1 -0
  32. package/dist/analyzers/dependencies/online.d.ts +19 -0
  33. package/dist/analyzers/dependencies/online.d.ts.map +1 -0
  34. package/dist/analyzers/dependencies/online.js +116 -0
  35. package/dist/analyzers/dependencies/online.js.map +1 -0
  36. package/dist/analyzers/dependencies/types.d.ts +49 -0
  37. package/dist/analyzers/dependencies/types.d.ts.map +1 -0
  38. package/dist/analyzers/dependencies/types.js +2 -0
  39. package/dist/analyzers/dependencies/types.js.map +1 -0
  40. package/dist/analyzers/documentation/index.d.ts +11 -0
  41. package/dist/analyzers/documentation/index.d.ts.map +1 -0
  42. package/dist/analyzers/documentation/index.js +166 -0
  43. package/dist/analyzers/documentation/index.js.map +1 -0
  44. package/dist/analyzers/git/index.d.ts +11 -0
  45. package/dist/analyzers/git/index.d.ts.map +1 -0
  46. package/dist/analyzers/git/index.js +180 -0
  47. package/dist/analyzers/git/index.js.map +1 -0
  48. package/dist/analyzers/project/index.d.ts +11 -0
  49. package/dist/analyzers/project/index.d.ts.map +1 -0
  50. package/dist/analyzers/project/index.js +95 -0
  51. package/dist/analyzers/project/index.js.map +1 -0
  52. package/dist/analyzers/quality/index.d.ts +11 -0
  53. package/dist/analyzers/quality/index.d.ts.map +1 -0
  54. package/dist/analyzers/quality/index.js +198 -0
  55. package/dist/analyzers/quality/index.js.map +1 -0
  56. package/dist/analyzers/security/index.d.ts +11 -0
  57. package/dist/analyzers/security/index.d.ts.map +1 -0
  58. package/dist/analyzers/security/index.js +236 -0
  59. package/dist/analyzers/security/index.js.map +1 -0
  60. package/dist/analyzers/testing/index.d.ts +11 -0
  61. package/dist/analyzers/testing/index.d.ts.map +1 -0
  62. package/dist/analyzers/testing/index.js +134 -0
  63. package/dist/analyzers/testing/index.js.map +1 -0
  64. package/dist/baseline/baseline.d.ts +20 -0
  65. package/dist/baseline/baseline.d.ts.map +1 -0
  66. package/dist/baseline/baseline.js +134 -0
  67. package/dist/baseline/baseline.js.map +1 -0
  68. package/dist/baseline/compare.d.ts +14 -0
  69. package/dist/baseline/compare.d.ts.map +1 -0
  70. package/dist/baseline/compare.js +113 -0
  71. package/dist/baseline/compare.js.map +1 -0
  72. package/dist/baseline/types.d.ts +25 -0
  73. package/dist/baseline/types.d.ts.map +1 -0
  74. package/dist/baseline/types.js +2 -0
  75. package/dist/baseline/types.js.map +1 -0
  76. package/dist/cli/commands.d.ts +39 -0
  77. package/dist/cli/commands.d.ts.map +1 -0
  78. package/dist/cli/commands.js +277 -0
  79. package/dist/cli/commands.js.map +1 -0
  80. package/dist/cli/index.d.ts +3 -0
  81. package/dist/cli/index.d.ts.map +1 -0
  82. package/dist/cli/index.js +29 -0
  83. package/dist/cli/index.js.map +1 -0
  84. package/dist/cli/options.d.ts +55 -0
  85. package/dist/cli/options.d.ts.map +1 -0
  86. package/dist/cli/options.js +258 -0
  87. package/dist/cli/options.js.map +1 -0
  88. package/dist/core/analyzer.d.ts +33 -0
  89. package/dist/core/analyzer.d.ts.map +1 -0
  90. package/dist/core/analyzer.js +19 -0
  91. package/dist/core/analyzer.js.map +1 -0
  92. package/dist/core/context.d.ts +90 -0
  93. package/dist/core/context.d.ts.map +1 -0
  94. package/dist/core/context.js +159 -0
  95. package/dist/core/context.js.map +1 -0
  96. package/dist/core/errors.d.ts +74 -0
  97. package/dist/core/errors.d.ts.map +1 -0
  98. package/dist/core/errors.js +109 -0
  99. package/dist/core/errors.js.map +1 -0
  100. package/dist/core/findings.d.ts +59 -0
  101. package/dist/core/findings.d.ts.map +1 -0
  102. package/dist/core/findings.js +34 -0
  103. package/dist/core/findings.js.map +1 -0
  104. package/dist/core/orchestrator.d.ts +44 -0
  105. package/dist/core/orchestrator.d.ts.map +1 -0
  106. package/dist/core/orchestrator.js +160 -0
  107. package/dist/core/orchestrator.js.map +1 -0
  108. package/dist/core/result.d.ts +169 -0
  109. package/dist/core/result.d.ts.map +1 -0
  110. package/dist/core/result.js +2 -0
  111. package/dist/core/result.js.map +1 -0
  112. package/dist/detectors/framework.d.ts +22 -0
  113. package/dist/detectors/framework.d.ts.map +1 -0
  114. package/dist/detectors/framework.js +147 -0
  115. package/dist/detectors/framework.js.map +1 -0
  116. package/dist/detectors/language.d.ts +13 -0
  117. package/dist/detectors/language.d.ts.map +1 -0
  118. package/dist/detectors/language.js +100 -0
  119. package/dist/detectors/language.js.map +1 -0
  120. package/dist/detectors/package-manager.d.ts +17 -0
  121. package/dist/detectors/package-manager.d.ts.map +1 -0
  122. package/dist/detectors/package-manager.js +67 -0
  123. package/dist/detectors/package-manager.js.map +1 -0
  124. package/dist/detectors/project-type.d.ts +20 -0
  125. package/dist/detectors/project-type.d.ts.map +1 -0
  126. package/dist/detectors/project-type.js +48 -0
  127. package/dist/detectors/project-type.js.map +1 -0
  128. package/dist/diff/analyzer.d.ts +16 -0
  129. package/dist/diff/analyzer.d.ts.map +1 -0
  130. package/dist/diff/analyzer.js +296 -0
  131. package/dist/diff/analyzer.js.map +1 -0
  132. package/dist/diff/git-diff.d.ts +44 -0
  133. package/dist/diff/git-diff.d.ts.map +1 -0
  134. package/dist/diff/git-diff.js +256 -0
  135. package/dist/diff/git-diff.js.map +1 -0
  136. package/dist/diff/types.d.ts +75 -0
  137. package/dist/diff/types.d.ts.map +1 -0
  138. package/dist/diff/types.js +2 -0
  139. package/dist/diff/types.js.map +1 -0
  140. package/dist/integrations/github/context.d.ts +22 -0
  141. package/dist/integrations/github/context.d.ts.map +1 -0
  142. package/dist/integrations/github/context.js +115 -0
  143. package/dist/integrations/github/context.js.map +1 -0
  144. package/dist/integrations/github/types.d.ts +30 -0
  145. package/dist/integrations/github/types.d.ts.map +1 -0
  146. package/dist/integrations/github/types.js +2 -0
  147. package/dist/integrations/github/types.js.map +1 -0
  148. package/dist/plugins/context.d.ts +13 -0
  149. package/dist/plugins/context.d.ts.map +1 -0
  150. package/dist/plugins/context.js +102 -0
  151. package/dist/plugins/context.js.map +1 -0
  152. package/dist/plugins/examples/react.d.ts +8 -0
  153. package/dist/plugins/examples/react.d.ts.map +1 -0
  154. package/dist/plugins/examples/react.js +129 -0
  155. package/dist/plugins/examples/react.js.map +1 -0
  156. package/dist/plugins/index.d.ts +5 -0
  157. package/dist/plugins/index.d.ts.map +1 -0
  158. package/dist/plugins/index.js +4 -0
  159. package/dist/plugins/index.js.map +1 -0
  160. package/dist/plugins/registry.d.ts +45 -0
  161. package/dist/plugins/registry.d.ts.map +1 -0
  162. package/dist/plugins/registry.js +236 -0
  163. package/dist/plugins/registry.js.map +1 -0
  164. package/dist/plugins/types.d.ts +148 -0
  165. package/dist/plugins/types.d.ts.map +1 -0
  166. package/dist/plugins/types.js +2 -0
  167. package/dist/plugins/types.js.map +1 -0
  168. package/dist/reporters/html.d.ts +11 -0
  169. package/dist/reporters/html.d.ts.map +1 -0
  170. package/dist/reporters/html.js +1352 -0
  171. package/dist/reporters/html.js.map +1 -0
  172. package/dist/reporters/json.d.ts +10 -0
  173. package/dist/reporters/json.d.ts.map +1 -0
  174. package/dist/reporters/json.js +11 -0
  175. package/dist/reporters/json.js.map +1 -0
  176. package/dist/reporters/markdown.d.ts +7 -0
  177. package/dist/reporters/markdown.d.ts.map +1 -0
  178. package/dist/reporters/markdown.js +74 -0
  179. package/dist/reporters/markdown.js.map +1 -0
  180. package/dist/reporters/sarif.d.ts +133 -0
  181. package/dist/reporters/sarif.d.ts.map +1 -0
  182. package/dist/reporters/sarif.js +268 -0
  183. package/dist/reporters/sarif.js.map +1 -0
  184. package/dist/reporters/terminal.d.ts +17 -0
  185. package/dist/reporters/terminal.d.ts.map +1 -0
  186. package/dist/reporters/terminal.js +423 -0
  187. package/dist/reporters/terminal.js.map +1 -0
  188. package/dist/rules/categories.d.ts +8 -0
  189. package/dist/rules/categories.d.ts.map +1 -0
  190. package/dist/rules/categories.js +23 -0
  191. package/dist/rules/categories.js.map +1 -0
  192. package/dist/rules/definitions.d.ts +25 -0
  193. package/dist/rules/definitions.d.ts.map +1 -0
  194. package/dist/rules/definitions.js +429 -0
  195. package/dist/rules/definitions.js.map +1 -0
  196. package/dist/rules/registry.d.ts +36 -0
  197. package/dist/rules/registry.d.ts.map +1 -0
  198. package/dist/rules/registry.js +64 -0
  199. package/dist/rules/registry.js.map +1 -0
  200. package/dist/rules/severity.d.ts +13 -0
  201. package/dist/rules/severity.d.ts.map +1 -0
  202. package/dist/rules/severity.js +15 -0
  203. package/dist/rules/severity.js.map +1 -0
  204. package/dist/scoring/confidence.d.ts +12 -0
  205. package/dist/scoring/confidence.d.ts.map +1 -0
  206. package/dist/scoring/confidence.js +22 -0
  207. package/dist/scoring/confidence.js.map +1 -0
  208. package/dist/scoring/score.d.ts +27 -0
  209. package/dist/scoring/score.d.ts.map +1 -0
  210. package/dist/scoring/score.js +81 -0
  211. package/dist/scoring/score.js.map +1 -0
  212. package/dist/scoring/weights.d.ts +11 -0
  213. package/dist/scoring/weights.d.ts.map +1 -0
  214. package/dist/scoring/weights.js +26 -0
  215. package/dist/scoring/weights.js.map +1 -0
  216. package/dist/utils/filesystem.d.ts +65 -0
  217. package/dist/utils/filesystem.d.ts.map +1 -0
  218. package/dist/utils/filesystem.js +299 -0
  219. package/dist/utils/filesystem.js.map +1 -0
  220. package/dist/utils/git.d.ts +47 -0
  221. package/dist/utils/git.d.ts.map +1 -0
  222. package/dist/utils/git.js +125 -0
  223. package/dist/utils/git.js.map +1 -0
  224. package/dist/utils/logger.d.ts +14 -0
  225. package/dist/utils/logger.d.ts.map +1 -0
  226. package/dist/utils/logger.js +25 -0
  227. package/dist/utils/logger.js.map +1 -0
  228. package/dist/utils/paths.d.ts +30 -0
  229. package/dist/utils/paths.d.ts.map +1 -0
  230. package/dist/utils/paths.js +48 -0
  231. package/dist/utils/paths.js.map +1 -0
  232. package/dist/utils/timing.d.ts +12 -0
  233. package/dist/utils/timing.d.ts.map +1 -0
  234. package/dist/utils/timing.js +19 -0
  235. package/dist/utils/timing.js.map +1 -0
  236. package/package.json +73 -0
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Queries the public Open Source Vulnerabilities (OSV) API in batch mode.
3
+ * Strictly respects timeouts and offline failures. Never transmits repository source code or tokens.
4
+ */
5
+ export async function queryVulnerabilitiesOnline(packages) {
6
+ if (packages.length === 0)
7
+ return [];
8
+ // Limit query batch to first 50 packages to preserve bounded network usage
9
+ const batch = packages.slice(0, 50);
10
+ const queries = batch.map((p) => ({
11
+ package: {
12
+ name: p.name,
13
+ ecosystem: p.ecosystem ?? 'npm',
14
+ },
15
+ version: p.version,
16
+ }));
17
+ try {
18
+ const controller = new AbortController();
19
+ const timer = setTimeout(() => controller.abort(), 3500);
20
+ const response = await fetch('https://api.osv.dev/v1/querybatch', {
21
+ method: 'POST',
22
+ headers: {
23
+ 'Content-Type': 'application/json',
24
+ 'User-Agent': 'Fathom-Repository-Intelligence/0.1.0',
25
+ },
26
+ body: JSON.stringify({ queries }),
27
+ signal: controller.signal,
28
+ });
29
+ clearTimeout(timer);
30
+ if (!response.ok)
31
+ return [];
32
+ const data = (await response.json());
33
+ const advisories = [];
34
+ if (Array.isArray(data.results)) {
35
+ data.results.forEach((res, idx) => {
36
+ const pkg = batch[idx];
37
+ if (!pkg || !res.vulns)
38
+ return;
39
+ for (const v of res.vulns) {
40
+ let severity = 'high';
41
+ const rawSev = v.database_specific?.severity?.toLowerCase();
42
+ if (rawSev === 'critical')
43
+ severity = 'critical';
44
+ else if (rawSev === 'high')
45
+ severity = 'high';
46
+ else if (rawSev === 'medium' || rawSev === 'moderate')
47
+ severity = 'medium';
48
+ else if (rawSev === 'low')
49
+ severity = 'low';
50
+ advisories.push({
51
+ id: v.id,
52
+ packageName: pkg.name,
53
+ affectedVersion: pkg.version,
54
+ severity,
55
+ title: v.summary ?? `Vulnerability in ${pkg.name} (${v.id})`,
56
+ url: `https://osv.dev/vulnerability/${v.id}`,
57
+ });
58
+ }
59
+ });
60
+ }
61
+ return advisories;
62
+ }
63
+ catch {
64
+ // Network errors, timeouts, or offline environments degrade gracefully to empty list
65
+ return [];
66
+ }
67
+ }
68
+ /**
69
+ * Checks for latest versions of direct dependencies against npm registry.
70
+ * Limited to first 25 packages with 2.5s individual timeout.
71
+ */
72
+ export async function checkOutdatedOnline(directDeps) {
73
+ const candidates = directDeps.slice(0, 25);
74
+ const results = [];
75
+ const checks = candidates.map(async (dep) => {
76
+ try {
77
+ const cleanVer = dep.currentVersion.replace(/^[\^~>=<v\s]+/, '').split(' ')[0] ?? '';
78
+ if (!cleanVer || cleanVer === '*' || cleanVer === 'latest')
79
+ return;
80
+ const controller = new AbortController();
81
+ const timer = setTimeout(() => controller.abort(), 2500);
82
+ // Encode package name (supports scoped packages @scope/pkg)
83
+ const encodedName = dep.name.startsWith('@')
84
+ ? `@${encodeURIComponent(dep.name.slice(1))}`
85
+ : encodeURIComponent(dep.name);
86
+ const res = await fetch(`https://registry.npmjs.org/${encodedName}/latest`, {
87
+ headers: {
88
+ 'User-Agent': 'Fathom-Repository-Intelligence/0.1.0',
89
+ },
90
+ signal: controller.signal,
91
+ });
92
+ clearTimeout(timer);
93
+ if (res.ok) {
94
+ const data = (await res.json());
95
+ if (data.version && data.version !== cleanVer) {
96
+ const latestMajor = parseInt(data.version.split('.')[0] ?? '0', 10);
97
+ const currentMajor = parseInt(cleanVer.split('.')[0] ?? '0', 10);
98
+ // Only flag if latest major is strictly greater or multiple minor versions behind
99
+ if (latestMajor > currentMajor) {
100
+ results.push({
101
+ packageName: dep.name,
102
+ currentVersion: cleanVer,
103
+ latestVersion: data.version,
104
+ });
105
+ }
106
+ }
107
+ }
108
+ }
109
+ catch {
110
+ return;
111
+ }
112
+ });
113
+ await Promise.allSettled(checks);
114
+ return results.sort((a, b) => a.packageName.localeCompare(b.packageName));
115
+ }
116
+ //# sourceMappingURL=online.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"online.js","sourceRoot":"","sources":["../../../src/analyzers/dependencies/online.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ export type DependencyType = 'direct' | 'dev' | 'peer' | 'transitive';
2
+ export interface DeclaredDependency {
3
+ name: string;
4
+ versionSpec: string;
5
+ type: DependencyType;
6
+ manifestPath: string;
7
+ }
8
+ export interface DuplicatePackage {
9
+ name: string;
10
+ versions: string[];
11
+ }
12
+ export interface SuspiciousDependency {
13
+ name: string;
14
+ versionSpec: string;
15
+ reason: string;
16
+ manifestPath: string;
17
+ }
18
+ export interface UnusedDependency {
19
+ name: string;
20
+ manifestPath: string;
21
+ confidence: number;
22
+ }
23
+ export interface VulnerabilityAdvisory {
24
+ id: string;
25
+ packageName: string;
26
+ affectedVersion: string;
27
+ severity: 'low' | 'medium' | 'high' | 'critical';
28
+ title: string;
29
+ url?: string | undefined;
30
+ }
31
+ export interface OutdatedDependency {
32
+ packageName: string;
33
+ currentVersion: string;
34
+ latestVersion: string;
35
+ }
36
+ export interface DependencyIntelligenceSummary {
37
+ manifests: string[];
38
+ lockfiles: string[];
39
+ directCount: number;
40
+ devCount: number;
41
+ transitiveCount: number;
42
+ duplicates: DuplicatePackage[];
43
+ suspicious: SuspiciousDependency[];
44
+ unused: UnusedDependency[];
45
+ vulnerabilities: VulnerabilityAdvisory[];
46
+ outdated: OutdatedDependency[];
47
+ isOnline: boolean;
48
+ }
49
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/analyzers/dependencies/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,YAAY,CAAC;AAEtE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,cAAc,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,6BAA6B;IAC5C,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,QAAQ,EAAE,OAAO,CAAC;CACnB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/analyzers/dependencies/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { Analyzer } from '../../core/analyzer.js';
2
+ import type { RepositoryContext } from '../../core/context.js';
3
+ import type { AnalyzerResult } from '../../core/result.js';
4
+ export declare class DocumentationAnalyzer implements Analyzer {
5
+ readonly id = "documentation";
6
+ readonly name = "Documentation";
7
+ readonly category: "documentation";
8
+ readonly description = "Checks for README, LICENSE, CONTRIBUTING, and SECURITY documentation.";
9
+ analyze(context: RepositoryContext): Promise<AnalyzerResult>;
10
+ }
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzers/documentation/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAW,MAAM,sBAAsB,CAAC;AAepE,qBAAa,qBAAsB,YAAW,QAAQ;IACpD,QAAQ,CAAC,EAAE,mBAAmB;IAC9B,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,QAAQ,EAAG,eAAe,CAAU;IAC7C,QAAQ,CAAC,WAAW,2EAA2E;IAEzF,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC;CAgLnE"}
@@ -0,0 +1,166 @@
1
+ import path from 'node:path';
2
+ import { createFindingId } from '../../core/findings.js';
3
+ import { createTimer } from '../../utils/timing.js';
4
+ import { readFileSafe } from '../../utils/filesystem.js';
5
+ const README_NAMES = ['README.md', 'README.txt', 'README.rst', 'README', 'readme.md'];
6
+ const LICENSE_NAMES = ['LICENSE', 'LICENSE.md', 'LICENSE.txt', 'LICENCE', 'LICENCE.md', 'COPYING'];
7
+ const CONTRIBUTING_NAMES = ['CONTRIBUTING.md', 'CONTRIBUTING.txt', 'CONTRIBUTING'];
8
+ const SECURITY_NAMES = ['SECURITY.md', 'SECURITY.txt', 'SECURITY'];
9
+ const INSTALL_KEYWORDS = ['install', 'setup', 'getting started', 'prerequisites', 'requirement'];
10
+ const USAGE_KEYWORDS = ['usage', 'example', 'quickstart', 'quick start', 'how to use'];
11
+ const DESCRIPTION_MIN_LENGTH = 100; // README needs at least this many chars to be considered described
12
+ export class DocumentationAnalyzer {
13
+ id = 'documentation';
14
+ name = 'Documentation';
15
+ category = 'documentation';
16
+ description = 'Checks for README, LICENSE, CONTRIBUTING, and SECURITY documentation.';
17
+ async analyze(context) {
18
+ const elapsed = createTimer();
19
+ const findings = [];
20
+ const warnings = [];
21
+ const rootFileSet = new Set(context.rootFilenames);
22
+ // DOC-001: README exists
23
+ const readmeFile = README_NAMES.find((name) => rootFileSet.has(name) || context.files.some((f) => path.basename(f.relativePath) === name));
24
+ if (!readmeFile) {
25
+ findings.push({
26
+ id: createFindingId('DOC-001'),
27
+ ruleId: 'DOC-001',
28
+ category: 'documentation',
29
+ severity: 'medium',
30
+ title: 'No README found',
31
+ description: 'A README is the first thing developers see when they discover your project.',
32
+ recommendation: 'Create a README.md with project description, installation, and usage information.',
33
+ confidence: 0.99,
34
+ autoFixable: false,
35
+ });
36
+ }
37
+ else {
38
+ // Read README content for deeper checks
39
+ const readmePath = context.files.find((f) => path.basename(f.relativePath) === readmeFile)?.absolutePath;
40
+ if (readmePath) {
41
+ const content = await readFileSafe(readmePath, 256 * 1024);
42
+ if (content) {
43
+ const lower = content.toLowerCase();
44
+ // DOC-007: Has project description
45
+ if (content.length < DESCRIPTION_MIN_LENGTH) {
46
+ findings.push({
47
+ id: createFindingId('DOC-007'),
48
+ ruleId: 'DOC-007',
49
+ category: 'documentation',
50
+ severity: 'low',
51
+ title: 'README appears to be a stub',
52
+ description: 'The README is very short and may not adequately describe the project.',
53
+ recommendation: 'Expand the README with a project description, features, and goals.',
54
+ confidence: 0.8,
55
+ location: { file: readmeFile },
56
+ autoFixable: false,
57
+ });
58
+ }
59
+ // DOC-002: Installation instructions
60
+ if (!INSTALL_KEYWORDS.some((kw) => lower.includes(kw))) {
61
+ findings.push({
62
+ id: createFindingId('DOC-002'),
63
+ ruleId: 'DOC-002',
64
+ category: 'documentation',
65
+ severity: 'low',
66
+ title: 'README may be missing installation instructions',
67
+ description: 'Installation instructions help new contributors get started.',
68
+ recommendation: 'Add an "Installation" or "Getting Started" section to the README.',
69
+ confidence: 0.75,
70
+ location: { file: readmeFile },
71
+ autoFixable: false,
72
+ });
73
+ }
74
+ // DOC-003: Usage information
75
+ if (!USAGE_KEYWORDS.some((kw) => lower.includes(kw))) {
76
+ findings.push({
77
+ id: createFindingId('DOC-003'),
78
+ ruleId: 'DOC-003',
79
+ category: 'documentation',
80
+ severity: 'low',
81
+ title: 'README may be missing usage information',
82
+ description: 'Usage examples help developers understand how to use your project.',
83
+ recommendation: 'Add a "Usage" or "Examples" section to the README.',
84
+ confidence: 0.75,
85
+ location: { file: readmeFile },
86
+ autoFixable: false,
87
+ });
88
+ }
89
+ }
90
+ }
91
+ }
92
+ const hasDocFile = (names) => names.some((name) => rootFileSet.has(name) ||
93
+ context.files.some((f) => f.relativePath === name ||
94
+ f.relativePath === `.github/${name}` ||
95
+ f.relativePath === `docs/${name}`));
96
+ // DOC-004: LICENSE
97
+ const hasLicense = hasDocFile(LICENSE_NAMES);
98
+ if (!hasLicense) {
99
+ findings.push({
100
+ id: createFindingId('DOC-004'),
101
+ ruleId: 'DOC-004',
102
+ category: 'documentation',
103
+ severity: 'medium',
104
+ title: 'No LICENSE file found',
105
+ description: 'Without a license, the project defaults to "all rights reserved" which prevents others from contributing or using it.',
106
+ recommendation: 'Add a LICENSE file. choosealicense.com can help you pick the right one.',
107
+ confidence: 0.99,
108
+ autoFixable: false,
109
+ references: ['https://choosealicense.com'],
110
+ });
111
+ }
112
+ // DOC-005: CONTRIBUTING
113
+ const hasContributing = hasDocFile(CONTRIBUTING_NAMES);
114
+ if (!hasContributing) {
115
+ findings.push({
116
+ id: createFindingId('DOC-005'),
117
+ ruleId: 'DOC-005',
118
+ category: 'documentation',
119
+ severity: 'low',
120
+ title: 'No CONTRIBUTING guide found',
121
+ description: 'A CONTRIBUTING guide helps new contributors understand how to participate.',
122
+ recommendation: 'Create a CONTRIBUTING.md explaining how to submit issues and pull requests.',
123
+ confidence: 0.99,
124
+ autoFixable: false,
125
+ });
126
+ }
127
+ // DOC-006: SECURITY
128
+ const hasSecurity = hasDocFile(SECURITY_NAMES);
129
+ if (!hasSecurity) {
130
+ findings.push({
131
+ id: createFindingId('DOC-006'),
132
+ ruleId: 'DOC-006',
133
+ category: 'documentation',
134
+ severity: 'low',
135
+ title: 'No SECURITY policy found',
136
+ description: 'A SECURITY policy tells users how to responsibly report vulnerabilities.',
137
+ recommendation: 'Create a SECURITY.md with your vulnerability disclosure process.',
138
+ confidence: 0.99,
139
+ autoFixable: false,
140
+ });
141
+ }
142
+ const metrics = {
143
+ hasReadme: !!readmeFile,
144
+ hasLicense,
145
+ hasContributing,
146
+ hasSecurityPolicy: hasSecurity,
147
+ documentationFiles: [
148
+ readmeFile,
149
+ hasLicense ? 'LICENSE' : null,
150
+ hasContributing ? 'CONTRIBUTING.md' : null,
151
+ hasSecurity ? 'SECURITY.md' : null,
152
+ ].filter(Boolean).length,
153
+ };
154
+ return {
155
+ analyzerId: this.id,
156
+ analyzerName: this.name,
157
+ category: this.category,
158
+ status: 'success',
159
+ findings,
160
+ metrics,
161
+ durationMs: elapsed(),
162
+ warnings,
163
+ };
164
+ }
165
+ }
166
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/documentation/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Analyzer } from '../../core/analyzer.js';
2
+ import type { RepositoryContext } from '../../core/context.js';
3
+ import type { AnalyzerResult } from '../../core/result.js';
4
+ export declare class GitAnalyzer implements Analyzer {
5
+ readonly id = "git";
6
+ readonly name = "Git";
7
+ readonly category: "git";
8
+ readonly description = "Checks Git repository hygiene, .gitignore configuration, and file tracking.";
9
+ analyze(context: RepositoryContext): Promise<AnalyzerResult>;
10
+ }
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzers/git/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAW,MAAM,sBAAsB,CAAC;AAqBpE,qBAAa,WAAY,YAAW,QAAQ;IAC1C,QAAQ,CAAC,EAAE,SAAS;IACpB,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,QAAQ,EAAG,KAAK,CAAU;IACnC,QAAQ,CAAC,WAAW,iFAC4D;IAE1E,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC;CAsKnE"}
@@ -0,0 +1,180 @@
1
+ import { createFindingId } from '../../core/findings.js';
2
+ import { createTimer } from '../../utils/timing.js';
3
+ import { hasUncommittedChanges, isPathMentionedInGitignore } from '../../utils/git.js';
4
+ const GENERATED_DIRS = [
5
+ 'node_modules',
6
+ 'dist',
7
+ 'build',
8
+ 'coverage',
9
+ '.next',
10
+ '.nuxt',
11
+ 'target',
12
+ 'vendor',
13
+ '__pycache__',
14
+ '.cache',
15
+ ];
16
+ const LARGE_FILE_THRESHOLD_BYTES = 10 * 1024 * 1024; // 10 MB
17
+ export class GitAnalyzer {
18
+ id = 'git';
19
+ name = 'Git';
20
+ category = 'git';
21
+ description = 'Checks Git repository hygiene, .gitignore configuration, and file tracking.';
22
+ async analyze(context) {
23
+ const elapsed = createTimer();
24
+ const findings = [];
25
+ const warnings = [];
26
+ // GIT-001: Is this a Git repository?
27
+ if (!context.git.isRepository) {
28
+ findings.push({
29
+ id: createFindingId('GIT-001'),
30
+ ruleId: 'GIT-001',
31
+ category: 'git',
32
+ severity: 'medium',
33
+ title: 'Not a Git repository',
34
+ description: 'This directory does not appear to be tracked by Git.',
35
+ recommendation: 'Run `git init` to initialize a Git repository.',
36
+ confidence: 0.99,
37
+ autoFixable: false,
38
+ });
39
+ return {
40
+ analyzerId: this.id,
41
+ analyzerName: this.name,
42
+ category: this.category,
43
+ status: 'success',
44
+ findings,
45
+ metrics: { isGitRepository: false },
46
+ durationMs: elapsed(),
47
+ warnings,
48
+ };
49
+ }
50
+ // GIT-002: .gitignore exists
51
+ if (!context.git.hasGitignore) {
52
+ findings.push({
53
+ id: createFindingId('GIT-002'),
54
+ ruleId: 'GIT-002',
55
+ category: 'git',
56
+ severity: 'medium',
57
+ title: 'No .gitignore found',
58
+ description: 'A .gitignore file helps prevent generated files and secrets from being committed.',
59
+ recommendation: 'Create a .gitignore appropriate for your project type.',
60
+ confidence: 0.99,
61
+ autoFixable: false,
62
+ references: ['https://git-scm.com/docs/gitignore', 'https://gitignore.io'],
63
+ });
64
+ }
65
+ else if (context.git.gitignoreContent) {
66
+ // GIT-003: Check that common generated dirs are gitignored
67
+ const gitignore = context.git.gitignoreContent;
68
+ const notIgnored = [];
69
+ for (const dir of GENERATED_DIRS) {
70
+ // Only flag dirs that are actually relevant (present or implied by ecosystem)
71
+ const isNodeProject = context.languages.some((l) => l.name === 'Node.js');
72
+ const isJavaProject = context.languages.some((l) => l.name === 'Java');
73
+ const isPythonProject = context.languages.some((l) => l.name === 'Python');
74
+ if (dir === 'node_modules' && !isNodeProject)
75
+ continue;
76
+ if (dir === 'target' && !isJavaProject)
77
+ continue;
78
+ if (dir === '__pycache__' && !isPythonProject)
79
+ continue;
80
+ // For framework-specific directories, only check if framework is present or dir exists
81
+ if (dir === '.next') {
82
+ const isNext = context.frameworks.some((f) => f.name === 'Next.js');
83
+ const hasNextDir = context.files.some((f) => f.relativePath.startsWith('.next/'));
84
+ if (!isNext && !hasNextDir)
85
+ continue;
86
+ }
87
+ if (dir === '.nuxt') {
88
+ const isNuxt = context.frameworks.some((f) => f.name === 'Nuxt');
89
+ const hasNuxtDir = context.files.some((f) => f.relativePath.startsWith('.nuxt/'));
90
+ if (!isNuxt && !hasNuxtDir)
91
+ continue;
92
+ }
93
+ if (!isPathMentionedInGitignore(gitignore, dir)) {
94
+ notIgnored.push(dir);
95
+ }
96
+ }
97
+ if (notIgnored.length > 0) {
98
+ findings.push({
99
+ id: createFindingId('GIT-003'),
100
+ ruleId: 'GIT-003',
101
+ category: 'git',
102
+ severity: 'medium',
103
+ title: 'Generated directories may not be gitignored',
104
+ description: `The following directories may not be in .gitignore: ${notIgnored.join(', ')}`,
105
+ recommendation: `Add these to .gitignore: ${notIgnored.map((d) => `\`${d}\``).join(', ')}`,
106
+ confidence: 0.75,
107
+ autoFixable: false,
108
+ });
109
+ }
110
+ }
111
+ // GIT-004: Large files
112
+ const largeFiles = context.files.filter((f) => f.sizeBytes >= LARGE_FILE_THRESHOLD_BYTES);
113
+ if (largeFiles.length > 0) {
114
+ for (const lf of largeFiles) {
115
+ const sizeMb = (lf.sizeBytes / (1024 * 1024)).toFixed(1);
116
+ findings.push({
117
+ id: createFindingId('GIT-004', lf.relativePath),
118
+ ruleId: 'GIT-004',
119
+ category: 'git',
120
+ severity: 'medium',
121
+ title: `Large file: ${lf.relativePath}`,
122
+ description: `This file is ${sizeMb} MB. Large files tracked in Git increase repository size and slow clones.`,
123
+ recommendation: 'Consider using Git LFS or excluding this file from the repository.',
124
+ confidence: 0.99,
125
+ location: { file: lf.relativePath },
126
+ evidence: `${sizeMb} MB`,
127
+ autoFixable: false,
128
+ references: ['https://git-lfs.github.com'],
129
+ });
130
+ }
131
+ }
132
+ // GIT-005: Uncommitted changes
133
+ const hasChanges = await hasUncommittedChanges(context.root);
134
+ if (hasChanges) {
135
+ findings.push({
136
+ id: createFindingId('GIT-005'),
137
+ ruleId: 'GIT-005',
138
+ category: 'git',
139
+ severity: 'info',
140
+ title: 'Uncommitted changes detected',
141
+ description: 'The working directory has uncommitted changes. This is informational.',
142
+ recommendation: 'Commit or stash changes before shipping.',
143
+ confidence: 0.99,
144
+ autoFixable: false,
145
+ });
146
+ }
147
+ // GIT-006: Empty repository
148
+ if (!context.git.hasCommits) {
149
+ findings.push({
150
+ id: createFindingId('GIT-006'),
151
+ ruleId: 'GIT-006',
152
+ category: 'git',
153
+ severity: 'info',
154
+ title: 'Repository has no commits',
155
+ description: 'This Git repository does not have any commits yet.',
156
+ recommendation: 'Make an initial commit to begin tracking history.',
157
+ confidence: 0.99,
158
+ autoFixable: false,
159
+ });
160
+ }
161
+ const metrics = {
162
+ isGitRepository: true,
163
+ hasGitignore: context.git.hasGitignore,
164
+ hasCommits: context.git.hasCommits,
165
+ hasUncommittedChanges: hasChanges,
166
+ largeFilesCount: largeFiles.length,
167
+ };
168
+ return {
169
+ analyzerId: this.id,
170
+ analyzerName: this.name,
171
+ category: this.category,
172
+ status: 'success',
173
+ findings,
174
+ metrics,
175
+ durationMs: elapsed(),
176
+ warnings,
177
+ };
178
+ }
179
+ }
180
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/git/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Analyzer } from '../../core/analyzer.js';
2
+ import type { RepositoryContext } from '../../core/context.js';
3
+ import type { AnalyzerResult } from '../../core/result.js';
4
+ export declare class ProjectAnalyzer implements Analyzer {
5
+ readonly id = "project";
6
+ readonly name = "Project";
7
+ readonly category: "project";
8
+ readonly description = "Detects ecosystems, frameworks, package managers, and repository size.";
9
+ analyze(context: RepositoryContext): Promise<AnalyzerResult>;
10
+ }
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzers/project/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAW,MAAM,sBAAsB,CAAC;AAKpE,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,QAAQ,CAAC,EAAE,aAAa;IACxB,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,QAAQ,EAAG,SAAS,CAAU;IACvC,QAAQ,CAAC,WAAW,4EAA4E;IAE1F,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC;CA6FnE"}