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
@@ -1,163 +1,143 @@
1
1
  // Offline explanations. When no LLM key is configured these are what the
2
2
  // user reads, so they're written like a colleague's notes, not a template
3
3
  // dump. Every claim comes straight from the static graph.
4
-
5
4
  import { baseName } from './pathUtil.js';
6
5
  import { roleOf, factIndex, scanIndex } from './graph.js';
7
6
  import { languageLabel } from './languages/index.js';
8
-
9
7
  const ROLE_LINES = {
10
- entry: 'This is one of the ways into the codebase — a good place to start reading.',
11
- hub: 'A lot of the codebase leans on this file. Changes here ripple outward.',
12
- leaf: 'Nothing this file uses lives in the repo — it sits at the end of a chain.',
13
- test: 'Test file. It verifies behavior rather than providing it.',
14
- config: 'Configuration — it shapes how the rest of the code runs.',
15
- module: 'A working part of the whole.',
8
+ entry: 'This is one of the ways into the codebase — a good place to start reading.',
9
+ hub: 'A lot of the codebase leans on this file. Changes here ripple outward.',
10
+ leaf: 'Nothing this file uses lives in the repo — it sits at the end of a chain.',
11
+ test: 'Test file. It verifies behavior rather than providing it.',
12
+ config: 'Configuration — it shapes how the rest of the code runs.',
13
+ module: 'A working part of the whole.',
16
14
  };
17
-
18
15
  export function explainFile(path, file, facts) {
19
- const role = roleOf(path, facts);
20
- const fin = facts.fanIn[path] || 0;
21
- const fout = facts.fanOut[path] || 0;
22
- const paras = [];
23
-
24
- paras.push(`**${baseName(path)}** — ${ROLE_LINES[role]}`);
25
-
26
- const parts = [];
27
- if (fout > 0) parts.push(`pulls in ${fout} other ${fout === 1 ? 'file' : 'files'}`);
28
- if (fin > 0) parts.push(`is pulled in by ${fin}`);
29
- if (fin === 0 && fout === 0 && role !== 'entry') parts.push('isn’t connected to anything else we can see');
30
- if (parts.length) paras.push(`It ${parts.join(' and ')}.`);
31
-
32
- const fns = (file?.functions || []).filter((f) => f.kind !== 'method');
33
- const methods = (file?.functions || []).filter((f) => f.kind === 'method');
34
- if (fns.length) {
35
- paras.push(
36
- `Defines ${fns.length} ${fns.length === 1 ? 'function' : 'functions'} — ` +
37
- `${fns.slice(0, 6).map((f) => '`' + f.name + '`').join(', ')}` +
38
- (fns.length > 6 ? ` and ${fns.length - 6} more` : '') + '.'
39
- );
40
- }
41
- if (methods.length) {
42
- paras.push(`Plus ${methods.length} ${methods.length === 1 ? 'method' : 'methods'} on its classes.`);
43
- }
44
- if (file?.classes?.length) {
45
- paras.push(`Classes: ${file.classes.map((c) => '`' + c.name + '`').join(', ')}.`);
46
- }
47
-
48
- const importers = (facts.importers[path] || []).slice(0, 5);
49
- if (importers.length) {
50
- paras.push(
51
- `If it broke, the first to notice would be ${importers.map((p) => '`' + baseName(p) + '`').join(', ')}` +
52
- (fin > 5 ? ` and ${fin - 5} others` : '') + '.'
53
- );
54
- }
55
-
56
- if (factIndex(facts).inCycle.has(path)) {
57
- const cycle = facts.cycles.find((c) => c.includes(path));
58
- if (cycle) {
59
- paras.push(
60
- `⚠ It sits in a circular dependency (${cycle.length} files importing each other in a loop). Worth knowing before you refactor.`
61
- );
62
- }
63
- }
64
-
65
- return paras.join('\n\n');
16
+ const role = roleOf(path, facts);
17
+ const fin = facts.fanIn[path] || 0;
18
+ const fout = facts.fanOut[path] || 0;
19
+ const paras = [];
20
+ paras.push(`**${baseName(path)}** — ${ROLE_LINES[role]}`);
21
+ const parts = [];
22
+ if (fout > 0)
23
+ parts.push(`pulls in ${fout} other ${fout === 1 ? 'file' : 'files'}`);
24
+ if (fin > 0)
25
+ parts.push(`is pulled in by ${fin}`);
26
+ if (fin === 0 && fout === 0 && role !== 'entry')
27
+ parts.push('isn’t connected to anything else we can see');
28
+ if (parts.length)
29
+ paras.push(`It ${parts.join(' and ')}.`);
30
+ const fns = (file?.functions || []).filter((f) => f.kind !== 'method');
31
+ const methods = (file?.functions || []).filter((f) => f.kind === 'method');
32
+ if (fns.length) {
33
+ paras.push(`Defines ${fns.length} ${fns.length === 1 ? 'function' : 'functions'} — ` +
34
+ `${fns.slice(0, 6).map((f) => '`' + f.name + '`').join(', ')}` +
35
+ (fns.length > 6 ? ` and ${fns.length - 6} more` : '') + '.');
36
+ }
37
+ if (methods.length) {
38
+ paras.push(`Plus ${methods.length} ${methods.length === 1 ? 'method' : 'methods'} on its classes.`);
39
+ }
40
+ if (file?.classes?.length) {
41
+ paras.push(`Classes: ${file.classes.map((c) => '`' + c.name + '`').join(', ')}.`);
42
+ }
43
+ const importers = (facts.importers[path] || []).slice(0, 5);
44
+ if (importers.length) {
45
+ paras.push(`If it broke, the first to notice would be ${importers.map((p) => '`' + baseName(p) + '`').join(', ')}` +
46
+ (fin > 5 ? ` and ${fin - 5} others` : '') + '.');
47
+ }
48
+ if (factIndex(facts).inCycle.has(path)) {
49
+ const cycle = facts.cycles.find((c) => c.includes(path));
50
+ if (cycle) {
51
+ paras.push(`⚠ It sits in a circular dependency (${cycle.length} files importing each other in a loop). Worth knowing before you refactor.`);
52
+ }
53
+ }
54
+ return paras.join('\n\n');
66
55
  }
