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/startup.js
CHANGED
|
@@ -19,27 +19,21 @@
|
|
|
19
19
|
// Deliberately no `sudo`, no writing into launchd's system domain, and nothing
|
|
20
20
|
// outside the user's own home. A login item is a convenience; it must never be
|
|
21
21
|
// the thing that needs an administrator password.
|
|
22
|
-
|
|
23
22
|
import { promises as fs } from 'node:fs';
|
|
24
23
|
import os from 'node:os';
|
|
25
24
|
import path from 'node:path';
|
|
26
25
|
import { spawnSync } from 'node:child_process';
|
|
27
26
|
import { fileURLToPath } from 'node:url';
|
|
28
|
-
|
|
29
27
|
import { configPath } from './config.js';
|
|
30
|
-
|
|
31
28
|
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
32
|
-
|
|
33
29
|
export const LABEL = 'com.onboarder.server';
|
|
34
30
|
export const UNIT = 'onboarder.service';
|
|
35
|
-
|
|
36
31
|
export function cliEntry() {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
// `bin/onboarder.js` next to `server/`, whether we were run from a checkout
|
|
33
|
+
// or from a global install. The env override is what lets a test point the
|
|
34
|
+
// generated unit at a fixture instead of the real machine.
|
|
35
|
+
return process.env.ONBOARDER_CLI || path.resolve(HERE, '..', 'bin', 'onboarder.js');
|
|
41
36
|
}
|
|
42
|
-
|
|
43
37
|
// The argv a login item runs.
|
|
44
38
|
//
|
|
45
39
|
// Note what is *not* here: `background`. launchd and systemd are already
|
|
@@ -49,24 +43,21 @@ export function cliEntry() {
|
|
|
49
43
|
// busy port into a respawn loop. So the generated command is a plain foreground
|
|
50
44
|
// `start`, and the OS owns the lifecycle from there.
|
|
51
45
|
export function startupCommand(configFile = configPath(), { node = process.execPath, entry = cliEntry() } = {}) {
|
|
52
|
-
|
|
46
|
+
return [node, entry, 'start', '--config', configFile];
|
|
53
47
|
}
|
|
54
|
-
|
|
55
48
|
function xmlEscape(value) {
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
const map = { '<': '<', '>': '>', '&': '&', "'": ''', '"': '"' };
|
|
50
|
+
return String(value).replace(/[<>&'"]/g, (c) => map[c]);
|
|
58
51
|
}
|
|
59
|
-
|
|
60
52
|
function argList(args) {
|
|
61
|
-
|
|
53
|
+
return args.map((a) => ` <string>${xmlEscape(a)}</string>`).join('\n');
|
|
62
54
|
}
|
|
63
|
-
|
|
64
55
|
export function renderLaunchAgent({ configFile = configPath(), log = '', ...options } = {}) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
56
|
+
const args = startupCommand(configFile, options);
|
|
57
|
+
const streams = log
|
|
58
|
+
? ` <key>StandardOutPath</key>\n <string>${xmlEscape(log)}</string>\n <key>StandardErrorPath</key>\n <string>${xmlEscape(log)}</string>\n`
|
|
59
|
+
: '';
|
|
60
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
70
61
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
71
62
|
<plist version="1.0">
|
|
72
63
|
<dict>
|
|
@@ -94,14 +85,13 @@ ${streams} <key>EnvironmentVariables</key>
|
|
|
94
85
|
</plist>
|
|
95
86
|
`;
|
|
96
87
|
}
|
|
97
|
-
|
|
98
88
|
export function renderSystemdUnit({ configFile = configPath(), log = '', ...options } = {}) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
89
|
+
const args = startupCommand(configFile, options);
|
|
90
|
+
// `Restart=always` would fight `onboarder stop`: a deliberate stop must stay
|
|
91
|
+
// stopped, so only a *failed* exit is restarted. `on-failure` is the honest
|
|
92
|
+
// setting here, and `SuccessfulExit=false` above is its launchd spelling.
|
|
93
|
+
const exec = args.map((a) => (/[\s"]/.test(a) ? JSON.stringify(a) : a)).join(' ');
|
|
94
|
+
return `[Unit]
|
|
105
95
|
Description=Onboarder — codebase visualizer and onboarding map
|
|
106
96
|
Documentation=https://github.com/Amitpandey88/onboarder
|
|
107
97
|
After=network-online.target
|
|
@@ -119,143 +109,148 @@ Environment=ONBOARDER_LAUNCH=startup
|
|
|
119
109
|
WantedBy=default.target
|
|
120
110
|
`;
|
|
121
111
|
}
|
|
122
|
-
|
|
123
112
|
export function renderWindowsStartup({ configFile = configPath(), log = '', ...options } = {}) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
113
|
+
const args = startupCommand(configFile, options);
|
|
114
|
+
const line = args.map((a) => `"${a}"`).join(' ');
|
|
115
|
+
return `@echo off\r\nrem Managed by "onboarder start startup". Edits are replaced.\r\nstart "" /b ${line}${log ? ` >> "${log}" 2>&1` : ''}\r\n`;
|
|
127
116
|
}
|
|
128
|
-
|
|
129
117
|
// The target carries its own platform, so every message about it can name the
|
|
130
118
|
// platform it was resolved for rather than the one this process happens to run
|
|
131
119
|
// on. A test (or a future cross-platform installer) resolves a plan9 target on a
|
|
132
120
|
// Mac; saying "darwin" in that error would be a lie.
|
|
133
121
|
export function startupTarget({ platform = process.platform, home = os.homedir(), env = process.env } = {}) {
|
|
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
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
122
|
+
// The per-user launchd domain. The system domain needs root, which this tool
|
|
123
|
+
// never asks for.
|
|
124
|
+
const domain = `gui/${process.getuid?.() ?? 501}`;
|
|
125
|
+
if (platform === 'darwin') {
|
|
126
|
+
return {
|
|
127
|
+
kind: 'launchd',
|
|
128
|
+
platform,
|
|
129
|
+
label: LABEL,
|
|
130
|
+
path: path.join(home, 'Library', 'LaunchAgents', LABEL + '.plist'),
|
|
131
|
+
render: renderLaunchAgent,
|
|
132
|
+
load: ['launchctl', 'bootstrap', domain, '{file}'],
|
|
133
|
+
unload: ['launchctl', 'bootout', `${domain}/{label}`],
|
|
134
|
+
status: ['launchctl', 'print', `${domain}/{label}`],
|
|
135
|
+
hint: 'launchd agent in ~/Library/LaunchAgents',
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
if (platform === 'linux') {
|
|
139
|
+
const configHome = env.XDG_CONFIG_HOME || path.join(home, '.config');
|
|
140
|
+
return {
|
|
141
|
+
kind: 'systemd',
|
|
142
|
+
platform,
|
|
143
|
+
label: UNIT,
|
|
144
|
+
path: path.join(configHome, 'systemd', 'user', UNIT),
|
|
145
|
+
render: renderSystemdUnit,
|
|
146
|
+
daemonReload: ['systemctl', '--user', 'daemon-reload'],
|
|
147
|
+
load: ['systemctl', '--user', 'enable', '--now', UNIT],
|
|
148
|
+
unload: ['systemctl', '--user', 'disable', '--now', UNIT],
|
|
149
|
+
status: ['systemctl', '--user', 'is-active', UNIT],
|
|
150
|
+
hint: 'systemd --user unit (no root; starts with your session)',
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (platform === 'win32') {
|
|
154
|
+
const appData = env.APPDATA || path.join(home, 'AppData', 'Roaming');
|
|
155
|
+
// Native separators throughout: this string goes into a .cmd file and into
|
|
156
|
+
// the Startup folder itself, and `path.join` would emit `\` mixed with `/`
|
|
157
|
+
// — which Windows tolerates in a file path but no one should have to read.
|
|
158
|
+
return {
|
|
159
|
+
kind: 'startup-folder',
|
|
160
|
+
platform,
|
|
161
|
+
label: 'Onboarder.cmd',
|
|
162
|
+
path: [
|
|
163
|
+
appData, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup', 'Onboarder.cmd',
|
|
164
|
+
].join('\\'),
|
|
165
|
+
render: renderWindowsStartup,
|
|
166
|
+
load: null, // the file *is* the registration
|
|
167
|
+
unload: null,
|
|
168
|
+
status: null,
|
|
169
|
+
hint: 'script in the Windows Startup folder',
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return { kind: 'unsupported', platform, label: '', path: '', render: null, load: null, unload: null, status: null, hint: '' };
|
|
185
173
|
}
|
|
186
|
-
|
|
187
174
|
// Substitute `{file}` / `{label}` and run without a shell — an argument is an
|
|
188
175
|
// argument, never a command line somebody else gets to compose. `spawn` is
|
|
189
176
|
// injected so a test can assert on the argv without touching launchd.
|
|
190
177
|
function exec(argv, { spawn = spawnSync } = {}) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
178
|
+
const result = spawn(argv[0], argv.slice(1), { encoding: 'utf8' });
|
|
179
|
+
return {
|
|
180
|
+
ok: !result.error && result.status === 0,
|
|
181
|
+
status: result.status ?? null,
|
|
182
|
+
output: String(result.stdout || result.stderr || '').trim(),
|
|
183
|
+
error: result.error?.message || '',
|
|
184
|
+
};
|
|
198
185
|
}
|
|
199
|
-
|
|
200
186
|
const fill = (argv, target) => argv
|
|
201
|
-
|
|
202
|
-
|
|
187
|
+
.map((a) => a.replace('{file}', target.path).replace('{label}', target.label));
|
|
203
188
|
export async function startupInstalled(target = startupTarget()) {
|
|
204
|
-
|
|
205
|
-
|
|
189
|
+
if (!target.path)
|
|
190
|
+
return false;
|
|
191
|
+
try {
|
|
192
|
+
await fs.access(target.path);
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
206
198
|
}
|
|
207
|
-
|
|
208
199
|
export async function startupStatus(target = startupTarget(), { run = spawnSync } = {}) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
200
|
+
const installed = await startupInstalled(target);
|
|
201
|
+
let active = null;
|
|
202
|
+
if (installed && target.status) {
|
|
203
|
+
const result = exec(fill(target.status, target), { spawn: run });
|
|
204
|
+
// systemd answers `active`/`inactive` on stdout; `launchctl print` succeeds
|
|
205
|
+
// only for a job that is actually loaded. Both answer "is it live now".
|
|
206
|
+
const text = result.output.toLowerCase();
|
|
207
|
+
active = target.kind === 'systemd'
|
|
208
|
+
? text.includes('active') && !text.includes('inactive')
|
|
209
|
+
: result.ok;
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
kind: target.kind,
|
|
213
|
+
supported: target.kind !== 'unsupported',
|
|
214
|
+
label: target.label,
|
|
215
|
+
path: target.path,
|
|
216
|
+
installed,
|
|
217
|
+
active,
|
|
218
|
+
detail: target.kind === 'unsupported'
|
|
219
|
+
? `no automatic-startup mechanism for ${target.platform || process.platform}`
|
|
220
|
+
: installed
|
|
221
|
+
? (active ? `running — ${target.hint}` : `installed, not running — ${target.hint}`)
|
|
222
|
+
: 'not installed',
|
|
223
|
+
hint: target.hint,
|
|
224
|
+
};
|
|
234
225
|
}
|
|
235
|
-
|
|
236
226
|
export async function installStartup({ configFile = configPath(), log = '', target = startupTarget(), run = spawnSync } = {}) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
227
|
+
if (target.kind === 'unsupported') {
|
|
228
|
+
return { ok: false, reason: `There is no automatic-startup mechanism Onboarder knows how to write on ${target.platform || process.platform}. Start it with \`onboarder start background\` from whatever your machine runs at boot.` };
|
|
229
|
+
}
|
|
230
|
+
await fs.mkdir(path.dirname(target.path), { recursive: true });
|
|
231
|
+
await fs.writeFile(target.path, target.render({ configFile, log }), { encoding: 'utf8', mode: 0o600 });
|
|
232
|
+
if (target.kind === 'systemd' && target.daemonReload)
|
|
233
|
+
exec(fill(target.daemonReload, target), { spawn: run });
|
|
234
|
+
if (!target.load)
|
|
235
|
+
return { ok: true, path: target.path, loaded: true, output: '' };
|
|
236
|
+
const result = exec(fill(target.load, target), { spawn: run });
|
|
237
|
+
// A unit that is already loaded is a success, not a failure — installing twice
|
|
238
|
+
// has to be idempotent, and `launchctl` says so in three different ways.
|
|
239
|
+
const already = /already (been )?(loaded|active|exists|running)|115|unit .*already/i.test(result.output);
|
|
240
|
+
if (!result.ok && !already) {
|
|
241
|
+
return { ok: false, path: target.path, output: result.output || result.error, error: result.error };
|
|
242
|
+
}
|
|
243
|
+
return { ok: true, path: target.path, loaded: true, output: result.output };
|
|
252
244
|
}
|
|
253
|
-
|
|
254
245
|
export async function removeStartup({ target = startupTarget(), run = spawnSync } = {}) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
246
|
+
if (target.kind === 'unsupported')
|
|
247
|
+
return { ok: false, reason: 'Nothing is installed for this platform.' };
|
|
248
|
+
let output = '';
|
|
249
|
+
if (target.unload)
|
|
250
|
+
output = exec(fill(target.unload, target), { spawn: run }).output;
|
|
251
|
+
await fs.rm(target.path, { force: true });
|
|
252
|
+
if (target.kind === 'systemd' && target.daemonReload)
|
|
253
|
+
exec(fill(target.daemonReload, target), { spawn: run });
|
|
254
|
+
return { ok: true, path: target.path, output };
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=startup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startup.js","sourceRoot":"","sources":["../src/server/startup.ts"],"names":[],"mappings":"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","sourcesContent":["// Start Onboarder when the machine boots, the way a person actually wants a\n// server they always want running to behave.\n//\n// \"Startup\" is three different mechanisms wearing one name, so this module\n// detects the platform and speaks its dialect — and, importantly, the *file\n// writing* is separated from the *service loading* so both are testable without\n// a Mac or a systemd:\n//\n// macOS ~/Library/LaunchAgents/<label>.plist → launchctl bootstrap\n// Linux ~/.config/systemd/user/<unit>.service → systemctl --user enable --now\n// Windows %APPDATA%\\...\\Startup\\Onboarder.cmd → being there is enough\n// other nothing; we say so rather than pretending\n//\n// Every artifact is generated from the *same* command line a person would type\n// (`<node> <cli> start background --config <file>`), so a login-started server\n// is indistinguishable from a hand-started one — same config, same pid file,\n// same `onboarder stop`.\n//\n// Deliberately no `sudo`, no writing into launchd's system domain, and nothing\n// outside the user's own home. A login item is a convenience; it must never be\n// the thing that needs an administrator password.\n\nimport { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { spawnSync } from 'node:child_process';\nimport { fileURLToPath } from 'node:url';\n\nimport { configPath } from './config.js';\n\nconst HERE = path.dirname(fileURLToPath(import.meta.url));\n\nexport const LABEL = 'com.onboarder.server';\nexport const UNIT = 'onboarder.service';\n\nexport function cliEntry() {\n // `bin/onboarder.js` next to `server/`, whether we were run from a checkout\n // or from a global install. The env override is what lets a test point the\n // generated unit at a fixture instead of the real machine.\n return process.env.ONBOARDER_CLI || path.resolve(HERE, '..', 'bin', 'onboarder.js');\n}\n\n// The argv a login item runs.\n//\n// Note what is *not* here: `background`. launchd and systemd are already\n// supervisors — they hold the process, restart it, and capture its output. A\n// login item that spawned a detached grandchild and exited immediately would\n// leave the supervisor watching a corpse, which defeats `KeepAlive` and turns a\n// busy port into a respawn loop. So the generated command is a plain foreground\n// `start`, and the OS owns the lifecycle from there.\nexport function startupCommand(configFile = configPath(), { node = process.execPath, entry = cliEntry() }: Record<string, any> = {}) {\n return [node, entry, 'start', '--config', configFile];\n}\n\nfunction xmlEscape(value) {\n const map = { '<': '<', '>': '>', '&': '&', \"'\": ''', '\"': '"' };\n return String(value).replace(/[<>&'\"]/g, (c) => map[c]);\n}\n\nfunction argList(args) {\n return args.map((a) => ` <string>${xmlEscape(a)}</string>`).join('\\n');\n}\n\nexport function renderLaunchAgent({ configFile = configPath(), log = '', ...options }: Record<string, any> = {}) {\n const args = startupCommand(configFile, options);\n const streams = log\n ? ` <key>StandardOutPath</key>\\n <string>${xmlEscape(log)}</string>\\n <key>StandardErrorPath</key>\\n <string>${xmlEscape(log)}</string>\\n`\n : '';\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${xmlEscape(LABEL)}</string>\n <key>ProgramArguments</key>\n <array>\n${argList(args)}\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <dict>\n <key>SuccessfulExit</key>\n <false/>\n </dict>\n${streams} <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>${xmlEscape(process.env.PATH || '/usr/local/bin:/usr/bin:/bin')}</string>\n <key>ONBOARDER_LAUNCH</key>\n <string>startup</string>\n </dict>\n</dict>\n</plist>\n`;\n}\n\nexport function renderSystemdUnit({ configFile = configPath(), log = '', ...options }: Record<string, any> = {}) {\n const args = startupCommand(configFile, options);\n // `Restart=always` would fight `onboarder stop`: a deliberate stop must stay\n // stopped, so only a *failed* exit is restarted. `on-failure` is the honest\n // setting here, and `SuccessfulExit=false` above is its launchd spelling.\n const exec = args.map((a) => (/[\\s\"]/.test(a) ? JSON.stringify(a) : a)).join(' ');\n return `[Unit]\nDescription=Onboarder — codebase visualizer and onboarding map\nDocumentation=https://github.com/Amitpandey88/onboarder\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nExecStart=${exec}\nRestart=on-failure\nRestartSec=3\n${log ? `StandardOutput=append:${log}\\nStandardError=append:${log}\\n` : ''}Environment=NO_COLOR=1\nEnvironment=ONBOARDER_LAUNCH=startup\n\n[Install]\nWantedBy=default.target\n`;\n}\n\nexport function renderWindowsStartup({ configFile = configPath(), log = '', ...options }: Record<string, any> = {}) {\n const args = startupCommand(configFile, options);\n const line = args.map((a) => `\"${a}\"`).join(' ');\n return `@echo off\\r\\nrem Managed by \"onboarder start startup\". Edits are replaced.\\r\\nstart \"\" /b ${line}${log ? ` >> \"${log}\" 2>&1` : ''}\\r\\n`;\n}\n\n// The target carries its own platform, so every message about it can name the\n// platform it was resolved for rather than the one this process happens to run\n// on. A test (or a future cross-platform installer) resolves a plan9 target on a\n// Mac; saying \"darwin\" in that error would be a lie.\nexport function startupTarget({ platform = process.platform, home = os.homedir(), env = process.env }: Record<string, any> = {}) {\n // The per-user launchd domain. The system domain needs root, which this tool\n // never asks for.\n const domain = `gui/${process.getuid?.() ?? 501}`;\n if (platform === 'darwin') {\n return {\n kind: 'launchd',\n platform,\n label: LABEL,\n path: path.join(home, 'Library', 'LaunchAgents', LABEL + '.plist'),\n render: renderLaunchAgent,\n load: ['launchctl', 'bootstrap', domain, '{file}'],\n unload: ['launchctl', 'bootout', `${domain}/{label}`],\n status: ['launchctl', 'print', `${domain}/{label}`],\n hint: 'launchd agent in ~/Library/LaunchAgents',\n };\n }\n if (platform === 'linux') {\n const configHome = env.XDG_CONFIG_HOME || path.join(home, '.config');\n return {\n kind: 'systemd',\n platform,\n label: UNIT,\n path: path.join(configHome, 'systemd', 'user', UNIT),\n render: renderSystemdUnit,\n daemonReload: ['systemctl', '--user', 'daemon-reload'],\n load: ['systemctl', '--user', 'enable', '--now', UNIT],\n unload: ['systemctl', '--user', 'disable', '--now', UNIT],\n status: ['systemctl', '--user', 'is-active', UNIT],\n hint: 'systemd --user unit (no root; starts with your session)',\n };\n }\n if (platform === 'win32') {\n const appData = env.APPDATA || path.join(home, 'AppData', 'Roaming');\n // Native separators throughout: this string goes into a .cmd file and into\n // the Startup folder itself, and `path.join` would emit `\\` mixed with `/`\n // — which Windows tolerates in a file path but no one should have to read.\n return {\n kind: 'startup-folder',\n platform,\n label: 'Onboarder.cmd',\n path: [\n appData, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup', 'Onboarder.cmd',\n ].join('\\\\'),\n render: renderWindowsStartup,\n load: null, // the file *is* the registration\n unload: null,\n status: null,\n hint: 'script in the Windows Startup folder',\n };\n }\n return { kind: 'unsupported', platform, label: '', path: '', render: null, load: null, unload: null, status: null, hint: '' };\n}\n\n// Substitute `{file}` / `{label}` and run without a shell — an argument is an\n// argument, never a command line somebody else gets to compose. `spawn` is\n// injected so a test can assert on the argv without touching launchd.\nfunction exec(argv, { spawn = spawnSync }: Record<string, any> = {}) {\n const result = spawn(argv[0], argv.slice(1), { encoding: 'utf8' });\n return {\n ok: !result.error && result.status === 0,\n status: result.status ?? null,\n output: String(result.stdout || result.stderr || '').trim(),\n error: result.error?.message || '',\n };\n}\n\nconst fill = (argv, target) => argv\n .map((a) => a.replace('{file}', target.path).replace('{label}', target.label));\n\nexport async function startupInstalled(target = startupTarget()) {\n if (!target.path) return false;\n try { await fs.access(target.path); return true; } catch { return false; }\n}\n\nexport async function startupStatus(target = startupTarget(), { run = spawnSync }: Record<string, any> = {}) {\n const installed = await startupInstalled(target);\n let active = null;\n if (installed && target.status) {\n const result = exec(fill(target.status, target), { spawn: run });\n // systemd answers `active`/`inactive` on stdout; `launchctl print` succeeds\n // only for a job that is actually loaded. Both answer \"is it live now\".\n const text = result.output.toLowerCase();\n active = target.kind === 'systemd'\n ? text.includes('active') && !text.includes('inactive')\n : result.ok;\n }\n return {\n kind: target.kind,\n supported: target.kind !== 'unsupported',\n label: target.label,\n path: target.path,\n installed,\n active,\n detail: target.kind === 'unsupported'\n ? `no automatic-startup mechanism for ${target.platform || process.platform}`\n : installed\n ? (active ? `running — ${target.hint}` : `installed, not running — ${target.hint}`)\n : 'not installed',\n hint: target.hint,\n };\n}\n\nexport async function installStartup({ configFile = configPath(), log = '', target = startupTarget(), run = spawnSync }: Record<string, any> = {}) {\n if (target.kind === 'unsupported') {\n return { ok: false, reason: `There is no automatic-startup mechanism Onboarder knows how to write on ${target.platform || process.platform}. Start it with \\`onboarder start background\\` from whatever your machine runs at boot.` };\n }\n await fs.mkdir(path.dirname(target.path), { recursive: true });\n await fs.writeFile(target.path, target.render({ configFile, log }), { encoding: 'utf8', mode: 0o600 });\n if (target.kind === 'systemd' && target.daemonReload) exec(fill(target.daemonReload, target), { spawn: run });\n if (!target.load) return { ok: true, path: target.path, loaded: true, output: '' };\n const result = exec(fill(target.load, target), { spawn: run });\n // A unit that is already loaded is a success, not a failure — installing twice\n // has to be idempotent, and `launchctl` says so in three different ways.\n const already = /already (been )?(loaded|active|exists|running)|115|unit .*already/i.test(result.output);\n if (!result.ok && !already) {\n return { ok: false, path: target.path, output: result.output || result.error, error: result.error };\n }\n return { ok: true, path: target.path, loaded: true, output: result.output };\n}\n\nexport async function removeStartup({ target = startupTarget(), run = spawnSync }: Record<string, any> = {}) {\n if (target.kind === 'unsupported') return { ok: false, reason: 'Nothing is installed for this platform.' };\n let output = '';\n if (target.unload) output = exec(fill(target.unload, target), { spawn: run }).output;\n await fs.rm(target.path, { force: true });\n if (target.kind === 'systemd' && target.daemonReload) exec(fill(target.daemonReload, target), { spawn: run });\n return { ok: true, path: target.path, output };\n}"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function resolveAsset(urlPath: any, { publicDir, sharedDir }: {
|
|
2
|
+
publicDir: any;
|
|
3
|
+
sharedDir: any;
|
|
4
|
+
}): string;
|
|
5
|
+
export declare function cacheControlFor(file: any): "no-cache" | "public, max-age=86400";
|
|
6
|
+
export declare function serveStatic(res: any, urlPath: any, dirs: any): Promise<void>;
|
package/server/static.js
CHANGED
|
@@ -7,53 +7,50 @@
|
|
|
7
7
|
// and work in both places, which is why browser modules reach for `/shared/...`
|
|
8
8
|
// and pure logic that Node needs to test lives in `shared/` rather than beside
|
|
9
9
|
// its caller.
|
|
10
|
-
|
|
11
10
|
import { promises as fs } from 'node:fs';
|
|
12
11
|
import path from 'node:path';
|
|
13
|
-
|
|
14
12
|
import { sendError } from './http.js';
|
|
15
13
|
import { resolveInside } from './paths.js';
|
|
16
|
-
|
|
17
14
|
const MIME = {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
15
|
+
'.html': 'text/html; charset=utf-8',
|
|
16
|
+
'.js': 'text/javascript; charset=utf-8',
|
|
17
|
+
'.mjs': 'text/javascript; charset=utf-8',
|
|
18
|
+
'.css': 'text/css; charset=utf-8',
|
|
19
|
+
'.json': 'application/json; charset=utf-8',
|
|
20
|
+
'.svg': 'image/svg+xml',
|
|
21
|
+
'.png': 'image/png',
|
|
22
|
+
'.ico': 'image/x-icon',
|
|
23
|
+
'.map': 'application/json',
|
|
24
|
+
'.woff2': 'font/woff2',
|
|
28
25
|
};
|
|
29
|
-
|
|
30
26
|
// `null` for anything that resolves outside the directory it was mapped into —
|
|
31
27
|
// `resolveInside` is the traversal guard, and a request for `/../../etc/passwd`
|
|
32
28
|
// has to fail here rather than reach `readFile`.
|
|
33
29
|
export function resolveAsset(urlPath, { publicDir, sharedDir }) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
if (urlPath === '/' || urlPath === '/index.html')
|
|
31
|
+
return path.join(publicDir, 'index.html');
|
|
32
|
+
if (urlPath.startsWith('/shared/'))
|
|
33
|
+
return resolveInside(sharedDir, urlPath.slice('/shared/'.length));
|
|
34
|
+
return resolveInside(publicDir, urlPath);
|
|
37
35
|
}
|
|
38
|
-
|
|
39
36
|
// Everything we author is served no-cache: the UI and the engine ship as loose
|
|
40
37
|
// modules with no build step and no content hashes, so a stale app.js against a
|
|
41
38
|
// fresh index.html breaks the whole page. Vendored builds are the exception —
|
|
42
39
|
// they are versioned by the directory they sit in and never edited in place.
|
|
43
40
|
export function cacheControlFor(file) {
|
|
44
|
-
|
|
41
|
+
return file.includes(path.sep + 'vendor' + path.sep) ? 'public, max-age=86400' : 'no-cache';
|
|
45
42
|
}
|
|
46
|
-
|
|
47
43
|
export async function serveStatic(res, urlPath, dirs) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
44
|
+
const file = resolveAsset(urlPath, dirs);
|
|
45
|
+
if (!file)
|
|
46
|
+
return sendError(res, 403, 'Not from here.');
|
|
47
|
+
const data = await fs.readFile(file).catch(() => null);
|
|
48
|
+
if (data === null)
|
|
49
|
+
return sendError(res, 404, 'Not found: ' + urlPath);
|
|
50
|
+
res.writeHead(200, {
|
|
51
|
+
'content-type': MIME[path.extname(file).toLowerCase()] || 'application/octet-stream',
|
|
52
|
+
'cache-control': cacheControlFor(file),
|
|
53
|
+
});
|
|
54
|
+
res.end(data);
|
|
59
55
|
}
|
|
56
|
+
//# sourceMappingURL=static.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static.js","sourceRoot":"","sources":["../src/server/static.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,4EAA4E;AAC5E,8EAA8E;AAC9E,8EAA8E;AAC9E,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAChF,+EAA+E;AAC/E,cAAc;AAEd,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,IAAI,GAAG;IACX,OAAO,EAAE,0BAA0B;IACnC,KAAK,EAAE,gCAAgC;IACvC,MAAM,EAAE,gCAAgC;IACxC,MAAM,EAAE,yBAAyB;IACjC,OAAO,EAAE,iCAAiC;IAC1C,MAAM,EAAE,eAAe;IACvB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,cAAc;IACtB,MAAM,EAAE,kBAAkB;IAC1B,QAAQ,EAAE,YAAY;CACvB,CAAC;AAEF,+EAA+E;AAC/E,gFAAgF;AAChF,iDAAiD;AACjD,MAAM,UAAU,YAAY,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE;IAC5D,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,aAAa;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAC5F,IAAI,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IACtG,OAAO,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,IAAI;IAClC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;AAC9F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI;IAClD,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,gBAAgB,CAAC,CAAC;IAExD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC;IAEvE,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,0BAA0B;QACpF,eAAe,EAAE,eAAe,CAAC,IAAI,CAAC;KACvC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC","sourcesContent":["// Serving the app itself: `public/` is the site root, and `/shared/` is mapped to\n// the repo's `shared/` directory so the analyzer the server imports and the\n// analyzer the browser imports are the same files. That mapping is the reason\n// nothing under `shared/` may touch `fs` or `window` — both runtimes load it.\n//\n// It also means no relative specifier can point from `public/js/` into `shared/`\n// and work in both places, which is why browser modules reach for `/shared/...`\n// and pure logic that Node needs to test lives in `shared/` rather than beside\n// its caller.\n\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\n\nimport { sendError } from './http.js';\nimport { resolveInside } from './paths.js';\n\nconst MIME = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.mjs': 'text/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.ico': 'image/x-icon',\n '.map': 'application/json',\n '.woff2': 'font/woff2',\n};\n\n// `null` for anything that resolves outside the directory it was mapped into —\n// `resolveInside` is the traversal guard, and a request for `/../../etc/passwd`\n// has to fail here rather than reach `readFile`.\nexport function resolveAsset(urlPath, { publicDir, sharedDir }) {\n if (urlPath === '/' || urlPath === '/index.html') return path.join(publicDir, 'index.html');\n if (urlPath.startsWith('/shared/')) return resolveInside(sharedDir, urlPath.slice('/shared/'.length));\n return resolveInside(publicDir, urlPath);\n}\n\n// Everything we author is served no-cache: the UI and the engine ship as loose\n// modules with no build step and no content hashes, so a stale app.js against a\n// fresh index.html breaks the whole page. Vendored builds are the exception —\n// they are versioned by the directory they sit in and never edited in place.\nexport function cacheControlFor(file) {\n return file.includes(path.sep + 'vendor' + path.sep) ? 'public, max-age=86400' : 'no-cache';\n}\n\nexport async function serveStatic(res, urlPath, dirs) {\n const file = resolveAsset(urlPath, dirs);\n if (!file) return sendError(res, 403, 'Not from here.');\n\n const data = await fs.readFile(file).catch(() => null);\n if (data === null) return sendError(res, 404, 'Not found: ' + urlPath);\n\n res.writeHead(200, {\n 'content-type': MIME[path.extname(file).toLowerCase()] || 'application/octet-stream',\n 'cache-control': cacheControlFor(file),\n });\n res.end(data);\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function plansFor(toolId: any, platform?: NodeJS.Platform): any;
|
|
2
|
+
export declare function planAvailability(toolId: any, options?: Record<string, any>): any;
|
|
3
|
+
export declare function isInstalling(toolId: any): boolean;
|
|
4
|
+
export declare function installTool(toolId: any, onEvent?: (event: Record<string, unknown>) => void): Promise<any>;
|