codebase-onboarder 0.5.0 → 0.7.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 (448) hide show
  1. package/README.md +196 -47
  2. package/bin/build-if-source.js +23 -0
  3. package/cli/commands.d.ts +26 -0
  4. package/cli/commands.js +836 -811
  5. package/cli/commands.js.map +1 -0
  6. package/cli/explorer/advanced.d.ts +14 -0
  7. package/cli/explorer/advanced.js +449 -0
  8. package/cli/explorer/advanced.js.map +1 -0
  9. package/cli/explorer/app.d.ts +1 -0
  10. package/cli/explorer/app.js +396 -229
  11. package/cli/explorer/app.js.map +1 -0
  12. package/cli/explorer/assistant.d.ts +9 -0
  13. package/cli/explorer/assistant.js +58 -0
  14. package/cli/explorer/assistant.js.map +1 -0
  15. package/cli/explorer/commands.d.ts +17 -0
  16. package/cli/explorer/commands.js +400 -162
  17. package/cli/explorer/commands.js.map +1 -0
  18. package/cli/explorer/featureViews.d.ts +124 -0
  19. package/cli/explorer/featureViews.js +179 -0
  20. package/cli/explorer/featureViews.js.map +1 -0
  21. package/cli/explorer/github.d.ts +21 -0
  22. package/cli/explorer/github.js +73 -0
  23. package/cli/explorer/github.js.map +1 -0
  24. package/cli/explorer/graphs.d.ts +7 -0
  25. package/cli/explorer/graphs.js +173 -0
  26. package/cli/explorer/graphs.js.map +1 -0
  27. package/cli/explorer/picker.d.ts +22 -0
  28. package/cli/explorer/picker.js +150 -0
  29. package/cli/explorer/picker.js.map +1 -0
  30. package/cli/explorer/report.d.ts +85 -0
  31. package/cli/explorer/report.js +60 -0
  32. package/cli/explorer/report.js.map +1 -0
  33. package/cli/explorer/session.d.ts +449 -0
  34. package/cli/explorer/session.js +184 -95
  35. package/cli/explorer/session.js.map +1 -0
  36. package/cli/explorer/views.d.ts +19 -0
  37. package/cli/explorer/views.js +496 -412
  38. package/cli/explorer/views.js.map +1 -0
  39. package/cli/explorer/wrap.d.ts +1 -0
  40. package/cli/explorer/wrap.js +33 -0
  41. package/cli/explorer/wrap.js.map +1 -0
  42. package/cli/main.d.ts +1 -0
  43. package/cli/main.js +235 -138
  44. package/cli/main.js.map +1 -0
  45. package/cli/prompt.d.ts +5 -0
  46. package/cli/prompt.js +84 -80
  47. package/cli/prompt.js.map +1 -0
  48. package/cli/scanOptions.d.ts +2 -0
  49. package/cli/scanOptions.js +11 -0
  50. package/cli/scanOptions.js.map +1 -0
  51. package/cli/ui.d.ts +33 -0
  52. package/cli/ui.js +55 -35
  53. package/cli/ui.js.map +1 -0
  54. package/cli/wizard.d.ts +187 -0
  55. package/cli/wizard.js +304 -284
  56. package/cli/wizard.js.map +1 -0
  57. package/package.json +15 -4
  58. package/public/app.d.ts +1 -0
  59. package/public/app.js +1057 -1009
  60. package/public/app.js.map +1 -0
  61. package/public/browser.d.ts +68 -0
  62. package/public/browser.js +2 -0
  63. package/public/browser.js.map +1 -0
  64. package/public/index.html +30 -13
  65. package/public/js/about.d.ts +6 -0
  66. package/public/js/about.js +165 -172
  67. package/public/js/about.js.map +1 -0
  68. package/public/js/aiDraft.d.ts +3 -0
  69. package/public/js/aiDraft.js +116 -124
  70. package/public/js/aiDraft.js.map +1 -0
  71. package/public/js/analysisPanel.d.ts +7 -0
  72. package/public/js/analysisPanel.js +166 -166
  73. package/public/js/analysisPanel.js.map +1 -0
  74. package/public/js/analysisReport.d.ts +38 -0
  75. package/public/js/analysisReport.js +105 -110
  76. package/public/js/analysisReport.js.map +1 -0
  77. package/public/js/api.d.ts +26 -0
  78. package/public/js/api.js +176 -167
  79. package/public/js/api.js.map +1 -0
  80. package/public/js/atlas.d.ts +6 -0
  81. package/public/js/atlas.js +50 -58
  82. package/public/js/atlas.js.map +1 -0
  83. package/public/js/blameView.d.ts +2 -0
  84. package/public/js/blameView.js +36 -37
  85. package/public/js/blameView.js.map +1 -0
  86. package/public/js/codeTab.d.ts +3 -0
  87. package/public/js/codeTab.js +175 -180
  88. package/public/js/codeTab.js.map +1 -0
  89. package/public/js/codeViewer.d.ts +5 -0
  90. package/public/js/codeViewer.js +162 -150
  91. package/public/js/codeViewer.js.map +1 -0
  92. package/public/js/components/FileChip.d.ts +9 -0
  93. package/public/js/components/FileChip.js +45 -49
  94. package/public/js/components/FileChip.js.map +1 -0
  95. package/public/js/components/MetricSparkline.d.ts +7 -0
  96. package/public/js/components/MetricSparkline.js +35 -44
  97. package/public/js/components/MetricSparkline.js.map +1 -0
  98. package/public/js/components/RiskBadge.d.ts +9 -0
  99. package/public/js/components/RiskBadge.js +55 -63
  100. package/public/js/components/RiskBadge.js.map +1 -0
  101. package/public/js/deepAnalysisView.d.ts +99 -0
  102. package/public/js/deepAnalysisView.js +282 -302
  103. package/public/js/deepAnalysisView.js.map +1 -0
  104. package/public/js/diagramPane.d.ts +8 -0
  105. package/public/js/diagramPane.js +133 -135
  106. package/public/js/diagramPane.js.map +1 -0
  107. package/public/js/diffView.d.ts +6 -0
  108. package/public/js/diffView.js +222 -209
  109. package/public/js/diffView.js.map +1 -0
  110. package/public/js/docsView.d.ts +2 -0
  111. package/public/js/docsView.js +441 -442
  112. package/public/js/docsView.js.map +1 -0
  113. package/public/js/dom.d.ts +189 -0
  114. package/public/js/dom.js +5 -0
  115. package/public/js/dom.js.map +1 -0
  116. package/public/js/fileSourceBrowser.d.ts +5 -0
  117. package/public/js/fileSourceBrowser.js +33 -41
  118. package/public/js/fileSourceBrowser.js.map +1 -0
  119. package/public/js/flameGraph.d.ts +5 -0
  120. package/public/js/flameGraph.js +62 -72
  121. package/public/js/flameGraph.js.map +1 -0
  122. package/public/js/forceGraph.d.ts +10 -0
  123. package/public/js/forceGraph.js +581 -556
  124. package/public/js/forceGraph.js.map +1 -0
  125. package/public/js/heatmap.d.ts +4 -0
  126. package/public/js/heatmap.js +142 -164
  127. package/public/js/heatmap.js.map +1 -0
  128. package/public/js/highlight.d.ts +2 -0
  129. package/public/js/highlight.js +116 -107
  130. package/public/js/highlight.js.map +1 -0
  131. package/public/js/html.d.ts +2 -0
  132. package/public/js/html.js +14 -44
  133. package/public/js/html.js.map +1 -0
  134. package/public/js/insightsView.d.ts +5 -0
  135. package/public/js/insightsView.js +93 -111
  136. package/public/js/insightsView.js.map +1 -0
  137. package/public/js/inspector.d.ts +37 -0
  138. package/public/js/inspector.js +416 -445
  139. package/public/js/inspector.js.map +1 -0
  140. package/public/js/llm.d.ts +113 -0
  141. package/public/js/llm.js +233 -272
  142. package/public/js/llm.js.map +1 -0
  143. package/public/js/mapView.d.ts +3 -0
  144. package/public/js/mapView.js +121 -120
  145. package/public/js/mapView.js.map +1 -0
  146. package/public/js/markdown.d.ts +3 -0
  147. package/public/js/markdown.js +84 -91
  148. package/public/js/markdown.js.map +1 -0
  149. package/public/js/mindmap.d.ts +32 -0
  150. package/public/js/mindmap.js +244 -259
  151. package/public/js/mindmap.js.map +1 -0
  152. package/public/js/mobilePanels.d.ts +5 -0
  153. package/public/js/mobilePanels.js +50 -0
  154. package/public/js/mobilePanels.js.map +1 -0
  155. package/public/js/repoFiles.d.ts +12 -0
  156. package/public/js/repoFiles.js +28 -27
  157. package/public/js/repoFiles.js.map +1 -0
  158. package/public/js/reviewView.d.ts +28 -0
  159. package/public/js/reviewView.js +256 -0
  160. package/public/js/reviewView.js.map +1 -0
  161. package/public/js/sbomView.d.ts +3 -0
  162. package/public/js/sbomView.js +59 -67
  163. package/public/js/sbomView.js.map +1 -0
  164. package/public/js/scanCache.d.ts +16 -0
  165. package/public/js/scanCache.js +67 -65
  166. package/public/js/scanCache.js.map +1 -0
  167. package/public/js/search.d.ts +7 -0
  168. package/public/js/search.js +868 -800
  169. package/public/js/search.js.map +1 -0
  170. package/public/js/searchLocal.d.ts +42 -0
  171. package/public/js/searchLocal.js +87 -0
  172. package/public/js/searchLocal.js.map +1 -0
  173. package/public/js/serverSettings.d.ts +5 -0
  174. package/public/js/serverSettings.js +153 -164
  175. package/public/js/serverSettings.js.map +1 -0
  176. package/public/js/state.d.ts +798 -0
  177. package/public/js/state.js +114 -122
  178. package/public/js/state.js.map +1 -0
  179. package/public/js/tour.d.ts +6 -0
  180. package/public/js/tour.js +5 -7
  181. package/public/js/tour.js.map +1 -0
  182. package/public/js/transitions.d.ts +2 -0
  183. package/public/js/transitions.js +9 -10
  184. package/public/js/transitions.js.map +1 -0
  185. package/public/js/tree.d.ts +12 -0
  186. package/public/js/tree.js +157 -154
  187. package/public/js/tree.js.map +1 -0
  188. package/public/js/workflowsView.d.ts +3 -0
  189. package/public/js/workflowsView.js +15 -22
  190. package/public/js/workflowsView.js.map +1 -0
  191. package/public/search.css +495 -0
  192. package/public/styles.css +163 -346
  193. package/public/workbench.css +166 -0
  194. package/server/apiAuth.d.ts +3 -0
  195. package/server/apiAuth.js +18 -20
  196. package/server/apiAuth.js.map +1 -0
  197. package/server/apiDiff.d.ts +2 -0
  198. package/server/apiDiff.js +20 -18
  199. package/server/apiDiff.js.map +1 -0
  200. package/server/apiDocs.d.ts +2 -0
  201. package/server/apiDocs.js +38 -40
  202. package/server/apiDocs.js.map +1 -0
  203. package/server/apiFile.d.ts +1 -0
  204. package/server/apiFile.js +14 -17
  205. package/server/apiFile.js.map +1 -0
  206. package/server/apiGitBlame.d.ts +2 -0
  207. package/server/apiGitBlame.js +50 -51
  208. package/server/apiGitBlame.js.map +1 -0
  209. package/server/apiMcp.d.ts +4 -0
  210. package/server/apiMcp.js +64 -66
  211. package/server/apiMcp.js.map +1 -0
  212. package/server/apiReview.d.ts +2 -0
  213. package/server/apiReview.js +45 -0
  214. package/server/apiReview.js.map +1 -0
  215. package/server/apiScan.d.ts +5 -0
  216. package/server/apiScan.js +90 -71
  217. package/server/apiScan.js.map +1 -0
  218. package/server/apiSearch.d.ts +33 -0
  219. package/server/apiSearch.js +184 -200
  220. package/server/apiSearch.js.map +1 -0
  221. package/server/apiSettings.d.ts +4 -0
  222. package/server/apiSettings.js +84 -85
  223. package/server/apiSettings.js.map +1 -0
  224. package/server/apiTools.d.ts +3 -0
  225. package/server/apiTools.js +55 -56
  226. package/server/apiTools.js.map +1 -0
  227. package/server/auth.d.ts +5 -0
  228. package/server/auth.js +54 -51
  229. package/server/auth.js.map +1 -0
  230. package/server/config.d.ts +42 -0
  231. package/server/config.js +189 -194
  232. package/server/config.js.map +1 -0
  233. package/server/daemon.d.ts +12 -0
  234. package/server/daemon.js +124 -114
  235. package/server/daemon.js.map +1 -0
  236. package/server/fileSourceNode.d.ts +2 -0
  237. package/server/fileSourceNode.js +34 -36
  238. package/server/fileSourceNode.js.map +1 -0
  239. package/server/gitClone.d.ts +9 -0
  240. package/server/gitClone.js +59 -61
  241. package/server/gitClone.js.map +1 -0
  242. package/server/gitDiff.d.ts +36 -0
  243. package/server/gitDiff.js +271 -169
  244. package/server/gitDiff.js.map +1 -0
  245. package/server/gitHistory.d.ts +12 -0
  246. package/server/gitHistory.js +80 -80
  247. package/server/gitHistory.js.map +1 -0
  248. package/server/gitRemote.d.ts +12 -0
  249. package/server/gitRemote.js +60 -0
  250. package/server/gitRemote.js.map +1 -0
  251. package/server/htmlText.d.ts +4 -0
  252. package/server/htmlText.js +16 -23
  253. package/server/htmlText.js.map +1 -0
  254. package/server/http.d.ts +5 -0
  255. package/server/http.js +27 -30
  256. package/server/http.js.map +1 -0
  257. package/server/httpGuards.d.ts +2 -0
  258. package/server/httpGuards.js +47 -43
  259. package/server/httpGuards.js.map +1 -0
  260. package/server/https.d.ts +34 -0
  261. package/server/https.js +121 -111
  262. package/server/https.js.map +1 -0
  263. package/server/index.d.ts +40 -0
  264. package/server/index.js +139 -147
  265. package/server/index.js.map +1 -0
  266. package/server/layout.d.ts +26 -0
  267. package/server/layout.js +59 -37
  268. package/server/layout.js.map +1 -0
  269. package/server/llmProxy.d.ts +3 -0
  270. package/server/llmProxy.js +137 -135
  271. package/server/llmProxy.js.map +1 -0
  272. package/server/logger.d.ts +38 -0
  273. package/server/logger.js +198 -211
  274. package/server/logger.js.map +1 -0
  275. package/server/mcp/analysis.d.ts +29 -0
  276. package/server/mcp/analysis.js +99 -120
  277. package/server/mcp/analysis.js.map +1 -0
  278. package/server/mcp/http.d.ts +9 -0
  279. package/server/mcp/http.js +128 -137
  280. package/server/mcp/http.js.map +1 -0
  281. package/server/mcp/runner.d.ts +68 -0
  282. package/server/mcp/runner.js +208 -218
  283. package/server/mcp/runner.js.map +1 -0
  284. package/server/mcp/server.d.ts +29 -0
  285. package/server/mcp/server.js +166 -179
  286. package/server/mcp/server.js.map +1 -0
  287. package/server/mcp/standalone.d.ts +1 -0
  288. package/server/mcp/standalone.js +8 -10
  289. package/server/mcp/standalone.js.map +1 -0
  290. package/server/mcp/tools.d.ts +2020 -0
  291. package/server/mcp/tools.js +523 -574
  292. package/server/mcp/tools.js.map +1 -0
  293. package/server/paths.d.ts +3 -0
  294. package/server/paths.js +17 -15
  295. package/server/paths.js.map +1 -0
  296. package/server/pidfile.d.ts +9 -0
  297. package/server/pidfile.js +43 -45
  298. package/server/pidfile.js.map +1 -0
  299. package/server/review.d.ts +5 -0
  300. package/server/review.js +35 -0
  301. package/server/review.js.map +1 -0
  302. package/server/router.d.ts +33 -0
  303. package/server/router.js +191 -197
  304. package/server/router.js.map +1 -0
  305. package/server/scanRequest.d.ts +3 -0
  306. package/server/scanRequest.js +36 -0
  307. package/server/scanRequest.js.map +1 -0
  308. package/server/searchIndex.d.ts +17 -0
  309. package/server/searchIndex.js +83 -80
  310. package/server/searchIndex.js.map +1 -0
  311. package/server/sessions.d.ts +14 -0
  312. package/server/sessions.js +62 -70
  313. package/server/sessions.js.map +1 -0
  314. package/server/startup.d.ts +118 -0
  315. package/server/startup.js +143 -148
  316. package/server/startup.js.map +1 -0
  317. package/server/static.d.ts +6 -0
  318. package/server/static.js +28 -31
  319. package/server/static.js.map +1 -0
  320. package/server/tools/install.d.ts +4 -0
  321. package/server/tools/install.js +176 -185
  322. package/server/tools/install.js.map +1 -0
  323. package/server/tools/parse.d.ts +8 -0
  324. package/server/tools/parse.js +112 -114
  325. package/server/tools/parse.js.map +1 -0
  326. package/server/tools/platform.d.ts +9 -0
  327. package/server/tools/platform.js +49 -47
  328. package/server/tools/platform.js.map +1 -0
  329. package/server/tools/registry.d.ts +137 -0
  330. package/server/tools/registry.js +173 -172
  331. package/server/tools/registry.js.map +1 -0
  332. package/server/tools/scan.d.ts +34 -0
  333. package/server/tools/scan.js +89 -98
  334. package/server/tools/scan.js.map +1 -0
  335. package/server/tools.d.ts +34 -0
  336. package/server/tools.js +94 -107
  337. package/server/tools.js.map +1 -0
  338. package/server/tunnel.d.ts +29 -0
  339. package/server/tunnel.js +61 -66
  340. package/server/tunnel.js.map +1 -0
  341. package/shared/analyzer/docs.d.ts +16 -0
  342. package/shared/analyzer/docs.js +99 -93
  343. package/shared/analyzer/docs.js.map +1 -0
  344. package/shared/analyzer/explainLocal.d.ts +4 -0
  345. package/shared/analyzer/explainLocal.js +122 -142
  346. package/shared/analyzer/explainLocal.js.map +1 -0
  347. package/shared/analyzer/github.d.ts +37 -0
  348. package/shared/analyzer/github.js +79 -0
  349. package/shared/analyzer/github.js.map +1 -0
  350. package/shared/analyzer/graph.d.ts +41 -0
  351. package/shared/analyzer/graph.js +393 -400
  352. package/shared/analyzer/graph.js.map +1 -0
  353. package/shared/analyzer/health.d.ts +33 -0
  354. package/shared/analyzer/health.js +197 -193
  355. package/shared/analyzer/health.js.map +1 -0
  356. package/shared/analyzer/history.d.ts +29 -0
  357. package/shared/analyzer/history.js +110 -111
  358. package/shared/analyzer/history.js.map +1 -0
  359. package/shared/analyzer/jsonConfig.d.ts +2 -0
  360. package/shared/analyzer/jsonConfig.js +61 -0
  361. package/shared/analyzer/jsonConfig.js.map +1 -0
  362. package/shared/analyzer/languages/csharp.d.ts +26 -0
  363. package/shared/analyzer/languages/csharp.js +83 -88
  364. package/shared/analyzer/languages/csharp.js.map +1 -0
  365. package/shared/analyzer/languages/generic.d.ts +23 -0
  366. package/shared/analyzer/languages/generic.js +94 -105
  367. package/shared/analyzer/languages/generic.js.map +1 -0
  368. package/shared/analyzer/languages/go.d.ts +24 -0
  369. package/shared/analyzer/languages/go.js +45 -54
  370. package/shared/analyzer/languages/go.js.map +1 -0
  371. package/shared/analyzer/languages/index.d.ts +6 -0
  372. package/shared/analyzer/languages/index.js +19 -20
  373. package/shared/analyzer/languages/index.js.map +1 -0
  374. package/shared/analyzer/languages/java.d.ts +20 -0
  375. package/shared/analyzer/languages/java.js +73 -78
  376. package/shared/analyzer/languages/java.js.map +1 -0
  377. package/shared/analyzer/languages/javascript.d.ts +12 -0
  378. package/shared/analyzer/languages/javascript.js +258 -209
  379. package/shared/analyzer/languages/javascript.js.map +1 -0
  380. package/shared/analyzer/languages/python.d.ts +23 -0
  381. package/shared/analyzer/languages/python.js +92 -100
  382. package/shared/analyzer/languages/python.js.map +1 -0
  383. package/shared/analyzer/languages/rust.d.ts +17 -0
  384. package/shared/analyzer/languages/rust.js +96 -98
  385. package/shared/analyzer/languages/rust.js.map +1 -0
  386. package/shared/analyzer/languages/typescript.d.ts +11 -0
  387. package/shared/analyzer/languages/typescript.js +117 -116
  388. package/shared/analyzer/languages/typescript.js.map +1 -0
  389. package/shared/analyzer/licenses.d.ts +18 -0
  390. package/shared/analyzer/licenses.js +130 -133
  391. package/shared/analyzer/licenses.js.map +1 -0
  392. package/shared/analyzer/metrics.d.ts +20 -0
  393. package/shared/analyzer/metrics.js +112 -104
  394. package/shared/analyzer/metrics.js.map +1 -0
  395. package/shared/analyzer/pathUtil.d.ts +10 -0
  396. package/shared/analyzer/pathUtil.js +29 -35
  397. package/shared/analyzer/pathUtil.js.map +1 -0
  398. package/shared/analyzer/patterns.d.ts +11 -0
  399. package/shared/analyzer/patterns.js +231 -253
  400. package/shared/analyzer/patterns.js.map +1 -0
  401. package/shared/analyzer/scan.d.ts +62 -0
  402. package/shared/analyzer/scan.js +451 -442
  403. package/shared/analyzer/scan.js.map +1 -0
  404. package/shared/analyzer/scanControl.d.ts +11 -0
  405. package/shared/analyzer/scanControl.js +62 -0
  406. package/shared/analyzer/scanControl.js.map +1 -0
  407. package/shared/analyzer/security.d.ts +18 -0
  408. package/shared/analyzer/security.js +159 -159
  409. package/shared/analyzer/security.js.map +1 -0
  410. package/shared/analyzer/services.d.ts +5 -0
  411. package/shared/analyzer/services.js +141 -138
  412. package/shared/analyzer/services.js.map +1 -0
  413. package/shared/analyzer/stack.d.ts +6 -0
  414. package/shared/analyzer/stack.js +134 -141
  415. package/shared/analyzer/stack.js.map +1 -0
  416. package/shared/analyzer/tour.d.ts +2 -0
  417. package/shared/analyzer/tour.js +45 -53
  418. package/shared/analyzer/tour.js.map +1 -0
  419. package/shared/analyzer/util.d.ts +8 -0
  420. package/shared/analyzer/util.js +130 -76
  421. package/shared/analyzer/util.js.map +1 -0
  422. package/shared/analyzer/workflows.d.ts +8 -0
  423. package/shared/analyzer/workflows.js +139 -134
  424. package/shared/analyzer/workflows.js.map +1 -0
  425. package/shared/contracts.d.ts +250 -0
  426. package/shared/contracts.js +2 -0
  427. package/shared/contracts.js.map +1 -0
  428. package/shared/diagram/aiFacts.d.ts +35 -0
  429. package/shared/diagram/aiFacts.js +102 -105
  430. package/shared/diagram/aiFacts.js.map +1 -0
  431. package/shared/diagram/aiMermaid.d.ts +5 -0
  432. package/shared/diagram/aiMermaid.js +46 -45
  433. package/shared/diagram/aiMermaid.js.map +1 -0
  434. package/shared/diagram/atlas.d.ts +16 -0
  435. package/shared/diagram/atlas.js +51 -60
  436. package/shared/diagram/atlas.js.map +1 -0
  437. package/shared/diagram/mermaid.d.ts +43 -0
  438. package/shared/diagram/mermaid.js +348 -370
  439. package/shared/diagram/mermaid.js.map +1 -0
  440. package/shared/review/contracts.d.ts +95 -0
  441. package/shared/review/contracts.js +2 -0
  442. package/shared/review/contracts.js.map +1 -0
  443. package/shared/review/review.d.ts +10 -0
  444. package/shared/review/review.js +184 -0
  445. package/shared/review/review.js.map +1 -0
  446. package/shared/search/query.d.ts +32 -0
  447. package/shared/search/query.js +395 -388
  448. package/shared/search/query.js.map +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/shared/analyzer/security.ts"],"names":[],"mappings":"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","sourcesContent":["// A built-in vulnerability & code-quality rule engine — a Semgrep-lite that\n// runs entirely locally, no external binary. Rules are regex/line based,\n// language-scoped, each with a severity and a category. Per-file findings are\n// attached during the scan; summarizeSecurity rolls them into a repo grade.\n\nimport { lineCounter } from './util.js';\n\nexport const SEVERITIES = ['info', 'low', 'medium', 'high', 'critical'];\nexport const sevRank = (s) => SEVERITIES.indexOf(s);\n\n// Each rule: id, severity, category, message, rx. `byLine` rules test each\n// line (and report the line number); others test the whole source once.\nconst RULES = [\n { id: 'hardcoded-secret', severity: 'critical', category: 'secret',\n message: 'Hardcoded credential — move it to env/config.',\n rx: /\\b(api[_-]?key|apikey|secret|client[_-]?secret|password|passwd|access[_-]?token|auth[_-]?token|private[_-]?key)\\b\\s*[:=]\\s*['\"`][^'\"`\\s]{8,}['\"`]/i, byLine: true },\n { id: 'aws-key', severity: 'critical', category: 'secret',\n message: 'Looks like an AWS access key id.',\n rx: /\\b(AKIA|ASIA)[0-9A-Z]{16}\\b/, byLine: true },\n { id: 'private-key-block', severity: 'critical', category: 'secret',\n message: 'A private key is committed to the source.',\n rx: /-----BEGIN (RSA|EC|DSA|OPENSSH|PGP) PRIVATE KEY-----/ },\n { id: 'eval', severity: 'high', category: 'injection', langs: ['javascript'],\n message: 'eval() executes strings as code — classic injection sink.',\n rx: /\\beval\\s*\\(/, byLine: true },\n { id: 'new-function', severity: 'high', category: 'injection', langs: ['javascript'],\n message: 'new Function() is eval in a trench coat.',\n rx: /\\bnew Function\\s*\\(/, byLine: true },\n { id: 'child-exec', severity: 'high', category: 'injection', langs: ['javascript'],\n message: 'Shelling out — if any argument is user input, this is command injection.',\n rx: /\\b(child_process\\.(exec|spawn)|execSync|spawnSync)\\s*\\(/, byLine: true },\n { id: 'os-system', severity: 'high', category: 'injection', langs: ['python'],\n message: 'os.system / shell=True runs a shell — sanitize any input reaching it.',\n rx: /\\bos\\.system\\s*\\(|shell\\s*=\\s*True/, byLine: true },\n { id: 'sql-concat', severity: 'high', category: 'injection',\n message: 'SQL built by string concatenation/formatting — use parameterized queries.',\n rx: /\\b(execute|query|exec|raw)\\s*\\(\\s*[^)]*(\\+|\\$\\{|\\.format\\(|f[\"'])/, byLine: true },\n { id: 'innerhtml', severity: 'medium', category: 'xss', langs: ['javascript'],\n message: 'Writing raw HTML — if the value is user-controlled, this is XSS.',\n rx: /\\b(innerHTML|outerHTML)\\s*=|dangerouslySetInnerHTML|document\\.write\\s*\\(/, byLine: true,\n ignore: /\\b(innerHTML|outerHTML)\\s*=\\s*(['\"`])\\2\\s*;?\\s*$/ },\n { id: 'weak-hash', severity: 'medium', category: 'crypto',\n message: 'MD5/SHA-1 are broken — use SHA-256+, and bcrypt/argon2 for passwords.',\n rx: /\\b(md5|sha1)\\s*\\(|createHash\\(\\s*['\"](md5|sha1)['\"]/, byLine: true },\n { id: 'math-random', severity: 'low', category: 'crypto', langs: ['javascript'],\n message: 'Math.random() is not cryptographically secure.',\n rx: /\\bMath\\.random\\s*\\(/, byLine: true },\n { id: 'insecure-deser', severity: 'high', category: 'deserialization',\n message: 'Insecure deserialization — untrusted data here is remote code execution.',\n rx: /\\b(pickle\\.loads?|yaml\\.load\\s*\\((?![^)]*SafeLoader)|unserialize\\s*\\(|ObjectInputStream)/, byLine: true },\n { id: 'open-redirect', severity: 'medium', category: 'redirect',\n message: 'Redirect target comes from the request — open-redirect risk.',\n rx: /\\b(res\\.redirect|redirect)\\s*\\(\\s*(req\\.|request\\.)/, byLine: true },\n { id: 'localhost-url', severity: 'low', category: 'config',\n message: 'Hardcoded localhost/127.0.0.1 — will break outside this machine.',\n rx: /['\"`](https?:\\/\\/(localhost|127\\.0\\.0\\.1)|localhost:\\d|127\\.0\\.0\\.1)/, byLine: true },\n { id: 'debugger', severity: 'low', category: 'debug', langs: ['javascript'],\n message: 'A debugger statement is left in.',\n rx: /\\bdebugger\\s*;?/, byLine: true },\n { id: 'console-log', severity: 'info', category: 'debug', langs: ['javascript'],\n message: 'console.log — fine locally, noise in production.',\n rx: /\\bconsole\\.(log|debug|info)\\s*\\(/, byLine: true },\n { id: 'print-stmt', severity: 'info', category: 'debug', langs: ['python'],\n message: 'print() — use the logger in production code.',\n rx: /^\\s*print\\s*\\(/, byLine: true },\n { id: 'todo', severity: 'info', category: 'quality',\n message: 'TODO/FIXME left in the source.',\n rx: /\\b(TODO|FIXME|XXX|HACK)\\b/, byLine: true },\n { id: 'loose-eq', severity: 'low', category: 'quality', langs: ['javascript'],\n message: 'Loose equality (==) coerces types — prefer ===.',\n rx: /[^=!<>]==[^=]/, byLine: true },\n { id: 'var-keyword', severity: 'low', category: 'quality', langs: ['javascript'],\n message: 'var is function-scoped and hoisted — prefer let/const.',\n rx: /\\bvar\\s+[A-Za-z_$]/, byLine: true },\n { id: 'empty-catch', severity: 'medium', category: 'quality',\n message: 'Swallowed exception — errors vanish silently here.',\n rx: /(catch\\s*\\([^)]*\\)\\s*\\{\\s*\\}|except\\s*\\w*\\s*:\\s*pass\\b)/, byLine: true },\n // JSON Web Tokens start with a base64-encoded header that is always\n // `eyJ…` (\"{\"). A line that contains one and treats it as a literal\n // string — rather than reading it from a vault — is the same shape of\n // mistake as a hardcoded API key. Three base64 segments separated by\n // dots is the JWT signature; we only require the first segment to keep\n // the rule cheap.\n { id: 'jwt-secret', severity: 'critical', category: 'secret',\n message: 'Looks like a hardcoded JWT — treat it like a credential, not a string.',\n rx: /['\"`](eyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,})['\"`]/, byLine: true },\n // The `os-system` rule already catches `os.system` and `shell=True` on\n // subprocess calls, but `subprocess.Popen(..., shell=True)` and\n // `subprocess.run(..., shell=True)` are the modern Python way to do\n // the same thing, and a regex on `shell=True` alone matches both\n // without the false-positive rate. A separate rule for Popen keeps the\n // message specific and the langs filter honest.\n { id: 'subprocess-shell', severity: 'high', category: 'injection', langs: ['python'],\n message: 'subprocess.* with shell=True runs a shell — sanitize any input reaching it.',\n rx: /\\bsubprocess\\.(Popen|run|call|check_output|check_call)\\s*\\([^)]*shell\\s*=\\s*True/, byLine: true },\n // Go's `http.ListenAndServe` defaults to binding all interfaces when\n // given a `\":port\"` address (the colon makes it a wildcard), and a\n // literal `0.0.0.0` does the same. That is fine inside a container with\n // a tight network policy and a bug everywhere else: the dev box, the\n // staging cluster, the CI runner, the laptop on coffee-shop Wi-Fi. The\n // rule does not distinguish \"0.0.0.0\" from \"127.0.0.1\" because the\n // safer pattern is always `127.0.0.1:<port>`, so the finding is a\n // nudge rather than an alarm.\n { id: 'go-public-listen', severity: 'medium', category: 'config', langs: ['go'],\n message: 'Go listener binds all interfaces (\":port\" or \"0.0.0.0\") — bind 127.0.0.1 explicitly.',\n rx: /(ListenAndServe|Listen|TLS\\s*\\.\\s*Listen|ListenAndServeTLS)\\s*\\(\\s*[\"'](:[0-9]+|0\\.0\\.0\\.0(?::[0-9]+)?|::)[\"']/, byLine: true },\n];\n\n// Findings for one file, run at scan time while the source is in hand.\nexport function analyzeSecurityFile(source, lang) {\n const findings = [];\n const text = String(source);\n const lines = text.split('\\n');\n // Whole-file rules report a byte offset and need it as a line number. Built\n // once and lazily: most files trip none of these rules and never build it.\n const lineAt = lineCounter(text);\n for (const rule of RULES) {\n if (rule.langs && !rule.langs.includes(lang)) continue;\n if (rule.byLine) {\n for (let i = 0; i < lines.length; i++) {\n if (rule.ignore && rule.ignore.test(lines[i])) continue;\n const m = lines[i].match(rule.rx);\n if (m) {\n findings.push({ rule: rule.id, severity: rule.severity, category: rule.category, message: rule.message, line: i + 1, excerpt: lines[i].trim().slice(0, 90) });\n }\n }\n } else {\n const m = text.match(rule.rx);\n if (m) {\n findings.push({ rule: rule.id, severity: rule.severity, category: rule.category, message: rule.message, line: lineAt(m.index), excerpt: (m[0] || '').slice(0, 90) });\n }\n }\n }\n return findings;\n}\n\n// Repo-level roll-up: counts by severity and category, the files carrying\n// findings (worst-first), and a 0–100 score + grade.\nexport function summarizeSecurity(scan) {\n const counts = { critical: 0, high: 0, medium: 0, low: 0, info: 0 };\n const byCat: Record<string, any> = {};\n const files = [];\n for (const f of scan.files) {\n const finds = f.findings || [];\n if (!finds.length) continue;\n let worst = 'info';\n for (const x of finds) {\n counts[x.severity]++;\n byCat[x.category] = (byCat[x.category] || 0) + 1;\n if (sevRank(x.severity) > sevRank(worst)) worst = x.severity;\n }\n files.push({ path: f.path, name: f.name, findings: finds, worst, count: finds.length });\n }\n files.sort((a, b) => sevRank(b.worst) - sevRank(a.worst) || b.count - a.count);\n\n let score = 100;\n score -= counts.critical * 15;\n score -= counts.high * 6;\n score -= counts.medium * 2;\n score -= Math.min(10, counts.low);\n score = Math.max(0, Math.round(score));\n const grade = score >= 90 ? 'A' : score >= 75 ? 'B' : score >= 60 ? 'C' : score >= 45 ? 'D' : 'F';\n\n return { counts, byCat, files, score, grade, total: files.reduce((s, f) => s + f.count, 0) };\n}\n\n// Fold an external engine's findings into the scan, in place, so the security\n// view — which reads `scan.files[].findings` and re-summarizes — sees one list.\n// Dedup is on (path, line, rule): two engines flagging the same line for the\n// same reason are one problem. This is the shared, pure half of the merge; the\n// fetching and spawning live on the server.\nexport function mergeFindingsIntoScan(scan, external) {\n if (!scan || !Array.isArray(external) || !external.length) return 0;\n const byPath = new Map<string, { findings?: any[] }>(scan.files.map((f) => [f.path, f]));\n let added = 0;\n for (const finding of external) {\n const file = byPath.get(finding.path);\n if (!file) continue; // a path the scanner never accepted is not ours to show\n const list = file.findings || (file.findings = []);\n const dupe = list.some((x) => x.line === finding.line && x.rule === finding.rule);\n if (dupe) continue;\n list.push(finding);\n added++;\n }\n return added;\n}\n\n"]}