67
-
68
56
  export function explainFolder(path, scan, facts) {
69
- const here = scanIndex(scan).filesIn(path);
70
- const entries = factIndex(facts).entries;
71
- const entriesHere = here.filter((f) => entries.has(f.path));
72
- const hubsHere = here
73
- .map((f) => ({ path: f.path, fanIn: facts.fanIn[f.path] || 0 }))
74
- .filter((h) => h.fanIn >= 3)
75
- .sort((a, b) => b.fanIn - a.fanIn);
76
-
77
- const paras = [];
78
- paras.push(`**${path}/** — ${here.length} parsed ${here.length === 1 ? 'file' : 'files'}.`);
79
- if (entriesHere.length) {
80
- paras.push(`The way in: ${entriesHere.map((f) => '`' + f.name + '`').join(', ')}.`);
81
- }
82
- if (hubsHere.length) {
83
- paras.push(
84
- `The load-bearing file${hubsHere.length > 1 ? 's' : ''}: ` +
85
- hubsHere.slice(0, 3).map((h) => `\`${baseName(h.path)}\` (${h.fanIn} dependents)`).join(', ') + '.'
86
- );
87
- }
88
- const internal = scan.edges.filter((e) => e.from.startsWith(path + '/') && e.to.startsWith(path + '/')).length;
89
- const outward = scan.edges.filter((e) => e.from.startsWith(path + '/') && !e.to.startsWith(path + '/')).length;
90
- if (internal || outward) {
91
- paras.push(`${internal} internal connections, ${outward} reaching out to other folders.`);
92
- }
93
- return paras.join('\n\n');
57
+ const here = scanIndex(scan).filesIn(path);
58
+ const entries = factIndex(facts).entries;
59
+ const entriesHere = here.filter((f) => entries.has(f.path));
60
+ const hubsHere = here
61
+ .map((f) => ({ path: f.path, fanIn: facts.fanIn[f.path] || 0 }))
62
+ .filter((h) => h.fanIn >= 3)
63
+ .sort((a, b) => b.fanIn - a.fanIn);
64
+ const paras = [];
65
+ paras.push(`**${path}/** — ${here.length} parsed ${here.length === 1 ? 'file' : 'files'}.`);
66
+ if (entriesHere.length) {
67
+ paras.push(`The way in: ${entriesHere.map((f) => '`' + f.name + '`').join(', ')}.`);
68
+ }
69
+ if (hubsHere.length) {
70
+ paras.push(`The load-bearing file${hubsHere.length > 1 ? 's' : ''}: ` +
71
+ hubsHere.slice(0, 3).map((h) => `\`${baseName(h.path)}\` (${h.fanIn} dependents)`).join(', ') + '.');
72
+ }
73
+ const internal = scan.edges.filter((e) => e.from.startsWith(path + '/') && e.to.startsWith(path + '/')).length;
74
+ const outward = scan.edges.filter((e) => e.from.startsWith(path + '/') && !e.to.startsWith(path + '/')).length;
75
+ if (internal || outward) {
76
+ paras.push(`${internal} internal connections, ${outward} reaching out to other folders.`);
77
+ }
78
+ return paras.join('\n\n');
94
79
  }
