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
package/server/searchIndex.js
CHANGED
|
@@ -17,52 +17,44 @@
|
|
|
17
17
|
// directory, re-reading every file, parsing its tokens — is gone. The
|
|
18
18
|
// per-request cost is one Map lookup plus the scoring pass over matching
|
|
19
19
|
// documents, which is bounded by the index size, not the repo size.
|
|
20
|
-
|
|
21
20
|
const DEFAULTS = {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
21
|
+
// Aggregate content size. Files beyond this are not indexed, only counted.
|
|
22
|
+
// 200 MB is enough to index the source of a large monorepo comfortably;
|
|
23
|
+
// past that the search would be matching against vendor copies and
|
|
24
|
+
// generated code more often than against code people wrote.
|
|
25
|
+
maxTotalBytes: 200 * 1024 * 1024,
|
|
26
|
+
// Per-file ceiling. Files larger than this are skipped (the scanner has
|
|
27
|
+
// its own ceiling for the same reason).
|
|
28
|
+
maxFileBytes: 1024 * 1024,
|
|
29
|
+
// Reads in flight at once. Same shape as `scan.js`'s read-ahead — a file
|
|
30
|
+
// is held in memory whole before the next one starts.
|
|
31
|
+
width: 8,
|
|
33
32
|
};
|
|
34
|
-
|
|
35
33
|
const BINARY_HEAD_BYTES = 1000;
|
|
36
|
-
|
|
37
34
|
function looksBinary(content) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
// NUL in the first KB is a reliable, cheap heuristic for "this is not
|
|
36
|
+
// text the search would help with". The first KB also covers the BOM and
|
|
37
|
+
// the shebang without missing the start of the file.
|
|
38
|
+
return content.slice(0, BINARY_HEAD_BYTES).includes('\0');
|
|
42
39
|
}
|
|
43
|
-
|
|
44
40
|
// Read each path's text up to width at a time. Failures are skipped, the
|
|
45
41
|
// same way `scan.js:readAhead` handles them: one unreadable file should not
|
|
46
42
|
// end an index build, and the caller counts it in `skipped.readFailed`.
|
|
47
43
|
async function* readAhead(source, paths, width) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (next < paths.length) inFlight.push(read(paths[next++]));
|
|
62
|
-
yield await settled;
|
|
63
|
-
}
|
|
44
|
+
const inFlight = [];
|
|
45
|
+
let next = 0;
|
|
46
|
+
const read = (p) => Promise.resolve()
|
|
47
|
+
.then(() => source.read(p))
|
|
48
|
+
.then((text) => ({ path: p, text, failed: false }), () => ({ path: p, text: '', failed: true }));
|
|
49
|
+
while (next < paths.length && inFlight.length < width)
|
|
50
|
+
inFlight.push(read(paths[next++]));
|
|
51
|
+
while (inFlight.length) {
|
|
52
|
+
const settled = inFlight.shift();
|
|
53
|
+
if (next < paths.length)
|
|
54
|
+
inFlight.push(read(paths[next++]));
|
|
55
|
+
yield await settled;
|
|
56
|
+
}
|
|
64
57
|
}
|
|
65
|
-
|
|
66
58
|
// Build the search index from the file list the scanner already produced.
|
|
67
59
|
// The scanner has read these files once for parsing; indexing reads them a
|
|
68
60
|
// second time for tokenizing, which is the cheapest place to do it — a
|
|
@@ -71,48 +63,59 @@ async function* readAhead(source, paths, width) {
|
|
|
71
63
|
// smallest change that closes the audit's three real concerns (first-search
|
|
72
64
|
// latency, no aggregate cap, no concurrency).
|
|
73
65
|
export async function buildSearchIndex(source, codeFiles, options = {}) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
66
|
+
const opts = { ...DEFAULTS, ...options };
|
|
67
|
+
const index = new Map();
|
|
68
|
+
const docCounts = new Map();
|
|
69
|
+
let totalDocs = 0;
|
|
70
|
+
let totalBytes = 0;
|
|
71
|
+
// Files the indexer cannot or will not index, broken down by reason. The
|
|
72
|
+
// shape matches `scan.js:skips` so a future UI surface can render one
|
|
73
|
+
// unified "what was left out" panel without translation.
|
|
74
|
+
const skipped = {
|
|
75
|
+
tooLarge: 0, // one file over maxFileBytes
|
|
76
|
+
overCap: 0, // a later file pushed the aggregate over maxTotalBytes
|
|
77
|
+
readFailed: 0, // the file would not read
|
|
78
|
+
binary: 0, // NUL in the first KB
|
|
79
|
+
noTokens: 0, // the file read, but tokenizing produced nothing useful
|
|
80
|
+
};
|
|
81
|
+
for await (const { path, text, failed } of readAhead(source, codeFiles, opts.width)) {
|
|
82
|
+
if (failed) {
|
|
83
|
+
skipped.readFailed++;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (text.length > opts.maxFileBytes) {
|
|
87
|
+
skipped.tooLarge++;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (totalBytes + text.length > opts.maxTotalBytes) {
|
|
91
|
+
skipped.overCap++;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (looksBinary(text)) {
|
|
95
|
+
skipped.binary++;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const tokens = text.toLowerCase().split(/\W+/).filter((t) => t.length > 1);
|
|
99
|
+
if (!tokens.length) {
|
|
100
|
+
skipped.noTokens++;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const tf = new Map();
|
|
104
|
+
for (const t of tokens)
|
|
105
|
+
tf.set(t, (tf.get(t) || 0) + 1);
|
|
106
|
+
for (const t of tf.keys())
|
|
107
|
+
docCounts.set(t, (docCounts.get(t) || 0) + 1);
|
|
108
|
+
index.set(path, { tf, content: text, tokenCount: tokens.length });
|
|
109
|
+
totalDocs++;
|
|
110
|
+
totalBytes += text.length;
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
index,
|
|
114
|
+
docCounts,
|
|
115
|
+
totalDocs,
|
|
116
|
+
totalBytes,
|
|
117
|
+
skipped,
|
|
118
|
+
cap: { maxFileBytes: opts.maxFileBytes, maxTotalBytes: opts.maxTotalBytes },
|
|
119
|
+
};
|
|
118
120
|
}
|
|
121
|
+
//# sourceMappingURL=searchIndex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchIndex.js","sourceRoot":"","sources":["../src/server/searchIndex.ts"],"names":[],"mappings":"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","sourcesContent":["// The search index lives with the scan, not behind a request. Building it\n// here means:\n//\n// * The first /api/search call is fast. The user is searching — make it feel\n// that way; the work that would have been a request-blocking second walk\n// is already done.\n// * The index reads exactly the files the scanner did. The caller hands us\n// `scan.files`, the list of paths the scanner accepted; we never walk\n// the tree ourselves, so the index can never disagree with the scan\n// about which files exist.\n// * The index has a hard cap. A repo with a single 200 MB SQL dump used to\n// hold its full content in the process for the lifetime of the session;\n// now it stops indexing at the cap and records what it skipped, so a\n// future \"why doesn't my file show up?\" question has a real answer.\n//\n// The on-disk cost of the work the old /api/search did — re-listing every\n// directory, re-reading every file, parsing its tokens — is gone. The\n// per-request cost is one Map lookup plus the scoring pass over matching\n// documents, which is bounded by the index size, not the repo size.\n\nconst DEFAULTS = {\n // Aggregate content size. Files beyond this are not indexed, only counted.\n // 200 MB is enough to index the source of a large monorepo comfortably;\n // past that the search would be matching against vendor copies and\n // generated code more often than against code people wrote.\n maxTotalBytes: 200 * 1024 * 1024,\n // Per-file ceiling. Files larger than this are skipped (the scanner has\n // its own ceiling for the same reason).\n maxFileBytes: 1024 * 1024,\n // Reads in flight at once. Same shape as `scan.js`'s read-ahead — a file\n // is held in memory whole before the next one starts.\n width: 8,\n};\n\nconst BINARY_HEAD_BYTES = 1000;\n\nfunction looksBinary(content) {\n // NUL in the first KB is a reliable, cheap heuristic for \"this is not\n // text the search would help with\". The first KB also covers the BOM and\n // the shebang without missing the start of the file.\n return content.slice(0, BINARY_HEAD_BYTES).includes('\\0');\n}\n\n// Read each path's text up to width at a time. Failures are skipped, the\n// same way `scan.js:readAhead` handles them: one unreadable file should not\n// end an index build, and the caller counts it in `skipped.readFailed`.\nasync function* readAhead(source, paths, width) {\n const inFlight = [];\n let next = 0;\n const read = (p) =>\n Promise.resolve()\n .then(() => source.read(p))\n .then(\n (text) => ({ path: p, text, failed: false }),\n () => ({ path: p, text: '', failed: true }),\n );\n\n while (next < paths.length && inFlight.length < width) inFlight.push(read(paths[next++]));\n while (inFlight.length) {\n const settled = inFlight.shift();\n if (next < paths.length) inFlight.push(read(paths[next++]));\n yield await settled;\n }\n}\n\n// Build the search index from the file list the scanner already produced.\n// The scanner has read these files once for parsing; indexing reads them a\n// second time for tokenizing, which is the cheapest place to do it — a\n// refactor that streamed text from the scanner into both consumers would\n// save one disk pass at the cost of a much larger refactor. This is the\n// smallest change that closes the audit's three real concerns (first-search\n// latency, no aggregate cap, no concurrency).\nexport async function buildSearchIndex(source, codeFiles, options: Record<string, any> = {}) {\n const opts = { ...DEFAULTS, ...options };\n const index = new Map();\n const docCounts = new Map();\n let totalDocs = 0;\n let totalBytes = 0;\n\n // Files the indexer cannot or will not index, broken down by reason. The\n // shape matches `scan.js:skips` so a future UI surface can render one\n // unified \"what was left out\" panel without translation.\n const skipped = {\n tooLarge: 0, // one file over maxFileBytes\n overCap: 0, // a later file pushed the aggregate over maxTotalBytes\n readFailed: 0, // the file would not read\n binary: 0, // NUL in the first KB\n noTokens: 0, // the file read, but tokenizing produced nothing useful\n };\n\n for await (const { path, text, failed } of readAhead(source, codeFiles, opts.width)) {\n if (failed) { skipped.readFailed++; continue; }\n\n if (text.length > opts.maxFileBytes) { skipped.tooLarge++; continue; }\n if (totalBytes + text.length > opts.maxTotalBytes) { skipped.overCap++; continue; }\n if (looksBinary(text)) { skipped.binary++; continue; }\n\n const tokens = text.toLowerCase().split(/\\W+/).filter((t) => t.length > 1);\n if (!tokens.length) { skipped.noTokens++; continue; }\n\n const tf = new Map();\n for (const t of tokens) tf.set(t, (tf.get(t) || 0) + 1);\n for (const t of tf.keys()) docCounts.set(t, (docCounts.get(t) || 0) + 1);\n\n index.set(path, { tf, content: text, tokenCount: tokens.length });\n totalDocs++;\n totalBytes += text.length;\n }\n\n return {\n index,\n docCounts,\n totalDocs,\n totalBytes,\n skipped,\n cap: { maxFileBytes: opts.maxFileBytes, maxTotalBytes: opts.maxTotalBytes },\n };\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const MAX_SESSIONS = 12;
|
|
2
|
+
export declare function openSession({ root, cloneDir, searchIndex }: {
|
|
3
|
+
cloneDir?: any;
|
|
4
|
+
root: any;
|
|
5
|
+
searchIndex?: any;
|
|
6
|
+
}): string;
|
|
7
|
+
export declare function getSession(scanId: any): any;
|
|
8
|
+
export declare function isCloneId(id: any): boolean;
|
|
9
|
+
export declare function closeClone(cloneId: any): Promise<boolean>;
|
|
10
|
+
export declare function removalsSettled(): Promise<void>;
|
|
11
|
+
export declare function sweepClonesSync(): void;
|
|
12
|
+
export declare function installExitCleanup(proc?: NodeJS.Process): void;
|
|
13
|
+
export declare function _resetSessions(): void;
|
|
14
|
+
export declare function _sessionCount(): number;
|
package/server/sessions.js
CHANGED
|
@@ -17,18 +17,14 @@
|
|
|
17
17
|
// * It leaked clones on exit. A clone lives in the OS temp dir until someone
|
|
18
18
|
// removes it, and only an explicit `DELETE /api/scan/:id` did. Ctrl-C left
|
|
19
19
|
// every clone of the session behind — hundreds of megabytes, silently.
|
|
20
|
-
|
|
21
20
|
import crypto from 'node:crypto';
|
|
22
21
|
import path from 'node:path';
|
|
23
22
|
import { realpathSync } from 'node:fs';
|
|
24
|
-
|
|
25
23
|
import { isCloneDir, removeClone, removeCloneSync } from './gitClone.js';
|
|
26
|
-
|
|
27
24
|
// Twelve repos is far more than anyone holds open at once, and each entry is a
|
|
28
25
|
// couple of strings — the cap is about not serving from a root the person has
|
|
29
26
|
// forgotten scanning, not about memory.
|
|
30
27
|
export const MAX_SESSIONS = 12;
|
|
31
|
-
|
|
32
28
|
// scanId -> { root, cloneDir, at, searchIndex? }. Insertion-ordered, which is
|
|
33
29
|
// what makes "oldest first" a `keys().next()` rather than a sort.
|
|
34
30
|
//
|
|
@@ -39,14 +35,12 @@ export const MAX_SESSIONS = 12;
|
|
|
39
35
|
// the same repo would rebuild it; the cost of one scan's worth of work is
|
|
40
36
|
// far below the cost of re-fetching the repo.
|
|
41
37
|
const sessions = new Map();
|
|
42
|
-
|
|
43
38
|
export function openSession({ root, cloneDir = null, searchIndex = null }) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
const scanId = crypto.randomBytes(8).toString('hex');
|
|
40
|
+
sessions.set(scanId, { root: canonicalRoot(root), cloneDir, at: Date.now(), searchIndex });
|
|
41
|
+
evictBeyondCap();
|
|
42
|
+
return scanId;
|
|
48
43
|
}
|
|
49
|
-
|
|
50
44
|
// Resolve symlinks once, so the root every consumer sees is the real one. On
|
|
51
45
|
// macOS `/tmp` is a symlink to `/private/tmp`, and an analyzer run against the
|
|
52
46
|
// alias reports paths rooted at the target — without this, `/api/tools/run`
|
|
@@ -54,110 +48,108 @@ export function openSession({ root, cloneDir = null, searchIndex = null }) {
|
|
|
54
48
|
// scanned through a symlinked path. Failing to resolve (a path that is gone)
|
|
55
49
|
// is not fatal: the original is used and the scan's own error path reports it.
|
|
56
50
|
function canonicalRoot(root) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
51
|
+
if (typeof root !== 'string' || !root)
|
|
52
|
+
return root;
|
|
53
|
+
try {
|
|
54
|
+
return realpathSync(root);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return root;
|
|
58
|
+
}
|
|
63
59
|
}
|
|
64
|
-
|
|
65
60
|
// Reading from a scan keeps it alive. Without the touch, opening files in the
|
|
66
61
|
// first repo you scanned is what evicts it — you would lose the one you are
|
|
67
62
|
// actually using and keep eleven you are not.
|
|
68
63
|
export function getSession(scanId) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
if (!scanId)
|
|
65
|
+
return null;
|
|
66
|
+
const session = sessions.get(scanId);
|
|
67
|
+
if (!session)
|
|
68
|
+
return null;
|
|
69
|
+
session.at = Date.now();
|
|
70
|
+
sessions.delete(scanId);
|
|
71
|
+
sessions.set(scanId, session);
|
|
72
|
+
return session;
|
|
76
73
|
}
|
|
77
|
-
|
|
78
74
|
// Clone ids are the 12 hex characters `gitClone` puts after `onboarder-`. The
|
|
79
75
|
// match is on the exact directory name: `endsWith(cloneId)` treated an empty id
|
|
80
76
|
// as a match against every clone, so `DELETE /api/scan/` used to delete
|
|
81
77
|
// whichever clone the map happened to yield first.
|
|
82
78
|
export function isCloneId(id) {
|
|
83
|
-
|
|
79
|
+
return /^[0-9a-f]{12}$/.test(id || '');
|
|
84
80
|
}
|
|
85
|
-
|
|
86
81
|
// Removes the clone with this id and forgets every scan pointing at it. Returns
|
|
87
82
|
// whether anything was there — a repeat DELETE is not an error; the page sends
|
|
88
83
|
// one on unload and may well be the second to arrive.
|
|
89
84
|
export async function closeClone(cloneId) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
85
|
+
const dirName = 'onboarder-' + cloneId;
|
|
86
|
+
let found = null;
|
|
87
|
+
for (const [scanId, session] of sessions) {
|
|
88
|
+
if (session.cloneDir && path.basename(session.cloneDir) === dirName) {
|
|
89
|
+
found = session.cloneDir;
|
|
90
|
+
sessions.delete(scanId);
|
|
91
|
+
}
|
|
96
92
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
if (found)
|
|
94
|
+
await removeClone(found);
|
|
95
|
+
return Boolean(found);
|
|
100
96
|
}
|
|
101
|
-
|
|
102
97
|
function evictBeyondCap() {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
98
|
+
while (sessions.size > MAX_SESSIONS) {
|
|
99
|
+
const [scanId, session] = sessions.entries().next().value;
|
|
100
|
+
sessions.delete(scanId);
|
|
101
|
+
if (session.cloneDir && !stillReferenced(session.cloneDir))
|
|
102
|
+
sweep(session.cloneDir);
|
|
103
|
+
}
|
|
108
104
|
}
|
|
109
|
-
|
|
110
105
|
// Eviction happens inside a scan request, and the person is waiting on the scan,
|
|
111
106
|
// not on a directory being swept — so the removal is started and not awaited. The
|
|
112
107
|
// promises are chained rather than dropped so that a caller who does need to know
|
|
113
108
|
// when the disk is quiet can wait for it; the only one that does is a test.
|
|
114
109
|
let removals = Promise.resolve();
|
|
115
|
-
|
|
116
110
|
function sweep(dir) {
|
|
117
|
-
|
|
111
|
+
removals = removals.then(() => removeClone(dir));
|
|
118
112
|
}
|
|
119
|
-
|
|
120
113
|
export function removalsSettled() {
|
|
121
|
-
|
|
114
|
+
return removals;
|
|
122
115
|
}
|
|
123
|
-
|
|
124
116
|
// Two sessions can name the same clone — scan a git URL, then scan the temp path
|
|
125
117
|
// it landed in. Do not delete a directory another live session still reads from.
|
|
126
118
|
function stillReferenced(dir) {
|
|
127
|
-
|
|
128
|
-
|
|
119
|
+
for (const session of sessions.values())
|
|
120
|
+
if (session.cloneDir === dir)
|
|
121
|
+
return true;
|
|
122
|
+
return false;
|
|
129
123
|
}
|
|
130
|
-
|
|
131
124
|
// Synchronous on purpose: this is what an exit handler can finish.
|
|
132
125
|
export function sweepClonesSync() {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
126
|
+
for (const [scanId, session] of sessions) {
|
|
127
|
+
sessions.delete(scanId);
|
|
128
|
+
if (isCloneDir(session.cloneDir))
|
|
129
|
+
removeCloneSync(session.cloneDir);
|
|
130
|
+
}
|
|
137
131
|
}
|
|
138
|
-
|
|
139
132
|
// Called from the `node server/index.js` path only, never on import. The tests
|
|
140
133
|
// drive the real router in-process, and a module that added signal handlers just
|
|
141
134
|
// by being imported would take Ctrl-C away from the test runner.
|
|
142
135
|
export function installExitCleanup(proc = process) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
136
|
+
proc.on('exit', sweepClonesSync);
|
|
137
|
+
// A signal does not run `exit` handlers on its own — the process dies where it
|
|
138
|
+
// stands. Sweeping in the signal handler and then exiting is what gets the
|
|
139
|
+
// clones removed.
|
|
140
|
+
for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP']) {
|
|
141
|
+
proc.on(signal, () => {
|
|
142
|
+
sweepClonesSync();
|
|
143
|
+
proc.exit(0);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
153
146
|
}
|
|
154
|
-
|
|
155
147
|
// Tests only. The store is module state, so a test that opens sessions would
|
|
156
148
|
// otherwise leak them into the next one.
|
|
157
149
|
export function _resetSessions() {
|
|
158
|
-
|
|
150
|
+
sessions.clear();
|
|
159
151
|
}
|
|
160
|
-
|
|
161
152
|
export function _sessionCount() {
|
|
162
|
-
|
|
153
|
+
return sessions.size;
|
|
163
154
|
}
|
|
155
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../src/server/sessions.ts"],"names":[],"mappings":"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","sourcesContent":["// What the server remembers between requests: which directory each scan came\n// from. `/api/file` needs it — the browser asks for `server/paths.js` and the\n// server has to know which root that is relative to — and the git-URL flow needs\n// it to find a clone again when the page says it is done with one.\n//\n// A scan id is the capability. Handing the browser a path and trusting it back\n// would make `/api/file` a \"read any file on this machine\" endpoint; handing it\n// an opaque id means the only readable roots are ones the person chose to scan\n// during this run.\n//\n// Two things the inline Map this replaces got wrong:\n//\n// * It never forgot. Every scan added an entry and nothing removed one, so an\n// afternoon of scanning left a growing list of roots still being served\n// from. A cap with oldest-out eviction bounds it, and evicting a cloned repo\n// deletes the clone with it.\n// * It leaked clones on exit. A clone lives in the OS temp dir until someone\n// removes it, and only an explicit `DELETE /api/scan/:id` did. Ctrl-C left\n// every clone of the session behind — hundreds of megabytes, silently.\n\nimport crypto from 'node:crypto';\nimport path from 'node:path';\nimport { realpathSync } from 'node:fs';\n\nimport { isCloneDir, removeClone, removeCloneSync } from './gitClone.js';\n\n// Twelve repos is far more than anyone holds open at once, and each entry is a\n// couple of strings — the cap is about not serving from a root the person has\n// forgotten scanning, not about memory.\nexport const MAX_SESSIONS = 12;\n\n// scanId -> { root, cloneDir, at, searchIndex? }. Insertion-ordered, which is\n// what makes \"oldest first\" a `keys().next()` rather than a sort.\n//\n// `searchIndex`, when present, is the TF-IDF index built at scan time\n// (`searchIndex.js`). It is held on the session for the same reason `root`\n// is — `/api/search` is a request that has to be answered against this\n// particular scan — and is dropped when the session is evicted. Reopening\n// the same repo would rebuild it; the cost of one scan's worth of work is\n// far below the cost of re-fetching the repo.\nconst sessions = new Map();\n\nexport function openSession({ root, cloneDir = null, searchIndex = null }) {\n const scanId = crypto.randomBytes(8).toString('hex');\n sessions.set(scanId, { root: canonicalRoot(root), cloneDir, at: Date.now(), searchIndex });\n evictBeyondCap();\n return scanId;\n}\n\n// Resolve symlinks once, so the root every consumer sees is the real one. On\n// macOS `/tmp` is a symlink to `/private/tmp`, and an analyzer run against the\n// alias reports paths rooted at the target — without this, `/api/tools/run`\n// findings and `/api/file` lookups would silently miss every file in a repo\n// scanned through a symlinked path. Failing to resolve (a path that is gone)\n// is not fatal: the original is used and the scan's own error path reports it.\nfunction canonicalRoot(root) {\n if (typeof root !== 'string' || !root) return root;\n try {\n return realpathSync(root);\n } catch {\n return root;\n }\n}\n\n// Reading from a scan keeps it alive. Without the touch, opening files in the\n// first repo you scanned is what evicts it — you would lose the one you are\n// actually using and keep eleven you are not.\nexport function getSession(scanId) {\n if (!scanId) return null;\n const session = sessions.get(scanId);\n if (!session) return null;\n session.at = Date.now();\n sessions.delete(scanId);\n sessions.set(scanId, session);\n return session;\n}\n\n// Clone ids are the 12 hex characters `gitClone` puts after `onboarder-`. The\n// match is on the exact directory name: `endsWith(cloneId)` treated an empty id\n// as a match against every clone, so `DELETE /api/scan/` used to delete\n// whichever clone the map happened to yield first.\nexport function isCloneId(id) {\n return /^[0-9a-f]{12}$/.test(id || '');\n}\n\n// Removes the clone with this id and forgets every scan pointing at it. Returns\n// whether anything was there — a repeat DELETE is not an error; the page sends\n// one on unload and may well be the second to arrive.\nexport async function closeClone(cloneId) {\n const dirName = 'onboarder-' + cloneId;\n let found = null;\n for (const [scanId, session] of sessions) {\n if (session.cloneDir && path.basename(session.cloneDir) === dirName) {\n found = session.cloneDir;\n sessions.delete(scanId);\n }\n }\n if (found) await removeClone(found);\n return Boolean(found);\n}\n\nfunction evictBeyondCap() {\n while (sessions.size > MAX_SESSIONS) {\n const [scanId, session] = sessions.entries().next().value;\n sessions.delete(scanId);\n if (session.cloneDir && !stillReferenced(session.cloneDir)) sweep(session.cloneDir);\n }\n}\n\n// Eviction happens inside a scan request, and the person is waiting on the scan,\n// not on a directory being swept — so the removal is started and not awaited. The\n// promises are chained rather than dropped so that a caller who does need to know\n// when the disk is quiet can wait for it; the only one that does is a test.\nlet removals = Promise.resolve();\n\nfunction sweep(dir) {\n removals = removals.then(() => removeClone(dir));\n}\n\nexport function removalsSettled() {\n return removals;\n}\n\n// Two sessions can name the same clone — scan a git URL, then scan the temp path\n// it landed in. Do not delete a directory another live session still reads from.\nfunction stillReferenced(dir) {\n for (const session of sessions.values()) if (session.cloneDir === dir) return true;\n return false;\n}\n\n// Synchronous on purpose: this is what an exit handler can finish.\nexport function sweepClonesSync() {\n for (const [scanId, session] of sessions) {\n sessions.delete(scanId);\n if (isCloneDir(session.cloneDir)) removeCloneSync(session.cloneDir);\n }\n}\n\n// Called from the `node server/index.js` path only, never on import. The tests\n// drive the real router in-process, and a module that added signal handlers just\n// by being imported would take Ctrl-C away from the test runner.\nexport function installExitCleanup(proc = process) {\n proc.on('exit', sweepClonesSync);\n // A signal does not run `exit` handlers on its own — the process dies where it\n // stands. Sweeping in the signal handler and then exiting is what gets the\n // clones removed.\n for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP']) {\n proc.on(signal, () => {\n sweepClonesSync();\n proc.exit(0);\n });\n }\n}\n\n// Tests only. The store is module state, so a test that opens sessions would\n// otherwise leak them into the next one.\nexport function _resetSessions() {\n sessions.clear();\n}\n\nexport function _sessionCount() {\n return sessions.size;\n}\n"]}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
export declare const LABEL = "com.onboarder.server";
|
|
2
|
+
export declare const UNIT = "onboarder.service";
|
|
3
|
+
export declare function cliEntry(): string;
|
|
4
|
+
export declare function startupCommand(configFile?: string, { node, entry }?: Record<string, any>): any[];
|
|
5
|
+
export declare function renderLaunchAgent({ configFile, log, ...options }?: Record<string, any>): string;
|
|
6
|
+
export declare function renderSystemdUnit({ configFile, log, ...options }?: Record<string, any>): string;
|
|
7
|
+
export declare function renderWindowsStartup({ configFile, log, ...options }?: Record<string, any>): string;
|
|
8
|
+
export declare function startupTarget({ platform, home, env }?: Record<string, any>): {
|
|
9
|
+
kind: string;
|
|
10
|
+
platform: any;
|
|
11
|
+
label: string;
|
|
12
|
+
path: string;
|
|
13
|
+
render: typeof renderLaunchAgent;
|
|
14
|
+
load: string[];
|
|
15
|
+
unload: string[];
|
|
16
|
+
status: string[];
|
|
17
|
+
hint: string;
|
|
18
|
+
daemonReload?: undefined;
|
|
19
|
+
} | {
|
|
20
|
+
kind: string;
|
|
21
|
+
platform: any;
|
|
22
|
+
label: string;
|
|
23
|
+
path: string;
|
|
24
|
+
render: typeof renderSystemdUnit;
|
|
25
|
+
daemonReload: string[];
|
|
26
|
+
load: string[];
|
|
27
|
+
unload: string[];
|
|
28
|
+
status: string[];
|
|
29
|
+
hint: string;
|
|
30
|
+
};
|
|
31
|
+
export declare function startupInstalled(target?: {
|
|
32
|
+
kind: string;
|
|
33
|
+
platform: any;
|
|
34
|
+
label: string;
|
|
35
|
+
path: string;
|
|
36
|
+
render: typeof renderLaunchAgent;
|
|
37
|
+
load: string[];
|
|
38
|
+
unload: string[];
|
|
39
|
+
status: string[];
|
|
40
|
+
hint: string;
|
|
41
|
+
daemonReload?: undefined;
|
|
42
|
+
} | {
|
|
43
|
+
kind: string;
|
|
44
|
+
platform: any;
|
|
45
|
+
label: string;
|
|
46
|
+
path: string;
|
|
47
|
+
render: typeof renderSystemdUnit;
|
|
48
|
+
daemonReload: string[];
|
|
49
|
+
load: string[];
|
|
50
|
+
unload: string[];
|
|
51
|
+
status: string[];
|
|
52
|
+
hint: string;
|
|
53
|
+
}): Promise<boolean>;
|
|
54
|
+
export declare function startupStatus(target?: {
|
|
55
|
+
kind: string;
|
|
56
|
+
platform: any;
|
|
57
|
+
label: string;
|
|
58
|
+
path: string;
|
|
59
|
+
render: typeof renderLaunchAgent;
|
|
60
|
+
load: string[];
|
|
61
|
+
unload: string[];
|
|
62
|
+
status: string[];
|
|
63
|
+
hint: string;
|
|
64
|
+
daemonReload?: undefined;
|
|
65
|
+
} | {
|
|
66
|
+
kind: string;
|
|
67
|
+
platform: any;
|
|
68
|
+
label: string;
|
|
69
|
+
path: string;
|
|
70
|
+
render: typeof renderSystemdUnit;
|
|
71
|
+
daemonReload: string[];
|
|
72
|
+
load: string[];
|
|
73
|
+
unload: string[];
|
|
74
|
+
status: string[];
|
|
75
|
+
hint: string;
|
|
76
|
+
}, { run }?: Record<string, any>): Promise<{
|
|
77
|
+
kind: string;
|
|
78
|
+
supported: boolean;
|
|
79
|
+
label: string;
|
|
80
|
+
path: string;
|
|
81
|
+
installed: boolean;
|
|
82
|
+
active: any;
|
|
83
|
+
detail: string;
|
|
84
|
+
hint: string;
|
|
85
|
+
}>;
|
|
86
|
+
export declare function installStartup({ configFile, log, target, run }?: Record<string, any>): Promise<{
|
|
87
|
+
path?: undefined;
|
|
88
|
+
ok: boolean;
|
|
89
|
+
reason: string;
|
|
90
|
+
loaded?: undefined;
|
|
91
|
+
output?: undefined;
|
|
92
|
+
error?: undefined;
|
|
93
|
+
} | {
|
|
94
|
+
reason?: undefined;
|
|
95
|
+
ok: boolean;
|
|
96
|
+
path: any;
|
|
97
|
+
loaded: boolean;
|
|
98
|
+
output: string;
|
|
99
|
+
error?: undefined;
|
|
100
|
+
} | {
|
|
101
|
+
reason?: undefined;
|
|
102
|
+
loaded?: undefined;
|
|
103
|
+
ok: boolean;
|
|
104
|
+
path: any;
|
|
105
|
+
output: any;
|
|
106
|
+
error: any;
|
|
107
|
+
}>;
|
|
108
|
+
export declare function removeStartup({ target, run }?: Record<string, any>): Promise<{
|
|
109
|
+
path?: undefined;
|
|
110
|
+
output?: undefined;
|
|
111
|
+
ok: boolean;
|
|
112
|
+
reason: string;
|
|
113
|
+
} | {
|
|
114
|
+
reason?: undefined;
|
|
115
|
+
ok: boolean;
|
|
116
|
+
path: any;
|
|
117
|
+
output: string;
|
|
118
|
+
}>;
|