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.
- package/README.md +196 -47
- package/bin/build-if-source.js +23 -0
- package/cli/commands.d.ts +26 -0
- package/cli/commands.js +836 -811
- package/cli/commands.js.map +1 -0
- package/cli/explorer/advanced.d.ts +14 -0
- package/cli/explorer/advanced.js +449 -0
- package/cli/explorer/advanced.js.map +1 -0
- package/cli/explorer/app.d.ts +1 -0
- package/cli/explorer/app.js +396 -229
- package/cli/explorer/app.js.map +1 -0
- package/cli/explorer/assistant.d.ts +9 -0
- package/cli/explorer/assistant.js +58 -0
- package/cli/explorer/assistant.js.map +1 -0
- package/cli/explorer/commands.d.ts +17 -0
- package/cli/explorer/commands.js +400 -162
- package/cli/explorer/commands.js.map +1 -0
- package/cli/explorer/featureViews.d.ts +124 -0
- package/cli/explorer/featureViews.js +179 -0
- package/cli/explorer/featureViews.js.map +1 -0
- package/cli/explorer/github.d.ts +21 -0
- package/cli/explorer/github.js +73 -0
- package/cli/explorer/github.js.map +1 -0
- package/cli/explorer/graphs.d.ts +7 -0
- package/cli/explorer/graphs.js +173 -0
- package/cli/explorer/graphs.js.map +1 -0
- package/cli/explorer/picker.d.ts +22 -0
- package/cli/explorer/picker.js +150 -0
- package/cli/explorer/picker.js.map +1 -0
- package/cli/explorer/report.d.ts +85 -0
- package/cli/explorer/report.js +60 -0
- package/cli/explorer/report.js.map +1 -0
- package/cli/explorer/session.d.ts +449 -0
- package/cli/explorer/session.js +184 -95
- package/cli/explorer/session.js.map +1 -0
- package/cli/explorer/views.d.ts +19 -0
- package/cli/explorer/views.js +496 -412
- package/cli/explorer/views.js.map +1 -0
- package/cli/explorer/wrap.d.ts +1 -0
- package/cli/explorer/wrap.js +33 -0
- package/cli/explorer/wrap.js.map +1 -0
- package/cli/main.d.ts +1 -0
- package/cli/main.js +235 -138
- package/cli/main.js.map +1 -0
- package/cli/prompt.d.ts +5 -0
- package/cli/prompt.js +84 -80
- package/cli/prompt.js.map +1 -0
- package/cli/scanOptions.d.ts +2 -0
- package/cli/scanOptions.js +11 -0
- package/cli/scanOptions.js.map +1 -0
- package/cli/ui.d.ts +33 -0
- package/cli/ui.js +55 -35
- package/cli/ui.js.map +1 -0
- package/cli/wizard.d.ts +187 -0
- package/cli/wizard.js +304 -284
- package/cli/wizard.js.map +1 -0
- package/package.json +15 -4
- package/public/app.d.ts +1 -0
- package/public/app.js +1057 -1009
- package/public/app.js.map +1 -0
- package/public/browser.d.ts +68 -0
- package/public/browser.js +2 -0
- package/public/browser.js.map +1 -0
- package/public/index.html +30 -13
- package/public/js/about.d.ts +6 -0
- package/public/js/about.js +165 -172
- package/public/js/about.js.map +1 -0
- package/public/js/aiDraft.d.ts +3 -0
- package/public/js/aiDraft.js +116 -124
- package/public/js/aiDraft.js.map +1 -0
- package/public/js/analysisPanel.d.ts +7 -0
- package/public/js/analysisPanel.js +166 -166
- package/public/js/analysisPanel.js.map +1 -0
- package/public/js/analysisReport.d.ts +38 -0
- package/public/js/analysisReport.js +105 -110
- package/public/js/analysisReport.js.map +1 -0
- package/public/js/api.d.ts +26 -0
- package/public/js/api.js +176 -167
- package/public/js/api.js.map +1 -0
- package/public/js/atlas.d.ts +6 -0
- package/public/js/atlas.js +50 -58
- package/public/js/atlas.js.map +1 -0
- package/public/js/blameView.d.ts +2 -0
- package/public/js/blameView.js +36 -37
- package/public/js/blameView.js.map +1 -0
- package/public/js/codeTab.d.ts +3 -0
- package/public/js/codeTab.js +175 -180
- package/public/js/codeTab.js.map +1 -0
- package/public/js/codeViewer.d.ts +5 -0
- package/public/js/codeViewer.js +162 -150
- package/public/js/codeViewer.js.map +1 -0
- package/public/js/components/FileChip.d.ts +9 -0
- package/public/js/components/FileChip.js +45 -49
- package/public/js/components/FileChip.js.map +1 -0
- package/public/js/components/MetricSparkline.d.ts +7 -0
- package/public/js/components/MetricSparkline.js +35 -44
- package/public/js/components/MetricSparkline.js.map +1 -0
- package/public/js/components/RiskBadge.d.ts +9 -0
- package/public/js/components/RiskBadge.js +55 -63
- package/public/js/components/RiskBadge.js.map +1 -0
- package/public/js/deepAnalysisView.d.ts +99 -0
- package/public/js/deepAnalysisView.js +282 -302
- package/public/js/deepAnalysisView.js.map +1 -0
- package/public/js/diagramPane.d.ts +8 -0
- package/public/js/diagramPane.js +133 -135
- package/public/js/diagramPane.js.map +1 -0
- package/public/js/diffView.d.ts +6 -0
- package/public/js/diffView.js +222 -209
- package/public/js/diffView.js.map +1 -0
- package/public/js/docsView.d.ts +2 -0
- package/public/js/docsView.js +441 -442
- package/public/js/docsView.js.map +1 -0
- package/public/js/dom.d.ts +189 -0
- package/public/js/dom.js +5 -0
- package/public/js/dom.js.map +1 -0
- package/public/js/fileSourceBrowser.d.ts +5 -0
- package/public/js/fileSourceBrowser.js +33 -41
- package/public/js/fileSourceBrowser.js.map +1 -0
- package/public/js/flameGraph.d.ts +5 -0
- package/public/js/flameGraph.js +62 -72
- package/public/js/flameGraph.js.map +1 -0
- package/public/js/forceGraph.d.ts +10 -0
- package/public/js/forceGraph.js +581 -556
- package/public/js/forceGraph.js.map +1 -0
- package/public/js/heatmap.d.ts +4 -0
- package/public/js/heatmap.js +142 -164
- package/public/js/heatmap.js.map +1 -0
- package/public/js/highlight.d.ts +2 -0
- package/public/js/highlight.js +116 -107
- package/public/js/highlight.js.map +1 -0
- package/public/js/html.d.ts +2 -0
- package/public/js/html.js +14 -44
- package/public/js/html.js.map +1 -0
- package/public/js/insightsView.d.ts +5 -0
- package/public/js/insightsView.js +93 -111
- package/public/js/insightsView.js.map +1 -0
- package/public/js/inspector.d.ts +37 -0
- package/public/js/inspector.js +416 -445
- package/public/js/inspector.js.map +1 -0
- package/public/js/llm.d.ts +113 -0
- package/public/js/llm.js +233 -272
- package/public/js/llm.js.map +1 -0
- package/public/js/mapView.d.ts +3 -0
- package/public/js/mapView.js +121 -120
- package/public/js/mapView.js.map +1 -0
- package/public/js/markdown.d.ts +3 -0
- package/public/js/markdown.js +84 -91
- package/public/js/markdown.js.map +1 -0
- package/public/js/mindmap.d.ts +32 -0
- package/public/js/mindmap.js +244 -259
- package/public/js/mindmap.js.map +1 -0
- package/public/js/mobilePanels.d.ts +5 -0
- package/public/js/mobilePanels.js +50 -0
- package/public/js/mobilePanels.js.map +1 -0
- package/public/js/repoFiles.d.ts +12 -0
- package/public/js/repoFiles.js +28 -27
- package/public/js/repoFiles.js.map +1 -0
- package/public/js/reviewView.d.ts +28 -0
- package/public/js/reviewView.js +256 -0
- package/public/js/reviewView.js.map +1 -0
- package/public/js/sbomView.d.ts +3 -0
- package/public/js/sbomView.js +59 -67
- package/public/js/sbomView.js.map +1 -0
- package/public/js/scanCache.d.ts +16 -0
- package/public/js/scanCache.js +67 -65
- package/public/js/scanCache.js.map +1 -0
- package/public/js/search.d.ts +7 -0
- package/public/js/search.js +868 -800
- package/public/js/search.js.map +1 -0
- package/public/js/searchLocal.d.ts +42 -0
- package/public/js/searchLocal.js +87 -0
- package/public/js/searchLocal.js.map +1 -0
- package/public/js/serverSettings.d.ts +5 -0
- package/public/js/serverSettings.js +153 -164
- package/public/js/serverSettings.js.map +1 -0
- package/public/js/state.d.ts +798 -0
- package/public/js/state.js +114 -122
- package/public/js/state.js.map +1 -0
- package/public/js/tour.d.ts +6 -0
- package/public/js/tour.js +5 -7
- package/public/js/tour.js.map +1 -0
- package/public/js/transitions.d.ts +2 -0
- package/public/js/transitions.js +9 -10
- package/public/js/transitions.js.map +1 -0
- package/public/js/tree.d.ts +12 -0
- package/public/js/tree.js +157 -154
- package/public/js/tree.js.map +1 -0
- package/public/js/workflowsView.d.ts +3 -0
- package/public/js/workflowsView.js +15 -22
- package/public/js/workflowsView.js.map +1 -0
- package/public/search.css +495 -0
- package/public/styles.css +163 -346
- package/public/workbench.css +166 -0
- package/server/apiAuth.d.ts +3 -0
- package/server/apiAuth.js +18 -20
- package/server/apiAuth.js.map +1 -0
- package/server/apiDiff.d.ts +2 -0
- package/server/apiDiff.js +20 -18
- package/server/apiDiff.js.map +1 -0
- package/server/apiDocs.d.ts +2 -0
- package/server/apiDocs.js +38 -40
- package/server/apiDocs.js.map +1 -0
- package/server/apiFile.d.ts +1 -0
- package/server/apiFile.js +14 -17
- package/server/apiFile.js.map +1 -0
- package/server/apiGitBlame.d.ts +2 -0
- package/server/apiGitBlame.js +50 -51
- package/server/apiGitBlame.js.map +1 -0
- package/server/apiMcp.d.ts +4 -0
- package/server/apiMcp.js +64 -66
- package/server/apiMcp.js.map +1 -0
- package/server/apiReview.d.ts +2 -0
- package/server/apiReview.js +45 -0
- package/server/apiReview.js.map +1 -0
- package/server/apiScan.d.ts +5 -0
- package/server/apiScan.js +90 -71
- package/server/apiScan.js.map +1 -0
- package/server/apiSearch.d.ts +33 -0
- package/server/apiSearch.js +184 -200
- package/server/apiSearch.js.map +1 -0
- package/server/apiSettings.d.ts +4 -0
- package/server/apiSettings.js +84 -85
- package/server/apiSettings.js.map +1 -0
- package/server/apiTools.d.ts +3 -0
- package/server/apiTools.js +55 -56
- package/server/apiTools.js.map +1 -0
- package/server/auth.d.ts +5 -0
- package/server/auth.js +54 -51
- package/server/auth.js.map +1 -0
- package/server/config.d.ts +42 -0
- package/server/config.js +189 -194
- package/server/config.js.map +1 -0
- package/server/daemon.d.ts +12 -0
- package/server/daemon.js +124 -114
- package/server/daemon.js.map +1 -0
- package/server/fileSourceNode.d.ts +2 -0
- package/server/fileSourceNode.js +34 -36
- package/server/fileSourceNode.js.map +1 -0
- package/server/gitClone.d.ts +9 -0
- package/server/gitClone.js +59 -61
- package/server/gitClone.js.map +1 -0
- package/server/gitDiff.d.ts +36 -0
- package/server/gitDiff.js +271 -169
- package/server/gitDiff.js.map +1 -0
- package/server/gitHistory.d.ts +12 -0
- package/server/gitHistory.js +80 -80
- package/server/gitHistory.js.map +1 -0
- package/server/gitRemote.d.ts +12 -0
- package/server/gitRemote.js +60 -0
- package/server/gitRemote.js.map +1 -0
- package/server/htmlText.d.ts +4 -0
- package/server/htmlText.js +16 -23
- package/server/htmlText.js.map +1 -0
- package/server/http.d.ts +5 -0
- package/server/http.js +27 -30
- package/server/http.js.map +1 -0
- package/server/httpGuards.d.ts +2 -0
- package/server/httpGuards.js +47 -43
- package/server/httpGuards.js.map +1 -0
- package/server/https.d.ts +34 -0
- package/server/https.js +121 -111
- package/server/https.js.map +1 -0
- package/server/index.d.ts +40 -0
- package/server/index.js +139 -147
- package/server/index.js.map +1 -0
- package/server/layout.d.ts +26 -0
- package/server/layout.js +59 -37
- package/server/layout.js.map +1 -0
- package/server/llmProxy.d.ts +3 -0
- package/server/llmProxy.js +137 -135
- package/server/llmProxy.js.map +1 -0
- package/server/logger.d.ts +38 -0
- package/server/logger.js +198 -211
- package/server/logger.js.map +1 -0
- package/server/mcp/analysis.d.ts +29 -0
- package/server/mcp/analysis.js +99 -120
- package/server/mcp/analysis.js.map +1 -0
- package/server/mcp/http.d.ts +9 -0
- package/server/mcp/http.js +128 -137
- package/server/mcp/http.js.map +1 -0
- package/server/mcp/runner.d.ts +68 -0
- package/server/mcp/runner.js +208 -218
- package/server/mcp/runner.js.map +1 -0
- package/server/mcp/server.d.ts +29 -0
- package/server/mcp/server.js +166 -179
- package/server/mcp/server.js.map +1 -0
- package/server/mcp/standalone.d.ts +1 -0
- package/server/mcp/standalone.js +8 -10
- package/server/mcp/standalone.js.map +1 -0
- package/server/mcp/tools.d.ts +2020 -0
- package/server/mcp/tools.js +523 -574
- package/server/mcp/tools.js.map +1 -0
- package/server/paths.d.ts +3 -0
- package/server/paths.js +17 -15
- package/server/paths.js.map +1 -0
- package/server/pidfile.d.ts +9 -0
- package/server/pidfile.js +43 -45
- package/server/pidfile.js.map +1 -0
- package/server/review.d.ts +5 -0
- package/server/review.js +35 -0
- package/server/review.js.map +1 -0
- package/server/router.d.ts +33 -0
- package/server/router.js +191 -197
- package/server/router.js.map +1 -0
- package/server/scanRequest.d.ts +3 -0
- package/server/scanRequest.js +36 -0
- package/server/scanRequest.js.map +1 -0
- package/server/searchIndex.d.ts +17 -0
- package/server/searchIndex.js +83 -80
- package/server/searchIndex.js.map +1 -0
- package/server/sessions.d.ts +14 -0
- package/server/sessions.js +62 -70
- package/server/sessions.js.map +1 -0
- package/server/startup.d.ts +118 -0
- package/server/startup.js +143 -148
- package/server/startup.js.map +1 -0
- package/server/static.d.ts +6 -0
- package/server/static.js +28 -31
- package/server/static.js.map +1 -0
- package/server/tools/install.d.ts +4 -0
- package/server/tools/install.js +176 -185
- package/server/tools/install.js.map +1 -0
- package/server/tools/parse.d.ts +8 -0
- package/server/tools/parse.js +112 -114
- package/server/tools/parse.js.map +1 -0
- package/server/tools/platform.d.ts +9 -0
- package/server/tools/platform.js +49 -47
- package/server/tools/platform.js.map +1 -0
- package/server/tools/registry.d.ts +137 -0
- package/server/tools/registry.js +173 -172
- package/server/tools/registry.js.map +1 -0
- package/server/tools/scan.d.ts +34 -0
- package/server/tools/scan.js +89 -98
- package/server/tools/scan.js.map +1 -0
- package/server/tools.d.ts +34 -0
- package/server/tools.js +94 -107
- package/server/tools.js.map +1 -0
- package/server/tunnel.d.ts +29 -0
- package/server/tunnel.js +61 -66
- package/server/tunnel.js.map +1 -0
- package/shared/analyzer/docs.d.ts +16 -0
- package/shared/analyzer/docs.js +99 -93
- package/shared/analyzer/docs.js.map +1 -0
- package/shared/analyzer/explainLocal.d.ts +4 -0
- package/shared/analyzer/explainLocal.js +122 -142
- package/shared/analyzer/explainLocal.js.map +1 -0
- package/shared/analyzer/github.d.ts +37 -0
- package/shared/analyzer/github.js +79 -0
- package/shared/analyzer/github.js.map +1 -0
- package/shared/analyzer/graph.d.ts +41 -0
- package/shared/analyzer/graph.js +393 -400
- package/shared/analyzer/graph.js.map +1 -0
- package/shared/analyzer/health.d.ts +33 -0
- package/shared/analyzer/health.js +197 -193
- package/shared/analyzer/health.js.map +1 -0
- package/shared/analyzer/history.d.ts +29 -0
- package/shared/analyzer/history.js +110 -111
- package/shared/analyzer/history.js.map +1 -0
- package/shared/analyzer/jsonConfig.d.ts +2 -0
- package/shared/analyzer/jsonConfig.js +61 -0
- package/shared/analyzer/jsonConfig.js.map +1 -0
- package/shared/analyzer/languages/csharp.d.ts +26 -0
- package/shared/analyzer/languages/csharp.js +83 -88
- package/shared/analyzer/languages/csharp.js.map +1 -0
- package/shared/analyzer/languages/generic.d.ts +23 -0
- package/shared/analyzer/languages/generic.js +94 -105
- package/shared/analyzer/languages/generic.js.map +1 -0
- package/shared/analyzer/languages/go.d.ts +24 -0
- package/shared/analyzer/languages/go.js +45 -54
- package/shared/analyzer/languages/go.js.map +1 -0
- package/shared/analyzer/languages/index.d.ts +6 -0
- package/shared/analyzer/languages/index.js +19 -20
- package/shared/analyzer/languages/index.js.map +1 -0
- package/shared/analyzer/languages/java.d.ts +20 -0
- package/shared/analyzer/languages/java.js +73 -78
- package/shared/analyzer/languages/java.js.map +1 -0
- package/shared/analyzer/languages/javascript.d.ts +12 -0
- package/shared/analyzer/languages/javascript.js +258 -209
- package/shared/analyzer/languages/javascript.js.map +1 -0
- package/shared/analyzer/languages/python.d.ts +23 -0
- package/shared/analyzer/languages/python.js +92 -100
- package/shared/analyzer/languages/python.js.map +1 -0
- package/shared/analyzer/languages/rust.d.ts +17 -0
- package/shared/analyzer/languages/rust.js +96 -98
- package/shared/analyzer/languages/rust.js.map +1 -0
- package/shared/analyzer/languages/typescript.d.ts +11 -0
- package/shared/analyzer/languages/typescript.js +117 -116
- package/shared/analyzer/languages/typescript.js.map +1 -0
- package/shared/analyzer/licenses.d.ts +18 -0
- package/shared/analyzer/licenses.js +130 -133
- package/shared/analyzer/licenses.js.map +1 -0
- package/shared/analyzer/metrics.d.ts +20 -0
- package/shared/analyzer/metrics.js +112 -104
- package/shared/analyzer/metrics.js.map +1 -0
- package/shared/analyzer/pathUtil.d.ts +10 -0
- package/shared/analyzer/pathUtil.js +29 -35
- package/shared/analyzer/pathUtil.js.map +1 -0
- package/shared/analyzer/patterns.d.ts +11 -0
- package/shared/analyzer/patterns.js +231 -253
- package/shared/analyzer/patterns.js.map +1 -0
- package/shared/analyzer/scan.d.ts +62 -0
- package/shared/analyzer/scan.js +451 -442
- package/shared/analyzer/scan.js.map +1 -0
- package/shared/analyzer/scanControl.d.ts +11 -0
- package/shared/analyzer/scanControl.js +62 -0
- package/shared/analyzer/scanControl.js.map +1 -0
- package/shared/analyzer/security.d.ts +18 -0
- package/shared/analyzer/security.js +159 -159
- package/shared/analyzer/security.js.map +1 -0
- package/shared/analyzer/services.d.ts +5 -0
- package/shared/analyzer/services.js +141 -138
- package/shared/analyzer/services.js.map +1 -0
- package/shared/analyzer/stack.d.ts +6 -0
- package/shared/analyzer/stack.js +134 -141
- package/shared/analyzer/stack.js.map +1 -0
- package/shared/analyzer/tour.d.ts +2 -0
- package/shared/analyzer/tour.js +45 -53
- package/shared/analyzer/tour.js.map +1 -0
- package/shared/analyzer/util.d.ts +8 -0
- package/shared/analyzer/util.js +130 -76
- package/shared/analyzer/util.js.map +1 -0
- package/shared/analyzer/workflows.d.ts +8 -0
- package/shared/analyzer/workflows.js +139 -134
- package/shared/analyzer/workflows.js.map +1 -0
- package/shared/contracts.d.ts +250 -0
- package/shared/contracts.js +2 -0
- package/shared/contracts.js.map +1 -0
- package/shared/diagram/aiFacts.d.ts +35 -0
- package/shared/diagram/aiFacts.js +102 -105
- package/shared/diagram/aiFacts.js.map +1 -0
- package/shared/diagram/aiMermaid.d.ts +5 -0
- package/shared/diagram/aiMermaid.js +46 -45
- package/shared/diagram/aiMermaid.js.map +1 -0
- package/shared/diagram/atlas.d.ts +16 -0
- package/shared/diagram/atlas.js +51 -60
- package/shared/diagram/atlas.js.map +1 -0
- package/shared/diagram/mermaid.d.ts +43 -0
- package/shared/diagram/mermaid.js +348 -370
- package/shared/diagram/mermaid.js.map +1 -0
- package/shared/review/contracts.d.ts +95 -0
- package/shared/review/contracts.js +2 -0
- package/shared/review/contracts.js.map +1 -0
- package/shared/review/review.d.ts +10 -0
- package/shared/review/review.js +184 -0
- package/shared/review/review.js.map +1 -0
- package/shared/search/query.d.ts +32 -0
- package/shared/search/query.js +395 -388
- 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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
paras.push(
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
|
|
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;
|