95
-
96
80
  export function explainOverview(scan, facts, manifest) {
97
- const paras = [];
98
- const langs = Object.entries(scan.stats.languages)
99
- .sort((a, b) => b[1] - a[1])
100
- .map(([k, v]) => `${v} ${langLabel(k)}`)
101
- .join(', ');
102
- paras.push(
103
- `**${scan.name}** — ${scan.stats.filesParsed} code files (${langs}), ${scan.stats.edgeCount} import connections.`
104
- );
105
- if (facts.entries.length) {
106
- paras.push(`Start reading at ${facts.entries.slice(0, 3).map((p) => '`' + p + '`').join(', ')}.`);
107
- }
108
- if (facts.hubs.length) {
109
- const top = facts.hubs[0];
110
- paras.push(`The file everyone depends on is \`${top.path}\` (${top.fanIn} dependents).`);
111
- }
112
- if (manifest?.services?.length) {
113
- paras.push(`Runs as ${manifest.services.length} ${manifest.services.length === 1 ? 'service' : 'services'}: ${manifest.services.map((s) => s.name).join(', ')}.`);
114
- }
115
- if (facts.cycles.length) {
116
- paras.push(`⚠ ${facts.cycles.length} circular ${facts.cycles.length === 1 ? 'dependency' : 'dependencies'} detected.`);
117
- }
118
- if (facts.orphans.length) {
119
- paras.push(`${facts.orphans.length} files aren’t imported by anything — dead code, or entry points we didn’t recognize.`);
120
- }
121
- paras.push(...scanCaveats(scan));
122
- return paras.join('\n\n');
81
+ const paras = [];
82
+ const langs = Object.entries(scan.stats.languages)
83
+ .sort((a, b) => Number(b[1]) - Number(a[1]))
84
+ .map(([k, v]) => `${v} ${langLabel(k)}`)
85
+ .join(', ');
86
+ paras.push(`**${scan.name}** — ${scan.stats.filesParsed} code files (${langs}), ${scan.stats.edgeCount} import connections.`);
87
+ if (facts.entries.length) {
88
+ paras.push(`Start reading at ${facts.entries.slice(0, 3).map((p) => '`' + p + '`').join(', ')}.`);
89
+ }
90
+ if (facts.hubs.length) {
91
+ const top = facts.hubs[0];
92
+ paras.push(`The file everyone depends on is \`${top.path}\` (${top.fanIn} dependents).`);
93
+ }
94
+ if (manifest?.services?.length) {
95
+ paras.push(`Runs as ${manifest.services.length} ${manifest.services.length === 1 ? 'service' : 'services'}: ${manifest.services.map((s) => s.name).join(', ')}.`);
96
+ }
97
+ if (facts.cycles.length) {
98
+ paras.push(`⚠ ${facts.cycles.length} circular ${facts.cycles.length === 1 ? 'dependency' : 'dependencies'} detected.`);
99
+ }
100
+ if (facts.orphans.length) {
101
+ paras.push(`${facts.orphans.length} files aren’t imported by anything — dead code, or entry points we didn’t recognize.`);
102
+ }
103
+ paras.push(...scanCaveats(scan));
104
+ return paras.join('\n\n');
123
105
  }
124
-
125
106
  // What the scan knows it doesn't know. These go last, in the same panel as the
126
107
  // findings, because a number you can't trust is worse than no number — and
127
108
  // every one of these changes how the rest of the page should be read.
