toolip 1.0.6 → 2.0.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 (308) hide show
  1. package/README.md +189 -448
  2. package/dist/src/analyzers/ast/ast-security-analyzer.d.ts +6 -0
  3. package/dist/src/analyzers/ast/ast-security-analyzer.js +64 -0
  4. package/dist/src/analyzers/ast/ast-security-analyzer.js.map +1 -0
  5. package/dist/src/analyzers/ast/rules.d.ts +48 -0
  6. package/dist/src/analyzers/ast/rules.js +39 -0
  7. package/dist/src/analyzers/ast/rules.js.map +1 -0
  8. package/dist/src/analyzers/ast/source-analysis.d.ts +2 -0
  9. package/dist/src/analyzers/ast/source-analysis.js +225 -0
  10. package/dist/src/analyzers/ast/source-analysis.js.map +1 -0
  11. package/dist/src/analyzers/dependency-confusion/analyzer.d.ts +9 -0
  12. package/dist/src/analyzers/dependency-confusion/analyzer.js +98 -0
  13. package/dist/src/analyzers/dependency-confusion/analyzer.js.map +1 -0
  14. package/dist/src/analyzers/docker/analyzer.d.ts +6 -0
  15. package/dist/src/analyzers/docker/analyzer.js +103 -0
  16. package/dist/src/analyzers/docker/analyzer.js.map +1 -0
  17. package/dist/src/analyzers/git-history/analyzer.d.ts +8 -0
  18. package/dist/src/analyzers/git-history/analyzer.js +157 -0
  19. package/dist/src/analyzers/git-history/analyzer.js.map +1 -0
  20. package/dist/src/analyzers/git-history/secret-patterns.d.ts +7 -0
  21. package/dist/src/analyzers/git-history/secret-patterns.js +33 -0
  22. package/dist/src/analyzers/git-history/secret-patterns.js.map +1 -0
  23. package/dist/src/analyzers/install-scripts/install-script-analyzer.d.ts +6 -0
  24. package/dist/src/analyzers/install-scripts/install-script-analyzer.js +135 -0
  25. package/dist/src/analyzers/install-scripts/install-script-analyzer.js.map +1 -0
  26. package/dist/src/analyzers/reachability/import-graph.d.ts +9 -0
  27. package/dist/src/analyzers/reachability/import-graph.js +110 -0
  28. package/dist/src/analyzers/reachability/import-graph.js.map +1 -0
  29. package/dist/src/analyzers/reachability/reachability-analyzer.d.ts +16 -0
  30. package/dist/src/analyzers/reachability/reachability-analyzer.js +95 -0
  31. package/dist/src/analyzers/reachability/reachability-analyzer.js.map +1 -0
  32. package/dist/src/analyzers/vulnerability/osv-analyzer.d.ts +9 -0
  33. package/dist/src/analyzers/vulnerability/osv-analyzer.js +94 -0
  34. package/dist/src/analyzers/vulnerability/osv-analyzer.js.map +1 -0
  35. package/dist/src/analyzers/vulnerability/severity.d.ts +3 -0
  36. package/dist/src/analyzers/vulnerability/severity.js +13 -0
  37. package/dist/src/analyzers/vulnerability/severity.js.map +1 -0
  38. package/dist/src/application/analyzer-runner.d.ts +12 -0
  39. package/dist/src/application/analyzer-runner.js +45 -0
  40. package/dist/src/application/analyzer-runner.js.map +1 -0
  41. package/dist/src/commands/alternatives.d.ts +2 -0
  42. package/dist/src/commands/alternatives.js +17 -0
  43. package/dist/src/commands/alternatives.js.map +1 -0
  44. package/dist/src/commands/announce.d.ts +2 -0
  45. package/dist/src/commands/announce.js +27 -0
  46. package/dist/src/commands/announce.js.map +1 -0
  47. package/dist/src/commands/ast-scan.d.ts +2 -0
  48. package/dist/src/commands/ast-scan.js +86 -0
  49. package/dist/src/commands/ast-scan.js.map +1 -0
  50. package/dist/src/commands/audit-repo.d.ts +2 -0
  51. package/dist/src/commands/audit-repo.js +20 -0
  52. package/dist/src/commands/audit-repo.js.map +1 -0
  53. package/dist/src/commands/compare.d.ts +2 -0
  54. package/dist/src/commands/compare.js +19 -0
  55. package/dist/src/commands/compare.js.map +1 -0
  56. package/dist/src/commands/config.d.ts +2 -0
  57. package/dist/src/commands/config.js +69 -0
  58. package/dist/src/commands/config.js.map +1 -0
  59. package/dist/src/commands/dependency-confusion.d.ts +2 -0
  60. package/dist/src/commands/dependency-confusion.js +37 -0
  61. package/dist/src/commands/dependency-confusion.js.map +1 -0
  62. package/dist/src/commands/diff.d.ts +2 -0
  63. package/dist/src/commands/diff.js +24 -0
  64. package/dist/src/commands/diff.js.map +1 -0
  65. package/dist/src/commands/docker-scan.d.ts +2 -0
  66. package/dist/src/commands/docker-scan.js +34 -0
  67. package/dist/src/commands/docker-scan.js.map +1 -0
  68. package/dist/src/commands/doctor.d.ts +2 -0
  69. package/dist/src/commands/doctor.js +42 -0
  70. package/dist/src/commands/doctor.js.map +1 -0
  71. package/dist/src/commands/git-audit.d.ts +2 -0
  72. package/dist/src/commands/git-audit.js +37 -0
  73. package/dist/src/commands/git-audit.js.map +1 -0
  74. package/dist/src/commands/git-history.d.ts +2 -0
  75. package/dist/src/commands/git-history.js +40 -0
  76. package/dist/src/commands/git-history.js.map +1 -0
  77. package/dist/src/commands/history.d.ts +2 -0
  78. package/dist/src/commands/history.js +69 -0
  79. package/dist/src/commands/history.js.map +1 -0
  80. package/dist/src/commands/hook.d.ts +2 -0
  81. package/dist/src/commands/hook.js +16 -0
  82. package/dist/src/commands/hook.js.map +1 -0
  83. package/dist/src/commands/inspect.d.ts +2 -0
  84. package/dist/src/commands/inspect.js +24 -0
  85. package/dist/src/commands/inspect.js.map +1 -0
  86. package/dist/src/commands/install-scripts.d.ts +2 -0
  87. package/dist/src/commands/install-scripts.js +52 -0
  88. package/dist/src/commands/install-scripts.js.map +1 -0
  89. package/dist/src/commands/learn.d.ts +2 -0
  90. package/dist/src/commands/learn.js +42 -0
  91. package/dist/src/commands/learn.js.map +1 -0
  92. package/dist/src/commands/licenses.d.ts +2 -0
  93. package/dist/src/commands/licenses.js +40 -0
  94. package/dist/src/commands/licenses.js.map +1 -0
  95. package/dist/src/commands/mcp.d.ts +2 -0
  96. package/dist/src/commands/mcp.js +10 -0
  97. package/dist/src/commands/mcp.js.map +1 -0
  98. package/dist/src/commands/monorepo.d.ts +2 -0
  99. package/dist/src/commands/monorepo.js +21 -0
  100. package/dist/src/commands/monorepo.js.map +1 -0
  101. package/dist/src/commands/package-health.d.ts +2 -0
  102. package/dist/src/commands/package-health.js +50 -0
  103. package/dist/src/commands/package-health.js.map +1 -0
  104. package/dist/src/commands/pre-commit.d.ts +2 -0
  105. package/dist/src/commands/pre-commit.js +37 -0
  106. package/dist/src/commands/pre-commit.js.map +1 -0
  107. package/dist/src/commands/profile.d.ts +2 -0
  108. package/dist/src/commands/profile.js +18 -0
  109. package/dist/src/commands/profile.js.map +1 -0
  110. package/dist/src/commands/publish.d.ts +2 -0
  111. package/dist/src/commands/publish.js +25 -0
  112. package/dist/src/commands/publish.js.map +1 -0
  113. package/dist/src/commands/reachability.d.ts +2 -0
  114. package/dist/src/commands/reachability.js +47 -0
  115. package/dist/src/commands/reachability.js.map +1 -0
  116. package/dist/src/commands/sbom.d.ts +2 -0
  117. package/dist/src/commands/sbom.js +33 -0
  118. package/dist/src/commands/sbom.js.map +1 -0
  119. package/dist/src/commands/scan.d.ts +2 -0
  120. package/dist/src/commands/scan.js +48 -0
  121. package/dist/src/commands/scan.js.map +1 -0
  122. package/dist/src/commands/score.d.ts +2 -0
  123. package/dist/src/commands/score.js +24 -0
  124. package/dist/src/commands/score.js.map +1 -0
  125. package/dist/src/commands/self-test.d.ts +2 -0
  126. package/dist/src/commands/self-test.js +63 -0
  127. package/dist/src/commands/self-test.js.map +1 -0
  128. package/dist/src/commands/tree.d.ts +2 -0
  129. package/dist/src/commands/tree.js +21 -0
  130. package/dist/src/commands/tree.js.map +1 -0
  131. package/dist/src/commands/upgrade-pr.d.ts +2 -0
  132. package/dist/src/commands/upgrade-pr.js +15 -0
  133. package/dist/src/commands/upgrade-pr.js.map +1 -0
  134. package/dist/src/commands/vault.d.ts +2 -0
  135. package/dist/src/commands/vault.js +86 -0
  136. package/dist/src/commands/vault.js.map +1 -0
  137. package/dist/src/commands/vulnerabilities.d.ts +2 -0
  138. package/dist/src/commands/vulnerabilities.js +42 -0
  139. package/dist/src/commands/vulnerabilities.js.map +1 -0
  140. package/dist/src/commands/watch.d.ts +2 -0
  141. package/dist/src/commands/watch.js +34 -0
  142. package/dist/src/commands/watch.js.map +1 -0
  143. package/dist/src/config/version.d.ts +6 -0
  144. package/dist/src/config/version.js +29 -0
  145. package/dist/src/config/version.js.map +1 -0
  146. package/dist/src/contracts/analyzer.d.ts +23 -0
  147. package/dist/src/contracts/analyzer.js +2 -0
  148. package/dist/src/contracts/analyzer.js.map +1 -0
  149. package/dist/src/contracts/finding.d.ts +35 -0
  150. package/dist/src/contracts/finding.js +13 -0
  151. package/dist/src/contracts/finding.js.map +1 -0
  152. package/dist/src/contracts/report.d.ts +30 -0
  153. package/dist/src/contracts/report.js +2 -0
  154. package/dist/src/contracts/report.js.map +1 -0
  155. package/dist/src/contracts/rule.d.ts +12 -0
  156. package/dist/src/contracts/rule.js +7 -0
  157. package/dist/src/contracts/rule.js.map +1 -0
  158. package/dist/src/core/alternatives.d.ts +8 -0
  159. package/dist/src/core/alternatives.js +35 -0
  160. package/dist/src/core/alternatives.js.map +1 -0
  161. package/dist/src/core/analyze-package.d.ts +2 -0
  162. package/dist/src/core/analyze-package.js +49 -0
  163. package/dist/src/core/analyze-package.js.map +1 -0
  164. package/dist/src/core/announce/generate.d.ts +9 -0
  165. package/dist/src/core/announce/generate.js +19 -0
  166. package/dist/src/core/announce/generate.js.map +1 -0
  167. package/dist/src/core/compare-packages.d.ts +7 -0
  168. package/dist/src/core/compare-packages.js +19 -0
  169. package/dist/src/core/compare-packages.js.map +1 -0
  170. package/dist/src/core/config/load.d.ts +3 -0
  171. package/dist/src/core/config/load.js +21 -0
  172. package/dist/src/core/config/load.js.map +1 -0
  173. package/dist/src/core/config/policy.d.ts +3 -0
  174. package/dist/src/core/config/policy.js +48 -0
  175. package/dist/src/core/config/policy.js.map +1 -0
  176. package/dist/src/core/config/schema.d.ts +172 -0
  177. package/dist/src/core/config/schema.js +84 -0
  178. package/dist/src/core/config/schema.js.map +1 -0
  179. package/dist/src/core/dependencies/inventory.d.ts +9 -0
  180. package/dist/src/core/dependencies/inventory.js +43 -0
  181. package/dist/src/core/dependencies/inventory.js.map +1 -0
  182. package/dist/src/core/dependency-scan.d.ts +17 -0
  183. package/dist/src/core/dependency-scan.js +70 -0
  184. package/dist/src/core/dependency-scan.js.map +1 -0
  185. package/dist/src/core/dependency-tree.d.ts +16 -0
  186. package/dist/src/core/dependency-tree.js +19 -0
  187. package/dist/src/core/dependency-tree.js.map +1 -0
  188. package/dist/src/core/dependency-types.d.ts +17 -0
  189. package/dist/src/core/dependency-types.js +2 -0
  190. package/dist/src/core/dependency-types.js.map +1 -0
  191. package/dist/src/core/diff/security-diff.d.ts +10 -0
  192. package/dist/src/core/diff/security-diff.js +20 -0
  193. package/dist/src/core/diff/security-diff.js.map +1 -0
  194. package/dist/src/core/file-walker.d.ts +6 -0
  195. package/dist/src/core/file-walker.js +27 -0
  196. package/dist/src/core/file-walker.js.map +1 -0
  197. package/dist/src/core/git-audit.d.ts +12 -0
  198. package/dist/src/core/git-audit.js +111 -0
  199. package/dist/src/core/git-audit.js.map +1 -0
  200. package/dist/src/core/github/remote-audit.d.ts +5 -0
  201. package/dist/src/core/github/remote-audit.js +28 -0
  202. package/dist/src/core/github/remote-audit.js.map +1 -0
  203. package/dist/src/core/github/upgrade-pr.d.ts +4 -0
  204. package/dist/src/core/github/upgrade-pr.js +41 -0
  205. package/dist/src/core/github/upgrade-pr.js.map +1 -0
  206. package/dist/src/core/history/git-metadata.d.ts +5 -0
  207. package/dist/src/core/history/git-metadata.js +37 -0
  208. package/dist/src/core/history/git-metadata.js.map +1 -0
  209. package/dist/src/core/history/store.d.ts +5 -0
  210. package/dist/src/core/history/store.js +65 -0
  211. package/dist/src/core/history/store.js.map +1 -0
  212. package/dist/src/core/history/types.d.ts +27 -0
  213. package/dist/src/core/history/types.js +2 -0
  214. package/dist/src/core/history/types.js.map +1 -0
  215. package/dist/src/core/hooks.d.ts +1 -0
  216. package/dist/src/core/hooks.js +14 -0
  217. package/dist/src/core/hooks.js.map +1 -0
  218. package/dist/src/core/learn.d.ts +11 -0
  219. package/dist/src/core/learn.js +163 -0
  220. package/dist/src/core/learn.js.map +1 -0
  221. package/dist/src/core/license-analysis.d.ts +18 -0
  222. package/dist/src/core/license-analysis.js +98 -0
  223. package/dist/src/core/license-analysis.js.map +1 -0
  224. package/dist/src/core/load-toolip-ignore.d.ts +5 -0
  225. package/dist/src/core/load-toolip-ignore.js +35 -0
  226. package/dist/src/core/load-toolip-ignore.js.map +1 -0
  227. package/dist/src/core/monorepo/discover.d.ts +7 -0
  228. package/dist/src/core/monorepo/discover.js +49 -0
  229. package/dist/src/core/monorepo/discover.js.map +1 -0
  230. package/dist/src/core/npm-registry.d.ts +3 -0
  231. package/dist/src/core/npm-registry.js +5 -0
  232. package/dist/src/core/npm-registry.js.map +1 -0
  233. package/dist/src/core/pre-commit.d.ts +11 -0
  234. package/dist/src/core/pre-commit.js +22 -0
  235. package/dist/src/core/pre-commit.js.map +1 -0
  236. package/dist/src/core/profile-project.d.ts +23 -0
  237. package/dist/src/core/profile-project.js +119 -0
  238. package/dist/src/core/profile-project.js.map +1 -0
  239. package/dist/src/core/publish/html.d.ts +6 -0
  240. package/dist/src/core/publish/html.js +44 -0
  241. package/dist/src/core/publish/html.js.map +1 -0
  242. package/dist/src/core/read-dependencies.d.ts +2 -0
  243. package/dist/src/core/read-dependencies.js +24 -0
  244. package/dist/src/core/read-dependencies.js.map +1 -0
  245. package/dist/src/core/report-writer.d.ts +5 -0
  246. package/dist/src/core/report-writer.js +61 -0
  247. package/dist/src/core/report-writer.js.map +1 -0
  248. package/dist/src/core/report.d.ts +34 -0
  249. package/dist/src/core/report.js +26 -0
  250. package/dist/src/core/report.js.map +1 -0
  251. package/dist/src/core/risk-score.d.ts +5 -0
  252. package/dist/src/core/risk-score.js +14 -0
  253. package/dist/src/core/risk-score.js.map +1 -0
  254. package/dist/src/core/sbom/generate.d.ts +2 -0
  255. package/dist/src/core/sbom/generate.js +120 -0
  256. package/dist/src/core/sbom/generate.js.map +1 -0
  257. package/dist/src/core/scanner-context.d.ts +12 -0
  258. package/dist/src/core/scanner-context.js +27 -0
  259. package/dist/src/core/scanner-context.js.map +1 -0
  260. package/dist/src/core/score.d.ts +13 -0
  261. package/dist/src/core/score.js +44 -0
  262. package/dist/src/core/score.js.map +1 -0
  263. package/dist/src/core/security-doctor.d.ts +12 -0
  264. package/dist/src/core/security-doctor.js +158 -0
  265. package/dist/src/core/security-doctor.js.map +1 -0
  266. package/dist/src/core/security-patterns.d.ts +14 -0
  267. package/dist/src/core/security-patterns.js +139 -0
  268. package/dist/src/core/security-patterns.js.map +1 -0
  269. package/dist/src/core/typosquat.d.ts +6 -0
  270. package/dist/src/core/typosquat.js +50 -0
  271. package/dist/src/core/typosquat.js.map +1 -0
  272. package/dist/src/core/vault.d.ts +48 -0
  273. package/dist/src/core/vault.js +127 -0
  274. package/dist/src/core/vault.js.map +1 -0
  275. package/dist/src/core/watch/watch.d.ts +5 -0
  276. package/dist/src/core/watch/watch.js +49 -0
  277. package/dist/src/core/watch/watch.js.map +1 -0
  278. package/dist/src/errors/toolip-error.d.ts +8 -0
  279. package/dist/src/errors/toolip-error.js +11 -0
  280. package/dist/src/errors/toolip-error.js.map +1 -0
  281. package/dist/src/index.d.ts +2 -0
  282. package/dist/src/index.js +89 -0
  283. package/dist/src/index.js.map +1 -0
  284. package/dist/src/mcp/server.d.ts +1 -0
  285. package/dist/src/mcp/server.js +64 -0
  286. package/dist/src/mcp/server.js.map +1 -0
  287. package/dist/src/providers/depsdev/client.d.ts +71 -0
  288. package/dist/src/providers/depsdev/client.js +44 -0
  289. package/dist/src/providers/depsdev/client.js.map +1 -0
  290. package/dist/src/providers/osv/client.d.ts +15 -0
  291. package/dist/src/providers/osv/client.js +51 -0
  292. package/dist/src/providers/osv/client.js.map +1 -0
  293. package/dist/src/providers/osv/types.d.ts +38 -0
  294. package/dist/src/providers/osv/types.js +2 -0
  295. package/dist/src/providers/osv/types.js.map +1 -0
  296. package/dist/src/storage/memory-cache.d.ts +7 -0
  297. package/dist/src/storage/memory-cache.js +25 -0
  298. package/dist/src/storage/memory-cache.js.map +1 -0
  299. package/dist/src/utils/error-handler.d.ts +1 -0
  300. package/dist/src/utils/error-handler.js +24 -0
  301. package/dist/src/utils/error-handler.js.map +1 -0
  302. package/dist/src/utils/output.d.ts +6 -0
  303. package/dist/src/utils/output.js +72 -0
  304. package/dist/src/utils/output.js.map +1 -0
  305. package/dist/src/utils/package-output.d.ts +4 -0
  306. package/dist/src/utils/package-output.js +40 -0
  307. package/dist/src/utils/package-output.js.map +1 -0
  308. package/package.json +13 -8