@@ -0,0 +1,5 @@
1
+ import type { FileSource, Manifest } from '../contracts.js';
2
+ export declare function detectManifest(source: FileSource): Promise<Manifest>;
3
+ export declare function parseRequirements(text: any): string[];
4
+ export declare function parseGoRequires(text: any): string[];
5
+ export declare function parseCargoDeps(text: any): any[];
@@ -1,157 +1,160 @@
1
1
  // Service and manifest detection: docker-compose services, package.json
2
2
  // (workspaces, scripts, entry points), Procfile. Regex/JSON based — a YAML
3
3
  // parser would be overkill for what is a navigational aid.
4
-
5
4
  export async function detectManifest(source) {
6
- const manifest = { entryPoints: [], services: [], packageName: '', scripts: [], workspaces: [], deps: { npm: {}, dev: {}, pip: [], go: [], cargo: [] } };
7
-
8
- // package.json
9
- try {
10
- const pkg = JSON.parse(await source.read('package.json'));
11
- manifest.packageName = pkg.name || '';
12
- manifest.scripts = Object.keys(pkg.scripts || {});
13
- manifest.deps.npm = pkg.dependencies || {};
14
- manifest.deps.dev = pkg.devDependencies || {};
15
- if (pkg.main) manifest.entryPoints.push(pkg.main.replace(/^\.\//, ''));
16
- if (pkg.bin) {
17
- for (const p of Object.values(typeof pkg.bin === 'string' ? { bin: pkg.bin } : pkg.bin)) {
18
- manifest.entryPoints.push(String(p).replace(/^\.\//, ''));
19
- }
5
+ const manifest = { entryPoints: [], services: [], packageName: '', scripts: [], workspaces: [], deps: { npm: {}, dev: {}, pip: [], go: [], cargo: [] } };
6
+ // package.json
7
+ try {
8
+ const pkg = JSON.parse(await source.read('package.json'));
9
+ manifest.packageName = pkg.name || '';
10
+ manifest.license = pkg.license || '';
11
+ manifest.scripts = Object.keys(pkg.scripts || {});
12
+ manifest.deps.npm = pkg.dependencies || {};
13
+ manifest.deps.dev = pkg.devDependencies || {};
14
+ if (pkg.main)
15
+ manifest.entryPoints.push(pkg.main.replace(/^\.\//, ''));
16
+ if (pkg.bin) {
17
+ for (const p of Object.values(typeof pkg.bin === 'string' ? { bin: pkg.bin } : pkg.bin)) {
18
+ manifest.entryPoints.push(String(p).replace(/^\.\//, ''));
19
+ }
20
+ }
21
+ const ws = pkg.workspaces;
22
+ const list = Array.isArray(ws) ? ws : ws?.packages || [];
23
+ manifest.workspaces = list.map((w) => w.replace(/\/$/, ''));
24
+ if (manifest.scripts.some((s) => /start|serve|dev/.test(s))) {
25
+ manifest.hasServerScript = true;
26
+ }
27
+ }
28
+ catch {
29
+ /* no package.json or unreadable — fine */
30
+ }
31
+ // requirements.txt
32
+ try {
33
+ manifest.deps.pip = parseRequirements(await source.read('requirements.txt'));
34
+ }
35
+ catch { /* none */ }
36
+ // go.mod
37
+ try {
38
+ manifest.deps.go = parseGoRequires(await source.read('go.mod'));
20
39
  }
21
- const ws = pkg.workspaces;
22
- const list = Array.isArray(ws) ? ws : ws?.packages || [];
23
- manifest.workspaces = list.map((w) => w.replace(/\/$/, ''));
24
- if (manifest.scripts.some((s) => /start|serve|dev/.test(s))) {
25
- manifest.hasServerScript = true;
40
+ catch { /* none */ }
41
+ // Cargo.toml
42
+ try {
43
+ manifest.deps.cargo = parseCargoDeps(await source.read('Cargo.toml'));
44
+ }
45
+ catch { /* none */ }
46
+ // docker-compose.yml / docker-compose.yaml / compose.yml
47
+ for (const name of ['docker-compose.yml', 'docker-compose.yaml', 'compose.yml', 'compose.yaml']) {
48
+ let text;
49
+ try {
50
+ text = await source.read(name);
51
+ }
52
+ catch {
53
+ continue;
54
+ }
55
+ manifest.composeFile = name;
56
+ manifest.services = parseComposeServices(text);
57
+ break;
26
58
  }
27
- } catch {
28
- /* no package.json or unreadable — fine */
29
- }
30
-
31
- // requirements.txt
32
- try {
33
- manifest.deps.pip = parseRequirements(await source.read('requirements.txt'));
34
- } catch { /* none */ }
35
-
36
- // go.mod
37
- try {
38
- manifest.deps.go = parseGoRequires(await source.read('go.mod'));
39
- } catch { /* none */ }
40
-
41
- // Cargo.toml
42
- try {
43
- manifest.deps.cargo = parseCargoDeps(await source.read('Cargo.toml'));
44
- } catch { /* none */ }
45
-
46
- // docker-compose.yml / docker-compose.yaml / compose.yml
47
- for (const name of ['docker-compose.yml', 'docker-compose.yaml', 'compose.yml', 'compose.yaml']) {
48
- let text;
59
+ // Procfile
49
60
  try {
50
- text = await source.read(name);
51
- } catch {
52
- continue;
61
+ const text = await source.read('Procfile');
62
+ for (const line of text.split('\n')) {
63
+ const m = line.match(/^([\w-]+):\s*(.+)$/);
64
+ if (m)
65
+ manifest.services.push({ name: m[1], command: m[2].trim(), source: 'Procfile' });
66
+ }
53
67
  }
54
- manifest.composeFile = name;
55
- manifest.services = parseComposeServices(text);
56
- break;
57
- }
58
-
59
- // Procfile
60
- try {
61
- const text = await source.read('Procfile');
62
- for (const line of text.split('\n')) {
63
- const m = line.match(/^([\w-]+):\s*(.+)$/);
64
- if (m) manifest.services.push({ name: m[1], command: m[2].trim(), source: 'Procfile' });
68
+ catch {
69
+ /* none */
65
70
  }
66
- } catch {
67
- /* none */
68
- }
69
-
70
- return manifest;
71
+ return manifest;
71
72
  }
72
-
73
73
  export function parseRequirements(text) {
74
- return String(text)
75
- .split('\n')
76
- .map((l) => l.split('#')[0].trim())
77
- .filter(Boolean)
78
- .map((l) => l.split(/[<>=!~;\[ ]/)[0].replace(/["']/g, '').trim())
79
- .filter(Boolean);
74
+ return String(text)
75
+ .split('\n')
76
+ .map((l) => l.split('#')[0].trim())
77
+ .filter(Boolean)
78
+ .map((l) => l.split(/[<>=!~;\[ ]/)[0].replace(/["']/g, '').trim())
79
+ .filter(Boolean);
80
80
  }
81
-
82
81
  export function parseGoRequires(text) {
83
- const s = String(text);
84
- const names = new Set();
85
- const block = s.match(/require\s*\(([\s\S]*?)\)/);
86
- const scoped = block ? block[1] : '';
87
- const single = (s.match(/require\s+([\w./-]+)(?:\s+v[\w.\-+]+)?(?:\n|$)/) || [, ''])[1];
88
- if (single) names.add(single);
89
- for (const [, name] of (scoped.matchAll(/^\s*([\w./-]+)\s+v?[\w.\-+]*/gm) || [])) if (name) names.add(name);
90
- const lines = scoped.length ? scoped.split('\n') : s.split('\n').filter((l) => l.trim().startsWith('require'));
91
- for (const line of lines) {
92
- const m = line.match(/\b([\w./-]+)\s+v[\w.\-+]+/);
93
- if (m) names.add(m[1]);
94
- }
95
- // drop the standard library pseudo module
96
- names.delete('.');
97
- return [...names].sort();
82
+ const s = String(text);
83
+ const names = new Set();
84
+ const block = s.match(/require\s*\(([\s\S]*?)\)/);
85
+ const scoped = block ? block[1] : '';
86
+ const single = (s.match(/require\s+([\w./-]+)(?:\s+v[\w.\-+]+)?(?:\n|$)/) || [, ''])[1];
87
+ if (single)
88
+ names.add(single);
89
+ for (const [, name] of (scoped.matchAll(/^\s*([\w./-]+)\s+v?[\w.\-+]*/gm) || []))
90
+ if (name)
91
+ names.add(name);
92
+ const lines = scoped.length ? scoped.split('\n') : s.split('\n').filter((l) => l.trim().startsWith('require'));
93
+ for (const line of lines) {
94
+ const m = line.match(/\b([\w./-]+)\s+v[\w.\-+]+/);
95
+ if (m)
96
+ names.add(m[1]);
97
+ }
98
+ // drop the standard library pseudo module
99
+ names.delete('.');
100
+ return [...names].sort();
98
101
  }
99
-
100
102
  export function parseCargoDeps(text) {
101
- const s = String(text);
102
- const sec = s.match(/\[dependencies\]([\s\S]*?)(?=\n\[|$)/);
103
- const body = sec ? sec[1] : '';
104
- const names = [];
105
- for (const line of body.split('\n')) {
106
- const m = line.match(/^([A-Za-z0-9_-]+)\s*(?:=\s*[^{]|\{)/);
107
- if (m) names.push(m[1]);
108
- }
109
- return [...new Set(names)];
103
+ const s = String(text);
104
+ const sec = s.match(/\[dependencies\]([\s\S]*?)(?=\n\[|$)/);
105
+ const body = sec ? sec[1] : '';
106
+ const names = [];
107
+ for (const line of body.split('\n')) {
108
+ const m = line.match(/^([A-Za-z0-9_-]+)\s*(?:=\s*[^{]|\{)/);
109
+ if (m)
110
+ names.push(m[1]);
111
+ }
112
+ return [...new Set(names)];
110
113
  }
111
-
112
114
  function parseComposeServices(text) {
113
- const lines = text.split('\n');
114
- const services = [];
115
- let inServices = false;
116
- let servicesIndent = 0;
117
- let current = null;
118
- let currentIndent = 0;
119
-
120
- for (const line of lines) {
121
- if (/^\s*#/.test(line) || line.trim() === '') continue;
122
- const indent = line.length - line.trimStart().length;
123
- const trimmed = line.trim();
124
-
125
- if (!inServices) {
126
- if (/^services:\s*$/.test(trimmed)) {
127
- inServices = true;
128
- servicesIndent = indent;
129
- }
130
- continue;
131
- }
132
-
133
- if (indent <= servicesIndent && !/^services:/.test(trimmed)) break; // left the block
134
-
135
- const svcMatch = trimmed.match(/^([\w.-]+):\s*$/);
136
- if (svcMatch && indent === servicesIndent + 2) {
137
- current = { name: svcMatch[1], source: 'compose', ports: [], dependsOn: [] };
138
- currentIndent = indent;
139
- services.push(current);
140
- continue;
141
- }
142
-
143
- if (!current || indent <= currentIndent) continue;
144
-
145
- let m;
146
- if ((m = trimmed.match(/^build:\s*(.+)$/))) {
147
- current.build = m[1].trim();
148
- } else if ((m = trimmed.match(/^image:\s*(.+)$/))) {
149
- current.image = m[1].trim();
150
- } else if ((m = trimmed.match(/^-\s*["']?(\d+):(\d+)/))) {
151
- current.ports.push(m[1] + ':' + m[2]);
152
- } else if ((m = trimmed.match(/^context:\s*(.+)$/))) {
153
- current.build = m[1].trim();
115
+ const lines = text.split('\n');
116
+ const services = [];
117
+ let inServices = false;
118
+ let servicesIndent = 0;
119
+ let current = null;
120
+ let currentIndent = 0;
121
+ for (const line of lines) {
122
+ if (/^\s*#/.test(line) || line.trim() === '')
123
+ continue;
124
+ const indent = line.length - line.trimStart().length;
125
+ const trimmed = line.trim();
126
+ if (!inServices) {
127
+ if (/^services:\s*$/.test(trimmed)) {
128
+ inServices = true;
129
+ servicesIndent = indent;
130
+ }
131
+ continue;
132
+ }
133
+ if (indent <= servicesIndent && !/^services:/.test(trimmed))
134
+ break; // left the block
135
+ const svcMatch = trimmed.match(/^([\w.-]+):\s*$/);
136
+ if (svcMatch && indent === servicesIndent + 2) {
137
+ current = { name: svcMatch[1], source: 'compose', ports: [], dependsOn: [] };
138
+ currentIndent = indent;
139
+ services.push(current);
140
+ continue;
141
+ }
142
+ if (!current || indent <= currentIndent)
143
+ continue;
144
+ let m;
145
+ if ((m = trimmed.match(/^build:\s*(.+)$/))) {
146
+ current.build = m[1].trim();
147
+ }
148
+ else if ((m = trimmed.match(/^image:\s*(.+)$/))) {
149
+ current.image = m[1].trim();
150
+ }
151
+ else if ((m = trimmed.match(/^-\s*["']?(\d+):(\d+)/))) {
152
+ current.ports.push(m[1] + ':' + m[2]);
153
+ }
154
+ else if ((m = trimmed.match(/^context:\s*(.+)$/))) {
155
+ current.build = m[1].trim();
156
+ }
154
157
  }
155
- }
156
- return services;
158
+ return services;
157
159
  }
160
+ //# sourceMappingURL=services.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services.js","sourceRoot":"","sources":["../../src/shared/analyzer/services.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FileSource, Manifest, Service } from '../contracts.js';\n// Service and manifest detection: docker-compose services, package.json\n// (workspaces, scripts, entry points), Procfile. Regex/JSON based — a YAML\n// parser would be overkill for what is a navigational aid.\n\nexport async function detectManifest(source: FileSource): Promise<Manifest> {\n const manifest: Manifest = { entryPoints: [], services: [], packageName: '', scripts: [], workspaces: [], deps: { npm: {}, dev: {}, pip: [], go: [], cargo: [] } };\n\n // package.json\n try {\n const pkg = JSON.parse(await source.read('package.json'));\n manifest.packageName = pkg.name || '';\n manifest.license = pkg.license || '';\n manifest.scripts = Object.keys(pkg.scripts || {});\n manifest.deps.npm = pkg.dependencies || {};\n manifest.deps.dev = pkg.devDependencies || {};\n if (pkg.main) manifest.entryPoints.push(pkg.main.replace(/^\\.\\//, ''));\n if (pkg.bin) {\n for (const p of Object.values(typeof pkg.bin === 'string' ? { bin: pkg.bin } : pkg.bin)) {\n manifest.entryPoints.push(String(p).replace(/^\\.\\//, ''));\n }\n }\n const ws = pkg.workspaces;\n const list = Array.isArray(ws) ? ws : ws?.packages || [];\n manifest.workspaces = list.map((w) => w.replace(/\\/$/, ''));\n if (manifest.scripts.some((s) => /start|serve|dev/.test(s))) {\n manifest.hasServerScript = true;\n }\n } catch {\n /* no package.json or unreadable — fine */\n }\n\n // requirements.txt\n try {\n manifest.deps.pip = parseRequirements(await source.read('requirements.txt'));\n } catch { /* none */ }\n\n // go.mod\n try {\n manifest.deps.go = parseGoRequires(await source.read('go.mod'));\n } catch { /* none */ }\n\n // Cargo.toml\n try {\n manifest.deps.cargo = parseCargoDeps(await source.read('Cargo.toml'));\n } catch { /* none */ }\n\n // docker-compose.yml / docker-compose.yaml / compose.yml\n for (const name of ['docker-compose.yml', 'docker-compose.yaml', 'compose.yml', 'compose.yaml']) {\n let text;\n try {\n text = await source.read(name);\n } catch {\n continue;\n }\n manifest.composeFile = name;\n manifest.services = parseComposeServices(text);\n break;\n }\n\n // Procfile\n try {\n const text = await source.read('Procfile');\n for (const line of text.split('\\n')) {\n const m = line.match(/^([\\w-]+):\\s*(.+)$/);\n if (m) manifest.services.push({ name: m[1], command: m[2].trim(), source: 'Procfile' });\n }\n } catch {\n /* none */\n }\n\n return manifest;\n}\n\nexport function parseRequirements(text) {\n return String(text)\n .split('\\n')\n .map((l) => l.split('#')[0].trim())\n .filter(Boolean)\n .map((l) => l.split(/[<>=!~;\\[ ]/)[0].replace(/[\"']/g, '').trim())\n .filter(Boolean);\n}\n\nexport function parseGoRequires(text) {\n const s = String(text);\n const names = new Set<string>();\n const block = s.match(/require\\s*\\(([\\s\\S]*?)\\)/);\n const scoped = block ? block[1] : '';\n const single = (s.match(/require\\s+([\\w./-]+)(?:\\s+v[\\w.\\-+]+)?(?:\\n|$)/) || [, ''])[1];\n if (single) names.add(single);\n for (const [, name] of (scoped.matchAll(/^\\s*([\\w./-]+)\\s+v?[\\w.\\-+]*/gm) || [])) if (name) names.add(name);\n const lines = scoped.length ? scoped.split('\\n') : s.split('\\n').filter((l) => l.trim().startsWith('require'));\n for (const line of lines) {\n const m = line.match(/\\b([\\w./-]+)\\s+v[\\w.\\-+]+/);\n if (m) names.add(m[1]);\n }\n // drop the standard library pseudo module\n names.delete('.');\n return [...names].sort();\n}\n\nexport function parseCargoDeps(text) {\n const s = String(text);\n const sec = s.match(/\\[dependencies\\]([\\s\\S]*?)(?=\\n\\[|$)/);\n const body = sec ? sec[1] : '';\n const names = [];\n for (const line of body.split('\\n')) {\n const m = line.match(/^([A-Za-z0-9_-]+)\\s*(?:=\\s*[^{]|\\{)/);\n if (m) names.push(m[1]);\n }\n return [...new Set(names)];\n}\n\nfunction parseComposeServices(text) {\n const lines = text.split('\\n');\n const services: Service[] = [];\n let inServices = false;\n let servicesIndent = 0;\n let current: Service | null = null;\n let currentIndent = 0;\n\n for (const line of lines) {\n if (/^\\s*#/.test(line) || line.trim() === '') continue;\n const indent = line.length - line.trimStart().length;\n const trimmed = line.trim();\n\n if (!inServices) {\n if (/^services:\\s*$/.test(trimmed)) {\n inServices = true;\n servicesIndent = indent;\n }\n continue;\n }\n\n if (indent <= servicesIndent && !/^services:/.test(trimmed)) break; // left the block\n\n const svcMatch = trimmed.match(/^([\\w.-]+):\\s*$/);\n if (svcMatch && indent === servicesIndent + 2) {\n current = { name: svcMatch[1], source: 'compose', ports: [], dependsOn: [] };\n currentIndent = indent;\n services.push(current);\n continue;\n }\n\n if (!current || indent <= currentIndent) continue;\n\n let m;\n if ((m = trimmed.match(/^build:\\s*(.+)$/))) {\n current.build = m[1].trim();\n } else if ((m = trimmed.match(/^image:\\s*(.+)$/))) {\n current.image = m[1].trim();\n } else if ((m = trimmed.match(/^-\\s*[\"']?(\\d+):(\\d+)/))) {\n current.ports.push(m[1] + ':' + m[2]);\n } else if ((m = trimmed.match(/^context:\\s*(.+)$/))) {\n current.build = m[1].trim();\n }\n }\n return services;\n}\n"]}
@@ -0,0 +1,6 @@
1
+ export declare const DOC_HOSTS: readonly string[];
2
+ export declare function analyzeStack(manifest?: Record<string, any>, languages?: Record<string, any>): {
3
+ languages: Record<string, any>;
4
+ pm: any[];
5
+ items: any[];
6
+ };