128
109
  export function scanCaveats(scan) {
129
- const out = [];
130
- const t = scan.stats.truncated;
131
- if (t) {
132
- out.push(
133
- `⚠ This is a partial scan. It stopped at ${t.atFiles} files with ${t.dirsQueued} ` +
134
- `${t.dirsQueued === 1 ? 'directory' : 'directories'} still unvisited, so hubs look smaller than they are ` +
135
- `and the unconnected-files count is inflated. Treat the health grade as indicative, not final.`
136
- );
137
- }
138
- const imp = scan.stats.imports;
139
- if (imp && imp.total) {
140
- if (imp.confidence < 90) {
141
- const worst = imp.worst.slice(0, 3).map((w) => '`' + w.spec + '`').join(', ');
142
- out.push(
143
- `${imp.confidence}% of the ${imp.total} imports found were placed — ${imp.unresolved} ` +
144
- `couldn’t be matched to a file or a package${worst ? ', most often ' + worst : ''}. ` +
145
- `Imports are read with regexes, so unresolved usually means a path alias, a generated ` +
146
- `file, or code quoted inside a string.`
147
- );
148
- }
149
- }
150
- const s = scan.stats.skips;
151
- if (s?.readFailed || s?.analyzeFailed || s?.listFailed) {
152
- const bits = [];
153
- if (s.listFailed) bits.push(`${s.listFailed} ${s.listFailed === 1 ? 'directory' : 'directories'} wouldn’t list`);
154
- if (s.readFailed) bits.push(`${s.readFailed} ${s.readFailed === 1 ? 'file' : 'files'} wouldn’t read`);
155
- if (s.analyzeFailed) bits.push(`${s.analyzeFailed} failed to parse`);
156
- out.push(`Not everything could be read: ${bits.join(', ')}. Those files are missing from the graph.`);
157
- }
158
- return out;
110
+ const out = [];
111
+ const t = scan.stats.truncated;
112
+ if (t) {
113
+ out.push(`⚠ This is a partial scan. It stopped at ${t.atFiles} files with ${t.dirsQueued} ` +
114
+ `${t.dirsQueued === 1 ? 'directory' : 'directories'} still unvisited, so hubs look smaller than they are ` +
115
+ `and the unconnected-files count is inflated. Treat the health grade as indicative, not final.`);
116
+ }
117
+ const imp = scan.stats.imports;
118
+ if (imp && imp.total) {
119
+ if (imp.confidence < 90) {
120
+ const worst = imp.worst.slice(0, 3).map((w) => '`' + w.spec + '`').join(', ');
121
+ out.push(`${imp.confidence}% of the ${imp.total} imports found were placed — ${imp.unresolved} ` +
122
+ `couldn’t be matched to a file or a package${worst ? ', most often ' + worst : ''}. ` +
123
+ `Imports are read with regexes, so unresolved usually means a path alias, a generated ` +
124
+ `file, or code quoted inside a string.`);
125
+ }
126
+ }
127
+ const s = scan.stats.skips;
128
+ if (s?.readFailed || s?.analyzeFailed || s?.listFailed) {
129
+ const bits = [];
130
+ if (s.listFailed)
131
+ bits.push(`${s.listFailed} ${s.listFailed === 1 ? 'directory' : 'directories'} wouldn’t list`);
132
+ if (s.readFailed)
133
+ bits.push(`${s.readFailed} ${s.readFailed === 1 ? 'file' : 'files'} wouldn’t read`);
134
+ if (s.analyzeFailed)
135
+ bits.push(`${s.analyzeFailed} failed to parse`);
136
+ out.push(`Not everything could be read: ${bits.join(', ')}. Those files are missing from the graph.`);
137
+ }
138
+ return out;
159
139
  }
160
-
161
140
  function langLabel(id) {
162
- return languageLabel(id, { short: true });
141
+ return languageLabel(id, { short: true });
163
142
  }