@@ -0,0 +1,23 @@
1
+ export type ProjectProfile = {
2
+ root: string;
3
+ name: string;
4
+ version: string;
5
+ description: string;
6
+ packageManager: 'npm' | 'pnpm' | 'yarn' | 'unknown';
7
+ hasTypeScript: boolean;
8
+ hasJavaScript: boolean;
9
+ hasReact: boolean;
10
+ hasExpress: boolean;
11
+ hasFastify: boolean;
12
+ hasPrisma: boolean;
13
+ hasDocker: boolean;
14
+ hasVitest: boolean;
15
+ hasJest: boolean;
16
+ hasESLint: boolean;
17
+ hasPrettier: boolean;
18
+ hasGitHubActions: boolean;
19
+ detected: string[];
20
+ languages: Record<string, number>;
21
+ packageScripts: string[];
22
+ };
23
+ export declare function profileProject(root: string): Promise<ProjectProfile>;
@@ -0,0 +1,119 @@
1
+ import { access, readFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { walkProjectFiles } from './file-walker.js';
4
+ async function fileExists(filePath) {
5
+ try {
6
+ await access(filePath);
7
+ return true;
8
+ }
9
+ catch {
10
+ return false;
11
+ }
12
+ }
13
+ async function readPackageJson(root) {
14
+ const packagePath = path.join(root, 'package.json');
15
+ if (!(await fileExists(packagePath))) {
16
+ return {};
17
+ }
18
+ const raw = await readFile(packagePath, 'utf8');
19
+ return JSON.parse(raw);
20
+ }
21
+ function dependencyNames(packageJson) {
22
+ const dependencies = packageJson.dependencies;
23
+ const devDependencies = packageJson.devDependencies;
24
+ return [
25
+ ...Object.keys(dependencies ?? {}),
26
+ ...Object.keys(devDependencies ?? {})
27
+ ];
28
+ }
29
+ function packageScripts(packageJson) {
30
+ const scripts = packageJson.scripts;
31
+ return Object.keys(scripts ?? {});
32
+ }
33
+ async function detectPackageManager(root) {
34
+ if (await fileExists(path.join(root, 'pnpm-lock.yaml')))
35
+ return 'pnpm';
36
+ if (await fileExists(path.join(root, 'yarn.lock')))
37
+ return 'yarn';
38
+ if (await fileExists(path.join(root, 'package-lock.json')))
39
+ return 'npm';
40
+ return 'unknown';
41
+ }
42
+ function summarizeLanguages(files) {
43
+ const languageMap = {
44
+ ts: 'TypeScript',
45
+ tsx: 'TypeScript React',
46
+ js: 'JavaScript',
47
+ jsx: 'JavaScript React',
48
+ json: 'JSON',
49
+ yml: 'YAML',
50
+ yaml: 'YAML',
51
+ md: 'Markdown',
52
+ css: 'CSS',
53
+ html: 'HTML',
54
+ env: 'Environment',
55
+ dockerfile: 'Docker'
56
+ };
57
+ return files.reduce((summary, file) => {
58
+ const extension = file.extension || file.relativePath.toLowerCase();
59
+ const language = languageMap[extension] ?? extension.toUpperCase();
60
+ summary[language] = (summary[language] ?? 0) + 1;
61
+ return summary;
62
+ }, {});
63
+ }
64
+ export async function profileProject(root) {
65
+ const absoluteRoot = path.resolve(root);
66
+ const packageJson = await readPackageJson(absoluteRoot);
67
+ const deps = dependencyNames(packageJson);
68
+ const scripts = packageScripts(packageJson);
69
+ const files = await walkProjectFiles(absoluteRoot);
70
+ const packageManager = await detectPackageManager(absoluteRoot);
71
+ const profile = {
72
+ root: absoluteRoot,
73
+ name: typeof packageJson.name === 'string' ? packageJson.name : 'unknown',
74
+ version: typeof packageJson.version === 'string' ? packageJson.version : 'unknown',
75
+ description: typeof packageJson.description === 'string' ? packageJson.description : '',
76
+ packageManager,
77
+ hasTypeScript: deps.includes('typescript') || await fileExists(path.join(absoluteRoot, 'tsconfig.json')),
78
+ hasJavaScript: files.some((file) => ['js', 'jsx'].includes(file.extension)),
79
+ hasReact: deps.includes('react'),
80
+ hasExpress: deps.includes('express'),
81
+ hasFastify: deps.includes('fastify'),
82
+ hasPrisma: deps.includes('prisma') || deps.includes('@prisma/client'),
83
+ hasDocker: await fileExists(path.join(absoluteRoot, 'Dockerfile')) || await fileExists(path.join(absoluteRoot, 'docker-compose.yml')),
84
+ hasVitest: deps.includes('vitest'),
85
+ hasJest: deps.includes('jest'),
86
+ hasESLint: deps.includes('eslint'),
87
+ hasPrettier: deps.includes('prettier'),
88
+ hasGitHubActions: await fileExists(path.join(absoluteRoot, '.github', 'workflows')),
89
+ detected: [],
90
+ languages: summarizeLanguages(files),
91
+ packageScripts: scripts
92
+ };
93
+ if (profile.hasTypeScript)
94
+ profile.detected.push('TypeScript');
95
+ if (profile.hasJavaScript)
96
+ profile.detected.push('JavaScript');
97
+ if (profile.hasReact)
98
+ profile.detected.push('React');
99
+ if (profile.hasExpress)
100
+ profile.detected.push('Express');
101
+ if (profile.hasFastify)
102
+ profile.detected.push('Fastify');
103
+ if (profile.hasPrisma)
104
+ profile.detected.push('Prisma');
105
+ if (profile.hasDocker)
106
+ profile.detected.push('Docker');
107
+ if (profile.hasVitest)
108
+ profile.detected.push('Vitest');
109
+ if (profile.hasJest)
110
+ profile.detected.push('Jest');
111
+ if (profile.hasESLint)
112
+ profile.detected.push('ESLint');
113
+ if (profile.hasPrettier)
114
+ profile.detected.push('Prettier');
115
+ if (profile.hasGitHubActions)
116
+ profile.detected.push('GitHub Actions');
117
+ return profile;
118
+ }
119
+ //# sourceMappingURL=profile-project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-project.js","sourceRoot":"","sources":["../../../src/core/profile-project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { ToolipFinding } from '../report.js';
2
+ export declare function renderHtmlReport(input: {
3
+ project: string;
4
+ generatedAt: string;
5
+ findings: ToolipFinding[];
6
+ }): string;
@@ -0,0 +1,44 @@
1
+ function escapeHtml(value) {
2
+ return value
3
+ .replaceAll('&', '&amp;')
4
+ .replaceAll('<', '&lt;')
5
+ .replaceAll('>', '&gt;')
6
+ .replaceAll('"', '&quot;')
7
+ .replaceAll("'", '&#039;');
8
+ }
9
+ export function renderHtmlReport(input) {
10
+ const rows = input.findings.map((finding) => `
11
+ <tr>
12
+ <td>${escapeHtml(finding.severity)}</td>
13
+ <td>${escapeHtml(finding.title)}</td>
14
+ <td>${escapeHtml(finding.file ?? '')}</td>
15
+ <td>${escapeHtml(finding.recommendation)}</td>
16
+ </tr>
17
+ `).join('');
18
+ return `<!doctype html>
19
+ <html lang="en">
20
+ <head>
21
+ <meta charset="utf-8">
22
+ <meta name="viewport" content="width=device-width,initial-scale=1">
23
+ <title>Toolip Security Report</title>
24
+ <style>
25
+ body{font-family:system-ui,sans-serif;max-width:1100px;margin:40px auto;padding:0 20px;color:#111}
26
+ table{width:100%;border-collapse:collapse}
27
+ th,td{border:1px solid #ddd;padding:10px;text-align:left;vertical-align:top}
28
+ th{background:#f5f5f5}
29
+ code{font-family:ui-monospace,monospace}
30
+ </style>
31
+ </head>
32
+ <body>
33
+ <h1>Toolip Security Report</h1>
34
+ <p><strong>Project:</strong> ${escapeHtml(input.project)}</p>
35
+ <p><strong>Generated:</strong> ${escapeHtml(input.generatedAt)}</p>
36
+ <p><strong>Findings:</strong> ${input.findings.length}</p>
37
+ <table>
38
+ <thead><tr><th>Severity</th><th>Finding</th><th>File</th><th>Recommendation</th></tr></thead>
39
+ <tbody>${rows}</tbody>
40
+ </table>
41
+ </body>
42
+ </html>`;
43
+ }
44
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../../../src/core/publish/html.ts"],"names":[],"mappings":"AAEA,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAIhC;IACC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;;YAEnC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC5B,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC;YACzB,UAAU,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;YAC9B,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC;;GAE3C,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEZ,OAAO;;;;;;;;;;;;;;;;+BAgBsB,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC;iCACvB,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC;gCAC9B,KAAK,CAAC,QAAQ,CAAC,MAAM;;;SAG5C,IAAI;;;QAGL,CAAC;AACT,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { DependencyInfo } from './dependency-types.js';
2
+ export declare function readDependencies(root: string): Promise<DependencyInfo[]>;
@@ -0,0 +1,24 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ export async function readDependencies(root) {
4
+ const packageJsonPath = path.join(root, 'package.json');
5
+ const raw = await readFile(packageJsonPath, 'utf8');
6
+ const pkg = JSON.parse(raw);
7
+ const results = [];
8
+ for (const [name, version] of Object.entries(pkg.dependencies ?? {})) {
9
+ results.push({
10
+ name,
11
+ version,
12
+ type: 'dependency'
13
+ });
14
+ }
15
+ for (const [name, version] of Object.entries(pkg.devDependencies ?? {})) {
16
+ results.push({
17
+ name,
18
+ version,
19
+ type: 'devDependency'
20
+ });
21
+ }
22
+ return results.sort((a, b) => a.name.localeCompare(b.name));
23
+ }
24
+ //# sourceMappingURL=read-dependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-dependencies.js","sourceRoot":"","sources":["../../../src/core/read-dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY;IACjD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAEpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAGzB,CAAC;IAEF,MAAM,OAAO,GAAqB,EAAE,CAAC;IAErC,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC;YACX,IAAI;YACJ,OAAO;YACP,IAAI,EAAE,YAAY;SACnB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC,EAAE,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC;YACX,IAAI;YACJ,OAAO;YACP,IAAI,EAAE,eAAe;SACtB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { ToolipReport } from './report.js';
2
+ export type ReportFormat = 'json' | 'md';
3
+ export declare function detectReportFormat(outputPath: string): ReportFormat;
4
+ export declare function writeReport(outputPath: string, report: ToolipReport): Promise<void>;
5
+ export declare function renderMarkdownReport(report: ToolipReport): string;
@@ -0,0 +1,61 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ export function detectReportFormat(outputPath) {
4
+ const extension = path.extname(outputPath).toLowerCase();
5
+ if (extension === '.md' || extension === '.markdown') {
6
+ return 'md';
7
+ }
8
+ return 'json';
9
+ }
10
+ export async function writeReport(outputPath, report) {
11
+ const format = detectReportFormat(outputPath);
12
+ if (format === 'md') {
13
+ await writeFile(outputPath, renderMarkdownReport(report), 'utf8');
14
+ return;
15
+ }
16
+ await writeFile(outputPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
17
+ }
18
+ export function renderMarkdownReport(report) {
19
+ const findings = report.findings.length
20
+ ? report.findings
21
+ .map((finding) => {
22
+ const fileLine = finding.file ? `\n- File: \`${finding.file}\`` : '';
23
+ const evidenceLine = finding.evidence ? `\n- Evidence: \`${finding.evidence}\`` : '';
24
+ return `### ${finding.title}
25
+
26
+ - ID: \`${finding.id}\`
27
+ - Severity: **${finding.severity.toUpperCase()}**
28
+ - Category: ${finding.category}${fileLine}${evidenceLine}
29
+
30
+ ${finding.message}
31
+
32
+ **Recommendation:** ${finding.recommendation}
33
+ `;
34
+ })
35
+ .join('\n')
36
+ : 'No findings were detected.';
37
+ return `# Toolip Report
38
+
39
+ Generated: ${report.generatedAt}
40
+
41
+ Root: \`${report.root}\`
42
+
43
+ Command: \`${report.command}\`
44
+
45
+ ## Summary
46
+
47
+ | Severity | Count |
48
+ |---|---:|
49
+ | Critical | ${report.summary.critical} |
50
+ | High | ${report.summary.high} |
51
+ | Medium | ${report.summary.medium} |
52
+ | Low | ${report.summary.low} |
53
+ | Info | ${report.summary.info} |
54
+ | Total | ${report.summary.totalFindings} |
55
+
56
+ ## Findings
57
+
58
+ ${findings}
59
+ `;
60
+ }
61
+ //# sourceMappingURL=report-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-writer.js","sourceRoot":"","sources":["../../../src/core/report-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,IAAI,MAAM,WAAW,CAAC;AAK7B,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IAEzD,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,WAAW,EAAE,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAkB,EAAE,MAAoB;IACxE,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAE9C,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,SAAS,CAAC,UAAU,EAAE,oBAAoB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;QAClE,OAAO;IACT,CAAC;IAED,MAAM,SAAS,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAoB;IACvD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM;QACrC,CAAC,CAAC,MAAM,CAAC,QAAQ;aACZ,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;YACf,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,mBAAmB,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAErF,OAAO,OAAO,OAAO,CAAC,KAAK;;UAE3B,OAAO,CAAC,EAAE;gBACJ,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE;cAChC,OAAO,CAAC,QAAQ,GAAG,QAAQ,GAAG,YAAY;;EAEtD,OAAO,CAAC,OAAO;;sBAEK,OAAO,CAAC,cAAc;CAC3C,CAAC;QACM,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC;QACf,CAAC,CAAC,4BAA4B,CAAC;IAEjC,OAAO;;aAEI,MAAM,CAAC,WAAW;;UAErB,MAAM,CAAC,IAAI;;aAER,MAAM,CAAC,OAAO;;;;;;eAMZ,MAAM,CAAC,OAAO,CAAC,QAAQ;WAC3B,MAAM,CAAC,OAAO,CAAC,IAAI;aACjB,MAAM,CAAC,OAAO,CAAC,MAAM;UACxB,MAAM,CAAC,OAAO,CAAC,GAAG;WACjB,MAAM,CAAC,OAAO,CAAC,IAAI;YAClB,MAAM,CAAC,OAAO,CAAC,aAAa;;;;EAItC,QAAQ;CACT,CAAC;AACF,CAAC"}
@@ -0,0 +1,34 @@
1
+ export type FindingSeverity = 'info' | 'low' | 'medium' | 'high' | 'critical';
2
+ export type ToolipFinding = {
3
+ id: string;
4
+ title: string;
5
+ severity: FindingSeverity;
6
+ category: string;
7
+ message: string;
8
+ recommendation: string;
9
+ file?: string;
10
+ evidence?: string;
11
+ };
12
+ export type ToolipReport = {
13
+ tool: 'toolip';
14
+ version: string;
15
+ command: string;
16
+ generatedAt: string;
17
+ root: string;
18
+ summary: {
19
+ totalFindings: number;
20
+ critical: number;
21
+ high: number;
22
+ medium: number;
23
+ low: number;
24
+ info: number;
25
+ };
26
+ findings: ToolipFinding[];
27
+ };
28
+ export declare function createReport(input: {
29
+ version: string;
30
+ command: string;
31
+ root: string;
32
+ findings: ToolipFinding[];
33
+ }): ToolipReport;
34
+ export declare function summarizeFindings(findings: ToolipFinding[]): ToolipReport['summary'];
@@ -0,0 +1,26 @@
1
+ export function createReport(input) {
2
+ return {
3
+ tool: 'toolip',
4
+ version: input.version,
5
+ command: input.command,
6
+ generatedAt: new Date().toISOString(),
7
+ root: input.root,
8
+ summary: summarizeFindings(input.findings),
9
+ findings: input.findings
10
+ };
11
+ }
12
+ export function summarizeFindings(findings) {
13
+ return findings.reduce((summary, finding) => {
14
+ summary.totalFindings += 1;
15
+ summary[finding.severity] += 1;
16
+ return summary;
17
+ }, {
18
+ totalFindings: 0,
19
+ critical: 0,
20
+ high: 0,
21
+ medium: 0,
22
+ low: 0,
23
+ info: 0
24
+ });
25
+ }
26
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/core/report.ts"],"names":[],"mappings":"AA8BA,MAAM,UAAU,YAAY,CAAC,KAK5B;IACC,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC1C,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAyB;IACzD,OAAO,QAAQ,CAAC,MAAM,CACpB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE;QACnB,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,OAAO,CAAC;IACjB,CAAC,EACD;QACE,aAAa,EAAE,CAAC;QAChB,QAAQ,EAAE,CAAC;QACX,IAAI,EAAE,CAAC;QACP,MAAM,EAAE,CAAC;QACT,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;KACR,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function calculateRiskScore(input: {
2
+ deprecated: boolean;
3
+ maintainers: number;
4
+ ageInDays: number | null;
5
+ }): number;
@@ -0,0 +1,14 @@
1
+ export function calculateRiskScore(input) {
2
+ let score = 0;
3
+ if (input.deprecated)
4
+ score += 40;
5
+ if (input.maintainers === 0)
6
+ score += 30;
7
+ else if (input.maintainers === 1)
8
+ score += 15;
9
+ if (input.ageInDays !== null && input.ageInDays > 730) {
10
+ score += 20;
11
+ }
12
+ return Math.min(score, 100);
13
+ }
14
+ //# sourceMappingURL=risk-score.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risk-score.js","sourceRoot":"","sources":["../../../src/core/risk-score.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,kBAAkB,CAAC,KAIlC;IACC,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,IAAI,KAAK,CAAC,UAAU;QAAE,KAAK,IAAI,EAAE,CAAC;IAElC,IAAI,KAAK,CAAC,WAAW,KAAK,CAAC;QAAE,KAAK,IAAI,EAAE,CAAC;SACpC,IAAI,KAAK,CAAC,WAAW,KAAK,CAAC;QAAE,KAAK,IAAI,EAAE,CAAC;IAE9C,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,IAAI,KAAK,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;QACtD,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export type SbomFormat = 'cyclonedx' | 'spdx';
2
+ export declare function generateSbom(root: string, format: SbomFormat): Promise<Record<string, unknown>>;
@@ -0,0 +1,120 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { readFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { readNpmDependencyInventory } from '../dependencies/inventory.js';
5
+ function purl(dependency) {
6
+ return (`pkg:npm/${encodeURIComponent(dependency.name)}@${encodeURIComponent(dependency.version)}`);
7
+ }
8
+ function bomRef(dependency) {
9
+ return purl(dependency);
10
+ }
11
+ function spdxId(value) {
12
+ return ('SPDXRef-' +
13
+ value.replaceAll(/[^A-Za-z0-9.-]/g, '-'));
14
+ }
15
+ function namespace(name, version) {
16
+ const digest = createHash('sha256')
17
+ .update(`${name}@${version}:${Date.now()}`)
18
+ .digest('hex')
19
+ .slice(0, 24);
20
+ return `https://toolip.dev/spdx/${encodeURIComponent(name)}/${version}/${digest}`;
21
+ }
22
+ export async function generateSbom(root, format) {
23
+ const manifest = JSON.parse(await readFile(path.join(root, 'package.json'), 'utf8'));
24
+ const dependencies = await readNpmDependencyInventory(root);
25
+ const rootName = manifest.name ?? 'unknown-project';
26
+ const rootVersion = manifest.version ?? '0.0.0';
27
+ if (format === 'cyclonedx') {
28
+ return {
29
+ bomFormat: 'CycloneDX',
30
+ specVersion: '1.5',
31
+ serialNumber: `urn:uuid:${crypto.randomUUID()}`,
32
+ version: 1,
33
+ metadata: {
34
+ timestamp: new Date().toISOString(),
35
+ tools: [
36
+ {
37
+ vendor: 'Toolip',
38
+ name: 'toolip'
39
+ }
40
+ ],
41
+ component: {
42
+ type: 'application',
43
+ name: rootName,
44
+ version: rootVersion,
45
+ description: manifest.description
46
+ }
47
+ },
48
+ components: dependencies.map((dependency) => ({
49
+ type: 'library',
50
+ 'bom-ref': bomRef(dependency),
51
+ name: dependency.name,
52
+ version: dependency.version,
53
+ scope: dependency.development
54
+ ? 'optional'
55
+ : 'required',
56
+ purl: purl(dependency),
57
+ properties: [
58
+ {
59
+ name: 'toolip:direct',
60
+ value: String(dependency.direct)
61
+ },
62
+ {
63
+ name: 'toolip:development',
64
+ value: String(dependency.development)
65
+ }
66
+ ]
67
+ })),
68
+ dependencies: dependencies.map((dependency) => ({
69
+ ref: bomRef(dependency),
70
+ dependsOn: []
71
+ }))
72
+ };
73
+ }
74
+ const documentId = 'SPDXRef-DOCUMENT';
75
+ const rootId = spdxId(`${rootName}-${rootVersion}`);
76
+ return {
77
+ spdxVersion: 'SPDX-2.3',
78
+ dataLicense: 'CC0-1.0',
79
+ SPDXID: documentId,
80
+ name: `${rootName}-${rootVersion}`,
81
+ documentNamespace: namespace(rootName, rootVersion),
82
+ creationInfo: {
83
+ created: new Date().toISOString(),
84
+ creators: ['Tool: Toolip']
85
+ },
86
+ packages: [
87
+ {
88
+ name: rootName,
89
+ SPDXID: rootId,
90
+ versionInfo: rootVersion,
91
+ downloadLocation: 'NOASSERTION',
92
+ filesAnalyzed: false,
93
+ licenseConcluded: manifest.license ?? 'NOASSERTION',
94
+ licenseDeclared: manifest.license ?? 'NOASSERTION'
95
+ },
96
+ ...dependencies.map((dependency) => ({
97
+ name: dependency.name,
98
+ SPDXID: spdxId(`${dependency.name}-${dependency.version}`),
99
+ versionInfo: dependency.version,
100
+ downloadLocation: 'NOASSERTION',
101
+ filesAnalyzed: false,
102
+ licenseConcluded: 'NOASSERTION',
103
+ licenseDeclared: 'NOASSERTION',
104
+ externalRefs: [
105
+ {
106
+ referenceCategory: 'PACKAGE-MANAGER',
107
+ referenceType: 'purl',
108
+ referenceLocator: purl(dependency)
109
+ }
110
+ ]
111
+ }))
112
+ ],
113
+ relationships: dependencies.map((dependency) => ({
114
+ spdxElementId: rootId,
115
+ relationshipType: 'DEPENDS_ON',
116
+ relatedSpdxElement: spdxId(`${dependency.name}-${dependency.version}`)
117
+ }))
118
+ };
119
+ }
120
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../../src/core/sbom/generate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { type ProjectFile } from './file-walker.js';
2
+ import { type ProjectProfile } from './profile-project.js';
3
+ export type ScannerContext = {
4
+ root: string;
5
+ profile: ProjectProfile;
6
+ files: ProjectFile[];
7
+ summary: {
8
+ totalFiles: number;
9
+ extensions: Record<string, number>;
10
+ };
11
+ };
12
+ export declare function createScannerContext(root: string): Promise<ScannerContext>;
@@ -0,0 +1,27 @@
1
+ import path from 'node:path';
2
+ import { walkProjectFiles } from './file-walker.js';
3
+ import { profileProject } from './profile-project.js';
4
+ function summarizeExtensions(files) {
5
+ return files.reduce((summary, file) => {
6
+ const key = file.extension || 'none';
7
+ summary[key] = (summary[key] ?? 0) + 1;
8
+ return summary;
9
+ }, {});
10
+ }
11
+ export async function createScannerContext(root) {
12
+ const absoluteRoot = path.resolve(root);
13
+ const [profile, files] = await Promise.all([
14
+ profileProject(absoluteRoot),
15
+ walkProjectFiles(absoluteRoot)
16
+ ]);
17
+ return {
18
+ root: absoluteRoot,
19
+ profile,
20
+ files,
21
+ summary: {
22
+ totalFiles: files.length,
23
+ extensions: summarizeExtensions(files)
24
+ }
25
+ };
26
+ }
27
+ //# sourceMappingURL=scanner-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner-context.js","sourceRoot":"","sources":["../../../src/core/scanner-context.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAuB,MAAM,sBAAsB,CAAC;AAY3E,SAAS,mBAAmB,CAAC,KAAoB;IAC/C,OAAO,KAAK,CAAC,MAAM,CAAyB,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;QAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC;IACjB,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAY;IACrD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACzC,cAAc,CAAC,YAAY,CAAC;QAC5B,gBAAgB,CAAC,YAAY,CAAC;KAC/B,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,OAAO;QACP,KAAK;QACL,OAAO,EAAE;YACP,UAAU,EAAE,KAAK,CAAC,MAAM;YACxB,UAAU,EAAE,mBAAmB,CAAC,KAAK,CAAC;SACvC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { ToolipFinding } from './report.js';
2
+ export type ScoreGrade = 'A' | 'B' | 'C' | 'D' | 'F';
3
+ export type ToolipScore = {
4
+ dependencyHealth: number;
5
+ secretHygiene: number;
6
+ configurationSecurity: number;
7
+ gitSafety: number;
8
+ overall: number;
9
+ grade: ScoreGrade;
10
+ };
11
+ export declare function calculateScore(input?: Partial<Omit<ToolipScore, 'overall' | 'grade'>>): ToolipScore;
12
+ export declare function calculateDependencyHealth(findings: ToolipFinding[]): number;
13
+ export declare function gradeScore(score: number): ScoreGrade;
@@ -0,0 +1,44 @@
1
+ export function calculateScore(input) {
2
+ const dependencyHealth = clamp(input?.dependencyHealth ?? 100);
3
+ const secretHygiene = clamp(input?.secretHygiene ?? 100);
4
+ const configurationSecurity = clamp(input?.configurationSecurity ?? 100);
5
+ const gitSafety = clamp(input?.gitSafety ?? 100);
6
+ const overall = Math.round((dependencyHealth + secretHygiene + configurationSecurity + gitSafety) / 4);
7
+ return {
8
+ dependencyHealth,
9
+ secretHygiene,
10
+ configurationSecurity,
11
+ gitSafety,
12
+ overall,
13
+ grade: gradeScore(overall)
14
+ };
15
+ }
16
+ export function calculateDependencyHealth(findings) {
17
+ const penalty = findings.reduce((total, finding) => {
18
+ if (finding.severity === 'critical')
19
+ return total + 35;
20
+ if (finding.severity === 'high')
21
+ return total + 25;
22
+ if (finding.severity === 'medium')
23
+ return total + 12;
24
+ if (finding.severity === 'low')
25
+ return total + 5;
26
+ return total + 0;
27
+ }, 0);
28
+ return clamp(100 - penalty);
29
+ }
30
+ function clamp(value) {
31
+ return Math.max(0, Math.min(100, Math.round(value)));
32
+ }
33
+ export function gradeScore(score) {
34
+ if (score >= 90)
35
+ return 'A';
36
+ if (score >= 80)
37
+ return 'B';
38
+ if (score >= 70)
39
+ return 'C';
40
+ if (score >= 60)
41
+ return 'D';
42
+ return 'F';
43
+ }
44
+ //# sourceMappingURL=score.js.map