143
+ //# sourceMappingURL=explainLocal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainLocal.js","sourceRoot":"","sources":["../../src/shared/analyzer/explainLocal.ts"],"names":[],"mappings":"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","sourcesContent":["// Offline explanations. When no LLM key is configured these are what the\n// user reads, so they're written like a colleague's notes, not a template\n// dump. Every claim comes straight from the static graph.\n\nimport { baseName } from './pathUtil.js';\nimport { roleOf, factIndex, scanIndex } from './graph.js';\nimport { languageLabel } from './languages/index.js';\n\nconst ROLE_LINES = {\n entry: 'This is one of the ways into the codebase — a good place to start reading.',\n hub: 'A lot of the codebase leans on this file. Changes here ripple outward.',\n leaf: 'Nothing this file uses lives in the repo — it sits at the end of a chain.',\n test: 'Test file. It verifies behavior rather than providing it.',\n config: 'Configuration — it shapes how the rest of the code runs.',\n module: 'A working part of the whole.',\n};\n\nexport function explainFile(path, file, facts) {\n const role = roleOf(path, facts);\n const fin = facts.fanIn[path] || 0;\n const fout = facts.fanOut[path] || 0;\n const paras = [];\n\n paras.push(`**${baseName(path)}** — ${ROLE_LINES[role]}`);\n\n const parts = [];\n if (fout > 0) parts.push(`pulls in ${fout} other ${fout === 1 ? 'file' : 'files'}`);\n if (fin > 0) parts.push(`is pulled in by ${fin}`);\n if (fin === 0 && fout === 0 && role !== 'entry') parts.push('isn’t connected to anything else we can see');\n if (parts.length) paras.push(`It ${parts.join(' and ')}.`);\n\n const fns = (file?.functions || []).filter((f) => f.kind !== 'method');\n const methods = (file?.functions || []).filter((f) => f.kind === 'method');\n if (fns.length) {\n paras.push(\n `Defines ${fns.length} ${fns.length === 1 ? 'function' : 'functions'} — ` +\n `${fns.slice(0, 6).map((f) => '`' + f.name + '`').join(', ')}` +\n (fns.length > 6 ? ` and ${fns.length - 6} more` : '') + '.'\n );\n }\n if (methods.length) {\n paras.push(`Plus ${methods.length} ${methods.length === 1 ? 'method' : 'methods'} on its classes.`);\n }\n if (file?.classes?.length) {\n paras.push(`Classes: ${file.classes.map((c) => '`' + c.name + '`').join(', ')}.`);\n }\n\n const importers = (facts.importers[path] || []).slice(0, 5);\n if (importers.length) {\n paras.push(\n `If it broke, the first to notice would be ${importers.map((p) => '`' + baseName(p) + '`').join(', ')}` +\n (fin > 5 ? ` and ${fin - 5} others` : '') + '.'\n );\n }\n\n if (factIndex(facts).inCycle.has(path)) {\n const cycle = facts.cycles.find((c) => c.includes(path));\n if (cycle) {\n paras.push(\n `⚠ It sits in a circular dependency (${cycle.length} files importing each other in a loop). Worth knowing before you refactor.`\n );\n }\n }\n\n return paras.join('\\n\\n');\n}\n\nexport function explainFolder(path, scan, facts) {\n const here = scanIndex(scan).filesIn(path);\n const entries = factIndex(facts).entries;\n const entriesHere = here.filter((f) => entries.has(f.path));\n const hubsHere = here\n .map((f) => ({ path: f.path, fanIn: facts.fanIn[f.path] || 0 }))\n .filter((h) => h.fanIn >= 3)\n .sort((a, b) => b.fanIn - a.fanIn);\n\n const paras = [];\n paras.push(`**${path}/** — ${here.length} parsed ${here.length === 1 ? 'file' : 'files'}.`);\n if (entriesHere.length) {\n paras.push(`The way in: ${entriesHere.map((f) => '`' + f.name + '`').join(', ')}.`);\n }\n if (hubsHere.length) {\n paras.push(\n `The load-bearing file${hubsHere.length > 1 ? 's' : ''}: ` +\n hubsHere.slice(0, 3).map((h) => `\\`${baseName(h.path)}\\` (${h.fanIn} dependents)`).join(', ') + '.'\n );\n }\n const internal = scan.edges.filter((e) => e.from.startsWith(path + '/') && e.to.startsWith(path + '/')).length;\n const outward = scan.edges.filter((e) => e.from.startsWith(path + '/') && !e.to.startsWith(path + '/')).length;\n if (internal || outward) {\n paras.push(`${internal} internal connections, ${outward} reaching out to other folders.`);\n }\n return paras.join('\\n\\n');\n}\n\nexport function explainOverview(scan, facts, manifest) {\n const paras = [];\n const langs = Object.entries(scan.stats.languages)\n .sort((a, b) => Number(b[1]) - Number(a[1]))\n .map(([k, v]) => `${v} ${langLabel(k)}`)\n .join(', ');\n paras.push(\n `**${scan.name}** — ${scan.stats.filesParsed} code files (${langs}), ${scan.stats.edgeCount} import connections.`\n );\n if (facts.entries.length) {\n paras.push(`Start reading at ${facts.entries.slice(0, 3).map((p) => '`' + p + '`').join(', ')}.`);\n }\n if (facts.hubs.length) {\n const top = facts.hubs[0];\n paras.push(`The file everyone depends on is \\`${top.path}\\` (${top.fanIn} dependents).`);\n }\n if (manifest?.services?.length) {\n paras.push(`Runs as ${manifest.services.length} ${manifest.services.length === 1 ? 'service' : 'services'}: ${manifest.services.map((s) => s.name).join(', ')}.`);\n }\n if (facts.cycles.length) {\n paras.push(`⚠ ${facts.cycles.length} circular ${facts.cycles.length === 1 ? 'dependency' : 'dependencies'} detected.`);\n }\n if (facts.orphans.length) {\n paras.push(`${facts.orphans.length} files aren’t imported by anything — dead code, or entry points we didn’t recognize.`);\n }\n paras.push(...scanCaveats(scan));\n return paras.join('\\n\\n');\n}\n\n// What the scan knows it doesn't know. These go last, in the same panel as the\n// findings, because a number you can't trust is worse than no number — and\n// every one of these changes how the rest of the page should be read.\nexport function scanCaveats(scan) {\n const out = [];\n const t = scan.stats.truncated;\n if (t) {\n out.push(\n `⚠ This is a partial scan. It stopped at ${t.atFiles} files with ${t.dirsQueued} ` +\n `${t.dirsQueued === 1 ? 'directory' : 'directories'} still unvisited, so hubs look smaller than they are ` +\n `and the unconnected-files count is inflated. Treat the health grade as indicative, not final.`\n );\n }\n const imp = scan.stats.imports;\n if (imp && imp.total) {\n if (imp.confidence < 90) {\n const worst = imp.worst.slice(0, 3).map((w) => '`' + w.spec + '`').join(', ');\n out.push(\n `${imp.confidence}% of the ${imp.total} imports found were placed — ${imp.unresolved} ` +\n `couldn’t be matched to a file or a package${worst ? ', most often ' + worst : ''}. ` +\n `Imports are read with regexes, so unresolved usually means a path alias, a generated ` +\n `file, or code quoted inside a string.`\n );\n }\n }\n const s = scan.stats.skips;\n if (s?.readFailed || s?.analyzeFailed || s?.listFailed) {\n const bits = [];\n if (s.listFailed) bits.push(`${s.listFailed} ${s.listFailed === 1 ? 'directory' : 'directories'} wouldn’t list`);\n if (s.readFailed) bits.push(`${s.readFailed} ${s.readFailed === 1 ? 'file' : 'files'} wouldn’t read`);\n if (s.analyzeFailed) bits.push(`${s.analyzeFailed} failed to parse`);\n out.push(`Not everything could be read: ${bits.join(', ')}. Those files are missing from the graph.`);\n }\n return out;\n}\n\nfunction langLabel(id) {\n return languageLabel(id, { short: true });\n}\n"]}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The `owner/repo` a git URL points at, or null if it is not a GitHub URL.
3
+ *
4
+ * Both URL shapes git accepts: `https://github.com/owner/repo(.git)` and
5
+ * `git@github.com:owner/repo(.git)`. Anything else is not GitHub, and gets no
6
+ * remote lookup — a GitLab or Bitbucket clone is a real outcome, not an error.
7
+ */
8
+ export declare function githubRepoPath(url: any): string;
9
+ /**
10
+ * The public facts worth showing, read out of `GET /repos/{owner}/{repo}`.
11
+ *
12
+ * Returns null for anything that is not an object, so a caller can tell "no
13
+ * facts" from "all zeroes" without a try/catch around every field.
14
+ */
15
+ export declare function remoteFacts(json: any): {
16
+ stars: number;
17
+ forks: number;
18
+ watching: number;
19
+ issues: number;
20
+ description: any;
21
+ license: any;
22
+ created: any;
23
+ pushed: any;
24
+ branch: any;
25
+ topics: any;
26
+ homepage: any;
27
+ archived: boolean;
28
+ };
29
+ /**
30
+ * Why a remote lookup did not produce facts, in the words a person can act on.
31
+ *
32
+ * 403, 404 and 429 are separated because they mean opposite things — one is
33
+ * "ask less often, or authenticate", one is "private, or gone, or never there",
34
+ * and one is "slow down" — and collapsing them into "GitHub said no" helps
35
+ * nobody diagnose anything.
36
+ */
37
+ export declare function remoteError(status: any): string;
@@ -0,0 +1,79 @@
1
+ // Reading a GitHub repository's public facts — the part the browser and the
2
+ // terminal both need, and the part that was quietly wrong in one of them.
3
+ //
4
+ // This module is pure: it takes an already-parsed API payload and returns plain
5
+ // data. The `fetch` deliberately stays on either side of it, because the two
6
+ // callers can do things the other cannot — the browser must not hold a token,
7
+ // and the terminal can. `shared/` may not know which runtime it is in, so the
8
+ // network call is not here; only the reading of the answer is.
9
+ //
10
+ // One implementation, because the previous arrangement had the browser with its
11
+ // own copy of the URL regex and its own idea of which counter means "watching",
12
+ // and the two drifted apart without anything noticing.
13
+ /**
14
+ * The `owner/repo` a git URL points at, or null if it is not a GitHub URL.
15
+ *
16
+ * Both URL shapes git accepts: `https://github.com/owner/repo(.git)` and
17
+ * `git@github.com:owner/repo(.git)`. Anything else is not GitHub, and gets no
18
+ * remote lookup — a GitLab or Bitbucket clone is a real outcome, not an error.
19
+ */
20
+ export function githubRepoPath(url) {
21
+ const m = String(url ?? '').match(/github\.com[:/]([^/\s]+\/[^/\s]+?)(?:\.git)?\/?$/);
22
+ return m ? m[1] : null;
23
+ }
24
+ /**
25
+ * The public facts worth showing, read out of `GET /repos/{owner}/{repo}`.
26
+ *
27
+ * Returns null for anything that is not an object, so a caller can tell "no
28
+ * facts" from "all zeroes" without a try/catch around every field.
29
+ */
30
+ export function remoteFacts(json) {
31
+ if (!json || typeof json !== 'object')
32
+ return null;
33
+ const count = (v) => (Number.isFinite(v) && v >= 0 ? Math.trunc(v) : 0);
34
+ return {
35
+ stars: count(json.stargazers_count),
36
+ forks: count(json.forks_count),
37
+ // `subscribers_count`, not `watchers_count`. The API has carried both for
38
+ // years and `watchers_count` is a legacy alias for the *stargazer* count —
39
+ // so labelling it "watching" printed the star number twice and called one
40
+ // of them watchers. The real watcher count is the subscribers number.
41
+ watching: count(json.subscribers_count),
42
+ issues: count(json.open_issues_count),
43
+ description: typeof json.description === 'string' ? json.description.trim() : '',
44
+ // "NOASSERTION" is GitHub's way of saying it found a license file it could
45
+ // not identify, which is not a license anyone can comply with.
46
+ license: json.license?.spdx_id && json.license.spdx_id !== 'NOASSERTION'
47
+ ? json.license.spdx_id
48
+ : '',
49
+ created: typeof json.created_at === 'string' ? json.created_at : '',
50
+ pushed: typeof json.pushed_at === 'string' ? json.pushed_at : '',
51
+ branch: typeof json.default_branch === 'string' ? json.default_branch : '',
52
+ topics: Array.isArray(json.topics)
53
+ ? json.topics.filter((t) => typeof t === 'string' && t).slice(0, 12)
54
+ : [],
55
+ homepage: typeof json.homepage === 'string' ? json.homepage.trim() : '',
56
+ archived: Boolean(json.archived),
57
+ };
58
+ }
59
+ /**
60
+ * Why a remote lookup did not produce facts, in the words a person can act on.
61
+ *
62
+ * 403, 404 and 429 are separated because they mean opposite things — one is
63
+ * "ask less often, or authenticate", one is "private, or gone, or never there",
64
+ * and one is "slow down" — and collapsing them into "GitHub said no" helps
65
+ * nobody diagnose anything.
66
+ */
67
+ export function remoteError(status) {
68
+ if (status === 403) {
69
+ return 'GitHub rate-limited the ask — the unauthenticated allowance is 60 an hour.';
70
+ }
71
+ if (status === 404) {
72
+ return 'GitHub has no such repository, or it is private.';
73
+ }
74
+ if (status === 429) {
75
+ return 'GitHub is throttling this machine — try again in a minute.';
76
+ }
77
+ return 'GitHub answered ' + status + '.';
78
+ }
79
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/shared/analyzer/github.ts"],"names":[],"mappings":"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","sourcesContent":["// Reading a GitHub repository's public facts — the part the browser and the\n// terminal both need, and the part that was quietly wrong in one of them.\n//\n// This module is pure: it takes an already-parsed API payload and returns plain\n// data. The `fetch` deliberately stays on either side of it, because the two\n// callers can do things the other cannot — the browser must not hold a token,\n// and the terminal can. `shared/` may not know which runtime it is in, so the\n// network call is not here; only the reading of the answer is.\n//\n// One implementation, because the previous arrangement had the browser with its\n// own copy of the URL regex and its own idea of which counter means \"watching\",\n// and the two drifted apart without anything noticing.\n\n/**\n * The `owner/repo` a git URL points at, or null if it is not a GitHub URL.\n *\n * Both URL shapes git accepts: `https://github.com/owner/repo(.git)` and\n * `git@github.com:owner/repo(.git)`. Anything else is not GitHub, and gets no\n * remote lookup — a GitLab or Bitbucket clone is a real outcome, not an error.\n */\nexport function githubRepoPath(url) {\n const m = String(url ?? '').match(/github\\.com[:/]([^/\\s]+\\/[^/\\s]+?)(?:\\.git)?\\/?$/);\n return m ? m[1] : null;\n}\n\n/**\n * The public facts worth showing, read out of `GET /repos/{owner}/{repo}`.\n *\n * Returns null for anything that is not an object, so a caller can tell \"no\n * facts\" from \"all zeroes\" without a try/catch around every field.\n */\nexport function remoteFacts(json) {\n if (!json || typeof json !== 'object') return null;\n const count = (v) => (Number.isFinite(v) && v >= 0 ? Math.trunc(v) : 0);\n\n return {\n stars: count(json.stargazers_count),\n forks: count(json.forks_count),\n // `subscribers_count`, not `watchers_count`. The API has carried both for\n // years and `watchers_count` is a legacy alias for the *stargazer* count —\n // so labelling it \"watching\" printed the star number twice and called one\n // of them watchers. The real watcher count is the subscribers number.\n watching: count(json.subscribers_count),\n issues: count(json.open_issues_count),\n description: typeof json.description === 'string' ? json.description.trim() : '',\n // \"NOASSERTION\" is GitHub's way of saying it found a license file it could\n // not identify, which is not a license anyone can comply with.\n license: json.license?.spdx_id && json.license.spdx_id !== 'NOASSERTION'\n ? json.license.spdx_id\n : '',\n created: typeof json.created_at === 'string' ? json.created_at : '',\n pushed: typeof json.pushed_at === 'string' ? json.pushed_at : '',\n branch: typeof json.default_branch === 'string' ? json.default_branch : '',\n topics: Array.isArray(json.topics)\n ? json.topics.filter((t) => typeof t === 'string' && t).slice(0, 12)\n : [],\n homepage: typeof json.homepage === 'string' ? json.homepage.trim() : '',\n archived: Boolean(json.archived),\n };\n}\n\n/**\n * Why a remote lookup did not produce facts, in the words a person can act on.\n *\n * 403, 404 and 429 are separated because they mean opposite things — one is\n * \"ask less often, or authenticate\", one is \"private, or gone, or never there\",\n * and one is \"slow down\" — and collapsing them into \"GitHub said no\" helps\n * nobody diagnose anything.\n */\nexport function remoteError(status) {\n if (status === 403) {\n return 'GitHub rate-limited the ask — the unauthenticated allowance is 60 an hour.';\n }\n if (status === 404) {\n return 'GitHub has no such repository, or it is private.';\n }\n if (status === 429) {\n return 'GitHub is throttling this machine — try again in a minute.';\n }\n return 'GitHub answered ' + status + '.';\n}"]}
@@ -0,0 +1,41 @@
1
+ export declare function computeFacts(scan: any, manifest?: Record<string, any>): {
2
+ communities: {
3
+ id: any;
4
+ members: any;
5
+ size: any;
6
+ }[];
7
+ betweenness: {
8
+ [k: string]: number;
9
+ };
10
+ betweennessExact: boolean;
11
+ fanIn: any;
12
+ fanOut: any;
13
+ importers: any;
14
+ importsOf: any;
15
+ entries: any;
16
+ hubs: any;
17
+ orphans: any;
18
+ cycles: any[];
19
+ inCycle: unknown[];
20
+ deadExports: any[];
21
+ testCoverage: {
22
+ testedCount: number;
23
+ totalNonTest: any;
24
+ ratio: number;
25
+ };
26
+ untestedHubs: any;
27
+ depsDrift: {
28
+ unusedDeclared: string[];
29
+ undeclaredImported: string[];
30
+ };
31
+ folderEdges: {
32
+ from: any;
33
+ to: any;
34
+ count: any;
35
+ }[];
36
+ entrySet: any;
37
+ };
38
+ export declare function factIndex(facts: any): any;
39
+ export declare function roleOf(path: any, facts: any): "config" | "entry" | "hub" | "leaf" | "module" | "test";
40
+ export declare function inCycle(path: any, facts: any): any;
41
+ export declare function scanIndex(scan: any): any;